Auto merge of #80995 - tmandry:instrument-method-checker, r=lcnr

Add tracing instrumentation to method typeck

I was recently digging into how this code works, and this instrumentation was helpful.
diff --git a/.github/ISSUE_TEMPLATE/library_tracking_issue.md b/.github/ISSUE_TEMPLATE/library_tracking_issue.md
index 3e42594..cbc4465 100644
--- a/.github/ISSUE_TEMPLATE/library_tracking_issue.md
+++ b/.github/ISSUE_TEMPLATE/library_tracking_issue.md
@@ -33,21 +33,41 @@
 -->
 
 ```rust
-...
+// core::magic
+
+pub struct Magic;
+
+impl Magic {
+    pub fn magic(self);
+}
 ```
 
 ### Steps / History
 
 <!--
-In the simplest case, this is a PR implementing the feature followed by a PR
-that stabilises the feature. However it's not uncommon for the feature to be
-changed before stabilization. For larger features, the implementation could be
-split up in multiple steps.
+For larger features, more steps might be involved.
+If the feature is changed later, please add those PRs here as well.
 -->
 
-- [ ] Implementation: ...
+- [ ] Implementation: #...
+- [ ] Final commenting period (FCP)
 - [ ] Stabilization PR
 
+<!--
+Once the feature has gone through a few release cycles and there are no
+unresolved questions left, the feature might be ready for stabilization.
+
+If this feature didn't go through the RFC process, a final commenting period
+(FCP) is always needed before stabilization. This works as follows:
+
+A library team member can kick off the stabilization process, at which point
+the rfcbot will ask all the team members to verify they agree with
+stabilization. Once enough members agree and there are no concerns, the final
+commenting period begins: this issue will be marked as such and will be listed
+in the next This Week in Rust newsletter. If no blocking concerns are raised in
+that period of 10 days, a stabilzation PR can be opened by anyone.
+-->
+
 ### Unresolved Questions
 
 <!--
diff --git a/.gitmodules b/.gitmodules
index 9841131..40e6fc2 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -37,7 +37,7 @@
 [submodule "src/llvm-project"]
 	path = src/llvm-project
 	url = https://github.com/rust-lang/llvm-project.git
-	branch = rustc/11.0-2020-10-12
+	branch = rustc/11.0-2021-01-05
 [submodule "src/doc/embedded-book"]
 	path = src/doc/embedded-book
 	url = https://github.com/rust-embedded/book.git
diff --git a/Cargo.lock b/Cargo.lock
index 4676e41..c2c06a2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -295,7 +295,7 @@
 
 [[package]]
 name = "cargo"
-version = "0.51.0"
+version = "0.52.0"
 dependencies = [
  "anyhow",
  "atty",
@@ -568,7 +568,7 @@
 
 [[package]]
 name = "clippy"
-version = "0.0.212"
+version = "0.1.51"
 dependencies = [
  "cargo_metadata 0.12.0",
  "clippy-mini-macro-test",
@@ -589,7 +589,7 @@
 
 [[package]]
 name = "clippy_lints"
-version = "0.0.212"
+version = "0.1.51"
 dependencies = [
  "cargo_metadata 0.12.0",
  "if_chain",
@@ -666,9 +666,9 @@
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.36"
+version = "0.1.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cd0782e0a7da7598164153173e5a5d4d9b1da094473c98dce0ff91406112369"
+checksum = "3748f82c7d366a0b4950257d19db685d4958d2fa27c6d164a3f069fec42b748b"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -1973,9 +1973,9 @@
 
 [[package]]
 name = "mdbook"
-version = "0.4.3"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29be448fcafb00c5a8966c4020c2a5ffbbc333e5b96d0bb5ef54b5bd0524d9ff"
+checksum = "b3d948b64449003363127ed6c6139f03273982c3fe97da4cb3dee933e38ce38f"
 dependencies = [
  "ammonia",
  "anyhow",
@@ -2720,9 +2720,9 @@
 
 [[package]]
 name = "racer"
-version = "2.1.41"
+version = "2.1.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2f1a4baaaf5c4a9aa30c708c339ae293d02976d2b7f1575a59f44558d25bfea"
+checksum = "d4463624cd50208e86382c13a84561fcd1d3e9d8ff4d97e8ef0c5e304df8d2b9"
 dependencies = [
  "bitflags",
  "clap",
@@ -2964,9 +2964,9 @@
 
 [[package]]
 name = "rls-data"
-version = "0.19.0"
+version = "0.19.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76c72ea97e045be5f6290bb157ebdc5ee9f2b093831ff72adfaf59025cf5c491"
+checksum = "a58135eb039f3a3279a33779192f0ee78b56f57ae636e25cec83530e41debb99"
 dependencies = [
  "rls-span",
  "serde",
@@ -3001,9 +3001,9 @@
 
 [[package]]
 name = "rls-span"
-version = "0.5.2"
+version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2e9bed56f6272bd85d9d06d1aaeef80c5fddc78a82199eb36dceb5f94e7d934"
+checksum = "f0eea58478fc06e15f71b03236612173a1b81e9770314edecfa664375e3e4c86"
 dependencies = [
  "serde",
 ]
@@ -3049,18 +3049,18 @@
 
 [[package]]
 name = "rustc-ap-rustc_arena"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81f7b9bc5a6f79b1f230833cb4c8f8928d48c129b21df5b372c202fb826c0b5e"
+checksum = "fb953bea2006184c8f01a6fd3ed51658c73380992a9aefc113e8d32ece6b7516"
 dependencies = [
  "smallvec 1.4.2",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_ast"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d77f313e9f30af93f2737f1a99d6552e26b702c5cef3bb65e35f5b4fe5191f1"
+checksum = "94da60fa49b2f60d2539e8823cf2b4d4e61583ba4ee796b8289e12f017d3dc5b"
 dependencies = [
  "bitflags",
  "rustc-ap-rustc_data_structures",
@@ -3075,9 +3075,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_ast_passes"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30408fbf42fa6fbeb383d3fce0f24d2490c3d12527beb2f48e6e728765bc8695"
+checksum = "3e9f9eaaee223832187a398abe0f9cb8bc4e5cd538322d8f3864aea65239c79e"
 dependencies = [
  "itertools 0.9.0",
  "rustc-ap-rustc_ast",
@@ -3094,9 +3094,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_ast_pretty"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d47b8a3adcccc204578b0ee9cd2f9952921fa43977f58343913cca04cce87043"
+checksum = "302b43429c62efc43b159b1f8ab94c8b517fb553cbae854c3fcf34e01c36accb"
 dependencies = [
  "rustc-ap-rustc_ast",
  "rustc-ap-rustc_span",
@@ -3106,9 +3106,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_attr"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66f5f53ecdbf7d8b47905936f93eb1fdae496137e94b7e4023a0b866b0e1a92d"
+checksum = "2cbd78cb6f7ca0991478d7f1bc5646b6eca58c37ccbdf70b5d83c490a7c47be7"
 dependencies = [
  "rustc-ap-rustc_ast",
  "rustc-ap-rustc_ast_pretty",
@@ -3125,9 +3125,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3aa913fa40b90157067b17dd7ddfd5df0d8566e339ffa8351a638bdf3fc7ee81"
+checksum = "7b9ebd359b0f21086a88595a25d92dc7e8e5f7b111e41c52bb6c97e2d95fd0bb"
 dependencies = [
  "arrayvec",
  "bitflags",
@@ -3156,9 +3156,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d4b4956287d7c4996409b8362aa69c0c9a6853751ff00ee0a6f78223c5ef3ad"
+checksum = "3b810fcac4d738c47d7793afe3e0f2e03d5193c36c698b0fbcebfb64e468c06b"
 dependencies = [
  "annotate-snippets 0.8.0",
  "atty",
@@ -3176,9 +3176,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_expand"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fa908bb1b67230dd4309e93edefc6a6c2f3d8b6a195f77c47743c882114a22e"
+checksum = "f5b44aadd09c05a42a21a063e9f2241fd3d9c00c3dd6e474e22c3a3e8274c959"
 dependencies = [
  "rustc-ap-rustc_ast",
  "rustc-ap-rustc_ast_passes",
@@ -3199,9 +3199,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_feature"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b7a1db115893ed7ed0db80f70d2246c1709de7854238acde76471495930f2a"
+checksum = "a2f4121cb9718c8c1c6350a3aaea619fbbae38fb1aadd3d7305586460babb531"
 dependencies = [
  "rustc-ap-rustc_data_structures",
  "rustc-ap-rustc_span",
@@ -3209,21 +3209,21 @@
 
 [[package]]
 name = "rustc-ap-rustc_fs_util"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55937887cb606cc72193ea3c5feb8bbbb810d812aa233b9a1e7749155c4a3501"
+checksum = "fdb0f36e34fafb725795bef3ec6f414cac34e7ca98e6d25927be36d95ae1c6ac"
 
 [[package]]
 name = "rustc-ap-rustc_graphviz"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e39e179e616356927f0c4eda43e3a35d88476f91e1ac8e4a0a09661dbab44a6e"
+checksum = "a98402e20e2913016ed54f12aead5c987fe227a0fb31cc720e17ff51c6f32466"
 
 [[package]]
 name = "rustc-ap-rustc_index"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "572d3962d6999f3b1a71d335308e939e204339d4ad36e6ebe7a591c9d4329f5d"
+checksum = "ec91408d727f73f682cd8ae836d762c8dab0ed4e81994ced03aa1edcee3b99a4"
 dependencies = [
  "arrayvec",
  "rustc-ap-rustc_macros",
@@ -3232,18 +3232,18 @@
 
 [[package]]
 name = "rustc-ap-rustc_lexer"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44bc89d9ca7a78fb82e103b389362c55f03800745f8ba14e068b805cfaf783ec"
+checksum = "67adbe260a0a11910624d6d28c0304fcf7b063e666682111005c83b09f73429d"
 dependencies = [
  "unicode-xid",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_lint_defs"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d39bda92aabd77e49ac8ad5e24fccf9d7245b8ff2bf1249ab98733e2e5a2863"
+checksum = "6bf11d0646da7bd136fbca53834afcc3760fbfc20fa4875e139b3ada41ec53a5"
 dependencies = [
  "rustc-ap-rustc_ast",
  "rustc-ap-rustc_data_structures",
@@ -3255,9 +3255,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_macros"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3295fbc9625197494e356e92d8ac08370eddafa60189861c7b2f084b3b5a6b8"
+checksum = "c454b10b66750ffd9bfd7d53b0f30eaba1462356e9ac91f0d037cb0556dc7681"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3267,9 +3267,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_parse"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ff5d0094396844efead43303a6eb25b8a4962e2c80fb0ea4a86e4101fbfd404"
+checksum = "3d03f423948137a8370a88447382a18015d47a273268e3ead2d0a987c3b14070"
 dependencies = [
  "bitflags",
  "rustc-ap-rustc_ast",
@@ -3287,9 +3287,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_serialize"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d5cff6709a8b51a3730288a9ead17cabe8146b1c787db52298447ef7890140a"
+checksum = "e7ed5df71bd37d1e179b4bbedf77db76c9e0eb2e03159c58a691adbf29f74682"
 dependencies = [
  "indexmap",
  "smallvec 1.4.2",
@@ -3297,9 +3297,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_session"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36bb15ef12174b5ed6419a7e4260a899ce8927e8c8fd1f0cddf178818737dcdf"
+checksum = "3e3b92b51fad25a897b23ec98961126aea038abeab8d47989f774f7727016b5e"
 dependencies = [
  "bitflags",
  "getopts",
@@ -3319,9 +3319,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_span"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "104d349a32be9cfd3d39a5a70ad6c5e682ce262fc5cc8717d35a01e980c0d8b2"
+checksum = "d98273206d8a571c780f233f3391ea30e29c5e75ecdc60335ccef346046e1953"
 dependencies = [
  "cfg-if 0.1.10",
  "md-5",
@@ -3339,9 +3339,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_target"
-version = "691.0.0"
+version = "697.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d7ac4ded9a6aecb534744c836a160497985f0d53b272581e95e7890d31b9e17"
+checksum = "08ce81fe0130e61112db5f3b2db6b21d407e4b14ae467ab9637f4696cc340ad1"
 dependencies = [
  "bitflags",
  "rustc-ap-rustc_data_structures",
@@ -3652,6 +3652,7 @@
 name = "rustc_driver"
 version = "0.0.0"
 dependencies = [
+ "atty",
  "libc",
  "rustc_ast",
  "rustc_ast_pretty",
@@ -3745,6 +3746,7 @@
 dependencies = [
  "rustc_ast",
  "rustc_data_structures",
+ "rustc_feature",
  "rustc_index",
  "rustc_macros",
  "rustc_serialize",
@@ -3894,6 +3896,7 @@
  "rustc_macros",
  "rustc_serialize",
  "rustc_span",
+ "rustc_target",
  "tracing",
 ]
 
@@ -4397,7 +4400,7 @@
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.4.30"
+version = "1.4.32"
 dependencies = [
  "annotate-snippets 0.6.1",
  "anyhow",
@@ -5343,7 +5346,7 @@
  "chrono",
  "lazy_static",
  "matchers",
- "parking_lot 0.9.0",
+ "parking_lot 0.11.0",
  "regex",
  "serde",
  "serde_json",
diff --git a/README.md b/README.md
index 07c0960..6ab11e7 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,4 @@
-<a href = "https://www.rust-lang.org/">
-<img width = "90%" height = "auto" src = "https://img.shields.io/badge/Rust-Programming%20Language-black?style=flat&logo=rust" alt = "The Rust Programming Language">
-</a>
+# The Rust Programming Language
 
 This is the main source code repository for [Rust]. It contains the compiler,
 standard library, and documentation.
diff --git a/RELEASES.md b/RELEASES.md
index 8f04980..4409b6a 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -45,7 +45,6 @@
 
 - [`RangeInclusive` now checks for exhaustion when calling `contains` and indexing.][78109]
 - [`ToString::to_string` now no longer shrinks the internal buffer in the default implementation.][77997]
-- [`ops::{Index, IndexMut}` are now implemented for fixed sized arrays of any length.][74989]
 
 Stabilized APIs
 ---------------
@@ -110,7 +109,6 @@
 [76199]: https://github.com/rust-lang/rust/pull/76199
 [76119]: https://github.com/rust-lang/rust/pull/76119
 [75914]: https://github.com/rust-lang/rust/pull/75914
-[74989]: https://github.com/rust-lang/rust/pull/74989
 [79004]: https://github.com/rust-lang/rust/pull/79004
 [78676]: https://github.com/rust-lang/rust/pull/78676
 [79904]: https://github.com/rust-lang/rust/issues/79904
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index cf31e56..ff89982 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -23,8 +23,8 @@
 pub use UnsafeSource::*;
 
 use crate::ptr::P;
-use crate::token::{self, CommentKind, DelimToken};
-use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream};
+use crate::token::{self, CommentKind, DelimToken, Token};
+use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree};
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -242,12 +242,21 @@
 /// A path like `Foo(A, B) -> C`.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct ParenthesizedArgs {
-    /// Overall span
+    /// ```text
+    /// Foo(A, B) -> C
+    /// ^^^^^^^^^^^^^^
+    /// ```
     pub span: Span,
 
     /// `(A, B)`
     pub inputs: Vec<P<Ty>>,
 
+    /// ```text
+    /// Foo(A, B) -> C
+    ///    ^^^^^^
+    /// ```
+    pub inputs_span: Span,
+
     /// `C`
     pub output: FnRetTy,
 }
@@ -368,6 +377,8 @@
         ty: P<Ty>,
         /// Span of the `const` keyword.
         kw_span: Span,
+        /// Optional default value for the const generic param
+        default: Option<AnonConst>,
     },
 }
 
@@ -431,9 +442,9 @@
 impl WherePredicate {
     pub fn span(&self) -> Span {
         match self {
-            &WherePredicate::BoundPredicate(ref p) => p.span,
-            &WherePredicate::RegionPredicate(ref p) => p.span,
-            &WherePredicate::EqPredicate(ref p) => p.span,
+            WherePredicate::BoundPredicate(p) => p.span,
+            WherePredicate::RegionPredicate(p) => p.span,
+            WherePredicate::EqPredicate(p) => p.span,
         }
     }
 }
@@ -914,16 +925,6 @@
         }
     }
 
-    pub fn set_tokens(&mut self, tokens: Option<LazyTokenStream>) {
-        match self.kind {
-            StmtKind::Local(ref mut local) => local.tokens = tokens,
-            StmtKind::Item(ref mut item) => item.tokens = tokens,
-            StmtKind::Expr(ref mut expr) | StmtKind::Semi(ref mut expr) => expr.tokens = tokens,
-            StmtKind::Empty => {}
-            StmtKind::MacCall(ref mut mac) => mac.tokens = tokens,
-        }
-    }
-
     pub fn has_trailing_semicolon(&self) -> bool {
         match &self.kind {
             StmtKind::Semi(_) => true,
@@ -1462,8 +1463,8 @@
     Eq(
         /// Span of the `=` token.
         Span,
-        /// Token stream of the "value".
-        TokenStream,
+        /// "value" as a nonterminal token.
+        Token,
     ),
 }
 
@@ -1476,10 +1477,10 @@
     }
 
     pub fn span(&self) -> Option<Span> {
-        match *self {
+        match self {
             MacArgs::Empty => None,
             MacArgs::Delimited(dspan, ..) => Some(dspan.entire()),
-            MacArgs::Eq(eq_span, ref tokens) => Some(eq_span.to(tokens.span().unwrap_or(eq_span))),
+            MacArgs::Eq(eq_span, token) => Some(eq_span.to(token.span)),
         }
     }
 
@@ -1488,7 +1489,8 @@
     pub fn inner_tokens(&self) -> TokenStream {
         match self {
             MacArgs::Empty => TokenStream::default(),
-            MacArgs::Delimited(.., tokens) | MacArgs::Eq(.., tokens) => tokens.clone(),
+            MacArgs::Delimited(.., tokens) => tokens.clone(),
+            MacArgs::Eq(.., token) => TokenTree::Token(token.clone()).into(),
         }
     }
 
@@ -2878,3 +2880,69 @@
 }
 
 pub type ForeignItem = Item<ForeignItemKind>;
+
+pub trait HasTokens {
+    /// Called by `Parser::collect_tokens` to store the collected
+    /// tokens inside an AST node
+    fn finalize_tokens(&mut self, tokens: LazyTokenStream);
+}
+
+impl<T: HasTokens + 'static> HasTokens for P<T> {
+    fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
+        (**self).finalize_tokens(tokens);
+    }
+}
+
+impl<T: HasTokens> HasTokens for Option<T> {
+    fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
+        if let Some(inner) = self {
+            inner.finalize_tokens(tokens);
+        }
+    }
+}
+
+impl HasTokens for Attribute {
+    fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
+        match &mut self.kind {
+            AttrKind::Normal(_, attr_tokens) => {
+                if attr_tokens.is_none() {
+                    *attr_tokens = Some(tokens);
+                }
+            }
+            AttrKind::DocComment(..) => {
+                panic!("Called finalize_tokens on doc comment attr {:?}", self)
+            }
+        }
+    }
+}
+
+impl HasTokens for Stmt {
+    fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
+        let stmt_tokens = match self.kind {
+            StmtKind::Local(ref mut local) => &mut local.tokens,
+            StmtKind::Item(ref mut item) => &mut item.tokens,
+            StmtKind::Expr(ref mut expr) | StmtKind::Semi(ref mut expr) => &mut expr.tokens,
+            StmtKind::Empty => return,
+            StmtKind::MacCall(ref mut mac) => &mut mac.tokens,
+        };
+        if stmt_tokens.is_none() {
+            *stmt_tokens = Some(tokens);
+        }
+    }
+}
+
+macro_rules! derive_has_tokens {
+    ($($ty:path),*) => { $(
+        impl HasTokens for $ty {
+            fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
+                if self.tokens.is_none() {
+                    self.tokens = Some(tokens);
+                }
+            }
+        }
+    )* }
+}
+
+derive_has_tokens! {
+    Item, Expr, Ty, AttrItem, Visibility, Path, Block, Pat
+}
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 726ae5e..6a54cb4 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -476,7 +476,7 @@
     pub fn mac_args(&self, span: Span) -> MacArgs {
         match self {
             MetaItemKind::Word => MacArgs::Empty,
-            MetaItemKind::NameValue(lit) => MacArgs::Eq(span, lit.token_tree().into()),
+            MetaItemKind::NameValue(lit) => MacArgs::Eq(span, lit.to_token()),
             MetaItemKind::List(list) => {
                 let mut tts = Vec::new();
                 for (i, item) in list.iter().enumerate() {
@@ -498,7 +498,10 @@
         match *self {
             MetaItemKind::Word => vec![],
             MetaItemKind::NameValue(ref lit) => {
-                vec![TokenTree::token(token::Eq, span).into(), lit.token_tree().into()]
+                vec![
+                    TokenTree::token(token::Eq, span).into(),
+                    TokenTree::Token(lit.to_token()).into(),
+                ]
             }
             MetaItemKind::List(ref list) => {
                 let mut tokens = Vec::new();
@@ -554,10 +557,7 @@
                 MetaItemKind::list_from_tokens(tokens.clone())
             }
             MacArgs::Delimited(..) => None,
-            MacArgs::Eq(_, tokens) => {
-                assert!(tokens.len() == 1);
-                MetaItemKind::name_value_from_tokens(&mut tokens.trees())
-            }
+            MacArgs::Eq(_, token) => Lit::from_token(token).ok().map(MetaItemKind::NameValue),
             MacArgs::Empty => Some(MetaItemKind::Word),
         }
     }
@@ -592,7 +592,7 @@
     fn token_trees_and_spacings(&self) -> Vec<TreeAndSpacing> {
         match *self {
             NestedMetaItem::MetaItem(ref item) => item.token_trees_and_spacings(),
-            NestedMetaItem::Literal(ref lit) => vec![lit.token_tree().into()],
+            NestedMetaItem::Literal(ref lit) => vec![TokenTree::Token(lit.to_token()).into()],
         }
     }
 
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 8a20dd7..0869549 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -13,6 +13,7 @@
 #![feature(const_fn_transmute)]
 #![feature(const_panic)]
 #![feature(crate_visibility_modifier)]
+#![feature(iterator_fold_self)]
 #![feature(label_break_value)]
 #![feature(nll)]
 #![feature(or_patterns)]
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 3889ede..35de744 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -365,18 +365,16 @@
             visit_delim_span(dspan, vis);
             visit_tts(tokens, vis);
         }
-        MacArgs::Eq(eq_span, tokens) => {
+        MacArgs::Eq(eq_span, token) => {
             vis.visit_span(eq_span);
-            visit_tts(tokens, vis);
-            // The value in `#[key = VALUE]` must be visited as an expression for backward
-            // compatibility, so that macros can be expanded in that position.
-            if !vis.token_visiting_enabled() {
-                match Lrc::make_mut(&mut tokens.0).get_mut(0) {
-                    Some((TokenTree::Token(token), _spacing)) => match &mut token.kind {
-                        token::Interpolated(nt) => match Lrc::make_mut(nt) {
-                            token::NtExpr(expr) => vis.visit_expr(expr),
-                            t => panic!("unexpected token in key-value attribute: {:?}", t),
-                        },
+            if vis.token_visiting_enabled() {
+                visit_token(token, vis);
+            } else {
+                // The value in `#[key = VALUE]` must be visited as an expression for backward
+                // compatibility, so that macros can be expanded in that position.
+                match &mut token.kind {
+                    token::Interpolated(nt) => match Lrc::make_mut(nt) {
+                        token::NtExpr(expr) => vis.visit_expr(expr),
                         t => panic!("unexpected token in key-value attribute: {:?}", t),
                     },
                     t => panic!("unexpected token in key-value attribute: {:?}", t),
@@ -567,7 +565,7 @@
     args: &mut ParenthesizedArgs,
     vis: &mut T,
 ) {
-    let ParenthesizedArgs { inputs, output, span } = args;
+    let ParenthesizedArgs { inputs, output, span, .. } = args;
     visit_vec(inputs, |input| vis.visit_ty(input));
     noop_visit_fn_ret_ty(output, vis);
     vis.visit_span(span);
@@ -790,8 +788,9 @@
         GenericParamKind::Type { default } => {
             visit_opt(default, |default| vis.visit_ty(default));
         }
-        GenericParamKind::Const { ty, kw_span: _ } => {
+        GenericParamKind::Const { ty, kw_span: _, default } => {
             vis.visit_ty(ty);
+            visit_opt(default, |default| vis.visit_anon_const(default));
         }
     }
     smallvec![param]
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index cd1e444..90bfb01 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -15,7 +15,7 @@
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::{self, FileName, RealFileName, Span, DUMMY_SP};
+use rustc_span::{self, edition::Edition, FileName, RealFileName, Span, DUMMY_SP};
 use std::borrow::Cow;
 use std::{fmt, mem};
 
@@ -690,7 +690,16 @@
     Item,
     Block,
     Stmt,
-    Pat,
+    Pat2018 {
+        /// Keep track of whether the user used `:pat2018` or `:pat` and we inferred it from the
+        /// edition of the span. This is used for diagnostics.
+        inferred: bool,
+    },
+    Pat2021 {
+        /// Keep track of whether the user used `:pat2018` or `:pat` and we inferred it from the
+        /// edition of the span. This is used for diagnostics.
+        inferred: bool,
+    },
     Expr,
     Ty,
     Ident,
@@ -703,12 +712,24 @@
 }
 
 impl NonterminalKind {
-    pub fn from_symbol(symbol: Symbol) -> Option<NonterminalKind> {
+    /// The `edition` closure is used to get the edition for the given symbol. Doing
+    /// `span.edition()` is expensive, so we do it lazily.
+    pub fn from_symbol(
+        symbol: Symbol,
+        edition: impl FnOnce() -> Edition,
+    ) -> Option<NonterminalKind> {
         Some(match symbol {
             sym::item => NonterminalKind::Item,
             sym::block => NonterminalKind::Block,
             sym::stmt => NonterminalKind::Stmt,
-            sym::pat => NonterminalKind::Pat,
+            sym::pat => match edition() {
+                Edition::Edition2015 | Edition::Edition2018 => {
+                    NonterminalKind::Pat2018 { inferred: true }
+                }
+                Edition::Edition2021 => NonterminalKind::Pat2021 { inferred: true },
+            },
+            sym::pat2018 => NonterminalKind::Pat2018 { inferred: false },
+            sym::pat2021 => NonterminalKind::Pat2021 { inferred: false },
             sym::expr => NonterminalKind::Expr,
             sym::ty => NonterminalKind::Ty,
             sym::ident => NonterminalKind::Ident,
@@ -726,7 +747,10 @@
             NonterminalKind::Item => sym::item,
             NonterminalKind::Block => sym::block,
             NonterminalKind::Stmt => sym::stmt,
-            NonterminalKind::Pat => sym::pat,
+            NonterminalKind::Pat2018 { inferred: false } => sym::pat2018,
+            NonterminalKind::Pat2021 { inferred: false } => sym::pat2021,
+            NonterminalKind::Pat2018 { inferred: true }
+            | NonterminalKind::Pat2021 { inferred: true } => sym::pat,
             NonterminalKind::Expr => sym::expr,
             NonterminalKind::Ty => sym::ty,
             NonterminalKind::Ident => sym::ident,
@@ -747,7 +771,7 @@
 }
 
 impl Nonterminal {
-    fn span(&self) -> Span {
+    pub fn span(&self) -> Span {
         match self {
             NtItem(item) => item.span,
             NtBlock(block) => block.span,
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 0550f53..00354b4 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -1,15 +1,15 @@
 //! # Token Streams
 //!
 //! `TokenStream`s represent syntactic objects before they are converted into ASTs.
-//! A `TokenStream` is, roughly speaking, a sequence (eg stream) of `TokenTree`s,
-//! which are themselves a single `Token` or a `Delimited` subsequence of tokens.
+//! A `TokenStream` is, roughly speaking, a sequence of [`TokenTree`]s,
+//! which are themselves a single [`Token`] or a `Delimited` subsequence of tokens.
 //!
 //! ## Ownership
 //!
 //! `TokenStream`s are persistent data structures constructed as ropes with reference
 //! counted-children. In general, this means that calling an operation on a `TokenStream`
 //! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to
-//! the original. This essentially coerces `TokenStream`s into 'views' of their subparts,
+//! the original. This essentially coerces `TokenStream`s into "views" of their subparts,
 //! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking
 //! ownership of the original.
 
@@ -24,9 +24,9 @@
 
 use std::{fmt, iter, mem};
 
-/// When the main rust parser encounters a syntax-extension invocation, it
-/// parses the arguments to the invocation as a token-tree. This is a very
-/// loose structure, such that all sorts of different AST-fragments can
+/// When the main Rust parser encounters a syntax-extension invocation, it
+/// parses the arguments to the invocation as a token tree. This is a very
+/// loose structure, such that all sorts of different AST fragments can
 /// be passed to syntax extensions using a uniform type.
 ///
 /// If the syntax extension is an MBE macro, it will attempt to match its
@@ -38,9 +38,9 @@
 /// Nothing special happens to misnamed or misplaced `SubstNt`s.
 #[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
 pub enum TokenTree {
-    /// A single token
+    /// A single token.
     Token(Token),
-    /// A delimited sequence of token trees
+    /// A delimited sequence of token trees.
     Delimited(DelimSpan, DelimToken, TokenStream),
 }
 
@@ -62,7 +62,7 @@
 }
 
 impl TokenTree {
-    /// Checks if this TokenTree is equal to the other, regardless of span information.
+    /// Checks if this `TokenTree` is equal to the other, regardless of span information.
     pub fn eq_unspanned(&self, other: &TokenTree) -> bool {
         match (self, other) {
             (TokenTree::Token(token), TokenTree::Token(token2)) => token.kind == token2.kind,
@@ -73,7 +73,7 @@
         }
     }
 
-    /// Retrieves the TokenTree's span.
+    /// Retrieves the `TokenTree`'s span.
     pub fn span(&self) -> Span {
         match self {
             TokenTree::Token(token) => token.span,
@@ -140,7 +140,7 @@
     }
 }
 
-/// A lazy version of `TokenStream`, which defers creation
+/// A lazy version of [`TokenStream`], which defers creation
 /// of an actual `TokenStream` until it is needed.
 /// `Box` is here only to reduce the structure size.
 #[derive(Clone)]
@@ -188,11 +188,12 @@
     }
 }
 
-/// A `TokenStream` is an abstract sequence of tokens, organized into `TokenTree`s.
+/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
 ///
 /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
 /// instead of a representation of the abstract syntax tree.
-/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat.
+/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for
+/// backwards compatability.
 #[derive(Clone, Debug, Default, Encodable, Decodable)]
 pub struct TokenStream(pub(crate) Lrc<Vec<TreeAndSpacing>>);
 
@@ -429,7 +430,7 @@
     }
 }
 
-/// By-reference iterator over a `TokenStream`.
+/// By-reference iterator over a [`TokenStream`].
 #[derive(Clone)]
 pub struct CursorRef<'t> {
     stream: &'t TokenStream,
@@ -457,8 +458,8 @@
     }
 }
 
-/// Owning by-value iterator over a `TokenStream`.
-/// FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones.
+/// Owning by-value iterator over a [`TokenStream`].
+// FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones.
 #[derive(Clone)]
 pub struct Cursor {
     pub stream: TokenStream,
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index f6f1ad0..2124f1e 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -2,7 +2,6 @@
 
 use crate::ast::{self, Lit, LitKind};
 use crate::token::{self, Token};
-use crate::tokenstream::TokenTree;
 
 use rustc_lexer::unescape::{unescape_byte, unescape_char};
 use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode};
@@ -88,7 +87,6 @@
                             }
                         });
                         error?;
-                        buf.shrink_to_fit();
                         Symbol::intern(&buf)
                     } else {
                         symbol
@@ -106,7 +104,6 @@
                     }
                 });
                 error?;
-                buf.shrink_to_fit();
                 LitKind::ByteStr(buf.into())
             }
             token::ByteStrRaw(_) => {
@@ -121,7 +118,6 @@
                         }
                     });
                     error?;
-                    buf.shrink_to_fit();
                     buf
                 } else {
                     symbol.to_string().into_bytes()
@@ -225,13 +221,13 @@
         Lit { token: kind.to_lit_token(), kind, span }
     }
 
-    /// Losslessly convert an AST literal into a token stream.
-    pub fn token_tree(&self) -> TokenTree {
-        let token = match self.token.kind {
+    /// Losslessly convert an AST literal into a token.
+    pub fn to_token(&self) -> Token {
+        let kind = match self.token.kind {
             token::Bool => token::Ident(self.token.symbol, false),
             _ => token::Literal(self.token),
         };
-        TokenTree::token(token, self.span)
+        Token::new(kind, self.span)
     }
 }
 
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index a420bb5..2ba1c49 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -15,7 +15,6 @@
 
 use crate::ast::*;
 use crate::token;
-use crate::tokenstream::TokenTree;
 
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::Span;
@@ -578,7 +577,12 @@
     match param.kind {
         GenericParamKind::Lifetime => (),
         GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default),
-        GenericParamKind::Const { ref ty, .. } => visitor.visit_ty(ty),
+        GenericParamKind::Const { ref ty, ref default, .. } => {
+            visitor.visit_ty(ty);
+            if let Some(default) = default {
+                visitor.visit_anon_const(default);
+            }
+        }
     }
 }
 
@@ -900,12 +904,9 @@
         MacArgs::Delimited(_dspan, _delim, _tokens) => {}
         // The value in `#[key = VALUE]` must be visited as an expression for backward
         // compatibility, so that macros can be expanded in that position.
-        MacArgs::Eq(_eq_span, tokens) => match tokens.trees_ref().next() {
-            Some(TokenTree::Token(token)) => match &token.kind {
-                token::Interpolated(nt) => match &**nt {
-                    token::NtExpr(expr) => visitor.visit_expr(expr),
-                    t => panic!("unexpected token in key-value attribute: {:?}", t),
-                },
+        MacArgs::Eq(_eq_span, token) => match &token.kind {
+            token::Interpolated(nt) => match &**nt {
+                token::NtExpr(expr) => visitor.visit_expr(expr),
                 t => panic!("unexpected token in key-value attribute: {:?}", t),
             },
             t => panic!("unexpected token in key-value attribute: {:?}", t),
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 9b1642d..1b9ccbd 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -87,9 +87,12 @@
                 ExprKind::Let(ref pat, ref scrutinee) => {
                     self.lower_expr_let(e.span, pat, scrutinee)
                 }
-                ExprKind::If(ref cond, ref then, ref else_opt) => {
-                    self.lower_expr_if(e.span, cond, then, else_opt.as_deref())
-                }
+                ExprKind::If(ref cond, ref then, ref else_opt) => match cond.kind {
+                    ExprKind::Let(ref pat, ref scrutinee) => {
+                        self.lower_expr_if_let(e.span, pat, scrutinee, then, else_opt.as_deref())
+                    }
+                    _ => self.lower_expr_if(cond, then, else_opt.as_deref()),
+                },
                 ExprKind::While(ref cond, ref body, opt_label) => self
                     .with_loop_scope(e.id, |this| {
                         this.lower_expr_while_in_loop_scope(e.span, cond, body, opt_label)
@@ -337,11 +340,31 @@
 
     fn lower_expr_if(
         &mut self,
-        span: Span,
         cond: &Expr,
         then: &Block,
         else_opt: Option<&Expr>,
     ) -> hir::ExprKind<'hir> {
+        macro_rules! make_if {
+            ($opt:expr) => {{
+                let then_expr = self.lower_block_expr(then);
+                hir::ExprKind::If(self.lower_expr(cond), self.arena.alloc(then_expr), $opt)
+            }};
+        }
+        if let Some(rslt) = else_opt {
+            make_if!(Some(self.lower_expr(rslt)))
+        } else {
+            make_if!(None)
+        }
+    }
+
+    fn lower_expr_if_let(
+        &mut self,
+        span: Span,
+        pat: &Pat,
+        scrutinee: &Expr,
+        then: &Block,
+        else_opt: Option<&Expr>,
+    ) -> hir::ExprKind<'hir> {
         // FIXME(#53667): handle lowering of && and parens.
 
         // `_ => else_block` where `else_block` is `{}` if there's `None`:
@@ -353,30 +376,13 @@
         let else_arm = self.arm(else_pat, else_expr);
 
         // Handle then + scrutinee:
-        let (then_pat, scrutinee, desugar) = match cond.kind {
-            // `<pat> => <then>`:
-            ExprKind::Let(ref pat, ref scrutinee) => {
-                let scrutinee = self.lower_expr(scrutinee);
-                let pat = self.lower_pat(pat);
-                (pat, scrutinee, hir::MatchSource::IfLetDesugar { contains_else_clause })
-            }
-            // `true => <then>`:
-            _ => {
-                // Lower condition:
-                let cond = self.lower_expr(cond);
-                let span_block =
-                    self.mark_span_with_reason(DesugaringKind::CondTemporary, cond.span, None);
-                // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
-                // to preserve drop semantics since `if cond { ... }` does not
-                // let temporaries live outside of `cond`.
-                let cond = self.expr_drop_temps(span_block, cond, ThinVec::new());
-                let pat = self.pat_bool(span, true);
-                (pat, cond, hir::MatchSource::IfDesugar { contains_else_clause })
-            }
-        };
+        let scrutinee = self.lower_expr(scrutinee);
+        let then_pat = self.lower_pat(pat);
+
         let then_expr = self.lower_block_expr(then);
         let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
 
+        let desugar = hir::MatchSource::IfLetDesugar { contains_else_clause };
         hir::ExprKind::Match(scrutinee, arena_vec![self; then_arm, else_arm], desugar)
     }
 
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index eef6d38..69257ce 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -134,7 +134,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(hir::Impl { ref generics, .. })
             | hir::ItemKind::Trait(_, _, ref generics, ..) => &generics.params[..],
             _ => &[],
         };
@@ -310,19 +310,24 @@
                     );
                     let sig = hir::FnSig {
                         decl,
-                        header: this.lower_fn_header(header),
+                        header: this.lower_fn_header(header, fn_sig_span, id),
                         span: fn_sig_span,
                     };
                     hir::ItemKind::Fn(sig, generics, body_id)
                 })
             }
             ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
-            ItemKind::ForeignMod(ref fm) => hir::ItemKind::ForeignMod {
-                abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
-                items: self
-                    .arena
-                    .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
-            },
+            ItemKind::ForeignMod(ref fm) => {
+                if fm.abi.is_none() {
+                    self.maybe_lint_missing_abi(span, id, abi::Abi::C);
+                }
+                hir::ItemKind::ForeignMod {
+                    abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
+                    items: self
+                        .arena
+                        .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
+                }
+            }
             ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
             ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => {
                 // We lower
@@ -431,7 +436,7 @@
                 // to not cause an assertion failure inside the `lower_defaultness` function.
                 let has_val = true;
                 let (defaultness, defaultness_span) = self.lower_defaultness(defaultness, has_val);
-                hir::ItemKind::Impl {
+                hir::ItemKind::Impl(hir::Impl {
                     unsafety: self.lower_unsafety(unsafety),
                     polarity,
                     defaultness,
@@ -441,7 +446,7 @@
                     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());
@@ -801,13 +806,13 @@
             AssocItemKind::Fn(_, ref sig, ref generics, None) => {
                 let names = self.lower_fn_params_to_names(&sig.decl);
                 let (generics, sig) =
-                    self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
+                    self.lower_method_sig(generics, sig, trait_item_def_id, false, None, i.id);
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)))
             }
             AssocItemKind::Fn(_, ref sig, ref generics, Some(ref body)) => {
                 let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body));
                 let (generics, sig) =
-                    self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
+                    self.lower_method_sig(generics, sig, trait_item_def_id, false, None, i.id);
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)))
             }
             AssocItemKind::TyAlias(_, ref generics, ref bounds, ref default) => {
@@ -877,6 +882,7 @@
                     impl_item_def_id,
                     impl_trait_return_allow,
                     asyncness.opt_return_id(),
+                    i.id,
                 );
 
                 (generics, hir::ImplItemKind::Fn(sig, body_id))
@@ -1270,8 +1276,9 @@
         fn_def_id: LocalDefId,
         impl_trait_return_allow: bool,
         is_async: Option<NodeId>,
+        id: NodeId,
     ) -> (hir::Generics<'hir>, hir::FnSig<'hir>) {
-        let header = self.lower_fn_header(sig.header);
+        let header = self.lower_fn_header(sig.header, sig.span, id);
         let (generics, decl) = self.add_in_band_defs(
             generics,
             fn_def_id,
@@ -1288,12 +1295,12 @@
         (generics, hir::FnSig { header, decl, span: sig.span })
     }
 
-    fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
+    fn lower_fn_header(&mut self, h: FnHeader, span: Span, id: NodeId) -> hir::FnHeader {
         hir::FnHeader {
             unsafety: self.lower_unsafety(h.unsafety),
             asyncness: self.lower_asyncness(h.asyncness),
             constness: self.lower_constness(h.constness),
-            abi: self.lower_extern(h.ext),
+            abi: self.lower_extern(h.ext, span, id),
         }
     }
 
@@ -1304,10 +1311,13 @@
         })
     }
 
-    pub(super) fn lower_extern(&mut self, ext: Extern) -> abi::Abi {
+    pub(super) fn lower_extern(&mut self, ext: Extern, span: Span, id: NodeId) -> abi::Abi {
         match ext {
             Extern::None => abi::Abi::Rust,
-            Extern::Implicit => abi::Abi::C,
+            Extern::Implicit => {
+                self.maybe_lint_missing_abi(span, id, abi::Abi::C);
+                abi::Abi::C
+            }
             Extern::Explicit(abi) => self.lower_abi(abi),
         }
     }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index d17b290..6d95da0 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -53,13 +53,15 @@
 use rustc_hir::intravisit;
 use rustc_hir::{ConstArg, GenericArg, ParamName};
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_session::lint::{builtin::BARE_TRAIT_OBJECTS, BuiltinLintDiagnostics, LintBuffer};
+use rustc_session::lint::builtin::{BARE_TRAIT_OBJECTS, MISSING_ABI};
+use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::parse::ParseSess;
 use rustc_session::Session;
 use rustc_span::hygiene::ExpnId;
-use rustc_span::source_map::{respan, DesugaringKind, ExpnData, ExpnKind};
+use rustc_span::source_map::{respan, DesugaringKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
+use rustc_target::spec::abi::Abi;
 
 use smallvec::{smallvec, SmallVec};
 use std::collections::BTreeMap;
@@ -206,8 +208,7 @@
     ) -> LocalDefId;
 }
 
-type NtToTokenstream =
-    fn(&Nonterminal, &ParseSess, Span, CanSynthesizeMissingTokens) -> TokenStream;
+type NtToTokenstream = fn(&Nonterminal, &ParseSess, CanSynthesizeMissingTokens) -> TokenStream;
 
 /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
 /// and if so, what meaning it has.
@@ -417,12 +418,7 @@
     fn lower_token(&mut self, token: Token) -> TokenStream {
         match token.kind {
             token::Interpolated(nt) => {
-                let tts = (self.nt_to_tokenstream)(
-                    &nt,
-                    self.parse_sess,
-                    token.span,
-                    self.synthesize_tokens,
-                );
+                let tts = (self.nt_to_tokenstream)(&nt, self.parse_sess, self.synthesize_tokens);
                 TokenTree::Delimited(
                     DelimSpan::from_single(token.span),
                     DelimToken::NoDelim,
@@ -743,10 +739,7 @@
         span: Span,
         allow_internal_unstable: Option<Lrc<[Symbol]>>,
     ) -> Span {
-        span.fresh_expansion(ExpnData {
-            allow_internal_unstable,
-            ..ExpnData::default(ExpnKind::Desugaring(reason), span, self.sess.edition(), None)
-        })
+        span.mark_with_reason(allow_internal_unstable, reason, self.sess.edition())
     }
 
     fn with_anonymous_lifetime_mode<R>(
@@ -1022,10 +1015,36 @@
             // This is an inert key-value attribute - it will never be visible to macros
             // after it gets lowered to HIR. Therefore, we can synthesize tokens with fake
             // spans to handle nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
-            MacArgs::Eq(eq_span, ref tokens) => MacArgs::Eq(
-                eq_span,
-                self.lower_token_stream(tokens.clone(), CanSynthesizeMissingTokens::Yes),
-            ),
+            MacArgs::Eq(eq_span, ref token) => {
+                // In valid code the value is always representable as a single literal token.
+                fn unwrap_single_token(sess: &Session, tokens: TokenStream, span: Span) -> Token {
+                    if tokens.len() != 1 {
+                        sess.diagnostic()
+                            .delay_span_bug(span, "multiple tokens in key-value attribute's value");
+                    }
+                    match tokens.into_trees().next() {
+                        Some(TokenTree::Token(token)) => token,
+                        Some(TokenTree::Delimited(_, delim, tokens)) => {
+                            if delim != token::NoDelim {
+                                sess.diagnostic().delay_span_bug(
+                                    span,
+                                    "unexpected delimiter in key-value attribute's value",
+                                )
+                            }
+                            unwrap_single_token(sess, tokens, span)
+                        }
+                        None => Token::dummy(),
+                    }
+                }
+
+                let tokens = TokenStreamLowering {
+                    parse_sess: &self.sess.parse_sess,
+                    synthesize_tokens: CanSynthesizeMissingTokens::Yes,
+                    nt_to_tokenstream: self.nt_to_tokenstream,
+                }
+                .lower_token(token.clone());
+                MacArgs::Eq(eq_span, unwrap_single_token(self.sess, tokens, token.span))
+            }
         }
     }
 
@@ -1271,6 +1290,7 @@
             }
             TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(&f.generic_params, |this| {
                 this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
+                    let span = this.sess.source_map().next_point(t.span.shrink_to_lo());
                     hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
                         generic_params: this.lower_generic_params(
                             &f.generic_params,
@@ -1278,7 +1298,7 @@
                             ImplTraitContext::disallowed(),
                         ),
                         unsafety: this.lower_unsafety(f.unsafety),
-                        abi: this.lower_extern(f.ext),
+                        abi: this.lower_extern(f.ext, span, t.id),
                         decl: this.lower_fn_decl(&f.decl, None, false, None),
                         param_names: this.lower_fn_params_to_names(&f.decl),
                     }))
@@ -2242,13 +2262,14 @@
 
                 (hir::ParamName::Plain(param.ident), kind)
             }
-            GenericParamKind::Const { ref ty, kw_span: _ } => {
+            GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
                 let ty = self
                     .with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
                         this.lower_ty(&ty, ImplTraitContext::disallowed())
                     });
+                let default = default.as_ref().map(|def| self.lower_anon_const(def));
 
-                (hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty })
+                (hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty, default })
             }
         };
 
@@ -2759,6 +2780,26 @@
             )
         }
     }
+
+    fn maybe_lint_missing_abi(&mut self, span: Span, id: NodeId, default: Abi) {
+        // FIXME(davidtwco): This is a hack to detect macros which produce spans of the
+        // call site which do not have a macro backtrace. See #61963.
+        let is_macro_callsite = self
+            .sess
+            .source_map()
+            .span_to_snippet(span)
+            .map(|snippet| snippet.starts_with("#["))
+            .unwrap_or(true);
+        if !is_macro_callsite {
+            self.resolver.lint_buffer().buffer_lint_with_diagnostic(
+                MISSING_ABI,
+                id,
+                span,
+                "extern declarations without an explicit ABI are deprecated",
+                BuiltinLintDiagnostics::MissingAbi(span, default),
+            )
+        }
+    }
 }
 
 fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body<'_>>) -> Vec<hir::BodyId> {
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 6afed35..9079e26 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -273,7 +273,7 @@
         if !generic_args.parenthesized && !has_lifetimes {
             generic_args.args = self
                 .elided_path_lifetimes(
-                    first_generic_span.map(|s| s.shrink_to_lo()).unwrap_or(segment.ident.span),
+                    first_generic_span.map_or(segment.ident.span, |s| s.shrink_to_lo()),
                     expected_lifetimes,
                 )
                 .map(GenericArg::Lifetime)
@@ -401,15 +401,15 @@
         // 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 ParenthesizedArgs { span, inputs, inputs_span, output } = data;
             let inputs = this.arena.alloc_from_iter(
                 inputs.iter().map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())),
             );
             let output_ty = match output {
                 FnRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()),
-                FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(span, &[])),
+                FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(*span, &[])),
             };
-            let args = smallvec![GenericArg::Type(this.ty_tup(span, inputs))];
+            let args = smallvec![GenericArg::Type(this.ty_tup(*inputs_span, inputs))];
             let binding = this.output_ty_binding(output_ty.span, output_ty);
             (
                 GenericArgsCtor { args, bindings: arena_vec![this; binding], parenthesized: true },
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index f9eb69b..baeadb2 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -16,7 +16,7 @@
 use rustc_errors::{error_code, pluralize, struct_span_err, Applicability};
 use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
-use rustc_session::lint::LintBuffer;
+use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::Session;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Span;
@@ -213,14 +213,14 @@
         err.emit();
     }
 
-    fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, bool)) {
+    fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
         for Param { pat, .. } in &decl.inputs {
             match pat.kind {
                 PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) | PatKind::Wild => {}
-                PatKind::Ident(BindingMode::ByValue(Mutability::Mut), _, None) => {
-                    report_err(pat.span, true)
+                PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ident, None) => {
+                    report_err(pat.span, Some(ident), true)
                 }
-                _ => report_err(pat.span, false),
+                _ => report_err(pat.span, None, false),
             }
         }
     }
@@ -717,35 +717,46 @@
 
 /// Checks that generic parameters are in the correct order,
 /// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`)
-fn validate_generic_param_order<'a>(
+fn validate_generic_param_order(
     sess: &Session,
     handler: &rustc_errors::Handler,
-    generics: impl Iterator<Item = (ParamKindOrd, Option<&'a [GenericBound]>, Span, Option<String>)>,
+    generics: &[GenericParam],
     span: Span,
 ) {
     let mut max_param: Option<ParamKindOrd> = None;
     let mut out_of_order = FxHashMap::default();
     let mut param_idents = vec![];
 
-    for (kind, bounds, span, ident) in generics {
+    for param in generics {
+        let ident = Some(param.ident.to_string());
+        let (kind, bounds, span) = (&param.kind, Some(&*param.bounds), param.ident.span);
+        let (ord_kind, ident) = match &param.kind {
+            GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident),
+            GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
+            GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
+                let ty = pprust::ty_to_string(ty);
+                let unordered = sess.features_untracked().const_generics;
+                (ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty)))
+            }
+        };
         if let Some(ident) = ident {
-            param_idents.push((kind, bounds, param_idents.len(), ident));
+            param_idents.push((kind, ord_kind, bounds, param_idents.len(), ident));
         }
         let max_param = &mut max_param;
         match max_param {
-            Some(max_param) if *max_param > kind => {
-                let entry = out_of_order.entry(kind).or_insert((*max_param, vec![]));
+            Some(max_param) if *max_param > ord_kind => {
+                let entry = out_of_order.entry(ord_kind).or_insert((*max_param, vec![]));
                 entry.1.push(span);
             }
-            Some(_) | None => *max_param = Some(kind),
+            Some(_) | None => *max_param = Some(ord_kind),
         };
     }
 
     let mut ordered_params = "<".to_string();
     if !out_of_order.is_empty() {
-        param_idents.sort_by_key(|&(po, _, i, _)| (po, i));
+        param_idents.sort_by_key(|&(_, po, _, i, _)| (po, i));
         let mut first = true;
-        for (_, bounds, _, ident) in param_idents {
+        for (kind, _, bounds, _, ident) in param_idents {
             if !first {
                 ordered_params += ", ";
             }
@@ -756,6 +767,16 @@
                     ordered_params += &pprust::bounds_to_string(&bounds);
                 }
             }
+            match kind {
+                GenericParamKind::Type { default: Some(default) } => {
+                    ordered_params += " = ";
+                    ordered_params += &pprust::ty_to_string(default);
+                }
+                GenericParamKind::Type { default: None } => (),
+                GenericParamKind::Lifetime => (),
+                // FIXME(const_generics_defaults)
+                GenericParamKind::Const { ty: _, kw_span: _, default: _ } => (),
+            }
             first = false;
         }
     }
@@ -813,7 +834,7 @@
         match ty.kind {
             TyKind::BareFn(ref bfty) => {
                 self.check_fn_decl(&bfty.decl, SelfSemantic::No);
-                Self::check_decl_no_pat(&bfty.decl, |span, _| {
+                Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
                     struct_span_err!(
                         self.session,
                         span,
@@ -1150,22 +1171,7 @@
         validate_generic_param_order(
             self.session,
             self.err_handler(),
-            generics.params.iter().map(|param| {
-                let ident = Some(param.ident.to_string());
-                let (kind, ident) = match &param.kind {
-                    GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident),
-                    GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
-                    GenericParamKind::Const { ref ty, kw_span: _ } => {
-                        let ty = pprust::ty_to_string(ty);
-                        let unordered = self.session.features_untracked().const_generics;
-                        (
-                            ParamKindOrd::Const { unordered },
-                            Some(format!("const {}: {}", param.ident, ty)),
-                        )
-                    }
-                };
-                (kind, Some(&*param.bounds), param.ident.span, ident)
-            }),
+            &generics.params,
             generics.span,
         );
 
@@ -1206,11 +1212,11 @@
     }
 
     fn visit_pat(&mut self, pat: &'a Pat) {
-        match pat.kind {
-            PatKind::Lit(ref expr) => {
+        match &pat.kind {
+            PatKind::Lit(expr) => {
                 self.check_expr_within_pat(expr, false);
             }
-            PatKind::Range(ref start, ref end, _) => {
+            PatKind::Range(start, end, _) => {
                 if let Some(expr) = start {
                     self.check_expr_within_pat(expr, true);
                 }
@@ -1283,7 +1289,7 @@
 
         // Functions without bodies cannot have patterns.
         if let FnKind::Fn(ctxt, _, sig, _, None) = fk {
-            Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
+            Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
                 let (code, msg, label) = match ctxt {
                     FnCtxt::Foreign => (
                         error_code!(E0130),
@@ -1297,7 +1303,16 @@
                     ),
                 };
                 if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
-                    self.lint_buffer.buffer_lint(PATTERNS_IN_FNS_WITHOUT_BODY, id, span, msg);
+                    if let Some(ident) = ident {
+                        let diag = BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident);
+                        self.lint_buffer.buffer_lint_with_diagnostic(
+                            PATTERNS_IN_FNS_WITHOUT_BODY,
+                            id,
+                            span,
+                            msg,
+                            diag,
+                        )
+                    }
                 } else {
                     self.err_handler()
                         .struct_span_err(span, msg)
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 6a9d6d2..7bd805f 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -14,6 +14,17 @@
 use tracing::debug;
 
 macro_rules! gate_feature_fn {
+    ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
+        let (visitor, has_feature, span, name, explain, help) =
+            (&*$visitor, $has_feature, $span, $name, $explain, $help);
+        let has_feature: bool = has_feature(visitor.features);
+        debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
+        if !has_feature && !span.allows_unstable($name) {
+            feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain)
+                .help(help)
+                .emit();
+        }
+    }};
     ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
         let (visitor, has_feature, span, name, explain) =
             (&*$visitor, $has_feature, $span, $name, $explain);
@@ -27,6 +38,9 @@
 }
 
 macro_rules! gate_feature_post {
+    ($visitor: expr, $feature: ident, $span: expr, $explain: expr, $help: expr) => {
+        gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain, $help)
+    };
     ($visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
         gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
     };
@@ -356,7 +370,7 @@
                     gate_feature_post!(
                         &self,
                         negative_impls,
-                        span.to(of_trait.as_ref().map(|t| t.path.span).unwrap_or(span)),
+                        span.to(of_trait.as_ref().map_or(span, |t| t.path.span)),
                         "negative trait bounds are not yet fully implemented; \
                          use marker types for now"
                     );
@@ -597,6 +611,13 @@
 
     let spans = sess.parse_sess.gated_spans.spans.borrow();
     macro_rules! gate_all {
+        ($gate:ident, $msg:literal, $help:literal) => {
+            if let Some(spans) = spans.get(&sym::$gate) {
+                for span in spans {
+                    gate_feature_post!(&visitor, $gate, *span, $msg, $help);
+                }
+            }
+        };
         ($gate:ident, $msg:literal) => {
             if let Some(spans) = spans.get(&sym::$gate) {
                 for span in spans {
@@ -607,7 +628,11 @@
     }
     gate_all!(if_let_guard, "`if let` guards are experimental");
     gate_all!(let_chains, "`let` expressions in this position are experimental");
-    gate_all!(async_closure, "async closures are unstable");
+    gate_all!(
+        async_closure,
+        "async closures are unstable",
+        "to use an async block, remove the `||`: `async {`"
+    );
     gate_all!(generators, "yield syntax is experimental");
     gate_all!(or_patterns, "or-patterns syntax is experimental");
     gate_all!(raw_ref_op, "raw address of syntax is experimental");
@@ -619,6 +644,10 @@
         extended_key_value_attributes,
         "arbitrary expressions in key-value attributes are unstable"
     );
+    gate_all!(
+        const_generics_defaults,
+        "default values for const generic parameters are experimental"
+    );
     if sess.parse_sess.span_diagnostic.err_count() == 0 {
         // Errors for `destructuring_assignment` can get quite noisy, especially where `_` is
         // involved, so we only emit errors where there are no other parsing errors.
diff --git a/compiler/rustc_ast_pretty/src/pprust/mod.rs b/compiler/rustc_ast_pretty/src/pprust/mod.rs
index b34ea41..b88699f 100644
--- a/compiler/rustc_ast_pretty/src/pprust/mod.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/mod.rs
@@ -8,11 +8,6 @@
 use rustc_ast::token::{Nonterminal, Token, TokenKind};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 
-pub fn nonterminal_to_string_no_extra_parens(nt: &Nonterminal) -> String {
-    let state = State::without_insert_extra_parens();
-    state.nonterminal_to_string(nt)
-}
-
 pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
     State::new().nonterminal_to_string(nt)
 }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 333a396..2c8caf6 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -88,13 +88,6 @@
     comments: Option<Comments<'a>>,
     ann: &'a (dyn PpAnn + 'a),
     is_expanded: bool,
-    // If `true`, additional parenthesis (separate from `ExprKind::Paren`)
-    // are inserted to ensure that proper precedence is preserved
-    // in the pretty-printed output.
-    //
-    // This is usually `true`, except when performing the pretty-print/reparse
-    // check in `nt_to_tokenstream`
-    insert_extra_parens: bool,
 }
 
 crate const INDENT_UNIT: usize = 4;
@@ -115,7 +108,6 @@
         comments: Some(Comments::new(sm, filename, input)),
         ann,
         is_expanded,
-        insert_extra_parens: true,
     };
 
     if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) {
@@ -235,7 +227,6 @@
 }
 
 pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::DerefMut {
-    fn insert_extra_parens(&self) -> bool;
     fn comments(&mut self) -> &mut Option<Comments<'a>>;
     fn print_ident(&mut self, ident: Ident);
     fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool);
@@ -454,10 +445,11 @@
             ),
             MacArgs::Empty | MacArgs::Eq(..) => {
                 self.print_path(&item.path, false, 0);
-                if let MacArgs::Eq(_, tokens) = &item.args {
+                if let MacArgs::Eq(_, token) = &item.args {
                     self.space();
                     self.word_space("=");
-                    self.print_tts(tokens, true);
+                    let token_str = self.token_to_string_ext(token, true);
+                    self.word(token_str);
                 }
             }
         }
@@ -819,16 +811,12 @@
 
     fn to_string(&self, f: impl FnOnce(&mut State<'_>)) -> String {
         let mut printer = State::new();
-        printer.insert_extra_parens = self.insert_extra_parens();
         f(&mut printer);
         printer.s.eof()
     }
 }
 
 impl<'a> PrintState<'a> for State<'a> {
-    fn insert_extra_parens(&self) -> bool {
-        self.insert_extra_parens
-    }
     fn comments(&mut self) -> &mut Option<Comments<'a>> {
         &mut self.comments
     }
@@ -865,17 +853,7 @@
 
 impl<'a> State<'a> {
     pub fn new() -> State<'a> {
-        State {
-            s: pp::mk_printer(),
-            comments: None,
-            ann: &NoAnn,
-            is_expanded: false,
-            insert_extra_parens: true,
-        }
-    }
-
-    pub(super) fn without_insert_extra_parens() -> State<'a> {
-        State { insert_extra_parens: false, ..State::new() }
+        State { s: pp::mk_printer(), comments: None, ann: &NoAnn, is_expanded: false }
     }
 
     // Synthesizes a comment that was not textually present in the original source
@@ -1680,8 +1658,7 @@
     }
 
     /// Prints `expr` or `(expr)` when `needs_par` holds.
-    fn print_expr_cond_paren(&mut self, expr: &ast::Expr, mut needs_par: bool) {
-        needs_par &= self.insert_extra_parens;
+    fn print_expr_cond_paren(&mut self, expr: &ast::Expr, needs_par: bool) {
         if needs_par {
             self.popen();
         }
@@ -2668,13 +2645,16 @@
                         s.print_type(default)
                     }
                 }
-                ast::GenericParamKind::Const { ref ty, kw_span: _ } => {
+                ast::GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
                     s.word_space("const");
                     s.print_ident(param.ident);
                     s.s.space();
                     s.word_space(":");
                     s.print_type(ty);
-                    s.print_type_bounds(":", &param.bounds)
+                    s.print_type_bounds(":", &param.bounds);
+                    if let Some(ref _default) = default {
+                        // FIXME(const_generics_defaults): print the `default` value here
+                    }
                 }
             }
         });
diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs
index 868f863..7114b98 100644
--- a/compiler/rustc_builtin_macros/src/deriving/hash.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs
@@ -48,8 +48,8 @@
 }
 
 fn hash_substructure(cx: &mut ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>) -> P<Expr> {
-    let state_expr = match &substr.nonself_args {
-        &[o_f] => o_f,
+    let state_expr = match substr.nonself_args {
+        [o_f] => o_f,
         _ => cx.span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`"),
     };
     let call_hash = |span, thing_expr| {
@@ -64,9 +64,9 @@
     };
     let mut stmts = Vec::new();
 
-    let fields = match *substr.fields {
-        Struct(_, ref fs) | EnumMatching(_, 1, .., ref fs) => fs,
-        EnumMatching(.., ref fs) => {
+    let fields = match substr.fields {
+        Struct(_, fs) | EnumMatching(_, 1, .., fs) => fs,
+        EnumMatching(.., fs) => {
             let variant_value = deriving::call_intrinsic(
                 cx,
                 trait_span,
diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs
index 1651180..3c8bf12 100644
--- a/compiler/rustc_builtin_macros/src/deriving/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs
@@ -145,7 +145,8 @@
                 *default = None;
                 ast::GenericArg::Type(cx.ty_ident(span, param.ident))
             }
-            ast::GenericParamKind::Const { ty: _, kw_span: _ } => {
+            ast::GenericParamKind::Const { ty: _, kw_span: _, default } => {
+                *default = None;
                 ast::GenericArg::Const(cx.const_ident(span, param.ident))
             }
         })
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 97cadb9..6358906 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -14,10 +14,9 @@
 
 use crate::deriving::*;
 
-use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtension, SyntaxExtensionKind};
+use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
 use rustc_expand::proc_macro::BangProcMacro;
-use rustc_span::edition::Edition;
-use rustc_span::symbol::{sym, Ident};
+use rustc_span::symbol::sym;
 
 mod asm;
 mod assert;
@@ -44,13 +43,8 @@
 pub mod standard_library_imports;
 pub mod test_harness;
 
-pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand, edition: Edition) {
-    let mut register = |name, kind| {
-        resolver.register_builtin_macro(
-            Ident::with_dummy_span(name),
-            SyntaxExtension { is_builtin: true, ..SyntaxExtension::default(kind, edition) },
-        )
-    };
+pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
+    let mut register = |name, kind| resolver.register_builtin_macro(name, kind);
     macro register_bang($($name:ident: $f:expr,)*) {
         $(register(sym::$name, SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)));)*
     }
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index be5b247..8946ac4 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -824,7 +824,7 @@
                     }
                     ty => unreachable!("bswap {}", ty),
                 }
-            };
+            }
             let res = CValue::by_val(swap(&mut fx.bcx, arg), fx.layout_of(T));
             ret.write_cvalue(fx, res);
         };
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 97c38e0..700f32e 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -127,13 +127,18 @@
         return;
     }
 
-    // Flag our internal `__rust_probestack` function as the stack probe symbol.
-    // This is defined in the `compiler-builtins` crate for each architecture.
     llvm::AddFunctionAttrStringValue(
         llfn,
         llvm::AttributePlace::Function,
         const_cstr!("probe-stack"),
-        const_cstr!("__rust_probestack"),
+        if llvm_util::get_version() < (11, 0, 1) {
+            // Flag our internal `__rust_probestack` function as the stack probe symbol.
+            // This is defined in the `compiler-builtins` crate for each architecture.
+            const_cstr!("__rust_probestack")
+        } else {
+            // On LLVM 11+, emit inline asm for stack probes instead of a function call.
+            const_cstr!("inline-asm")
+        },
     );
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 230e11f..e225730 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -164,7 +164,8 @@
 
     let code_model = to_llvm_code_model(sess.code_model());
 
-    let features = attributes::llvm_target_features(sess).collect::<Vec<_>>();
+    let mut features = llvm_util::handle_native_features(sess);
+    features.extend(attributes::llvm_target_features(sess).map(|s| s.to_owned()));
     let mut singlethread = sess.target.singlethread;
 
     // On the wasm target once the `atomics` feature is enabled that means that
@@ -1001,8 +1002,7 @@
     // reasonable defaults and prepare it to actually populate the pass
     // manager.
     let builder = llvm::LLVMPassManagerBuilderCreate();
-    let opt_size =
-        config.opt_size.map(|x| to_llvm_opt_settings(x).1).unwrap_or(llvm::CodeGenOptSizeNone);
+    let opt_size = config.opt_size.map_or(llvm::CodeGenOptSizeNone, |x| to_llvm_opt_settings(x).1);
     let inline_threshold = config.inline_threshold;
     let pgo_gen_path = get_pgo_gen_path(config);
     let pgo_use_path = get_pgo_use_path(config);
diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs
index 7d01f6a..d5be313 100644
--- a/compiler/rustc_codegen_llvm/src/base.rs
+++ b/compiler/rustc_codegen_llvm/src/base.rs
@@ -1,17 +1,15 @@
-//! Codegen the completed AST to the LLVM IR.
-//!
-//! Some functions here, such as codegen_block and codegen_expr, return a value --
-//! the result of the codegen to LLVM -- while others, such as codegen_fn
-//! and mono_item, are called only for the side effect of adding a
-//! particular definition to the LLVM IR output we're producing.
+//! Codegen the MIR to the LLVM IR.
 //!
 //! Hopefully useful general knowledge about codegen:
 //!
-//! * There's no way to find out the `Ty` type of a Value. Doing so
+//! * There's no way to find out the [`Ty`] type of a [`Value`]. Doing so
 //!   would be "trying to get the eggs out of an omelette" (credit:
-//!   pcwalton). You can, instead, find out its `llvm::Type` by calling `val_ty`,
-//!   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`.
+//!   pcwalton). You can, instead, find out its [`llvm::Type`] by calling [`val_ty`],
+//!   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`].
+//!
+//! [`Ty`]: rustc_middle::ty::Ty
+//! [`val_ty`]: common::val_ty
 
 use super::ModuleLlvm;
 
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index 34e1b7a..58af9d4 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -314,6 +314,7 @@
     }
 }
 
+/// Get the [LLVM type][Type] of a [`Value`].
 pub fn val_ty(v: &Value) -> &Type {
     unsafe { llvm::LLVMTypeOf(v) }
 }
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 8dd4030..6acd26b 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -114,7 +114,7 @@
     let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
 
     let mut target_data_layout = sess.target.data_layout.clone();
-    if llvm_util::get_major_version() < 10
+    if llvm_util::get_version() < (10, 0, 0)
         && (sess.target.arch == "x86" || sess.target.arch == "x86_64")
     {
         target_data_layout = strip_x86_address_spaces(target_data_layout);
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 72ba5bb..444a9d4 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -292,7 +292,7 @@
         if let Some(non_codegenned_file_name) = tcx.covered_file_name(non_codegenned_def_id) {
             let def_ids = unreachable_def_ids_by_file
                 .entry(*non_codegenned_file_name)
-                .or_insert_with(|| Vec::new());
+                .or_insert_with(Vec::new);
             def_ids.push(non_codegenned_def_id);
         }
     }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 36a21b3..b9ae796 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -1832,8 +1832,9 @@
     fn source_info(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option<SourceInfo<'ll>> {
         match self {
             VariantInfo::Generator { def_id, variant_index, .. } => {
-                let span =
-                    cx.tcx.generator_layout(*def_id).variant_source_info[*variant_index].span;
+                let span = cx.tcx.generator_layout(*def_id).unwrap().variant_source_info
+                    [*variant_index]
+                    .span;
                 if !span.is_dummy() {
                     let loc = cx.lookup_debug_loc(span.lo());
                     return Some(SourceInfo {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index ccbe732..955e739 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -552,7 +552,6 @@
 
         unsafe {
             llvm::LLVMRustDIBuilderCreateDebugLocation(
-                utils::debug_context(self).llcontext,
                 line.unwrap_or(UNKNOWN_LINE_NUMBER),
                 col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
                 scope,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 707aaa2..d9f42ef 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1708,6 +1708,10 @@
         PM: &PassManager<'_>,
     );
 
+    pub fn LLVMGetHostCPUFeatures() -> *mut c_char;
+
+    pub fn LLVMDisposeMessage(message: *mut c_char);
+
     // Stuff that's in llvm-wrapper/ because it's not upstream yet.
 
     /// Opens an object file.
@@ -1807,6 +1811,7 @@
     pub fn LLVMRustDebugMetadataVersion() -> u32;
     pub fn LLVMRustVersionMajor() -> u32;
     pub fn LLVMRustVersionMinor() -> u32;
+    pub fn LLVMRustVersionPatch() -> u32;
 
     pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32);
 
@@ -2098,7 +2103,6 @@
     );
 
     pub fn LLVMRustDIBuilderCreateDebugLocation(
-        Context: &'a Context,
         Line: c_uint,
         Column: c_uint,
         Scope: &'a DIScope,
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index a3139ce..544ef38 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -8,7 +8,7 @@
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{MergeFunctions, PanicStrategy};
-use std::ffi::CString;
+use std::ffi::{CStr, CString};
 
 use std::slice;
 use std::str;
@@ -171,14 +171,15 @@
 }
 
 pub fn print_version() {
-    // Can be called without initializing LLVM
-    unsafe {
-        println!("LLVM version: {}.{}", llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
-    }
+    let (major, minor, patch) = get_version();
+    println!("LLVM version: {}.{}.{}", major, minor, patch);
 }
 
-pub fn get_major_version() -> u32 {
-    unsafe { llvm::LLVMRustVersionMajor() }
+pub fn get_version() -> (u32, u32, u32) {
+    // Can be called without initializing LLVM
+    unsafe {
+        (llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor(), llvm::LLVMRustVersionPatch())
+    }
 }
 
 pub fn print_passes() {
@@ -213,17 +214,42 @@
 }
 
 pub fn target_cpu(sess: &Session) -> &str {
-    let name = match sess.opts.cg.target_cpu {
-        Some(ref s) => &**s,
-        None => &*sess.target.cpu,
-    };
-
+    let name = sess.opts.cg.target_cpu.as_ref().unwrap_or(&sess.target.cpu);
     handle_native(name)
 }
 
-pub fn tune_cpu(sess: &Session) -> Option<&str> {
-    match sess.opts.debugging_opts.tune_cpu {
-        Some(ref s) => Some(handle_native(&**s)),
-        None => None,
+pub fn handle_native_features(sess: &Session) -> Vec<String> {
+    match sess.opts.cg.target_cpu {
+        Some(ref s) => {
+            if s != "native" {
+                return vec![];
+            }
+
+            let features_string = unsafe {
+                let ptr = llvm::LLVMGetHostCPUFeatures();
+                let features_string = if !ptr.is_null() {
+                    CStr::from_ptr(ptr)
+                        .to_str()
+                        .unwrap_or_else(|e| {
+                            bug!("LLVM returned a non-utf8 features string: {}", e);
+                        })
+                        .to_owned()
+                } else {
+                    bug!("could not allocate host CPU features, LLVM returned a `null` string");
+                };
+
+                llvm::LLVMDisposeMessage(ptr);
+
+                features_string
+            };
+
+            features_string.split(",").map(|s| s.to_owned()).collect()
+        }
+        None => vec![],
     }
 }
+
+pub fn tune_cpu(sess: &Session) -> Option<&str> {
+    let name = sess.opts.debugging_opts.tune_cpu.as_ref()?;
+    Some(handle_native(name))
+}
diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs
index 3fc56ee..07fde27 100644
--- a/compiler/rustc_codegen_llvm/src/va_arg.rs
+++ b/compiler/rustc_codegen_llvm/src/va_arg.rs
@@ -9,7 +9,7 @@
 };
 use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_middle::ty::Ty;
-use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size};
+use rustc_target::abi::{Align, Endian, HasDataLayout, LayoutOf, Size};
 
 fn round_pointer_up_to_alignment(
     bx: &mut Builder<'a, 'll, 'tcx>,
@@ -52,7 +52,7 @@
     let next = bx.inbounds_gep(addr, &[full_direct_size]);
     bx.store(next, va_list_addr, bx.tcx().data_layout.pointer_align.abi);
 
-    if size.bytes() < slot_size.bytes() && &*bx.tcx().sess.target.endian == "big" {
+    if size.bytes() < slot_size.bytes() && bx.tcx().sess.target.endian == Endian::Big {
         let adjusted_size = bx.cx().const_i32((slot_size.bytes() - size.bytes()) as i32);
         let adjusted = bx.inbounds_gep(addr, &[adjusted_size]);
         (bx.bitcast(adjusted, bx.cx().type_ptr_to(llty)), addr_align)
@@ -105,7 +105,7 @@
     let mut end = bx.build_sibling_block("va_arg.end");
     let zero = bx.const_i32(0);
     let offset_align = Align::from_bytes(4).unwrap();
-    assert!(&*bx.tcx().sess.target.endian == "little");
+    assert_eq!(bx.tcx().sess.target.endian, Endian::Little);
 
     let gr_type = target_ty.is_any_ptr() || target_ty.is_integral();
     let (reg_off, reg_top_index, slot_size) = if gr_type {
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index a3a2ef0..ff77db9 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -166,7 +166,7 @@
         _ => match flavor {
             LinkerFlavor::Lld(f) => Command::lld(linker, f),
             LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => {
-                Command::new(msvc_tool.as_ref().map(|t| t.path()).unwrap_or(linker))
+                Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path()))
             }
             _ => Command::new(linker),
         },
@@ -895,7 +895,7 @@
         .unwrap_or_default();
 
     match sess.opts.target_triple.triple() {
-        "x86_64-apple-darwin" => {
+        "aarch64-apple-darwin" | "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
@@ -1276,6 +1276,7 @@
 
 fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
     let kind = match (crate_type, sess.crt_static(Some(crate_type)), sess.relocation_model()) {
+        (CrateType::Executable, _, _) if sess.is_wasi_reactor() => LinkOutputKind::WasiReactorExe,
         (CrateType::Executable, false, RelocModel::Pic) => LinkOutputKind::DynamicPicExe,
         (CrateType::Executable, false, _) => LinkOutputKind::DynamicNoPicExe,
         (CrateType::Executable, true, RelocModel::Pic) => LinkOutputKind::StaticPicExe,
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 3df956c..bb35e7e 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -314,6 +314,10 @@
                 self.cmd.arg("-static");
                 self.build_dylib(out_filename);
             }
+            LinkOutputKind::WasiReactorExe => {
+                self.linker_arg("--entry");
+                self.linker_arg("_initialize");
+            }
         }
         // VxWorks compiler driver introduced `--static-crt` flag specifically for rustc,
         // it switches linking for libc and similar system libraries to static without using
@@ -662,6 +666,9 @@
                 arg.push(out_filename.with_extension("dll.lib"));
                 self.cmd.arg(arg);
             }
+            LinkOutputKind::WasiReactorExe => {
+                panic!("can't link as reactor on non-wasi target");
+            }
         }
     }
 
@@ -1085,6 +1092,10 @@
             LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
                 self.cmd.arg("--no-entry");
             }
+            LinkOutputKind::WasiReactorExe => {
+                self.cmd.arg("--entry");
+                self.cmd.arg("_initialize");
+            }
         }
     }
 
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 14ace02..2ce5fe5 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -1,18 +1,3 @@
-//! Codegen the completed AST to the LLVM IR.
-//!
-//! Some functions here, such as `codegen_block` and `codegen_expr`, return a value --
-//! the result of the codegen to LLVM -- while others, such as `codegen_fn`
-//! and `mono_item`, are called only for the side effect of adding a
-//! particular definition to the LLVM IR output we're producing.
-//!
-//! Hopefully useful general knowledge about codegen:
-//!
-//! * There's no way to find out the `Ty` type of a `Value`. Doing so
-//!   would be "trying to get the eggs out of an omelette" (credit:
-//!   pcwalton). You can, instead, find out its `llvm::Type` by calling `val_ty`,
-//!   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 crate::back::write::{
     compute_per_cgu_lto_type, start_async_codegen, submit_codegened_module_to_llvm,
     submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen,
@@ -44,7 +29,6 @@
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_session::cgu_reuse_tracker::CguReuse;
 use rustc_session::config::{self, EntryFnType};
-use rustc_session::utils::NativeLibKind;
 use rustc_session::Session;
 use rustc_target::abi::{Align, LayoutOf, VariantIdx};
 
@@ -832,32 +816,6 @@
         }
         tcx.sess.opts.optimize
     };
-
-    providers.dllimport_foreign_items = |tcx, krate| {
-        let module_map = tcx.foreign_modules(krate);
-
-        let dllimports = tcx
-            .native_libraries(krate)
-            .iter()
-            .filter(|lib| {
-                if !matches!(lib.kind, NativeLibKind::Dylib | NativeLibKind::Unspecified) {
-                    return false;
-                }
-                let cfg = match lib.cfg {
-                    Some(ref cfg) => cfg,
-                    None => return true,
-                };
-                attr::cfg_matches(cfg, &tcx.sess.parse_sess, None)
-            })
-            .filter_map(|lib| lib.foreign_module)
-            .map(|id| &module_map[&id])
-            .flat_map(|module| module.foreign_items.iter().cloned())
-            .collect();
-        dllimports
-    };
-
-    providers.is_dllimport_foreign_item =
-        |tcx, def_id| tcx.dllimport_foreign_items(def_id.krate).contains(&def_id);
 }
 
 fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguReuse {
diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs
index b0d7953..549b8d4 100644
--- a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs
+++ b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs
@@ -170,30 +170,30 @@
         // `expression_index`s lower than the referencing `Expression`. Therefore, it is
         // reasonable to look up the new index of an expression operand while the `new_indexes`
         // vector is only complete up to the current `ExpressionIndex`.
-        let id_to_counter =
-            |new_indexes: &IndexVec<InjectedExpressionIndex, Option<MappedExpressionIndex>>,
-             id: ExpressionOperandId| {
-                if id == ExpressionOperandId::ZERO {
-                    Some(Counter::zero())
-                } else if id.index() < self.counters.len() {
-                    // Note: Some codegen-injected Counters may be only referenced by `Expression`s,
-                    // and may not have their own `CodeRegion`s,
-                    let index = CounterValueReference::from(id.index());
-                    Some(Counter::counter_value_reference(index))
-                } else {
-                    let index = self.expression_index(u32::from(id));
-                    self.expressions
-                        .get(index)
-                        .expect("expression id is out of range")
-                        .as_ref()
-                        // If an expression was optimized out, assume it would have produced a count
-                        // of zero. This ensures that expressions dependent on optimized-out
-                        // expressions are still valid.
-                        .map_or(Some(Counter::zero()), |_| {
-                            new_indexes[index].map(|new_index| Counter::expression(new_index))
-                        })
-                }
-            };
+        let id_to_counter = |new_indexes: &IndexVec<
+            InjectedExpressionIndex,
+            Option<MappedExpressionIndex>,
+        >,
+                             id: ExpressionOperandId| {
+            if id == ExpressionOperandId::ZERO {
+                Some(Counter::zero())
+            } else if id.index() < self.counters.len() {
+                // Note: Some codegen-injected Counters may be only referenced by `Expression`s,
+                // and may not have their own `CodeRegion`s,
+                let index = CounterValueReference::from(id.index());
+                Some(Counter::counter_value_reference(index))
+            } else {
+                let index = self.expression_index(u32::from(id));
+                self.expressions
+                    .get(index)
+                    .expect("expression id is out of range")
+                    .as_ref()
+                    // If an expression was optimized out, assume it would have produced a count
+                    // of zero. This ensures that expressions dependent on optimized-out
+                    // expressions are still valid.
+                    .map_or(Some(Counter::zero()), |_| new_indexes[index].map(Counter::expression))
+            }
+        };
 
         for (original_index, expression) in
             self.expressions.iter_enumerated().filter_map(|(original_index, entry)| {
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index 57e49ba..b1e372a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -104,7 +104,7 @@
     ) {
         let cx = self.fx.cx;
 
-        if let &[ref proj_base @ .., elem] = place_ref.projection {
+        if let Some((place_base, elem)) = place_ref.last_projection() {
             let mut base_context = if context.is_mutating_use() {
                 PlaceContext::MutatingUse(MutatingUseContext::Projection)
             } else {
@@ -119,8 +119,7 @@
                 )
             );
             if is_consume {
-                let base_ty =
-                    mir::Place::ty_from(place_ref.local, proj_base, self.fx.mir, cx.tcx());
+                let base_ty = mir::PlaceRef::ty(&place_base, self.fx.mir, cx.tcx());
                 let base_ty = self.fx.monomorphize(base_ty);
 
                 // ZSTs don't require any actual memory access.
@@ -175,11 +174,7 @@
                 base_context = context;
             }
 
-            self.process_place(
-                &mir::PlaceRef { local: place_ref.local, projection: proj_base },
-                base_context,
-                location,
-            );
+            self.process_place(&place_base, base_context, location);
             // HACK(eddyb) this emulates the old `visit_projection_elem`, this
             // entire `visit_place`-like `process_place` method should be rewritten,
             // now that we have moved to the "slice of projections" representation.
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index e4f4c88..958e4eb 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -178,16 +178,8 @@
         // Get the alignment of the field
         let (_, unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta);
 
-        // Bump the unaligned offset up to the appropriate alignment using the
-        // following expression:
-        //
-        //     (unaligned offset + (align - 1)) & -align
-
-        // Calculate offset.
-        let align_sub_1 = bx.sub(unsized_align, bx.cx().const_usize(1u64));
-        let and_lhs = bx.add(unaligned_offset, align_sub_1);
-        let and_rhs = bx.neg(unsized_align);
-        let offset = bx.and(and_lhs, and_rhs);
+        // Bump the unaligned offset up to the appropriate alignment
+        let offset = round_up_const_value_to_alignment(bx, unaligned_offset, unsized_align);
 
         debug!("struct_field_ptr: DST field offset: {:?}", offset);
 
@@ -514,7 +506,49 @@
 
     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.local, place_ref.projection, self.mir, tcx);
+        let place_ty = mir::PlaceRef::ty(&place_ref, self.mir, tcx);
         self.monomorphize(place_ty.ty)
     }
 }
+
+fn round_up_const_value_to_alignment<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
+    bx: &mut Bx,
+    value: Bx::Value,
+    align: Bx::Value,
+) -> Bx::Value {
+    // In pseudo code:
+    //
+    //     if value & (align - 1) == 0 {
+    //         value
+    //     } else {
+    //         (value & !(align - 1)) + align
+    //     }
+    //
+    // Usually this is written without branches as
+    //
+    //     (value + align - 1) & !(align - 1)
+    //
+    // But this formula cannot take advantage of constant `value`. E.g. if `value` is known
+    // at compile time to be `1`, this expression should be optimized to `align`. However,
+    // optimization only holds if `align` is a power of two. Since the optimizer doesn't know
+    // that `align` is a power of two, it cannot perform this optimization.
+    //
+    // Instead we use
+    //
+    //     value + (-value & (align - 1))
+    //
+    // Since `align` is used only once, the expression can be optimized. For `value = 0`
+    // its optimized to `0` even in debug mode.
+    //
+    // NB: The previous version of this code used
+    //
+    //     (value + align - 1) & -align
+    //
+    // Even though `-align == !(align - 1)`, LLVM failed to optimize this even for
+    // `value = 0`. Bug report: https://bugs.llvm.org/show_bug.cgi?id=48559
+    let one = bx.const_usize(1);
+    let align_minus_1 = bx.sub(align, one);
+    let neg_value = bx.neg(value);
+    let offset = bx.and(neg_value, align_minus_1);
+    bx.add(value, offset)
+}
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index 01efcaf..08c3419 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -1,10 +1,10 @@
 use crate::stable_hasher;
 use rustc_serialize::{
-    opaque::{self, EncodeResult},
+    opaque::{self, EncodeResult, FileEncodeResult},
     Decodable, Encodable,
 };
 use std::hash::{Hash, Hasher};
-use std::mem;
+use std::mem::{self, MaybeUninit};
 
 #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy)]
 pub struct Fingerprint(u64, u64);
@@ -53,15 +53,8 @@
         format!("{:x}{:x}", self.0, self.1)
     }
 
-    pub fn encode_opaque(&self, encoder: &mut opaque::Encoder) -> EncodeResult {
-        let bytes: [u8; 16] = unsafe { mem::transmute([self.0.to_le(), self.1.to_le()]) };
-
-        encoder.emit_raw_bytes(&bytes);
-        Ok(())
-    }
-
     pub fn decode_opaque(decoder: &mut opaque::Decoder<'_>) -> Result<Fingerprint, String> {
-        let mut bytes = [0; 16];
+        let mut bytes: [MaybeUninit<u8>; 16] = MaybeUninit::uninit_array();
 
         decoder.read_raw_bytes(&mut bytes)?;
 
@@ -142,7 +135,16 @@
 
 impl FingerprintEncoder for opaque::Encoder {
     fn encode_fingerprint(&mut self, f: &Fingerprint) -> EncodeResult {
-        f.encode_opaque(self)
+        let bytes: [u8; 16] = unsafe { mem::transmute([f.0.to_le(), f.1.to_le()]) };
+        self.emit_raw_bytes(&bytes);
+        Ok(())
+    }
+}
+
+impl FingerprintEncoder for opaque::FileEncoder {
+    fn encode_fingerprint(&mut self, f: &Fingerprint) -> FileEncodeResult {
+        let bytes: [u8; 16] = unsafe { mem::transmute([f.0.to_le(), f.1.to_le()]) };
+        self.emit_raw_bytes(&bytes)
     }
 }
 
@@ -198,7 +200,7 @@
 impl<D: rustc_serialize::Decoder> Decodable<D> for PackedFingerprint {
     #[inline]
     fn decode(d: &mut D) -> Result<Self, D::Error> {
-        Fingerprint::decode(d).map(|f| PackedFingerprint(f))
+        Fingerprint::decode(d).map(PackedFingerprint)
     }
 }
 
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 5d13b7f..b16d5a9 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -166,7 +166,7 @@
         // If there is no SelfProfiler then the filter mask is set to NONE,
         // ensuring that nothing ever tries to actually access it.
         let event_filter_mask =
-            profiler.as_ref().map(|p| p.event_filter_mask).unwrap_or(EventFilter::empty());
+            profiler.as_ref().map_or(EventFilter::empty(), |p| p.event_filter_mask);
 
         SelfProfilerRef {
             profiler,
diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml
index 0adc006..b88b556 100644
--- a/compiler/rustc_driver/Cargo.toml
+++ b/compiler/rustc_driver/Cargo.toml
@@ -9,6 +9,7 @@
 
 [dependencies]
 libc = "0.2"
+atty = "0.2"
 tracing = { version = "0.1.18" }
 tracing-subscriber = { version = "0.2.13", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
 tracing-tree = "0.1.6"
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index d57ab24..15b984a 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -546,24 +546,12 @@
 #[derive(Copy, Clone)]
 pub struct RustcDefaultCalls;
 
-// FIXME remove these and use winapi 0.3 instead
-// Duplicates: bootstrap/compile.rs, librustc_errors/emitter.rs
-#[cfg(unix)]
 fn stdout_isatty() -> bool {
-    unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 }
+    atty::is(atty::Stream::Stdout)
 }
 
-#[cfg(windows)]
-fn stdout_isatty() -> 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;
-        GetConsoleMode(handle, &mut out) != 0
-    }
+fn stderr_isatty() -> bool {
+    atty::is(atty::Stream::Stderr)
 }
 
 fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
@@ -810,7 +798,7 @@
         println!("commit-date: {}", unw(util::commit_date_str()));
         println!("host: {}", config::host_triple());
         println!("release: {}", unw(util::release_str()));
-        if cfg!(llvm) {
+        if cfg!(feature = "llvm") {
             get_builtin_codegen_backend("llvm")().print_version();
         }
     }
@@ -1099,7 +1087,7 @@
     }
 
     if cg_flags.iter().any(|x| *x == "passes=list") {
-        if cfg!(llvm) {
+        if cfg!(feature = "llvm") {
             get_builtin_codegen_backend("llvm")().print_passes();
         }
         return None;
@@ -1248,7 +1236,7 @@
     }
 
     // If backtraces are enabled, also print the query stack
-    let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false);
+    let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");
 
     let num_frames = if backtrace { None } else { Some(2) };
 
@@ -1290,7 +1278,7 @@
         Ok(value) => match value.as_ref() {
             "always" => true,
             "never" => false,
-            "auto" => stdout_isatty(),
+            "auto" => stderr_isatty(),
             _ => early_error(
                 ErrorOutputType::default(),
                 &format!(
@@ -1299,7 +1287,7 @@
                 ),
             ),
         },
-        Err(std::env::VarError::NotPresent) => stdout_isatty(),
+        Err(std::env::VarError::NotPresent) => stderr_isatty(),
         Err(std::env::VarError::NotUnicode(_value)) => early_error(
             ErrorOutputType::default(),
             "non-Unicode log color value: expected one of always, never, or auto",
diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs
index 305fa83..b7edc24 100644
--- a/compiler/rustc_driver/src/pretty.rs
+++ b/compiler/rustc_driver/src/pretty.rs
@@ -363,8 +363,15 @@
 
 fn get_source(input: &Input, sess: &Session) -> (String, FileName) {
     let src_name = input.source_name();
-    let src =
-        String::clone(&sess.source_map().get_source_file(&src_name).unwrap().src.as_ref().unwrap());
+    let src = String::clone(
+        &sess
+            .source_map()
+            .get_source_file(&src_name)
+            .expect("get_source_file")
+            .src
+            .as_ref()
+            .expect("src"),
+    );
     (src, src_name)
 }
 
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index fef6602..c669f7f 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -464,6 +464,7 @@
 E0777: include_str!("./error_codes/E0777.md"),
 E0778: include_str!("./error_codes/E0778.md"),
 E0779: include_str!("./error_codes/E0779.md"),
+E0780: include_str!("./error_codes/E0780.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/compiler/rustc_error_codes/src/error_codes/E0044.md b/compiler/rustc_error_codes/src/error_codes/E0044.md
index 635ff95..ed7daf8 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0044.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0044.md
@@ -3,13 +3,13 @@
 Example of erroneous code:
 
 ```compile_fail,E0044
-extern { fn some_func<T>(x: T); }
+extern "C" { fn some_func<T>(x: T); }
 ```
 
 To fix this, replace the generic parameter with the specializations that you
 need:
 
 ```
-extern { fn some_func_i32(x: i32); }
-extern { fn some_func_i64(x: i64); }
+extern "C" { fn some_func_i32(x: i32); }
+extern "C" { fn some_func_i64(x: i64); }
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0130.md b/compiler/rustc_error_codes/src/error_codes/E0130.md
index a270fea..2cd27b5 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0130.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0130.md
@@ -3,7 +3,7 @@
 Erroneous code example:
 
 ```compile_fail,E0130
-extern {
+extern "C" {
     fn foo((a, b): (u32, u32)); // error: patterns aren't allowed in foreign
                                 //        function declarations
 }
@@ -17,7 +17,7 @@
     b: u32,
 }
 
-extern {
+extern "C" {
     fn foo(s: SomeStruct); // ok!
 }
 ```
@@ -25,7 +25,7 @@
 Or:
 
 ```
-extern {
+extern "C" {
     fn foo(a: (u32, u32)); // ok!
 }
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0373.md b/compiler/rustc_error_codes/src/error_codes/E0373.md
index fd96987..effa597 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0373.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0373.md
@@ -50,3 +50,24 @@
 
 Now that the closure has its own copy of the data, there's no need to worry
 about safety.
+
+This error may also be encountered while using `async` blocks:
+
+```compile_fail,E0373,edition2018
+use std::future::Future;
+
+async fn f() {
+    let v = vec![1, 2, 3i32];
+    spawn(async { //~ ERROR E0373
+        println!("{:?}", v)
+    });
+}
+
+fn spawn<F: Future + Send + 'static>(future: F) {
+    unimplemented!()
+}
+```
+
+Similarly to closures, `async` blocks are not executed immediately and may
+capture closed-over data by reference. For more information, see
+https://rust-lang.github.io/async-book/03_async_await/01_chapter.html.
diff --git a/compiler/rustc_error_codes/src/error_codes/E0435.md b/compiler/rustc_error_codes/src/error_codes/E0435.md
index 424e5ce..798a20d 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0435.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0435.md
@@ -7,6 +7,12 @@
 let a: [u8; foo]; // error: attempt to use a non-constant value in a constant
 ```
 
+'constant' means 'a compile-time value'.
+
+More details can be found in the [Variables and Mutability] section of the book.
+
+[Variables and Mutability]: https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
+
 To fix this error, please replace the value with a constant. Example:
 
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0454.md b/compiler/rustc_error_codes/src/error_codes/E0454.md
index 23ca6c7..95a22b9 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0454.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0454.md
@@ -3,7 +3,7 @@
 Erroneous code example:
 
 ```compile_fail,E0454
-#[link(name = "")] extern {}
+#[link(name = "")] extern "C" {}
 // error: `#[link(name = "")]` given with empty name
 ```
 
@@ -11,5 +11,5 @@
 name. Example:
 
 ```no_run
-#[link(name = "some_lib")] extern {} // ok!
+#[link(name = "some_lib")] extern "C" {} // ok!
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0455.md b/compiler/rustc_error_codes/src/error_codes/E0455.md
index 2f80c34..84689b3 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0455.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0455.md
@@ -4,7 +4,7 @@
 Erroneous code example:
 
 ```ignore (should-compile_fail-but-cannot-doctest-conditionally-without-macos)
-#[link(name = "FooCoreServices", kind = "framework")] extern {}
+#[link(name = "FooCoreServices", kind = "framework")] extern "C" {}
 // OS used to compile is Linux for example
 ```
 
@@ -12,7 +12,7 @@
 
 ```
 #[cfg_attr(target="macos", link(name = "FooCoreServices", kind = "framework"))]
-extern {}
+extern "C" {}
 ```
 
 Learn more in the [Conditional Compilation][conditional-compilation] section
diff --git a/compiler/rustc_error_codes/src/error_codes/E0458.md b/compiler/rustc_error_codes/src/error_codes/E0458.md
index 075226a..359aeb6 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0458.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0458.md
@@ -3,7 +3,7 @@
 Erroneous code example:
 
 ```compile_fail,E0458
-#[link(kind = "wonderful_unicorn")] extern {}
+#[link(kind = "wonderful_unicorn")] extern "C" {}
 // error: unknown kind: `wonderful_unicorn`
 ```
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0459.md b/compiler/rustc_error_codes/src/error_codes/E0459.md
index 6f75f2a..4a49a76 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0459.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0459.md
@@ -3,7 +3,7 @@
 Erroneous code example:
 
 ```compile_fail,E0459
-#[link(kind = "dylib")] extern {}
+#[link(kind = "dylib")] extern "C" {}
 // error: `#[link(...)]` specified without `name = "foo"`
 ```
 
@@ -11,5 +11,5 @@
 you want. Example:
 
 ```no_run
-#[link(kind = "dylib", name = "some_lib")] extern {} // ok!
+#[link(kind = "dylib", name = "some_lib")] extern "C" {} // ok!
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0492.md b/compiler/rustc_error_codes/src/error_codes/E0492.md
index 1caa599..79e7c06 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0492.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0492.md
@@ -6,7 +6,7 @@
 use std::sync::atomic::AtomicUsize;
 
 const A: AtomicUsize = AtomicUsize::new(0);
-static B: &'static AtomicUsize = &A;
+const B: &'static AtomicUsize = &A;
 // error: cannot borrow a constant which may contain interior mutability,
 //        create a static instead
 ```
@@ -18,7 +18,7 @@
 it. That is, a constant value could be mutated. On the other hand, a `static` is
 explicitly a single memory location, which can be mutated at will.
 
-So, in order to solve this error, either use statics which are `Sync`:
+So, in order to solve this error, use statics which are `Sync`:
 
 ```
 use std::sync::atomic::AtomicUsize;
diff --git a/compiler/rustc_error_codes/src/error_codes/E0617.md b/compiler/rustc_error_codes/src/error_codes/E0617.md
index 61b5676..1c5d1f8 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0617.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0617.md
@@ -3,7 +3,7 @@
 Erroneous code example:
 
 ```compile_fail,E0617
-extern {
+extern "C" {
     fn printf(c: *const i8, ...);
 }
 
@@ -21,7 +21,7 @@
 In this case, `c_double` has the same size as `f64` so we can use it directly:
 
 ```no_run
-# extern {
+# extern "C" {
 #     fn printf(c: *const i8, ...);
 # }
 unsafe {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0633.md b/compiler/rustc_error_codes/src/error_codes/E0633.md
index 7f488cd..4d1f0c4 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0633.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0633.md
@@ -6,7 +6,7 @@
 #![feature(unwind_attributes)]
 
 #[unwind()] // error: expected one argument
-pub extern fn something() {}
+pub extern "C" fn something() {}
 
 fn main() {}
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0724.md b/compiler/rustc_error_codes/src/error_codes/E0724.md
index e8f84d0..70578ac 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0724.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0724.md
@@ -18,7 +18,7 @@
 ```
 #![feature(ffi_returns_twice)]
 
-extern {
+extern "C" {
    #[ffi_returns_twice] // ok!
    pub fn foo();
 }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0780.md b/compiler/rustc_error_codes/src/error_codes/E0780.md
new file mode 100644
index 0000000..704b4ae
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0780.md
@@ -0,0 +1,19 @@
+Cannot use `doc(inline)` with anonymous imports
+
+Erroneous code example:
+
+```ignore (cannot-doctest-multicrate-project)
+
+#[doc(inline)] // error: invalid doc argument
+pub use foo::Foo as _;
+```
+
+Anonymous imports are always rendered with `#[doc(no_inline)]`. To fix this
+error, remove the `#[doc(inline)]` attribute.
+
+Example:
+
+```ignore (cannot-doctest-multicrate-project)
+
+pub use foo::Foo as _;
+```
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 32104e6..00882bb 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -644,6 +644,8 @@
         code_offset: usize,
         margin: Margin,
     ) {
+        // Tabs are assumed to have been replaced by spaces in calling code.
+        assert!(!source_string.contains('\t'));
         let line_len = source_string.len();
         // Create the source line we will highlight.
         let left = margin.left(line_len);
@@ -707,7 +709,7 @@
         }
 
         let source_string = match file.get_line(line.line_index - 1) {
-            Some(s) => s,
+            Some(s) => replace_tabs(&*s),
             None => return Vec::new(),
         };
 
@@ -1376,8 +1378,17 @@
                     let file = annotated_file.file.clone();
                     let line = &annotated_file.lines[line_idx];
                     if let Some(source_string) = file.get_line(line.line_index - 1) {
-                        let leading_whitespace =
-                            source_string.chars().take_while(|c| c.is_whitespace()).count();
+                        let leading_whitespace = source_string
+                            .chars()
+                            .take_while(|c| c.is_whitespace())
+                            .map(|c| {
+                                match c {
+                                    // Tabs are displayed as 4 spaces
+                                    '\t' => 4,
+                                    _ => 1,
+                                }
+                            })
+                            .sum();
                         if source_string.chars().any(|c| !c.is_whitespace()) {
                             whitespace_margin = min(whitespace_margin, leading_whitespace);
                         }
@@ -1502,7 +1513,7 @@
 
                             self.draw_line(
                                 &mut buffer,
-                                &unannotated_line,
+                                &replace_tabs(&unannotated_line),
                                 annotated_file.lines[line_idx + 1].line_index - 1,
                                 last_buffer_line_num,
                                 width_offset,
@@ -1598,7 +1609,7 @@
                 );
                 // print the suggestion
                 draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
-                buffer.append(row_num, line, Style::NoStyle);
+                buffer.append(row_num, &replace_tabs(line), Style::NoStyle);
                 row_num += 1;
             }
 
@@ -1930,6 +1941,10 @@
     }
 }
 
+fn replace_tabs(str: &str) -> String {
+    str.replace('\t', "    ")
+}
+
 fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) {
     buffer.puts(line, col, "| ", Style::LineNumber);
 }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 593e0d9..e184e92 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -804,7 +804,7 @@
     }
 
     fn treat_err_as_bug(&self) -> bool {
-        self.flags.treat_err_as_bug.map(|c| self.err_count() >= c).unwrap_or(false)
+        self.flags.treat_err_as_bug.map_or(false, |c| self.err_count() >= c)
     }
 
     fn print_error_count(&mut self, registry: &Registry) {
@@ -913,7 +913,7 @@
         // This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
         // incrementing `err_count` by one, so we need to +1 the comparing.
         // FIXME: Would be nice to increment err_count in a more coherent way.
-        if self.flags.treat_err_as_bug.map(|c| self.err_count() + 1 >= c).unwrap_or(false) {
+        if self.flags.treat_err_as_bug.map_or(false, |c| self.err_count() + 1 >= c) {
             // FIXME: don't abort here if report_delayed_bugs is off
             self.span_bug(sp, msg);
         }
diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs
index f2d255d..a4dd0f3 100644
--- a/compiler/rustc_errors/src/styled_buffer.rs
+++ b/compiler/rustc_errors/src/styled_buffer.rs
@@ -13,34 +13,13 @@
         StyledBuffer { text: vec![], styles: vec![] }
     }
 
-    fn replace_tabs(&mut self) {
-        for (line_pos, line) in self.text.iter_mut().enumerate() {
-            let mut tab_pos = vec![];
-            for (pos, c) in line.iter().enumerate() {
-                if *c == '\t' {
-                    tab_pos.push(pos);
-                }
-            }
-            // start with the tabs at the end of the line to replace them with 4 space chars
-            for pos in tab_pos.iter().rev() {
-                assert_eq!(line.remove(*pos), '\t');
-                // fix the position of the style to match up after replacing the tabs
-                let s = self.styles[line_pos].remove(*pos);
-                for _ in 0..4 {
-                    line.insert(*pos, ' ');
-                    self.styles[line_pos].insert(*pos, s);
-                }
-            }
-        }
-    }
+    pub fn render(&self) -> Vec<Vec<StyledString>> {
+        // Tabs are assumed to have been replaced by spaces in calling code.
+        assert!(self.text.iter().all(|r| !r.contains(&'\t')));
 
-    pub fn render(&mut self) -> Vec<Vec<StyledString>> {
         let mut output: Vec<Vec<StyledString>> = vec![];
         let mut styled_vec: Vec<StyledString> = vec![];
 
-        // before we render, replace tabs with spaces
-        self.replace_tabs();
-
         for (row, row_style) in self.text.iter().zip(&self.styles) {
             let mut current_style = Style::NoStyle;
             let mut current_text = String::new();
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 774a076..2f43940 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -12,7 +12,7 @@
 use rustc_errors::{DiagnosticBuilder, ErrorReported};
 use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
 use rustc_session::{parse::ParseSess, Limit, Session};
-use rustc_span::def_id::{DefId, LOCAL_CRATE};
+use rustc_span::def_id::DefId;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
 use rustc_span::source_map::SourceMap;
@@ -141,7 +141,7 @@
     }
 
     crate fn into_tokens(self, sess: &ParseSess) -> TokenStream {
-        nt_to_tokenstream(&self.into_nonterminal(), sess, DUMMY_SP, CanSynthesizeMissingTokens::No)
+        nt_to_tokenstream(&self.into_nonterminal(), sess, CanSynthesizeMissingTokens::No)
     }
 
     pub fn expect_item(self) -> P<ast::Item> {
@@ -728,9 +728,7 @@
     pub edition: Edition,
     /// Built-in macros have a couple of special properties like availability
     /// in `#[no_implicit_prelude]` modules, so we have to keep this flag.
-    pub is_builtin: bool,
-    /// We have to identify macros providing a `Copy` impl early for compatibility reasons.
-    pub is_derive_copy: bool,
+    pub builtin_name: Option<Symbol>,
 }
 
 impl SyntaxExtension {
@@ -758,8 +756,7 @@
             deprecation: None,
             helper_attrs: Vec::new(),
             edition,
-            is_builtin: false,
-            is_derive_copy: false,
+            builtin_name: None,
             kind,
         }
     }
@@ -785,7 +782,9 @@
             }
         }
 
-        let is_builtin = sess.contains_name(attrs, sym::rustc_builtin_macro);
+        let builtin_name = sess
+            .find_by_name(attrs, sym::rustc_builtin_macro)
+            .map(|a| a.value_str().unwrap_or(name));
         let (stability, const_stability) = attr::find_stability(&sess, attrs, span);
         if const_stability.is_some() {
             sess.parse_sess
@@ -803,8 +802,7 @@
             deprecation: attr::find_deprecation(&sess, attrs).map(|(d, _)| d),
             helper_attrs,
             edition,
-            is_builtin,
-            is_derive_copy: is_builtin && name == sym::Copy,
+            builtin_name,
         }
     }
 
@@ -842,19 +840,17 @@
         descr: Symbol,
         macro_def_id: Option<DefId>,
     ) -> ExpnData {
-        ExpnData {
-            kind: ExpnKind::Macro(self.macro_kind(), descr),
+        ExpnData::new(
+            ExpnKind::Macro(self.macro_kind(), descr),
             parent,
             call_site,
-            def_site: self.span,
-            allow_internal_unstable: self.allow_internal_unstable.clone(),
-            allow_internal_unsafe: self.allow_internal_unsafe,
-            local_inner_macros: self.local_inner_macros,
-            edition: self.edition,
+            self.span,
+            self.allow_internal_unstable.clone(),
+            self.allow_internal_unsafe,
+            self.local_inner_macros,
+            self.edition,
             macro_def_id,
-            krate: LOCAL_CRATE,
-            orig_id: None,
-        }
+        )
     }
 }
 
@@ -872,7 +868,7 @@
 
     fn resolve_dollar_crates(&mut self);
     fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment);
-    fn register_builtin_macro(&mut self, ident: Ident, ext: SyntaxExtension);
+    fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind);
 
     fn expansion_for_ast_pass(
         &mut self,
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 1193f66..b07bce94 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -423,7 +423,7 @@
 
     /// If attributes are not allowed on expressions, emit an error for `attr`
     pub fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
-        if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) {
+        if !self.features.map_or(true, |features| features.stmt_expr_attributes) {
             let mut err = feature_err(
                 &self.sess.parse_sess,
                 sym::stmt_expr_attributes,
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 5d40d47..16913db 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -743,7 +743,6 @@
                         AttrStyle::Inner => rustc_parse::fake_token_stream(
                             &self.cx.sess.parse_sess,
                             &item.into_nonterminal(),
-                            span,
                         ),
                     };
                     let attr_item = attr.unwrap_normal_item();
@@ -1020,15 +1019,16 @@
         // with exception of the derive container case which is not resolved and can get
         // its expansion data immediately.
         let expn_data = match &kind {
-            InvocationKind::DeriveContainer { item, .. } => Some(ExpnData {
-                parent: self.cx.current_expansion.id,
-                ..ExpnData::default(
+            InvocationKind::DeriveContainer { item, .. } => {
+                let mut expn_data = ExpnData::default(
                     ExpnKind::Macro(MacroKind::Attr, sym::derive),
                     item.span(),
                     self.cx.sess.parse_sess.edition,
                     None,
-                )
-            }),
+                );
+                expn_data.parent = self.cx.current_expansion.id;
+                Some(expn_data)
+            }
             _ => None,
         };
         let expn_id = ExpnId::fresh(expn_data);
@@ -1543,13 +1543,8 @@
     }
 
     fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
-        match item {
-            ast::ItemKind::MacroDef(..) => {}
-            _ => {
-                self.cfg.configure_item_kind(item);
-                noop_visit_item_kind(item, self);
-            }
-        }
+        self.cfg.configure_item_kind(item);
+        noop_visit_item_kind(item, self);
     }
 
     fn flat_map_generic_param(
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 0c44f5f..1aed42a 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -77,9 +77,9 @@
 use crate::mbe::{self, TokenTree};
 
 use rustc_ast::token::{self, DocComment, Nonterminal, Token};
-use rustc_parse::parser::{OrPatNonterminalMode, Parser};
+use rustc_parse::parser::Parser;
 use rustc_session::parse::ParseSess;
-use rustc_span::{edition::Edition, symbol::MacroRulesNormalizedIdent};
+use rustc_span::symbol::MacroRulesNormalizedIdent;
 
 use smallvec::{smallvec, SmallVec};
 
@@ -419,18 +419,6 @@
     }
 }
 
-/// In edition 2015/18, `:pat` can only match `pat<no_top_alt>` because otherwise, we have
-/// breakage. As of edition 2021, `:pat` matches `top_pat`.
-///
-/// See <https://github.com/rust-lang/rust/issues/54883> for more info.
-fn or_pat_mode(edition: Edition) -> OrPatNonterminalMode {
-    match edition {
-        Edition::Edition2015 | Edition::Edition2018 => OrPatNonterminalMode::NoTopAlt,
-        // FIXME(mark-i-m): uncomment this when edition 2021 machinery is added.
-        // Edition::Edition2021 =>  OrPatNonterminalMode::TopPat,
-    }
-}
-
 /// Process the matcher positions of `cur_items` until it is empty. In the process, this will
 /// produce more items in `next_items`, `eof_items`, and `bb_items`.
 ///
@@ -512,7 +500,7 @@
                 if idx == len && item.sep.is_some() {
                     // We have a separator, and it is the current token. We can advance past the
                     // separator token.
-                    if item.sep.as_ref().map(|sep| token_name_eq(token, sep)).unwrap_or(false) {
+                    if item.sep.as_ref().map_or(false, |sep| token_name_eq(token, sep)) {
                         item.idx += 1;
                         next_items.push(item);
                     }
@@ -578,14 +566,13 @@
 
                 // We need to match a metavar with a valid ident... call out to the black-box
                 // parser by adding an item to `bb_items`.
-                TokenTree::MetaVarDecl(span, _, Some(kind)) => {
+                TokenTree::MetaVarDecl(_, _, Some(kind)) => {
                     // Built-in nonterminals never start with these tokens, so we can eliminate
                     // them from consideration.
                     //
                     // We use the span of the metavariable declaration to determine any
                     // edition-specific matching behavior for non-terminals.
-                    if Parser::nonterminal_may_begin_with(kind, token, or_pat_mode(span.edition()))
-                    {
+                    if Parser::nonterminal_may_begin_with(kind, token) {
                         bb_items.push(item);
                     }
                 }
@@ -749,8 +736,7 @@
                 let match_cur = item.match_cur;
                 // We use the span of the metavariable declaration to determine any
                 // edition-specific matching behavior for non-terminals.
-                let nt = match parser.to_mut().parse_nonterminal(kind, or_pat_mode(span.edition()))
-                {
+                let nt = match parser.to_mut().parse_nonterminal(kind) {
                     Err(mut err) => {
                         err.span_label(
                             span,
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 89d375b..e8c711c 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -56,36 +56,11 @@
     };
 }
 
-/// Instead of e.g. `vec![a, b, c]` in a pattern context, suggest `[a, b, c]`.
-fn suggest_slice_pat(e: &mut DiagnosticBuilder<'_>, site_span: Span, parser: &Parser<'_>) {
-    let mut suggestion = None;
-    if let Ok(code) = parser.sess.source_map().span_to_snippet(site_span) {
-        if let Some(bang) = code.find('!') {
-            suggestion = Some(code[bang + 1..].to_string());
-        }
-    }
-    if let Some(suggestion) = suggestion {
-        e.span_suggestion(
-            site_span,
-            "use a slice pattern here instead",
-            suggestion,
-            Applicability::MachineApplicable,
-        );
-    } else {
-        e.span_label(site_span, "use a slice pattern here instead");
-    }
-    e.help(
-        "for more information, see https://doc.rust-lang.org/edition-guide/\
-        rust-2018/slice-patterns.html",
-    );
-}
-
 fn emit_frag_parse_err(
     mut e: DiagnosticBuilder<'_>,
     parser: &Parser<'_>,
     orig_parser: &mut Parser<'_>,
     site_span: Span,
-    macro_ident: Ident,
     arm_span: Span,
     kind: AstFragmentKind,
 ) {
@@ -113,9 +88,6 @@
         e.span_label(site_span, "in this macro invocation");
     }
     match kind {
-        AstFragmentKind::Pat if macro_ident.name == sym::vec => {
-            suggest_slice_pat(&mut e, site_span, parser);
-        }
         // Try a statement if an expression is wanted but failed and suggest adding `;` to call.
         AstFragmentKind::Expr => match parse_ast_fragment(orig_parser, AstFragmentKind::Stmts) {
             Err(mut err) => err.cancel(),
@@ -143,7 +115,7 @@
         let fragment = match parse_ast_fragment(parser, kind) {
             Ok(f) => f,
             Err(err) => {
-                emit_frag_parse_err(err, parser, snapshot, site_span, macro_ident, arm_span, kind);
+                emit_frag_parse_err(err, parser, snapshot, site_span, arm_span, kind);
                 return kind.dummy(site_span);
             }
         };
@@ -203,7 +175,7 @@
 }
 
 fn trace_macros_note(cx_expansions: &mut FxHashMap<Span, Vec<String>>, sp: Span, message: String) {
-    let sp = sp.macro_backtrace().last().map(|trace| trace.call_site).unwrap_or(sp);
+    let sp = sp.macro_backtrace().last().map_or(sp, |trace| trace.call_site);
     cx_expansions.entry(sp).or_default().push(message);
 }
 
@@ -476,10 +448,15 @@
             .map(|m| {
                 if let MatchedNonterminal(ref nt) = *m {
                     if let NtTT(ref tt) = **nt {
-                        let tt =
-                            mbe::quoted::parse(tt.clone().into(), true, &sess.parse_sess, def.id)
-                                .pop()
-                                .unwrap();
+                        let tt = mbe::quoted::parse(
+                            tt.clone().into(),
+                            true,
+                            &sess.parse_sess,
+                            def.id,
+                            features,
+                        )
+                        .pop()
+                        .unwrap();
                         valid &= check_lhs_nt_follows(&sess.parse_sess, features, &def.attrs, &tt);
                         return tt;
                     }
@@ -501,6 +478,7 @@
                             false,
                             &sess.parse_sess,
                             def.id,
+                            features,
                         )
                         .pop()
                         .unwrap();
@@ -1090,7 +1068,7 @@
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            NonterminalKind::Pat => {
+            NonterminalKind::Pat2018 { .. } | NonterminalKind::Pat2021 { .. } => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index 01b11bb..c804949 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -5,8 +5,9 @@
 use rustc_ast::tokenstream;
 use rustc_ast::{NodeId, DUMMY_NODE_ID};
 use rustc_ast_pretty::pprust;
-use rustc_session::parse::ParseSess;
-use rustc_span::symbol::{kw, Ident};
+use rustc_feature::Features;
+use rustc_session::parse::{feature_err, ParseSess};
+use rustc_span::symbol::{kw, sym, Ident};
 
 use rustc_span::Span;
 
@@ -29,10 +30,8 @@
 ///   `ident` are "matchers". They are not present in the body of a macro rule -- just in the
 ///   pattern, so we pass a parameter to indicate whether to expect them or not.
 /// - `sess`: the parsing session. Any errors will be emitted to this session.
-/// - `features`, `attrs`: language feature flags and attributes so that we know whether to use
-///   unstable features or not.
-/// - `edition`: which edition are we in.
-/// - `macro_node_id`: the NodeId of the macro we are parsing.
+/// - `node_id`: the NodeId of the macro we are parsing.
+/// - `features`: language features so we can do feature gating.
 ///
 /// # Returns
 ///
@@ -42,6 +41,7 @@
     expect_matchers: bool,
     sess: &ParseSess,
     node_id: NodeId,
+    features: &Features,
 ) -> Vec<TokenTree> {
     // Will contain the final collection of `self::TokenTree`
     let mut result = Vec::new();
@@ -52,7 +52,7 @@
     while let Some(tree) = trees.next() {
         // Given the parsed tree, if there is a metavar and we are expecting matchers, actually
         // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`).
-        let tree = parse_tree(tree, &mut trees, expect_matchers, sess, node_id);
+        let tree = parse_tree(tree, &mut trees, expect_matchers, sess, node_id, features);
         match tree {
             TokenTree::MetaVar(start_sp, ident) if expect_matchers => {
                 let span = match trees.next() {
@@ -61,27 +61,48 @@
                             Some(tokenstream::TokenTree::Token(token)) => match token.ident() {
                                 Some((frag, _)) => {
                                     let span = token.span.with_lo(start_sp.lo());
-                                    let kind = token::NonterminalKind::from_symbol(frag.name)
-                                        .unwrap_or_else(|| {
-                                            let msg = format!(
-                                                "invalid fragment specifier `{}`",
-                                                frag.name
-                                            );
-                                            sess.span_diagnostic
-                                                .struct_span_err(span, &msg)
-                                                .help(VALID_FRAGMENT_NAMES_MSG)
+
+                                    match frag.name {
+                                        sym::pat2018 | sym::pat2021 => {
+                                            if !features.edition_macro_pats {
+                                                feature_err(
+                                                    sess,
+                                                    sym::edition_macro_pats,
+                                                    frag.span,
+                                                    "`pat2018` and `pat2021` are unstable.",
+                                                )
                                                 .emit();
-                                            token::NonterminalKind::Ident
-                                        });
+                                            }
+                                        }
+                                        _ => {}
+                                    }
+
+                                    let kind =
+                                        token::NonterminalKind::from_symbol(frag.name, || {
+                                            span.edition()
+                                        })
+                                        .unwrap_or_else(
+                                            || {
+                                                let msg = format!(
+                                                    "invalid fragment specifier `{}`",
+                                                    frag.name
+                                                );
+                                                sess.span_diagnostic
+                                                    .struct_span_err(span, &msg)
+                                                    .help(VALID_FRAGMENT_NAMES_MSG)
+                                                    .emit();
+                                                token::NonterminalKind::Ident
+                                            },
+                                        );
                                     result.push(TokenTree::MetaVarDecl(span, ident, Some(kind)));
                                     continue;
                                 }
                                 _ => token.span,
                             },
-                            tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(span),
+                            tree => tree.as_ref().map_or(span, tokenstream::TokenTree::span),
                         }
                     }
-                    tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(start_sp),
+                    tree => tree.as_ref().map_or(start_sp, tokenstream::TokenTree::span),
                 };
                 if node_id != DUMMY_NODE_ID {
                     // Macros loaded from other crates have dummy node ids.
@@ -110,14 +131,14 @@
 ///   converting `tree`
 /// - `expect_matchers`: same as for `parse` (see above).
 /// - `sess`: the parsing session. Any errors will be emitted to this session.
-/// - `features`, `attrs`: language feature flags and attributes so that we know whether to use
-///   unstable features or not.
+/// - `features`: language features so we can do feature gating.
 fn parse_tree(
     tree: tokenstream::TokenTree,
     outer_trees: &mut impl Iterator<Item = tokenstream::TokenTree>,
     expect_matchers: bool,
     sess: &ParseSess,
     node_id: NodeId,
+    features: &Features,
 ) -> TokenTree {
     // Depending on what `tree` is, we could be parsing different parts of a macro
     match tree {
@@ -145,7 +166,7 @@
                         sess.span_diagnostic.span_err(span.entire(), &msg);
                     }
                     // Parse the contents of the sequence itself
-                    let sequence = parse(tts, expect_matchers, sess, node_id);
+                    let sequence = parse(tts, expect_matchers, sess, node_id, features);
                     // Get the Kleene operator and optional separator
                     let (separator, kleene) =
                         parse_sep_and_kleene_op(&mut trees, span.entire(), sess);
@@ -196,7 +217,10 @@
         // descend into the delimited set and further parse it.
         tokenstream::TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited(
             span,
-            Lrc::new(Delimited { delim, tts: parse(tts, expect_matchers, sess, node_id) }),
+            Lrc::new(Delimited {
+                delim,
+                tts: parse(tts, expect_matchers, sess, node_id, features),
+            }),
         ),
     }
 }
@@ -226,7 +250,7 @@
             Some(op) => Ok(Ok((op, token.span))),
             None => Ok(Err(token)),
         },
-        tree => Err(tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(span)),
+        tree => Err(tree.as_ref().map_or(span, tokenstream::TokenTree::span)),
     }
 }
 
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index ce19e81..d040539c 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -258,12 +258,9 @@
 
     fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
         match item.kind {
-            ast::ItemKind::MacCall(_) => return self.remove(item.id).make_items(),
-            ast::ItemKind::MacroDef(_) => return smallvec![item],
-            _ => {}
+            ast::ItemKind::MacCall(_) => self.remove(item.id).make_items(),
+            _ => noop_flat_map_item(item, self),
         }
-
-        noop_flat_map_item(item, self)
     }
 
     fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index e8e098b..02129e9 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -94,12 +94,7 @@
         let input = if item.pretty_printing_compatibility_hack() {
             TokenTree::token(token::Interpolated(Lrc::new(item)), DUMMY_SP).into()
         } else {
-            nt_to_tokenstream(
-                &item,
-                &ecx.sess.parse_sess,
-                DUMMY_SP,
-                CanSynthesizeMissingTokens::Yes,
-            )
+            nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::Yes)
         };
 
         let server = proc_macro_server::Rustc::new(ecx);
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 02ae842..b6195d3 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -179,7 +179,7 @@
                 {
                     TokenTree::Ident(Ident::new(sess, name.name, is_raw, name.span))
                 } else {
-                    let stream = nt_to_tokenstream(&nt, sess, span, CanSynthesizeMissingTokens::No);
+                    let stream = nt_to_tokenstream(&nt, sess, CanSynthesizeMissingTokens::No);
                     TokenTree::Group(Group {
                         delimiter: Delimiter::None,
                         stream,
diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs
index 6993ce5..f2345ff 100644
--- a/compiler/rustc_expand/src/tests.rs
+++ b/compiler/rustc_expand/src/tests.rs
@@ -92,7 +92,7 @@
 
 /// Advances the given peekable `Iterator` until it reaches a non-whitespace character.
 fn scan_for_non_ws_or_end<I: Iterator<Item = char>>(iter: &mut Peekable<I>) {
-    while iter.peek().copied().map(|c| rustc_lexer::is_whitespace(c)) == Some(true) {
+    while iter.peek().copied().map(rustc_lexer::is_whitespace) == Some(true) {
         iter.next();
     }
 }
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index d60ae8e..3b54ffb 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -581,7 +581,7 @@
     /// Allows `if let` guard in match arms.
     (active, if_let_guard, "1.47.0", Some(51114), None),
 
-    /// Allows non-trivial generic constants which have to be manually propageted upwards.
+    /// Allows non-trivial generic constants which have to be manually propagated upwards.
     (active, const_evaluatable_checked, "1.48.0", Some(76560), None),
 
     /// Allows basic arithmetic on floating point types in a `const fn`.
@@ -620,6 +620,15 @@
     /// Allows arbitrary expressions in key-value attributes at parse time.
     (active, extended_key_value_attributes, "1.50.0", Some(78835), None),
 
+    /// `:pat2018` and `:pat2021` macro matchers.
+    (active, edition_macro_pats, "1.51.0", Some(54883), None),
+
+    /// Allows const generics to have default values (e.g. `struct Foo<const N: usize = 3>(...);`).
+    (active, const_generics_defaults, "1.51.0", Some(44580), None),
+
+    /// Allows references to types with interior mutability within constants
+    (active, const_refs_to_cell, "1.51.0", Some(80384), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
@@ -644,6 +653,7 @@
     sym::repr128,
     sym::unsized_locals,
     sym::capture_disjoint_fields,
+    sym::const_generics_defaults,
 ];
 
 /// Some features are not allowed to be used together at the same time, if
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index fa8edba..3ed5320 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -442,7 +442,7 @@
     // Internal attributes, Macro related:
     // ==========================================================================
 
-    rustc_attr!(rustc_builtin_macro, AssumedUsed, template!(Word), IMPL_DETAIL),
+    rustc_attr!(rustc_builtin_macro, AssumedUsed, template!(Word, NameValueStr: "name"), IMPL_DETAIL),
     rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE),
     rustc_attr!(
         rustc_macro_transparency, AssumedUsed,
diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs
index 7742961..87e97c7 100644
--- a/compiler/rustc_fs_util/src/lib.rs
+++ b/compiler/rustc_fs_util/src/lib.rs
@@ -62,8 +62,10 @@
 pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Q) -> io::Result<LinkOrCopy> {
     let p = p.as_ref();
     let q = q.as_ref();
-    if q.exists() {
-        fs::remove_file(&q)?;
+    match fs::remove_file(&q) {
+        Ok(()) => (),
+        Err(err) if err.kind() == io::ErrorKind::NotFound => (),
+        Err(err) => return Err(err),
     }
 
     match fs::hard_link(p, q) {
diff --git a/compiler/rustc_graphviz/src/tests.rs b/compiler/rustc_graphviz/src/tests.rs
index 055e131..70b8197 100644
--- a/compiler/rustc_graphviz/src/tests.rs
+++ b/compiler/rustc_graphviz/src/tests.rs
@@ -55,7 +55,7 @@
     fn to_opt_strs(self) -> Vec<Option<&'static str>> {
         match self {
             UnlabelledNodes(len) => vec![None; len],
-            AllNodesLabelled(lbls) => lbls.into_iter().map(|l| Some(l)).collect(),
+            AllNodesLabelled(lbls) => lbls.into_iter().map(Some).collect(),
             SomeNodesLabelled(lbls) => lbls.into_iter().collect(),
         }
     }
diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml
index b24c208..c141654 100644
--- a/compiler/rustc_hir/Cargo.toml
+++ b/compiler/rustc_hir/Cargo.toml
@@ -9,6 +9,7 @@
 
 [dependencies]
 rustc_target = { path = "../rustc_target" }
+rustc_feature = { path = "../rustc_feature" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_index = { path = "../rustc_index" }
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 4ede9d6..a81eb74 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -5,6 +5,7 @@
 use rustc_ast::NodeId;
 use rustc_macros::HashStable_Generic;
 use rustc_span::hygiene::MacroKind;
+use rustc_span::Symbol;
 
 use std::array::IntoIter;
 use std::fmt::Debug;
@@ -34,7 +35,7 @@
 #[derive(HashStable_Generic)]
 pub enum NonMacroAttrKind {
     /// Single-segment attribute defined by the language (`#[inline]`)
-    Builtin,
+    Builtin(Symbol),
     /// Multi-segment custom attribute living in a "tool module" (`#[rustfmt::skip]`).
     Tool,
     /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
@@ -371,7 +372,7 @@
 impl NonMacroAttrKind {
     pub fn descr(self) -> &'static str {
         match self {
-            NonMacroAttrKind::Builtin => "built-in attribute",
+            NonMacroAttrKind::Builtin(..) => "built-in attribute",
             NonMacroAttrKind::Tool => "tool attribute",
             NonMacroAttrKind::DeriveHelper | NonMacroAttrKind::DeriveHelperCompat => {
                 "derive helper attribute"
@@ -393,7 +394,7 @@
             NonMacroAttrKind::Tool
             | NonMacroAttrKind::DeriveHelper
             | NonMacroAttrKind::DeriveHelperCompat => true,
-            NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered => false,
+            NonMacroAttrKind::Builtin(..) | NonMacroAttrKind::Registered => false,
         }
     }
 }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 4ba1416..3673e5c 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -11,9 +11,9 @@
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
 use rustc_macros::HashStable_Generic;
-use rustc_span::def_id::LocalDefId;
-use rustc_span::source_map::Spanned;
+use rustc_span::source_map::{SourceMap, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{def_id::LocalDefId, BytePos};
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use rustc_target::asm::InlineAsmRegOrRegClass;
 use rustc_target::spec::abi::Abi;
@@ -231,7 +231,11 @@
         PathSegment { ident, hir_id: None, res: None, infer_args: true, args: None }
     }
 
-    pub fn generic_args(&self) -> &GenericArgs<'hir> {
+    pub fn invalid() -> Self {
+        Self::from_ident(Ident::invalid())
+    }
+
+    pub fn args(&self) -> &GenericArgs<'hir> {
         if let Some(ref args) = self.args {
             args
         } else {
@@ -275,6 +279,10 @@
         matches!(self, GenericArg::Const(_))
     }
 
+    pub fn is_synthetic(&self) -> bool {
+        matches!(self, GenericArg::Lifetime(lifetime) if lifetime.name.ident() == Ident::invalid())
+    }
+
     pub fn descr(&self) -> &'static str {
         match self {
             GenericArg::Lifetime(_) => "lifetime",
@@ -283,11 +291,11 @@
         }
     }
 
-    pub fn short_descr(&self) -> &'static str {
+    pub fn to_ord(&self, feats: &rustc_feature::Features) -> ast::ParamKindOrd {
         match self {
-            GenericArg::Lifetime(_) => "lifetime",
-            GenericArg::Type(_) => "type",
-            GenericArg::Const(_) => "const",
+            GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime,
+            GenericArg::Type(_) => ast::ParamKindOrd::Type,
+            GenericArg::Const(_) => ast::ParamKindOrd::Const { unordered: feats.const_generics },
         }
     }
 }
@@ -344,6 +352,39 @@
 
         own_counts
     }
+
+    pub fn span(&self) -> Option<Span> {
+        self.args
+            .iter()
+            .filter(|arg| !arg.is_synthetic())
+            .map(|arg| arg.span())
+            .fold_first(|span1, span2| span1.to(span2))
+    }
+
+    /// Returns span encompassing arguments and their surrounding `<>` or `()`
+    pub fn span_ext(&self, sm: &SourceMap) -> Option<Span> {
+        let mut span = self.span()?;
+
+        let (o, c) = if self.parenthesized { ('(', ')') } else { ('<', '>') };
+
+        if let Ok(snippet) = sm.span_to_snippet(span) {
+            let snippet = snippet.as_bytes();
+
+            if snippet[0] != (o as u8) || snippet[snippet.len() - 1] != (c as u8) {
+                span = sm.span_extend_to_prev_char(span, o, true);
+                span = span.with_lo(span.lo() - BytePos(1));
+
+                span = sm.span_extend_to_next_char(span, c, true);
+                span = span.with_hi(span.hi() + BytePos(1));
+            }
+        }
+
+        Some(span)
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.args.is_empty()
+    }
 }
 
 /// A modifier on a bound, currently this is only used for `?Sized`, where the
@@ -378,9 +419,9 @@
 
     pub fn span(&self) -> Span {
         match self {
-            &GenericBound::Trait(ref t, ..) => t.span,
-            &GenericBound::LangItemTrait(_, span, ..) => span,
-            &GenericBound::Outlives(ref l) => l.span,
+            GenericBound::Trait(t, ..) => t.span,
+            GenericBound::LangItemTrait(_, span, ..) => *span,
+            GenericBound::Outlives(l) => l.span,
         }
     }
 }
@@ -418,6 +459,8 @@
     },
     Const {
         ty: &'hir Ty<'hir>,
+        /// Optional default value for the const generic param
+        default: Option<AnonConst>,
     },
 }
 
@@ -518,7 +561,7 @@
     ///  in `fn foo<T>(t: T) where T: Foo,` so we don't suggest two trailing commas.
     pub fn tail_span_for_suggestion(&self) -> Span {
         let end = self.span_for_predicates_or_empty_place().shrink_to_hi();
-        self.predicates.last().map(|p| p.span()).unwrap_or(end).shrink_to_hi().to(end)
+        self.predicates.last().map_or(end, |p| p.span()).shrink_to_hi().to(end)
     }
 }
 
@@ -536,9 +579,9 @@
 impl WherePredicate<'_> {
     pub fn span(&self) -> Span {
         match self {
-            &WherePredicate::BoundPredicate(ref p) => p.span,
-            &WherePredicate::RegionPredicate(ref p) => p.span,
-            &WherePredicate::EqPredicate(ref p) => p.span,
+            WherePredicate::BoundPredicate(p) => p.span,
+            WherePredicate::RegionPredicate(p) => p.span,
+            WherePredicate::EqPredicate(p) => p.span,
         }
     }
 }
@@ -760,9 +803,9 @@
     pub default_binding_modes: bool,
 }
 
-impl Pat<'_> {
+impl<'hir> Pat<'hir> {
     // FIXME(#19596) this is a workaround, but there should be a better way
-    fn walk_short_(&self, it: &mut impl FnMut(&Pat<'_>) -> bool) -> bool {
+    fn walk_short_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) -> bool {
         if !it(self) {
             return false;
         }
@@ -785,12 +828,12 @@
     /// Note that when visiting e.g. `Tuple(ps)`,
     /// if visiting `ps[0]` returns `false`,
     /// then `ps[1]` will not be visited.
-    pub fn walk_short(&self, mut it: impl FnMut(&Pat<'_>) -> bool) -> bool {
+    pub fn walk_short(&self, mut it: impl FnMut(&Pat<'hir>) -> bool) -> bool {
         self.walk_short_(&mut it)
     }
 
     // FIXME(#19596) this is a workaround, but there should be a better way
-    fn walk_(&self, it: &mut impl FnMut(&Pat<'_>) -> bool) {
+    fn walk_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) {
         if !it(self) {
             return;
         }
@@ -810,7 +853,7 @@
     /// Walk the pattern in left-to-right order.
     ///
     /// If `it(pat)` returns `false`, the children are not visited.
-    pub fn walk(&self, mut it: impl FnMut(&Pat<'_>) -> bool) {
+    pub fn walk(&self, mut it: impl FnMut(&Pat<'hir>) -> bool) {
         self.walk_(&mut it)
     }
 
@@ -1388,6 +1431,7 @@
             ExprKind::Lit(_) => ExprPrecedence::Lit,
             ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
             ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
+            ExprKind::If(..) => ExprPrecedence::If,
             ExprKind::Loop(..) => ExprPrecedence::Loop,
             ExprKind::Match(..) => ExprPrecedence::Match,
             ExprKind::Closure(..) => ExprPrecedence::Closure,
@@ -1449,6 +1493,7 @@
             | ExprKind::MethodCall(..)
             | ExprKind::Struct(..)
             | ExprKind::Tup(..)
+            | ExprKind::If(..)
             | ExprKind::Match(..)
             | ExprKind::Closure(..)
             | ExprKind::Block(..)
@@ -1565,6 +1610,10 @@
     /// This construct only exists to tweak the drop order in HIR lowering.
     /// An example of that is the desugaring of `for` loops.
     DropTemps(&'hir Expr<'hir>),
+    /// An `if` block, with an optional else block.
+    ///
+    /// I.e., `if <expr> { <expr> } else { <expr> }`.
+    If(&'hir Expr<'hir>, &'hir Expr<'hir>, Option<&'hir Expr<'hir>>),
     /// A conditionless loop (can be exited with `break`, `continue`, or `return`).
     ///
     /// I.e., `'label: loop { <block> }`.
@@ -1718,8 +1767,6 @@
 pub enum MatchSource {
     /// A `match _ { .. }`.
     Normal,
-    /// An `if _ { .. }` (optionally with `else { .. }`).
-    IfDesugar { contains_else_clause: bool },
     /// An `if let _ = _ { .. }` (optionally with `else { .. }`).
     IfLetDesugar { contains_else_clause: bool },
     /// An `if let _ = _ => { .. }` match guard.
@@ -1742,7 +1789,7 @@
         use MatchSource::*;
         match self {
             Normal => "match",
-            IfDesugar { .. } | IfLetDesugar { .. } | IfLetGuardDesugar => "if",
+            IfLetDesugar { .. } | IfLetGuardDesugar => "if",
             WhileDesugar | WhileLetDesugar => "while",
             ForLoopDesugar => "for",
             TryDesugar => "?",
@@ -2552,22 +2599,25 @@
     TraitAlias(Generics<'hir>, GenericBounds<'hir>),
 
     /// An implementation, e.g., `impl<A> Trait for Foo { .. }`.
-    Impl {
-        unsafety: Unsafety,
-        polarity: ImplPolarity,
-        defaultness: Defaultness,
-        // We do not put a `Span` in `Defaultness` because it breaks foreign crate metadata
-        // decoding as `Span`s cannot be decoded when a `Session` is not available.
-        defaultness_span: Option<Span>,
-        constness: Constness,
-        generics: Generics<'hir>,
+    Impl(Impl<'hir>),
+}
 
-        /// The trait being implemented, if any.
-        of_trait: Option<TraitRef<'hir>>,
+#[derive(Debug, HashStable_Generic)]
+pub struct Impl<'hir> {
+    pub unsafety: Unsafety,
+    pub polarity: ImplPolarity,
+    pub defaultness: Defaultness,
+    // We do not put a `Span` in `Defaultness` because it breaks foreign crate metadata
+    // decoding as `Span`s cannot be decoded when a `Session` is not available.
+    pub defaultness_span: Option<Span>,
+    pub constness: Constness,
+    pub generics: Generics<'hir>,
 
-        self_ty: &'hir Ty<'hir>,
-        items: &'hir [ImplItemRef<'hir>],
-    },
+    /// The trait being implemented, if any.
+    pub of_trait: Option<TraitRef<'hir>>,
+
+    pub self_ty: &'hir Ty<'hir>,
+    pub items: &'hir [ImplItemRef<'hir>],
 }
 
 impl ItemKind<'_> {
@@ -2580,7 +2630,7 @@
             | ItemKind::Struct(_, ref generics)
             | ItemKind::Union(_, ref generics)
             | ItemKind::Trait(_, _, ref generics, _, _)
-            | ItemKind::Impl { ref generics, .. } => generics,
+            | ItemKind::Impl(Impl { ref generics, .. }) => generics,
             _ => return None,
         })
     }
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 03c8b17..8707a84 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -611,7 +611,7 @@
             // `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 {
+        ItemKind::Impl(Impl {
             unsafety: _,
             defaultness: _,
             polarity: _,
@@ -621,7 +621,7 @@
             ref of_trait,
             ref self_ty,
             items,
-        } => {
+        }) => {
             visitor.visit_id(item.hir_id);
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_trait_ref, of_trait);
@@ -877,7 +877,12 @@
     match param.kind {
         GenericParamKind::Lifetime { .. } => {}
         GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default),
-        GenericParamKind::Const { ref ty } => visitor.visit_ty(ty),
+        GenericParamKind::Const { ref ty, ref default } => {
+            visitor.visit_ty(ty);
+            if let Some(ref default) = default {
+                visitor.visit_anon_const(default);
+            }
+        }
     }
     walk_list!(visitor, visit_param_bound, param.bounds);
 }
@@ -891,8 +896,8 @@
     visitor: &mut V,
     predicate: &'v WherePredicate<'v>,
 ) {
-    match predicate {
-        &WherePredicate::BoundPredicate(WhereBoundPredicate {
+    match *predicate {
+        WherePredicate::BoundPredicate(WhereBoundPredicate {
             ref bounded_ty,
             bounds,
             bound_generic_params,
@@ -902,11 +907,11 @@
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_generic_param, bound_generic_params);
         }
-        &WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime, bounds, .. }) => {
+        WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime, bounds, .. }) => {
             visitor.visit_lifetime(lifetime);
             walk_list!(visitor, visit_param_bound, bounds);
         }
-        &WherePredicate::EqPredicate(WhereEqPredicate {
+        WherePredicate::EqPredicate(WhereEqPredicate {
             hir_id, ref lhs_ty, ref rhs_ty, ..
         }) => {
             visitor.visit_id(hir_id);
@@ -1141,6 +1146,11 @@
         ExprKind::DropTemps(ref subexpression) => {
             visitor.visit_expr(subexpression);
         }
+        ExprKind::If(ref cond, ref then, ref else_opt) => {
+            visitor.visit_expr(cond);
+            visitor.visit_expr(then);
+            walk_list!(visitor, visit_expr, else_opt);
+        }
         ExprKind::Loop(ref block, ref opt_label, _) => {
             walk_list!(visitor, visit_label, opt_label);
             visitor.visit_block(block);
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 3e4eb9e..e82ea31 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -157,7 +157,7 @@
 }
 
 language_item_table! {
-//  Variant name,            Name,                    Method name,             Target;
+//  Variant name,            Name,                     Method name,                Target;
     Bool,                    sym::bool,                bool_impl,                  Target::Impl;
     Char,                    sym::char,                char_impl,                  Target::Impl;
     Str,                     sym::str,                 str_impl,                   Target::Impl;
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 9d931b3..8b55ec6 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -7,6 +7,7 @@
 #![feature(const_fn)] // For the unsizing cast on `&[]`
 #![feature(const_panic)]
 #![feature(in_band_lifetimes)]
+#![feature(iterator_fold_self)]
 #![feature(once_cell)]
 #![feature(or_patterns)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 0b5eb1d..a3ab1d9 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -138,9 +138,6 @@
 }
 
 impl<'a> PrintState<'a> for State<'a> {
-    fn insert_extra_parens(&self) -> bool {
-        true
-    }
     fn comments(&mut self) -> &mut Option<Comments<'a>> {
         &mut self.comments
     }
@@ -687,7 +684,7 @@
                 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(hir::Impl {
                 unsafety,
                 polarity,
                 defaultness,
@@ -697,7 +694,7 @@
                 ref of_trait,
                 ref self_ty,
                 items,
-            } => {
+            }) => {
                 self.head("");
                 self.print_visibility(&item.vis);
                 self.print_defaultness(defaultness);
@@ -1083,6 +1080,50 @@
         self.ann.post(self, AnnNode::Block(blk))
     }
 
+    fn print_else(&mut self, els: Option<&hir::Expr<'_>>) {
+        match els {
+            Some(_else) => {
+                match _else.kind {
+                    // "another else-if"
+                    hir::ExprKind::If(ref i, ref then, ref e) => {
+                        self.cbox(INDENT_UNIT - 1);
+                        self.ibox(0);
+                        self.s.word(" else if ");
+                        self.print_expr_as_cond(&i);
+                        self.s.space();
+                        self.print_expr(&then);
+                        self.print_else(e.as_ref().map(|e| &**e))
+                    }
+                    // "final else"
+                    hir::ExprKind::Block(ref b, _) => {
+                        self.cbox(INDENT_UNIT - 1);
+                        self.ibox(0);
+                        self.s.word(" else ");
+                        self.print_block(&b)
+                    }
+                    // BLEAH, constraints would be great here
+                    _ => {
+                        panic!("print_if saw if with weird alternative");
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
+
+    pub fn print_if(
+        &mut self,
+        test: &hir::Expr<'_>,
+        blk: &hir::Expr<'_>,
+        elseopt: Option<&hir::Expr<'_>>,
+    ) {
+        self.head("if");
+        self.print_expr_as_cond(test);
+        self.s.space();
+        self.print_expr(blk);
+        self.print_else(elseopt)
+    }
+
     pub fn print_anon_const(&mut self, constant: &hir::AnonConst) {
         self.ann.nested(self, Nested::Body(constant.body))
     }
@@ -1216,7 +1257,7 @@
         self.s.word(".");
         self.print_ident(segment.ident);
 
-        let generic_args = segment.generic_args();
+        let generic_args = segment.args();
         if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() {
             self.print_generic_args(generic_args, segment.infer_args, true);
         }
@@ -1352,6 +1393,9 @@
                 // Print `}`:
                 self.bclose_maybe_open(expr.span, true);
             }
+            hir::ExprKind::If(ref test, ref blk, ref elseopt) => {
+                self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e));
+            }
             hir::ExprKind::Loop(ref blk, opt_label, _) => {
                 if let Some(label) = opt_label {
                     self.print_ident(label.ident);
@@ -1664,11 +1708,7 @@
             }
             if segment.ident.name != kw::PathRoot {
                 self.print_ident(segment.ident);
-                self.print_generic_args(
-                    segment.generic_args(),
-                    segment.infer_args,
-                    colons_before_params,
-                );
+                self.print_generic_args(segment.args(), segment.infer_args, colons_before_params);
             }
         }
     }
@@ -1676,7 +1716,7 @@
     pub fn print_path_segment(&mut self, segment: &hir::PathSegment<'_>) {
         if segment.ident.name != kw::PathRoot {
             self.print_ident(segment.ident);
-            self.print_generic_args(segment.generic_args(), segment.infer_args, false);
+            self.print_generic_args(segment.args(), segment.infer_args, false);
         }
     }
 
@@ -1696,7 +1736,7 @@
                     if segment.ident.name != kw::PathRoot {
                         self.print_ident(segment.ident);
                         self.print_generic_args(
-                            segment.generic_args(),
+                            segment.args(),
                             segment.infer_args,
                             colons_before_params,
                         );
@@ -1708,7 +1748,7 @@
                 let item_segment = path.segments.last().unwrap();
                 self.print_ident(item_segment.ident);
                 self.print_generic_args(
-                    item_segment.generic_args(),
+                    item_segment.args(),
                     item_segment.infer_args,
                     colons_before_params,
                 )
@@ -1728,7 +1768,7 @@
                 self.s.word("::");
                 self.print_ident(item_segment.ident);
                 self.print_generic_args(
-                    item_segment.generic_args(),
+                    item_segment.args(),
                     item_segment.infer_args,
                     colons_before_params,
                 )
@@ -2205,9 +2245,12 @@
                     self.print_type(&default)
                 }
             }
-            GenericParamKind::Const { ref ty } => {
+            GenericParamKind::Const { ref ty, ref default } => {
                 self.word_space(":");
-                self.print_type(ty)
+                self.print_type(ty);
+                if let Some(ref _default) = default {
+                    // FIXME(const_generics_defaults): print the `default` value here
+                }
             }
         }
     }
@@ -2230,19 +2273,19 @@
             }
 
             match predicate {
-                &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
-                    ref bound_generic_params,
-                    ref bounded_ty,
+                hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
+                    bound_generic_params,
+                    bounded_ty,
                     bounds,
                     ..
                 }) => {
                     self.print_formal_generic_params(bound_generic_params);
                     self.print_type(&bounded_ty);
-                    self.print_bounds(":", bounds);
+                    self.print_bounds(":", *bounds);
                 }
-                &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
-                    ref lifetime,
-                    ref bounds,
+                hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
+                    lifetime,
+                    bounds,
                     ..
                 }) => {
                     self.print_lifetime(lifetime);
@@ -2261,10 +2304,8 @@
                         }
                     }
                 }
-                &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
-                    ref lhs_ty,
-                    ref rhs_ty,
-                    ..
+                hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
+                    lhs_ty, rhs_ty, ..
                 }) => {
                     self.print_type(lhs_ty);
                     self.s.space();
@@ -2435,7 +2476,13 @@
 //
 // Duplicated from `parse::classify`, but adapted for the HIR.
 fn expr_requires_semi_to_be_stmt(e: &hir::Expr<'_>) -> bool {
-    !matches!(e.kind, hir::ExprKind::Match(..) | hir::ExprKind::Block(..) | hir::ExprKind::Loop(..))
+    !matches!(
+        e.kind,
+        hir::ExprKind::If(..)
+            | hir::ExprKind::Match(..)
+            | hir::ExprKind::Block(..)
+            | hir::ExprKind::Loop(..)
+    )
 }
 
 /// This statement requires a semicolon after it.
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs
index 9b4388c..f39a92b 100644
--- a/compiler/rustc_incremental/src/assert_dep_graph.rs
+++ b/compiler/rustc_incremental/src/assert_dep_graph.rs
@@ -310,13 +310,13 @@
     sources: &Option<FxHashSet<&'q DepNode>>,
     targets: &Option<FxHashSet<&'q DepNode>>,
 ) -> FxHashSet<&'q DepNode> {
-    if let &Some(ref sources) = sources {
-        if let &Some(ref targets) = targets {
+    if let Some(sources) = sources {
+        if let Some(targets) = targets {
             walk_between(query, sources, targets)
         } else {
             walk_nodes(query, sources, OUTGOING)
         }
-    } else if let &Some(ref targets) = targets {
+    } else if let Some(targets) = targets {
         walk_nodes(query, targets, INCOMING)
     } else {
         query.nodes().into_iter().collect()
diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs
index a80c4be..95456c0 100644
--- a/compiler/rustc_incremental/src/lib.rs
+++ b/compiler/rustc_incremental/src/lib.rs
@@ -17,7 +17,6 @@
 pub use assert_dep_graph::assert_dep_graph;
 pub use persist::copy_cgu_workproduct_to_incr_comp_cache_dir;
 pub use persist::delete_workproduct_files;
-pub use persist::dep_graph_tcx_init;
 pub use persist::finalize_session_directory;
 pub use persist::garbage_collect_session_directories;
 pub use persist::in_incr_comp_dir;
diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs
index e185ee2..087f83c 100644
--- a/compiler/rustc_incremental/src/persist/file_format.rs
+++ b/compiler/rustc_incremental/src/persist/file_format.rs
@@ -14,7 +14,7 @@
 use std::io::{self, Read};
 use std::path::Path;
 
-use rustc_serialize::opaque::Encoder;
+use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 
 /// The first few bytes of files generated by incremental compilation.
 const FILE_MAGIC: &[u8] = b"RSIC";
@@ -27,15 +27,17 @@
 /// the Git commit hash.
 const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
 
-pub fn write_file_header(stream: &mut Encoder, nightly_build: bool) {
-    stream.emit_raw_bytes(FILE_MAGIC);
-    stream
-        .emit_raw_bytes(&[(HEADER_FORMAT_VERSION >> 0) as u8, (HEADER_FORMAT_VERSION >> 8) as u8]);
+pub fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) -> FileEncodeResult {
+    stream.emit_raw_bytes(FILE_MAGIC)?;
+    stream.emit_raw_bytes(&[
+        (HEADER_FORMAT_VERSION >> 0) as u8,
+        (HEADER_FORMAT_VERSION >> 8) as u8,
+    ])?;
 
     let rustc_version = rustc_version(nightly_build);
     assert_eq!(rustc_version.len(), (rustc_version.len() as u8) as usize);
-    stream.emit_raw_bytes(&[rustc_version.len() as u8]);
-    stream.emit_raw_bytes(rustc_version.as_bytes());
+    stream.emit_raw_bytes(&[rustc_version.len() as u8])?;
+    stream.emit_raw_bytes(rustc_version.as_bytes())
 }
 
 /// Reads the contents of a file with a file header as defined in this module.
@@ -52,11 +54,11 @@
     path: &Path,
     nightly_build: bool,
 ) -> io::Result<Option<(Vec<u8>, usize)>> {
-    if !path.exists() {
-        return Ok(None);
-    }
-
-    let data = fs::read(path)?;
+    let data = match fs::read(path) {
+        Ok(data) => data,
+        Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(None),
+        Err(err) => return Err(err),
+    };
 
     let mut file = io::Cursor::new(data);
 
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 9fdf0a5..7a1976b 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -922,22 +922,24 @@
 /// before passing it to std::fs::remove_dir_all(). This will convert the path
 /// into the '\\?\' format, which supports much longer paths.
 fn safe_remove_dir_all(p: &Path) -> io::Result<()> {
-    if p.exists() {
-        let canonicalized = p.canonicalize()?;
-        std_fs::remove_dir_all(canonicalized)
-    } else {
-        Ok(())
-    }
+    let canonicalized = match std_fs::canonicalize(p) {
+        Ok(canonicalized) => canonicalized,
+        Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(()),
+        Err(err) => return Err(err),
+    };
+
+    std_fs::remove_dir_all(canonicalized)
 }
 
 fn safe_remove_file(p: &Path) -> io::Result<()> {
-    if p.exists() {
-        let canonicalized = p.canonicalize()?;
-        match std_fs::remove_file(canonicalized) {
-            Err(ref err) if err.kind() == io::ErrorKind::NotFound => Ok(()),
-            result => result,
-        }
-    } else {
-        Ok(())
+    let canonicalized = match std_fs::canonicalize(p) {
+        Ok(canonicalized) => canonicalized,
+        Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(()),
+        Err(err) => return Err(err),
+    };
+
+    match std_fs::remove_file(canonicalized) {
+        Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(()),
+        result => result,
     }
 }
diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs
index 35428dc..0add0c5 100644
--- a/compiler/rustc_incremental/src/persist/load.rs
+++ b/compiler/rustc_incremental/src/persist/load.rs
@@ -4,7 +4,6 @@
 use rustc_hir::definitions::Definitions;
 use rustc_middle::dep_graph::{PreviousDepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
 use rustc_middle::ty::query::OnDiskCache;
-use rustc_middle::ty::TyCtxt;
 use rustc_serialize::opaque::Decoder;
 use rustc_serialize::Decodable as RustcDecodable;
 use rustc_session::Session;
@@ -15,14 +14,6 @@
 use super::fs::*;
 use super::work_product;
 
-pub fn dep_graph_tcx_init(tcx: TyCtxt<'_>) {
-    if !tcx.dep_graph.is_fully_enabled() {
-        return;
-    }
-
-    tcx.allocate_metadata_dep_nodes();
-}
-
 type WorkProductMap = FxHashMap<WorkProductId, WorkProduct>;
 
 pub enum LoadResult<T> {
diff --git a/compiler/rustc_incremental/src/persist/mod.rs b/compiler/rustc_incremental/src/persist/mod.rs
index 7bc3b47..8821b34 100644
--- a/compiler/rustc_incremental/src/persist/mod.rs
+++ b/compiler/rustc_incremental/src/persist/mod.rs
@@ -15,7 +15,6 @@
 pub use fs::in_incr_comp_dir;
 pub use fs::in_incr_comp_dir_sess;
 pub use fs::prepare_session_directory;
-pub use load::dep_graph_tcx_init;
 pub use load::load_query_result_cache;
 pub use load::LoadResult;
 pub use load::{load_dep_graph, DepGraphFuture};
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 102a77e..f63cdfc 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -2,10 +2,11 @@
 use rustc_data_structures::sync::join;
 use rustc_middle::dep_graph::{DepGraph, DepKind, WorkProduct, WorkProductId};
 use rustc_middle::ty::TyCtxt;
-use rustc_serialize::opaque::Encoder;
+use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_serialize::Encodable as RustcEncodable;
 use rustc_session::Session;
 use std::fs;
+use std::io;
 use std::path::PathBuf;
 
 use super::data::*;
@@ -32,12 +33,12 @@
         join(
             move || {
                 sess.time("incr_comp_persist_result_cache", || {
-                    save_in(sess, query_cache_path, |e| encode_query_cache(tcx, e));
+                    save_in(sess, query_cache_path, "query cache", |e| encode_query_cache(tcx, e));
                 });
             },
             || {
                 sess.time("incr_comp_persist_dep_graph", || {
-                    save_in(sess, dep_graph_path, |e| {
+                    save_in(sess, dep_graph_path, "dependency graph", |e| {
                         sess.time("incr_comp_encode_dep_graph", || encode_dep_graph(tcx, e))
                     });
                 });
@@ -64,7 +65,7 @@
     debug!("save_work_product_index()");
     dep_graph.assert_ignored();
     let path = work_products_path(sess);
-    save_in(sess, path, |e| encode_work_product_index(&new_work_products, e));
+    save_in(sess, path, "work product index", |e| encode_work_product_index(&new_work_products, e));
 
     // We also need to clean out old work-products, as not all of them are
     // deleted during invalidation. Some object files don't change their
@@ -91,52 +92,61 @@
     });
 }
 
-fn save_in<F>(sess: &Session, path_buf: PathBuf, encode: F)
+fn save_in<F>(sess: &Session, path_buf: PathBuf, name: &str, encode: F)
 where
-    F: FnOnce(&mut Encoder),
+    F: FnOnce(&mut FileEncoder) -> FileEncodeResult,
 {
     debug!("save: storing data in {}", path_buf.display());
 
-    // delete the old dep-graph, if any
+    // Delete the old file, if any.
     // Note: It's important that we actually delete the old file and not just
     // truncate and overwrite it, since it might be a shared hard-link, the
     // underlying data of which we don't want to modify
-    if path_buf.exists() {
-        match fs::remove_file(&path_buf) {
-            Ok(()) => {
-                debug!("save: remove old file");
-            }
-            Err(err) => {
-                sess.err(&format!(
-                    "unable to delete old dep-graph at `{}`: {}",
-                    path_buf.display(),
-                    err
-                ));
-                return;
-            }
+    match fs::remove_file(&path_buf) {
+        Ok(()) => {
+            debug!("save: remove old file");
         }
-    }
-
-    // generate the data in a memory buffer
-    let mut encoder = Encoder::new(Vec::new());
-    file_format::write_file_header(&mut encoder, sess.is_nightly_build());
-    encode(&mut encoder);
-
-    // write the data out
-    let data = encoder.into_inner();
-    match fs::write(&path_buf, data) {
-        Ok(_) => {
-            debug!("save: data written to disk successfully");
-        }
+        Err(err) if err.kind() == io::ErrorKind::NotFound => (),
         Err(err) => {
-            sess.err(&format!("failed to write dep-graph to `{}`: {}", path_buf.display(), err));
+            sess.err(&format!(
+                "unable to delete old {} at `{}`: {}",
+                name,
+                path_buf.display(),
+                err
+            ));
+            return;
         }
     }
+
+    let mut encoder = match FileEncoder::new(&path_buf) {
+        Ok(encoder) => encoder,
+        Err(err) => {
+            sess.err(&format!("failed to create {} at `{}`: {}", name, path_buf.display(), err));
+            return;
+        }
+    };
+
+    if let Err(err) = file_format::write_file_header(&mut encoder, sess.is_nightly_build()) {
+        sess.err(&format!("failed to write {} header to `{}`: {}", name, path_buf.display(), err));
+        return;
+    }
+
+    if let Err(err) = encode(&mut encoder) {
+        sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err));
+        return;
+    }
+
+    if let Err(err) = encoder.flush() {
+        sess.err(&format!("failed to flush {} to `{}`: {}", name, path_buf.display(), err));
+        return;
+    }
+
+    debug!("save: data written to disk successfully");
 }
 
-fn encode_dep_graph(tcx: TyCtxt<'_>, encoder: &mut Encoder) {
+fn encode_dep_graph(tcx: TyCtxt<'_>, encoder: &mut FileEncoder) -> FileEncodeResult {
     // First encode the commandline arguments hash
-    tcx.sess.opts.dep_tracking_hash().encode(encoder).unwrap();
+    tcx.sess.opts.dep_tracking_hash().encode(encoder)?;
 
     // Encode the graph data.
     let serialized_graph =
@@ -214,15 +224,13 @@
         println!("[incremental]");
     }
 
-    tcx.sess.time("incr_comp_encode_serialized_dep_graph", || {
-        serialized_graph.encode(encoder).unwrap();
-    });
+    tcx.sess.time("incr_comp_encode_serialized_dep_graph", || serialized_graph.encode(encoder))
 }
 
 fn encode_work_product_index(
     work_products: &FxHashMap<WorkProductId, WorkProduct>,
-    encoder: &mut Encoder,
-) {
+    encoder: &mut FileEncoder,
+) -> FileEncodeResult {
     let serialized_products: Vec<_> = work_products
         .iter()
         .map(|(id, work_product)| SerializedWorkProduct {
@@ -231,11 +239,9 @@
         })
         .collect();
 
-    serialized_products.encode(encoder).unwrap();
+    serialized_products.encode(encoder)
 }
 
-fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut Encoder) {
-    tcx.sess.time("incr_comp_serialize_result_cache", || {
-        tcx.serialize_query_result_cache(encoder).unwrap();
-    })
+fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut FileEncoder) -> FileEncodeResult {
+    tcx.sess.time("incr_comp_serialize_result_cache", || tcx.serialize_query_result_cache(encoder))
 }
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 71ce50f..4357eb3 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -530,10 +530,10 @@
 
             let atom = match k1.unpack() {
                 GenericArgKind::Lifetime(r1) => {
-                    ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r1, r2))
+                    ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
                 }
                 GenericArgKind::Type(t1) => {
-                    ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(t1, r2))
+                    ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(t1, r2))
                 }
                 GenericArgKind::Const(..) => {
                     // Consts cannot outlive one another, so we don't expect to
@@ -541,8 +541,7 @@
                     span_bug!(cause.span, "unexpected const outlives {:?}", constraint);
                 }
             };
-            let predicate =
-                predicate.rebind(atom).potentially_quantified(self.tcx, ty::PredicateKind::ForAll);
+            let predicate = predicate.rebind(atom).to_predicate(self.tcx);
 
             Obligation::new(cause.clone(), param_env, predicate)
         })
@@ -664,7 +663,7 @@
         self.obligations.push(Obligation {
             cause: self.cause.clone(),
             param_env: self.param_env,
-            predicate: ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(sup, sub))
+            predicate: ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(sup, sub))
                 .to_predicate(self.infcx.tcx),
             recursion_depth: 0,
         });
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index e38eebe..b344086 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -358,7 +358,7 @@
             self.obligations.push(Obligation::new(
                 self.trace.cause.clone(),
                 self.param_env,
-                ty::PredicateAtom::WellFormed(b_ty.into()).to_predicate(self.infcx.tcx),
+                ty::PredicateKind::WellFormed(b_ty.into()).to_predicate(self.infcx.tcx),
             ));
         }
 
@@ -451,9 +451,9 @@
         b: &'tcx ty::Const<'tcx>,
     ) {
         let predicate = if a_is_expected {
-            ty::PredicateAtom::ConstEquate(a, b)
+            ty::PredicateKind::ConstEquate(a, b)
         } else {
-            ty::PredicateAtom::ConstEquate(b, a)
+            ty::PredicateKind::ConstEquate(b, a)
         };
         self.obligations.push(Obligation::new(
             self.trace.cause.clone(),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 6d6bf4b..c39daea 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -69,7 +69,7 @@
     subst::{Subst, SubstsRef},
     Region, Ty, TyCtxt, TypeFoldable,
 };
-use rustc_span::{BytePos, DesugaringKind, Pos, Span};
+use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span};
 use rustc_target::spec::abi;
 use std::ops::ControlFlow;
 use std::{cmp, fmt};
@@ -98,7 +98,7 @@
         // uh oh, hope no user ever sees THIS
         ty::ReEmpty(ui) => (format!("the empty lifetime in universe {:?}", ui), None),
 
-        ty::RePlaceholder(_) => ("any other region".to_string(), None),
+        ty::RePlaceholder(_) => return,
 
         // FIXME(#13998) RePlaceholder should probably print like
         // ReFree rather than dumping Debug output on the user.
@@ -153,6 +153,7 @@
         Some(Node::Item(it)) => item_scope_tag(&it),
         Some(Node::TraitItem(it)) => trait_item_scope_tag(&it),
         Some(Node::ImplItem(it)) => impl_item_scope_tag(&it),
+        Some(Node::ForeignItem(it)) => foreign_item_scope_tag(&it),
         _ => unreachable!(),
     };
     let (prefix, span) = match *region {
@@ -233,6 +234,13 @@
     }
 }
 
+fn foreign_item_scope_tag(item: &hir::ForeignItem<'_>) -> &'static str {
+    match item.kind {
+        hir::ForeignItemKind::Fn(..) => "method body",
+        hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => "associated item",
+    }
+}
+
 fn explain_span(tcx: TyCtxt<'tcx>, heading: &str, span: Span) -> (String, Option<Span>) {
     let lo = tcx.sess.source_map().lookup_char_pos(span.lo());
     (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span))
@@ -907,7 +915,7 @@
                 self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
                 return Some(());
             }
-            if let &ty::Adt(def, _) = ta.kind() {
+            if let ty::Adt(def, _) = ta.kind() {
                 let path_ = self.tcx.def_path_str(def.did);
                 if path_ == other_path {
                     self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
@@ -950,7 +958,7 @@
                 ty::GenericParamDefKind::Type { has_default, .. } => {
                     Some((param.def_id, has_default))
                 }
-                ty::GenericParamDefKind::Const => None, // FIXME(const_generics:defaults)
+                ty::GenericParamDefKind::Const => None, // FIXME(const_generics_defaults)
             })
             .peekable();
         let has_default = {
@@ -1667,6 +1675,16 @@
         self.check_and_note_conflicting_crates(diag, terr);
         self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id());
 
+        if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values {
+            if let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind() {
+                if let Some(def_id) = def_id.as_local() {
+                    let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
+                    let span = self.tcx.hir().span(hir_id);
+                    diag.span_note(span, "this closure does not fulfill the lifetime requirements");
+                }
+            }
+        }
+
         // It reads better to have the error origin as the final
         // thing.
         self.note_error_origin(diag, cause, exp_found);
@@ -1688,8 +1706,8 @@
 
             for (predicate, _) in bounds {
                 let predicate = predicate.subst(self.tcx, substs);
-                if let ty::PredicateAtom::Projection(projection_predicate) =
-                    predicate.skip_binders()
+                if let ty::PredicateKind::Projection(projection_predicate) =
+                    predicate.kind().skip_binder()
                 {
                     if projection_predicate.projection_ty.item_def_id == item_def_id {
                         // We don't account for multiple `Future::Output = Ty` contraints.
@@ -2100,7 +2118,7 @@
                 let consider = format!(
                     "{} {}...",
                     msg,
-                    if type_param_span.map(|(_, _, is_impl_trait)| is_impl_trait).unwrap_or(false) {
+                    if type_param_span.map_or(false, |(_, _, is_impl_trait)| is_impl_trait) {
                         format!(" `{}` to `{}`", sub, bound_kind)
                     } else {
                         format!("`{}: {}`", bound_kind, sub)
@@ -2274,6 +2292,14 @@
         self.note_region_origin(&mut err, &sub_origin);
         err.emit();
     }
+
+    /// Determine whether an error associated with the given span and definition
+    /// should be treated as being caused by the implicit `From` conversion
+    /// within `?` desugaring.
+    pub fn is_try_conversion(&self, span: Span, trait_def_id: DefId) -> bool {
+        span.is_desugaring(DesugaringKind::QuestionMark)
+            && self.tcx.is_diagnostic_item(sym::from_trait, trait_def_id)
+    }
 }
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 373f0a6..aaab89a 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -3,13 +3,14 @@
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace};
+use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, Pat};
 use rustc_middle::hir::map::Map;
 use rustc_middle::infer::unify_key::ConstVariableOriginKind;
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
-use rustc_middle::ty::{self, DefIdTree, InferConst, Ty};
+use rustc_middle::ty::{self, DefIdTree, InferConst, Ty, TyCtxt};
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::kw;
 use rustc_span::Span;
@@ -25,6 +26,7 @@
     found_closure: Option<&'tcx Expr<'tcx>>,
     found_method_call: Option<&'tcx Expr<'tcx>>,
     found_exact_method_call: Option<&'tcx Expr<'tcx>>,
+    found_use_diagnostic: Option<UseDiagnostic<'tcx>>,
 }
 
 impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> {
@@ -39,44 +41,43 @@
             found_closure: None,
             found_method_call: None,
             found_exact_method_call: None,
+            found_use_diagnostic: None,
         }
     }
 
-    fn node_ty_contains_target(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
-        let ty_opt = self
-            .infcx
-            .in_progress_typeck_results
-            .and_then(|typeck_results| typeck_results.borrow().node_type_opt(hir_id));
-        match ty_opt {
-            Some(ty) => {
-                let ty = self.infcx.resolve_vars_if_possible(ty);
-                if ty.walk().any(|inner| {
-                    inner == self.target
-                        || match (inner.unpack(), self.target.unpack()) {
-                            (GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => {
-                                match (inner_ty.kind(), target_ty.kind()) {
-                                    (
-                                        &ty::Infer(ty::TyVar(a_vid)),
-                                        &ty::Infer(ty::TyVar(b_vid)),
-                                    ) => self
-                                        .infcx
-                                        .inner
-                                        .borrow_mut()
-                                        .type_variables()
-                                        .sub_unified(a_vid, b_vid),
-                                    _ => false,
-                                }
+    fn node_type_opt(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
+        self.infcx.in_progress_typeck_results?.borrow().node_type_opt(hir_id)
+    }
+
+    fn node_ty_contains_target(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
+        self.node_type_opt(hir_id).map(|ty| self.infcx.resolve_vars_if_possible(ty)).filter(|ty| {
+            ty.walk().any(|inner| {
+                inner == self.target
+                    || match (inner.unpack(), self.target.unpack()) {
+                        (GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => {
+                            use ty::{Infer, TyVar};
+                            match (inner_ty.kind(), target_ty.kind()) {
+                                (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => self
+                                    .infcx
+                                    .inner
+                                    .borrow_mut()
+                                    .type_variables()
+                                    .sub_unified(a_vid, b_vid),
+                                _ => false,
                             }
-                            _ => false,
                         }
-                }) {
-                    Some(ty)
-                } else {
-                    None
-                }
-            }
-            None => None,
-        }
+                        _ => false,
+                    }
+            })
+        })
+    }
+
+    /// Determine whether the expression, assumed to be the callee within a `Call`,
+    /// corresponds to the `From::from` emitted in desugaring of the `?` operator.
+    fn is_try_conversion(&self, callee: &Expr<'tcx>) -> bool {
+        self.infcx
+            .trait_def_from_hir_fn(callee.hir_id)
+            .map_or(false, |def_id| self.infcx.is_try_conversion(callee.span, def_id))
     }
 }
 
@@ -129,10 +130,23 @@
         // are handled specially, but instead they should be handled in `annotate_method_call`,
         // which currently doesn't work because this evaluates to `false` for const arguments.
         // See https://github.com/rust-lang/rust/pull/77758 for more details.
-        if self.node_ty_contains_target(expr.hir_id).is_some() {
+        if let Some(ty) = self.node_ty_contains_target(expr.hir_id) {
             match expr.kind {
                 ExprKind::Closure(..) => self.found_closure = Some(&expr),
                 ExprKind::MethodCall(..) => self.found_method_call = Some(&expr),
+
+                // If the given expression falls within the target span and is a
+                // `From::from(e)` call emitted during desugaring of the `?` operator,
+                // extract the types inferred before and after the call
+                ExprKind::Call(callee, [arg])
+                    if self.target_span.contains(expr.span)
+                        && self.found_use_diagnostic.is_none()
+                        && self.is_try_conversion(callee) =>
+                {
+                    self.found_use_diagnostic = self.node_type_opt(arg.hir_id).map(|pre_ty| {
+                        UseDiagnostic::TryConversion { pre_ty, post_ty: ty, span: callee.span }
+                    });
+                }
                 _ => {}
             }
         }
@@ -140,17 +154,70 @@
     }
 }
 
+/// An observation about the use site of a type to be emitted as an additional
+/// note in an inference failure error.
+enum UseDiagnostic<'tcx> {
+    /// Records the types inferred before and after `From::from` is called on the
+    /// error value within the desugaring of the `?` operator.
+    TryConversion { pre_ty: Ty<'tcx>, post_ty: Ty<'tcx>, span: Span },
+}
+
+impl UseDiagnostic<'_> {
+    /// Return a descriptor of the value at the use site
+    fn descr(&self) -> &'static str {
+        match self {
+            Self::TryConversion { .. } => "error for `?` operator",
+        }
+    }
+
+    /// Return a descriptor of the type at the use site
+    fn type_descr(&self) -> &'static str {
+        match self {
+            Self::TryConversion { .. } => "error type for `?` operator",
+        }
+    }
+
+    fn applies_to(&self, span: Span) -> bool {
+        match *self {
+            // In some cases the span for an inference failure due to try
+            // conversion contains the antecedent expression as well as the `?`
+            Self::TryConversion { span: s, .. } => span.contains(s) && span.hi() == s.hi(),
+        }
+    }
+
+    fn attach_note(&self, err: &mut DiagnosticBuilder<'_>) {
+        match *self {
+            Self::TryConversion { pre_ty, post_ty, .. } => {
+                let intro = "`?` implicitly converts the error value";
+
+                let msg = match (pre_ty.is_ty_infer(), post_ty.is_ty_infer()) {
+                    (true, true) => format!("{} using the `From` trait", intro),
+                    (false, true) => {
+                        format!("{} into a type implementing `From<{}>`", intro, pre_ty)
+                    }
+                    (true, false) => {
+                        format!("{} into `{}` using the `From` trait", intro, post_ty)
+                    }
+                    (false, false) => {
+                        format!(
+                            "{} into `{}` using its implementation of `From<{}>`",
+                            intro, post_ty, pre_ty
+                        )
+                    }
+                };
+
+                err.note(&msg);
+            }
+        }
+    }
+}
+
 /// Suggest giving an appropriate return type to a closure expression.
 fn closure_return_type_suggestion(
-    span: Span,
     err: &mut DiagnosticBuilder<'_>,
     output: &FnRetTy<'_>,
     body: &Body<'_>,
-    descr: &str,
-    name: &str,
     ret: &str,
-    parent_name: Option<String>,
-    parent_descr: Option<&str>,
 ) {
     let (arrow, post) = match output {
         FnRetTy::DefaultReturn(_) => ("-> ", " "),
@@ -168,10 +235,6 @@
         suggestion,
         Applicability::HasPlaceholders,
     );
-    err.span_label(
-        span,
-        InferCtxt::cannot_infer_msg("type", &name, &descr, parent_name, parent_descr),
-    );
 }
 
 /// Given a closure signature, return a `String` containing a list of all its argument types.
@@ -216,9 +279,67 @@
 pub struct InferenceDiagnosticsData {
     pub name: String,
     pub span: Option<Span>,
-    pub description: Cow<'static, str>,
-    pub parent_name: Option<String>,
-    pub parent_description: Option<&'static str>,
+    pub kind: UnderspecifiedArgKind,
+    pub parent: Option<InferenceDiagnosticsParentData>,
+}
+
+/// Data on the parent definition where a generic argument was declared.
+pub struct InferenceDiagnosticsParentData {
+    pub prefix: &'static str,
+    pub name: String,
+}
+
+pub enum UnderspecifiedArgKind {
+    Type { prefix: Cow<'static, str> },
+    Const { is_parameter: bool },
+}
+
+impl InferenceDiagnosticsData {
+    /// Generate a label for a generic argument which can't be inferred. When not
+    /// much is known about the argument, `use_diag` may be used to describe the
+    /// labeled value.
+    fn cannot_infer_msg(&self, use_diag: Option<&UseDiagnostic<'_>>) -> String {
+        if self.name == "_" && matches!(self.kind, UnderspecifiedArgKind::Type { .. }) {
+            if let Some(use_diag) = use_diag {
+                return format!("cannot infer type of {}", use_diag.descr());
+            }
+
+            return "cannot infer type".to_string();
+        }
+
+        let suffix = match (&self.parent, use_diag) {
+            (Some(parent), _) => format!(" declared on the {} `{}`", parent.prefix, parent.name),
+            (None, Some(use_diag)) => format!(" in {}", use_diag.type_descr()),
+            (None, None) => String::new(),
+        };
+
+        // For example: "cannot infer type for type parameter `T`"
+        format!("cannot infer {} `{}`{}", self.kind.prefix_string(), self.name, suffix)
+    }
+}
+
+impl InferenceDiagnosticsParentData {
+    fn for_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<InferenceDiagnosticsParentData> {
+        let parent_def_id = tcx.parent(def_id)?;
+
+        let parent_name =
+            tcx.def_key(parent_def_id).disambiguated_data.data.get_opt_name()?.to_string();
+
+        Some(InferenceDiagnosticsParentData {
+            prefix: tcx.def_kind(parent_def_id).descr(parent_def_id),
+            name: parent_name,
+        })
+    }
+}
+
+impl UnderspecifiedArgKind {
+    fn prefix_string(&self) -> Cow<'static, str> {
+        match self {
+            Self::Type { prefix } => format!("type for {}", prefix).into(),
+            Self::Const { is_parameter: true } => "the value of const parameter".into(),
+            Self::Const { is_parameter: false } => "the value of the constant".into(),
+        }
+    }
 }
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
@@ -238,32 +359,16 @@
                     if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) =
                         var_origin.kind
                     {
-                        let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id));
-                        let (parent_name, parent_description) =
-                            if let Some(parent_def_id) = parent_def_id {
-                                let parent_name = self
-                                    .tcx
-                                    .def_key(parent_def_id)
-                                    .disambiguated_data
-                                    .data
-                                    .get_opt_name()
-                                    .map(|parent_symbol| parent_symbol.to_string());
-
-                                (
-                                    parent_name,
-                                    Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)),
-                                )
-                            } else {
-                                (None, None)
-                            };
-
                         if name != kw::SelfUpper {
                             return InferenceDiagnosticsData {
                                 name: name.to_string(),
                                 span: Some(var_origin.span),
-                                description: "type parameter".into(),
-                                parent_name,
-                                parent_description,
+                                kind: UnderspecifiedArgKind::Type {
+                                    prefix: "type parameter".into(),
+                                },
+                                parent: def_id.and_then(|def_id| {
+                                    InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id)
+                                }),
                             };
                         }
                     }
@@ -278,9 +383,8 @@
                 InferenceDiagnosticsData {
                     name: s,
                     span: None,
-                    description: ty.prefix_string(),
-                    parent_name: None,
-                    parent_description: None,
+                    kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string() },
+                    parent: None,
                 }
             }
             GenericArgKind::Const(ct) => {
@@ -290,31 +394,11 @@
                     if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) =
                         origin.kind
                     {
-                        let parent_def_id = self.tcx.parent(def_id);
-                        let (parent_name, parent_description) =
-                            if let Some(parent_def_id) = parent_def_id {
-                                let parent_name = self
-                                    .tcx
-                                    .def_key(parent_def_id)
-                                    .disambiguated_data
-                                    .data
-                                    .get_opt_name()
-                                    .map(|parent_symbol| parent_symbol.to_string());
-
-                                (
-                                    parent_name,
-                                    Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)),
-                                )
-                            } else {
-                                (None, None)
-                            };
-
                         return InferenceDiagnosticsData {
                             name: name.to_string(),
                             span: Some(origin.span),
-                            description: "const parameter".into(),
-                            parent_name,
-                            parent_description,
+                            kind: UnderspecifiedArgKind::Const { is_parameter: true },
+                            parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
                         };
                     }
 
@@ -329,9 +413,8 @@
                     InferenceDiagnosticsData {
                         name: s,
                         span: Some(origin.span),
-                        description: "the constant".into(),
-                        parent_name: None,
-                        parent_description: None,
+                        kind: UnderspecifiedArgKind::Const { is_parameter: false },
+                        parent: None,
                     }
                 } else {
                     bug!("unexpect const: {:?}", ct);
@@ -430,7 +513,7 @@
 
         // When `arg_data.name` corresponds to a type argument, show the path of the full type we're
         // trying to infer. In the following example, `ty_msg` contains
-        // " in `std::result::Result<i32, E>`":
+        // " for `std::result::Result<i32, E>`":
         // ```
         // error[E0282]: type annotations needed for `std::result::Result<i32, E>`
         //  --> file.rs:L:CC
@@ -448,6 +531,13 @@
             error_code,
         );
 
+        let use_diag = local_visitor.found_use_diagnostic.as_ref();
+        if let Some(use_diag) = use_diag {
+            if use_diag.applies_to(err_span) {
+                use_diag.attach_note(&mut err);
+            }
+        }
+
         let suffix = match local_visitor.found_node_ty {
             Some(ty) if ty.is_closure() => {
                 let substs =
@@ -463,18 +553,17 @@
 
                 if let Some((decl, body_id)) = closure_decl_and_body_id {
                     closure_return_type_suggestion(
-                        span,
                         &mut err,
                         &decl.output,
                         self.tcx.hir().body(body_id),
-                        &arg_data.description,
-                        &arg_data.name,
                         &ret,
-                        arg_data.parent_name,
-                        arg_data.parent_description,
                     );
                     // We don't want to give the other suggestions when the problem is the
                     // closure return type.
+                    err.span_label(
+                        span,
+                        arg_data.cannot_infer_msg(use_diag.filter(|d| d.applies_to(span))),
+                    );
                     return err;
                 }
 
@@ -611,6 +700,8 @@
         //   |
         //   = note: type must be known at this point
         let span = arg_data.span.unwrap_or(err_span);
+
+        // Avoid multiple labels pointing at `span`.
         if !err
             .span
             .span_labels()
@@ -618,44 +709,44 @@
             .any(|span_label| span_label.label.is_some() && span_label.span == span)
             && local_visitor.found_arg_pattern.is_none()
         {
-            let (kind_str, const_value) = match arg.unpack() {
-                GenericArgKind::Type(_) => ("type", None),
-                GenericArgKind::Const(_) => ("the value", Some(())),
-                GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
-            };
-
             // FIXME(const_generics): we would like to handle const arguments
             // as part of the normal diagnostics flow below, but there appear to
             // be subtleties in doing so, so for now we special-case const args
             // here.
-            if let Some(suggestion) = const_value
-                .and_then(|_| arg_data.parent_name.as_ref())
-                .map(|parent| format!("{}::<{}>", parent, arg_data.name))
+            if let (UnderspecifiedArgKind::Const { .. }, Some(parent_data)) =
+                (&arg_data.kind, &arg_data.parent)
             {
                 err.span_suggestion_verbose(
                     span,
                     "consider specifying the const argument",
-                    suggestion,
+                    format!("{}::<{}>", parent_data.name, arg_data.name),
                     Applicability::MaybeIncorrect,
                 );
             }
 
-            // Avoid multiple labels pointing at `span`.
             err.span_label(
                 span,
-                InferCtxt::cannot_infer_msg(
-                    kind_str,
-                    &arg_data.name,
-                    &arg_data.description,
-                    arg_data.parent_name,
-                    arg_data.parent_description,
-                ),
+                arg_data.cannot_infer_msg(use_diag.filter(|d| d.applies_to(span))),
             );
         }
 
         err
     }
 
+    fn trait_def_from_hir_fn(&self, hir_id: hir::HirId) -> Option<DefId> {
+        // The DefId will be the method's trait item ID unless this is an inherent impl
+        if let Some((DefKind::AssocFn, def_id)) =
+            self.in_progress_typeck_results?.borrow().type_dependent_def(hir_id)
+        {
+            return self
+                .tcx
+                .parent(def_id)
+                .filter(|&parent_def_id| self.tcx.is_trait(parent_def_id));
+        }
+
+        None
+    }
+
     /// If the `FnSig` for the method call can be found and type arguments are identified as
     /// needed, suggest annotating the call, otherwise point out the resulting type of the call.
     fn annotate_method_call(
@@ -718,49 +809,7 @@
             "type inside {} must be known in this context",
             kind,
         );
-        err.span_label(
-            span,
-            InferCtxt::cannot_infer_msg(
-                "type",
-                &data.name,
-                &data.description,
-                data.parent_name,
-                data.parent_description,
-            ),
-        );
+        err.span_label(span, data.cannot_infer_msg(None));
         err
     }
-
-    fn cannot_infer_msg(
-        kind_str: &str,
-        type_name: &str,
-        descr: &str,
-        parent_name: Option<String>,
-        parent_descr: Option<&str>,
-    ) -> String {
-        if type_name == "_" {
-            format!("cannot infer {}", kind_str)
-        } else {
-            let parent_desc = if let Some(parent_name) = parent_name {
-                let parent_type_descr = if let Some(parent_descr) = parent_descr {
-                    format!(" the {}", parent_descr)
-                } else {
-                    "".into()
-                };
-
-                format!(" declared on{} `{}`", parent_type_descr, parent_name)
-            } else {
-                "".to_string()
-            };
-
-            // FIXME: We really shouldn't be dealing with strings here
-            // but instead use a sensible enum for cases like this.
-            let preposition = if "the value" == kind_str { "of" } else { "for" };
-            // For example: "cannot infer type for type parameter `T`"
-            format!(
-                "cannot infer {} {} {} `{}`{}",
-                kind_str, preposition, descr, type_name, parent_desc
-            )
-        }
-    }
 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 5264854..c6ae71b 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -345,9 +345,10 @@
         match tcx.hir().get_if_local(def_id) {
             Some(Node::ImplItem(ImplItem { ident, hir_id, .. })) => {
                 match tcx.hir().find(tcx.hir().get_parent_item(*hir_id)) {
-                    Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) => {
-                        Some((*ident, self_ty))
-                    }
+                    Some(Node::Item(Item {
+                        kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
+                        ..
+                    })) => Some((*ident, self_ty)),
                     _ => None,
                 }
             }
@@ -367,7 +368,7 @@
                                 let impl_did = tcx.hir().local_def_id(*impl_node);
                                 match tcx.hir().get_if_local(impl_did.to_def_id()) {
                                     Some(Node::Item(Item {
-                                        kind: ItemKind::Impl { self_ty, .. },
+                                        kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
                                         ..
                                     })) if trait_objects.iter().all(|did| {
                                         // FIXME: we should check `self_ty` against the receiver
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index 7fb9433..c88869a 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -1,6 +1,7 @@
 use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt};
 use crate::infer::{self, InferCtxt, SubregionOrigin};
 use rustc_errors::{struct_span_err, DiagnosticBuilder};
+use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::{self, Region};
 
@@ -107,14 +108,37 @@
             infer::Subtype(box trace) => {
                 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
                 let mut err = self.report_and_explain_type_error(trace, &terr);
-                note_and_explain_region(self.tcx, &mut err, "", sup, "...");
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "...does not necessarily outlive ",
-                    sub,
-                    "",
-                );
+                match (sub, sup) {
+                    (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
+                    (ty::RePlaceholder(_), _) => {
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "",
+                            sup,
+                            " doesn't meet the lifetime requirements",
+                        );
+                    }
+                    (_, ty::RePlaceholder(_)) => {
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "the required lifetime does not necessarily outlive ",
+                            sub,
+                            "",
+                        );
+                    }
+                    _ => {
+                        note_and_explain_region(self.tcx, &mut err, "", sup, "...");
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "...does not necessarily outlive ",
+                            sub,
+                            "",
+                        );
+                    }
+                }
                 err
             }
             infer::Reborrow(span) => {
@@ -286,13 +310,31 @@
         sup: Region<'tcx>,
     ) -> DiagnosticBuilder<'tcx> {
         // I can't think how to do better than this right now. -nikomatsakis
+        debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
         match placeholder_origin {
+            infer::Subtype(box ref trace)
+                if matches!(
+                    &trace.cause.code.peel_derives(),
+                    ObligationCauseCode::BindingObligation(..)
+                ) =>
+            {
+                // Hack to get around the borrow checker because trace.cause has an `Rc`.
+                if let ObligationCauseCode::BindingObligation(_, span) =
+                    &trace.cause.code.peel_derives()
+                {
+                    let span = *span;
+                    let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
+                    err.span_note(span, "the lifetime requirement is introduced here");
+                    err
+                } else {
+                    unreachable!()
+                }
+            }
             infer::Subtype(box trace) => {
                 let terr = TypeError::RegionsPlaceholderMismatch;
-                self.report_and_explain_type_error(trace, &terr)
+                return self.report_and_explain_type_error(trace, &terr);
             }
-
-            _ => self.report_concrete_failure(placeholder_origin, sub, sup),
+            _ => return self.report_concrete_failure(placeholder_origin, sub, sup),
         }
     }
 }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 56d9634..27545c1 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1533,7 +1533,7 @@
                 // Note: if these two lines are combined into one we get
                 // dynamic borrow errors on `self.inner`.
                 let known = self.inner.borrow_mut().type_variables().probe(v).known();
-                known.map(|t| self.shallow_resolve_ty(t)).unwrap_or(typ)
+                known.map_or(typ, |t| self.shallow_resolve_ty(t))
             }
 
             ty::Infer(ty::IntVar(v)) => self
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index de98ccc..07c75d5 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -6,7 +6,6 @@
 
 use rustc_middle::traits::query::OutlivesBound;
 use rustc_middle::ty;
-use rustc_middle::ty::fold::TypeFoldable;
 
 pub fn explicit_outlives_bounds<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
@@ -15,20 +14,20 @@
     param_env
         .caller_bounds()
         .into_iter()
-        .map(ty::Predicate::skip_binders)
-        .filter(|atom| !atom.has_escaping_bound_vars())
-        .filter_map(move |atom| match atom {
-            ty::PredicateAtom::Projection(..)
-            | ty::PredicateAtom::Trait(..)
-            | ty::PredicateAtom::Subtype(..)
-            | ty::PredicateAtom::WellFormed(..)
-            | ty::PredicateAtom::ObjectSafe(..)
-            | ty::PredicateAtom::ClosureKind(..)
-            | ty::PredicateAtom::TypeOutlives(..)
-            | ty::PredicateAtom::ConstEvaluatable(..)
-            | ty::PredicateAtom::ConstEquate(..)
-            | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
-            ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
+        .map(ty::Predicate::kind)
+        .filter_map(ty::Binder::no_bound_vars)
+        .filter_map(move |kind| match kind {
+            ty::PredicateKind::Projection(..)
+            | ty::PredicateKind::Trait(..)
+            | ty::PredicateKind::Subtype(..)
+            | ty::PredicateKind::WellFormed(..)
+            | ty::PredicateKind::ObjectSafe(..)
+            | ty::PredicateKind::ClosureKind(..)
+            | ty::PredicateKind::TypeOutlives(..)
+            | ty::PredicateKind::ConstEvaluatable(..)
+            | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
+            ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
                 Some(OutlivesBound::RegionSubRegion(r_b, r_a))
             }
         })
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index a676c5e..6687198 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -100,7 +100,7 @@
                 self.fields.obligations.push(Obligation::new(
                     self.fields.trace.cause.clone(),
                     self.fields.param_env,
-                    ty::PredicateAtom::Subtype(ty::SubtypePredicate {
+                    ty::PredicateKind::Subtype(ty::SubtypePredicate {
                         a_is_expected: self.a_is_expected,
                         a,
                         b,
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 8273c2d..13cf1e10 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -9,13 +9,8 @@
     tcx: TyCtxt<'tcx>,
     pred: ty::Predicate<'tcx>,
 ) -> ty::Predicate<'tcx> {
-    match *pred.kind() {
-        ty::PredicateKind::ForAll(binder) => {
-            let new = ty::PredicateKind::ForAll(tcx.anonymize_late_bound_regions(binder));
-            tcx.reuse_or_mk_predicate(pred, new)
-        }
-        ty::PredicateKind::Atom(_) => pred,
-    }
+    let new = tcx.anonymize_late_bound_regions(pred.kind());
+    tcx.reuse_or_mk_predicate(pred, new)
 }
 
 struct PredicateSet<'tcx> {
@@ -126,9 +121,9 @@
     fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
         let tcx = self.visited.tcx;
 
-        let bound_predicate = obligation.predicate.bound_atom();
+        let bound_predicate = obligation.predicate.kind();
         match bound_predicate.skip_binder() {
-            ty::PredicateAtom::Trait(data, _) => {
+            ty::PredicateKind::Trait(data, _) => {
                 // Get predicates declared on the trait.
                 let predicates = tcx.super_predicates_of(data.def_id());
 
@@ -150,36 +145,36 @@
 
                 self.stack.extend(obligations);
             }
-            ty::PredicateAtom::WellFormed(..) => {
+            ty::PredicateKind::WellFormed(..) => {
                 // Currently, we do not elaborate WF predicates,
                 // although we easily could.
             }
-            ty::PredicateAtom::ObjectSafe(..) => {
+            ty::PredicateKind::ObjectSafe(..) => {
                 // Currently, we do not elaborate object-safe
                 // predicates.
             }
-            ty::PredicateAtom::Subtype(..) => {
+            ty::PredicateKind::Subtype(..) => {
                 // Currently, we do not "elaborate" predicates like `X <: Y`,
                 // though conceivably we might.
             }
-            ty::PredicateAtom::Projection(..) => {
+            ty::PredicateKind::Projection(..) => {
                 // Nothing to elaborate in a projection predicate.
             }
-            ty::PredicateAtom::ClosureKind(..) => {
+            ty::PredicateKind::ClosureKind(..) => {
                 // Nothing to elaborate when waiting for a closure's kind to be inferred.
             }
-            ty::PredicateAtom::ConstEvaluatable(..) => {
+            ty::PredicateKind::ConstEvaluatable(..) => {
                 // Currently, we do not elaborate const-evaluatable
                 // predicates.
             }
-            ty::PredicateAtom::ConstEquate(..) => {
+            ty::PredicateKind::ConstEquate(..) => {
                 // Currently, we do not elaborate const-equate
                 // predicates.
             }
-            ty::PredicateAtom::RegionOutlives(..) => {
+            ty::PredicateKind::RegionOutlives(..) => {
                 // Nothing to elaborate from `'a: 'b`.
             }
-            ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
+            ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
                 // We know that `T: 'a` for some type `T`. We can
                 // often elaborate this. For example, if we know that
                 // `[U]: 'a`, that implies that `U: 'a`. Similarly, if
@@ -209,7 +204,7 @@
                                 if r.is_late_bound() {
                                     None
                                 } else {
-                                    Some(ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(
+                                    Some(ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(
                                         r, r_min,
                                     )))
                                 }
@@ -217,7 +212,7 @@
 
                             Component::Param(p) => {
                                 let ty = tcx.mk_ty_param(p.index, p.name);
-                                Some(ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(
+                                Some(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
                                     ty, r_min,
                                 )))
                             }
@@ -242,7 +237,7 @@
                         }),
                 );
             }
-            ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+            ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                 // Nothing to elaborate
             }
         }
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 461ee08..ead2512 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -236,7 +236,7 @@
     pre_expansion_lint(sess, lint_store, &krate);
 
     let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas);
-    rustc_builtin_macros::register_builtin_macros(&mut resolver, sess.edition());
+    rustc_builtin_macros::register_builtin_macros(&mut resolver);
 
     krate = sess.time("crate_injection", || {
         let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s));
@@ -797,12 +797,6 @@
         })
     });
 
-    // Do some initialization of the DepGraph that can only be done with the tcx available.
-    let icx = ty::tls::ImplicitCtxt::new(&gcx);
-    ty::tls::enter_context(&icx, |_| {
-        icx.tcx.sess.time("dep_graph_tcx_init", || rustc_incremental::dep_graph_tcx_init(icx.tcx));
-    });
-
     QueryContext(gcx)
 }
 
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 3e94f16..55d521a 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -7,7 +7,7 @@
 use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
 use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
 use rustc_session::config::{
-    Externs, OutputType, OutputTypes, SanitizerSet, SymbolManglingVersion,
+    Externs, OutputType, OutputTypes, SanitizerSet, SymbolManglingVersion, WasiExecModel,
 };
 use rustc_session::lint::Level;
 use rustc_session::search_paths::SearchPath;
@@ -597,6 +597,7 @@
     tracked!(unleash_the_miri_inside_of_you, true);
     tracked!(use_ctors_section, Some(true));
     tracked!(verify_llvm_ir, true);
+    tracked!(wasi_exec_model, Some(WasiExecModel::Reactor));
 }
 
 #[test]
diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs
index c0045d3..297f3d1 100644
--- a/compiler/rustc_lexer/src/cursor.rs
+++ b/compiler/rustc_lexer/src/cursor.rs
@@ -33,7 +33,7 @@
 
         #[cfg(not(debug_assertions))]
         {
-            '\0'
+            EOF_CHAR
         }
     }
 
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index a837127..8cdb33e 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -43,6 +43,7 @@
 use rustc_middle::lint::LintDiagnosticBuilder;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::subst::{GenericArgKind, Subst};
+use rustc_middle::ty::Instance;
 use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_span::edition::Edition;
@@ -541,7 +542,7 @@
                     return;
                 }
             }
-            hir::ItemKind::Impl { of_trait: Some(ref trait_ref), items, .. } => {
+            hir::ItemKind::Impl(hir::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();
@@ -938,8 +939,8 @@
             if attr.ident().map(|ident| ident.name) == Some(n) {
                 if let &AttributeGate::Gated(
                     Stability::Deprecated(link, suggestion),
-                    ref name,
-                    ref reason,
+                    name,
+                    reason,
                     _,
                 ) = g
                 {
@@ -1549,13 +1550,13 @@
 impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
         use rustc_middle::ty::fold::TypeFoldable;
-        use rustc_middle::ty::PredicateAtom::*;
+        use rustc_middle::ty::PredicateKind::*;
 
         if cx.tcx.features().trivial_bounds {
             let def_id = cx.tcx.hir().local_def_id(item.hir_id);
             let predicates = cx.tcx.predicates_of(def_id);
             for &(predicate, span) in predicates.predicates {
-                let predicate_kind_name = match predicate.skip_binders() {
+                let predicate_kind_name = match predicate.kind().skip_binder() {
                     Trait(..) => "Trait",
                     TypeOutlives(..) |
                     RegionOutlives(..) => "Lifetime",
@@ -1935,8 +1936,8 @@
     ) -> Vec<ty::Region<'tcx>> {
         inferred_outlives
             .iter()
-            .filter_map(|(pred, _)| match pred.skip_binders() {
-                ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(a, b)) => match a {
+            .filter_map(|(pred, _)| match pred.kind().skip_binder() {
+                ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match a {
                     ty::ReEarlyBound(ebr) if ebr.index == index => Some(b),
                     _ => None,
                 },
@@ -1951,8 +1952,8 @@
     ) -> Vec<ty::Region<'tcx>> {
         inferred_outlives
             .iter()
-            .filter_map(|(pred, _)| match pred.skip_binders() {
-                ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
+            .filter_map(|(pred, _)| match pred.kind().skip_binder() {
+                ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
                     a.is_param(index).then_some(b)
                 }
                 _ => None,
@@ -2595,7 +2596,12 @@
 }
 
 pub struct ClashingExternDeclarations {
-    seen_decls: FxHashMap<Symbol, HirId>,
+    /// Map of function symbol name to the first-seen hir id for that symbol name.. If seen_decls
+    /// contains an entry for key K, it means a symbol with name K has been seen by this lint and
+    /// the symbol should be reported as a clashing declaration.
+    // FIXME: Technically, we could just store a &'tcx str here without issue; however, the
+    // `impl_lint_pass` macro doesn't currently support lints parametric over a lifetime.
+    seen_decls: FxHashMap<String, HirId>,
 }
 
 /// Differentiate between whether the name for an extern decl came from the link_name attribute or
@@ -2626,16 +2632,17 @@
     fn insert(&mut self, tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> Option<HirId> {
         let hid = fi.hir_id;
 
-        let name =
-            &tcx.codegen_fn_attrs(tcx.hir().local_def_id(hid)).link_name.unwrap_or(fi.ident.name);
-
-        if self.seen_decls.contains_key(name) {
+        let local_did = tcx.hir().local_def_id(fi.hir_id);
+        let did = local_did.to_def_id();
+        let instance = Instance::new(did, ty::List::identity_for_item(tcx, did));
+        let name = tcx.symbol_name(instance).name;
+        if let Some(&hir_id) = self.seen_decls.get(name) {
             // Avoid updating the map with the new entry when we do find a collision. We want to
             // make sure we're always pointing to the first definition as the previous declaration.
             // This lets us avoid emitting "knock-on" diagnostics.
-            Some(*self.seen_decls.get(name).unwrap())
+            Some(hir_id)
         } else {
-            self.seen_decls.insert(*name, hid)
+            self.seen_decls.insert(name.to_owned(), hid)
         }
     }
 
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index ea4f7da..3971a30 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -261,6 +261,7 @@
         }
     }
 
+    #[track_caller]
     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,
@@ -353,10 +354,23 @@
             lint_name.to_string()
         };
         // If the lint was scoped with `tool::` check if the tool lint exists
-        if tool_name.is_some() {
+        if let Some(tool_name) = tool_name {
             match self.by_name.get(&complete_name) {
                 None => match self.lint_groups.get(&*complete_name) {
-                    None => return CheckLintNameResult::Tool(Err((None, String::new()))),
+                    // If the lint isn't registered, there are two possibilities:
+                    None => {
+                        // 1. The tool is currently running, so this lint really doesn't exist.
+                        // FIXME: should this handle tools that never register a lint, like rustfmt?
+                        tracing::debug!("lints={:?}", self.by_name.keys().collect::<Vec<_>>());
+                        let tool_prefix = format!("{}::", tool_name);
+                        return if self.by_name.keys().any(|lint| lint.starts_with(&tool_prefix)) {
+                            self.no_lint_suggestion(&complete_name)
+                        } else {
+                            // 2. The tool isn't currently running, so no lints will be registered.
+                            // To avoid giving a false positive, ignore all unknown lints.
+                            CheckLintNameResult::Tool(Err((None, String::new())))
+                        };
+                    }
                     Some(LintGroup { lint_ids, .. }) => {
                         return CheckLintNameResult::Tool(Ok(&lint_ids));
                     }
@@ -397,6 +411,21 @@
         }
     }
 
+    fn no_lint_suggestion(&self, lint_name: &str) -> CheckLintNameResult<'_> {
+        let name_lower = lint_name.to_lowercase();
+        let symbols =
+            self.get_lints().iter().map(|l| Symbol::intern(&l.name_lower())).collect::<Vec<_>>();
+
+        if lint_name.chars().any(char::is_uppercase) && self.find_lints(&name_lower).is_ok() {
+            // First check if the lint name is (partly) in upper case instead of lower case...
+            CheckLintNameResult::NoLint(Some(Symbol::intern(&name_lower)))
+        } else {
+            // ...if not, search for lints with a similar name
+            let suggestion = find_best_match_for_name(&symbols, Symbol::intern(&name_lower), None);
+            CheckLintNameResult::NoLint(suggestion)
+        }
+    }
+
     fn check_tool_name_for_backwards_compat(
         &self,
         lint_name: &str,
@@ -406,18 +435,7 @@
         match self.by_name.get(&complete_name) {
             None => match self.lint_groups.get(&*complete_name) {
                 // Now we are sure, that this lint exists nowhere
-                None => {
-                    let symbols =
-                        self.by_name.keys().map(|name| Symbol::intern(&name)).collect::<Vec<_>>();
-
-                    let suggestion = find_best_match_for_name(
-                        &symbols,
-                        Symbol::intern(&lint_name.to_lowercase()),
-                        None,
-                    );
-
-                    CheckLintNameResult::NoLint(suggestion)
-                }
+                None => self.no_lint_suggestion(lint_name),
                 Some(LintGroup { lint_ids, depr, .. }) => {
                     // Reaching this would be weird, but let's cover this case anyway
                     if let Some(LintAlias { name, silent }) = depr {
@@ -596,6 +614,13 @@
                     db.help("to document an item produced by a macro, \
                                   the macro must produce the documentation as part of its expansion");
                 }
+                BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident) => {
+                    db.span_suggestion(span, "remove `mut` from the parameter", ident.to_string(), Applicability::MachineApplicable);
+                }
+                BuiltinLintDiagnostics::MissingAbi(span, default_abi) => {
+                    db.span_label(span, "ABI should be specified here");
+                    db.help(&format!("the default ABI is {}", default_abi.name()));
+                }
             }
             // Rewrap `db`, and pass control to the user.
             decorate(LintDiagnosticBuilder::new(db));
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 5cece56..fc8f844 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -10,7 +10,7 @@
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_hir::{intravisit, HirId};
 use rustc_middle::hir::map::Map;
-use rustc_middle::lint::LevelSource;
+use rustc_middle::lint::LevelAndSource;
 use rustc_middle::lint::LintDiagnosticBuilder;
 use rustc_middle::lint::{
     struct_lint_level, LintLevelMap, LintLevelSets, LintLevelSource, LintSet,
@@ -106,9 +106,9 @@
     /// diagnostic with no change to `specs`.
     fn insert_spec(
         &mut self,
-        specs: &mut FxHashMap<LintId, LevelSource>,
+        specs: &mut FxHashMap<LintId, LevelAndSource>,
         id: LintId,
-        (level, src): LevelSource,
+        (level, src): LevelAndSource,
     ) {
         // Setting to a non-forbid level is an error if the lint previously had
         // a forbid level. Note that this is not necessarily true even with a
@@ -381,6 +381,11 @@
                             src,
                             Some(li.span().into()),
                             |lint| {
+                                let name = if let Some(tool_name) = tool_name {
+                                    format!("{}::{}", tool_name, name)
+                                } else {
+                                    name.to_string()
+                                };
                                 let mut db = lint.build(&format!("unknown lint: `{}`", name));
                                 if let Some(suggestion) = suggestion {
                                     db.span_suggestion(
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 6d61b86..ebd6190 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -275,10 +275,25 @@
                     // We have a valid span in almost all cases, but we don't have one when linting a crate
                     // name provided via the command line.
                     if !ident.span.is_dummy() {
+                        let sc_ident = Ident::from_str_and_span(&sc, ident.span);
+                        let (message, suggestion) = if sc_ident.is_reserved() {
+                            // We shouldn't suggest a reserved identifier to fix non-snake-case identifiers.
+                            // Instead, recommend renaming the identifier entirely or, if permitted,
+                            // escaping it to create a raw identifier.
+                            if sc_ident.name.can_be_raw() {
+                                ("rename the identifier or convert it to a snake case raw identifier", sc_ident.to_string())
+                            } else {
+                                err.note(&format!("`{}` cannot be used as a raw identifier", sc));
+                                ("rename the identifier", String::new())
+                            }
+                        } else {
+                            ("convert the identifier to snake case", sc)
+                        };
+
                         err.span_suggestion(
                             ident.span,
-                            "convert the identifier to snake case",
-                            sc,
+                            message,
+                            suggestion,
                             Applicability::MaybeIncorrect,
                         );
                     } else {
@@ -397,7 +412,7 @@
     }
 
     fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) {
-        if let &PatKind::Binding(_, hid, 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 {
diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs
index d4f7903..b031c11 100644
--- a/compiler/rustc_lint/src/traits.rs
+++ b/compiler/rustc_lint/src/traits.rs
@@ -45,12 +45,12 @@
 
 impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
-        use rustc_middle::ty::PredicateAtom::*;
+        use rustc_middle::ty::PredicateKind::*;
 
         let def_id = cx.tcx.hir().local_def_id(item.hir_id);
         let predicates = cx.tcx.explicit_predicates_of(def_id);
         for &(predicate, span) in predicates.predicates {
-            let trait_predicate = match predicate.skip_binders() {
+            let trait_predicate = match predicate.kind().skip_binder() {
                 Trait(trait_predicate, _constness) => trait_predicate,
                 _ => continue,
             };
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 9ad9d53..424f91b 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -647,8 +647,7 @@
     let param_env = tcx.param_env(variant.def_id);
     for field in &variant.fields {
         let field_ty = tcx.type_of(field.did);
-        let is_zst =
-            tcx.layout_of(param_env.and(field_ty)).map(|layout| layout.is_zst()).unwrap_or(false);
+        let is_zst = tcx.layout_of(param_env.and(field_ty)).map_or(false, |layout| layout.is_zst());
 
         if !is_zst {
             return Some(field);
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 5e1f94c..c1a3eec 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -202,8 +202,8 @@
                     let mut has_emitted = false;
                     for &(predicate, _) in cx.tcx.explicit_item_bounds(def) {
                         // We only look at the `DefId`, so it is safe to skip the binder here.
-                        if let ty::PredicateAtom::Trait(ref poly_trait_predicate, _) =
-                            predicate.skip_binders()
+                        if let ty::PredicateKind::Trait(ref poly_trait_predicate, _) =
+                            predicate.kind().skip_binder()
                         {
                             let def_id = poly_trait_predicate.trait_ref.def_id;
                             let descr_pre =
@@ -529,8 +529,8 @@
             pprust::expr_to_string(value)
         };
         let keep_space = (
-            left_pos.map(|s| s >= value.span.lo()).unwrap_or(false),
-            right_pos.map(|s| s <= value.span.hi()).unwrap_or(false),
+            left_pos.map_or(false, |s| s >= value.span.lo()),
+            right_pos.map_or(false, |s| s <= value.span.hi()),
         );
         self.emit_unused_delims(cx, value.span, &expr_text, ctx.into(), keep_space);
     }
@@ -862,11 +862,11 @@
     }
 
     fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
-        if let &ast::TyKind::Paren(ref r) = &ty.kind {
+        if let ast::TyKind::Paren(r) = &ty.kind {
             match &r.kind {
-                &ast::TyKind::TraitObject(..) => {}
-                &ast::TyKind::ImplTrait(_, ref bounds) if bounds.len() > 1 => {}
-                &ast::TyKind::Array(_, ref len) => {
+                ast::TyKind::TraitObject(..) => {}
+                ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {}
+                ast::TyKind::Array(_, len) => {
                     self.check_unused_delims_expr(
                         cx,
                         &len.value,
diff --git a/compiler/rustc_lint_defs/Cargo.toml b/compiler/rustc_lint_defs/Cargo.toml
index 7f90808..f909f15 100644
--- a/compiler/rustc_lint_defs/Cargo.toml
+++ b/compiler/rustc_lint_defs/Cargo.toml
@@ -11,3 +11,4 @@
 rustc_span = { path = "../rustc_span" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_macros = { path = "../rustc_macros" }
+rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 1c692d4..20052ad 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -4,7 +4,7 @@
 //! compiler code, rather than using their own custom pass. Those
 //! lints are all available in `rustc_lint::builtin`.
 
-use crate::{declare_lint, declare_lint_pass, declare_tool_lint};
+use crate::{declare_lint, declare_lint_pass};
 use rustc_span::edition::Edition;
 use rustc_span::symbol::sym;
 
@@ -221,14 +221,10 @@
     ///
     /// ### Explanation
     ///
-    /// This lint detects code that is very likely incorrect. When possible,
-    /// the compiler will attempt to detect situations where code can be
-    /// evaluated at compile-time to generate more efficient code. While
-    /// evaluating such code, if it detects that the code will unconditionally
-    /// panic, this usually indicates that it is doing something incorrectly.
-    /// If this lint is allowed, then the code will not be evaluated at
-    /// compile-time, and instead continue to generate code to evaluate at
-    /// runtime, which may panic during runtime.
+    /// This lint detects code that is very likely incorrect because it will
+    /// always panic, such as division by zero and out-of-bounds array
+    /// accesses. Consider adjusting your code if this is a bug, or using the
+    /// `panic!` or `unreachable!` macro instead in case the panic is intended.
     pub UNCONDITIONAL_PANIC,
     Deny,
     "operation will cause a panic at runtime"
@@ -2829,8 +2825,29 @@
     };
 }
 
-declare_tool_lint! {
-    pub rustc::INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
+declare_lint! {
+    /// The `ineffective_unstable_trait_impl` lint detects `#[unstable]` attributes which are not used.
+    ///
+    /// ### Example
+    ///
+    /// ```compile_fail
+    /// #![feature(staged_api)]
+    ///
+    /// #[derive(Clone)]
+    /// #[stable(feature = "x", since = "1")]
+    /// struct S {}
+    ///
+    /// #[unstable(feature = "y", issue = "none")]
+    /// impl Copy for S {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// `staged_api` does not currently support using a stability attribute on `impl` blocks.
+    /// `impl`s are always stable if both the type and trait are stable, and always unstable otherwise.
+    pub INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
     Deny,
     "detects `#[unstable]` on stable trait implementations for stable types"
 }
@@ -2921,6 +2938,7 @@
         FUNCTION_ITEM_REFERENCES,
         USELESS_DEPRECATED,
         UNSUPPORTED_NAKED_FUNCTIONS,
+        MISSING_ABI,
     ]
 }
 
@@ -2948,3 +2966,28 @@
 }
 
 declare_lint_pass!(UnusedDocComment => [UNUSED_DOC_COMMENTS]);
+
+declare_lint! {
+    /// The `missing_abi` lint detects cases where the ABI is omitted from
+    /// extern declarations.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![deny(missing_abi)]
+    ///
+    /// extern fn foo() {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Historically, Rust implicitly selected C as the ABI for extern
+    /// declarations. We expect to add new ABIs, like `C-unwind`, in the future,
+    /// though this has not yet happened, and especially with their addition
+    /// seeing the ABI easily will make code review easier.
+    pub MISSING_ABI,
+    Allow,
+    "No declared ABI for extern declaration"
+}
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index aec0fc2..9d60a51 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -6,6 +6,7 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 use rustc_span::edition::Edition;
 use rustc_span::{sym, symbol::Ident, MultiSpan, Span, Symbol};
+use rustc_target::spec::abi::Abi;
 
 pub mod builtin;
 
@@ -252,7 +253,9 @@
     UnusedImports(String, Vec<(Span, String)>),
     RedundantImport(Vec<(Span, bool)>, Ident),
     DeprecatedMacro(Option<Symbol>, Span),
+    MissingAbi(Span, Abi),
     UnusedDocComment(Span),
+    PatternsInFnsWithoutBody(Span, Ident),
 }
 
 /// Lints that are buffered up early on in the `Session` before the
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index c0ff62c..1d89fc8 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -660,6 +660,8 @@
   return DEBUG_METADATA_VERSION;
 }
 
+extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
+
 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
 
 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
@@ -994,11 +996,9 @@
 }
 
 extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateDebugLocation(LLVMContextRef ContextRef, unsigned Line,
-                                     unsigned Column, LLVMMetadataRef Scope,
+LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
+                                     LLVMMetadataRef Scope,
                                      LLVMMetadataRef InlinedAt) {
-  LLVMContext &Context = *unwrap(ContextRef);
-
   DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr<MDNode>(Scope),
                                      unwrapDIPtr<MDNode>(InlinedAt));
 
diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs
index b2ffa27..592010d 100644
--- a/compiler/rustc_llvm/src/lib.rs
+++ b/compiler/rustc_llvm/src/lib.rs
@@ -38,7 +38,7 @@
         ($cfg:meta, $($method:ident),*) => { {
             #[cfg($cfg)]
             fn init() {
-                extern {
+                extern "C" {
                     $(fn $method();)*
                 }
                 unsafe {
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index 6d87678..d264462 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -429,7 +429,7 @@
     };
 
     let (tcx, desc) = modifiers.desc;
-    let tcx = tcx.as_ref().map(|t| quote! { #t }).unwrap_or(quote! { _ });
+    let tcx = tcx.as_ref().map_or(quote! { _ }, |t| quote! { #t });
 
     let desc = quote! {
         #[allow(unused_variables)]
diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs
index dbeb3c7..72bd480 100644
--- a/compiler/rustc_macros/src/serialize.rs
+++ b/compiler/rustc_macros/src/serialize.rs
@@ -203,7 +203,7 @@
                                 #field_name,
                                 #field_idx,
                                 |__encoder|
-                                ::rustc_serialize::Encodable::encode(#bind_ident, __encoder),
+                                ::rustc_serialize::Encodable::<#encoder_ty>::encode(#bind_ident, __encoder),
                             ) {
                                 ::std::result::Result::Ok(()) => (),
                                 ::std::result::Result::Err(__err)
@@ -237,7 +237,7 @@
                                 __encoder,
                                 #field_idx,
                                 |__encoder|
-                                ::rustc_serialize::Encodable::encode(#bind_ident, __encoder),
+                                ::rustc_serialize::Encodable::<#encoder_ty>::encode(#bind_ident, __encoder),
                             ) {
                                 ::std::result::Result::Ok(()) => (),
                                 ::std::result::Result::Err(__err)
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 019ca51..a7bf79d 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -326,7 +326,7 @@
         self.verify_no_symbol_conflicts(&crate_root)?;
 
         let private_dep =
-            self.sess.opts.externs.get(&name.as_str()).map(|e| e.is_private_dep).unwrap_or(false);
+            self.sess.opts.externs.get(&name.as_str()).map_or(false, |e| e.is_private_dep);
 
         // Claim this crate number and cache it
         let cnum = self.cstore.alloc_new_crate_num();
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 744fdc8..8d09943 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -132,7 +132,7 @@
 
 impl Collector<'tcx> {
     fn register_native_lib(&mut self, span: Option<Span>, lib: NativeLib) {
-        if lib.name.as_ref().map(|&s| s == kw::Empty).unwrap_or(false) {
+        if lib.name.as_ref().map_or(false, |&s| s == kw::Empty) {
             match span {
                 Some(span) => {
                     struct_span_err!(
@@ -192,13 +192,13 @@
     fn process_command_line(&mut self) {
         // First, check for errors
         let mut renames = FxHashSet::default();
-        for &(ref name, ref new_name, _) in &self.tcx.sess.opts.libs {
-            if let &Some(ref new_name) = new_name {
+        for (name, new_name, _) in &self.tcx.sess.opts.libs {
+            if let Some(ref new_name) = new_name {
                 let any_duplicate = self
                     .libs
                     .iter()
                     .filter_map(|lib| lib.name.as_ref())
-                    .any(|n| n.as_str() == *name);
+                    .any(|n| &n.as_str() == name);
                 if new_name.is_empty() {
                     self.tcx.sess.err(&format!(
                         "an empty renaming target was specified for library `{}`",
@@ -240,7 +240,7 @@
                             if kind != NativeLibKind::Unspecified {
                                 lib.kind = kind;
                             }
-                            if let &Some(ref new_name) = new_name {
+                            if let Some(new_name) = new_name {
                                 lib.name = Some(Symbol::intern(new_name));
                             }
                             return true;
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 43f7b2a..115569f 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -10,7 +10,8 @@
 use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, OnceCell};
+use rustc_data_structures::sync::{Lock, LockGuard, Lrc, OnceCell};
+use rustc_data_structures::unhash::UnhashMap;
 use rustc_errors::ErrorReported;
 use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
 use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
@@ -20,7 +21,6 @@
 use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc_hir::lang_items;
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_middle::dep_graph::{self, DepNode, DepNodeExt, DepNodeIndex};
 use rustc_middle::hir::exports::Export;
 use rustc_middle::middle::cstore::{CrateSource, ExternCrate};
 use rustc_middle::middle::cstore::{ForeignModule, LinkagePreference, NativeLib};
@@ -80,14 +80,9 @@
     /// For every definition in this crate, maps its `DefPathHash` to its
     /// `DefIndex`. See `raw_def_id_to_def_id` for more details about how
     /// this is used.
-    def_path_hash_map: OnceCell<FxHashMap<DefPathHash, DefIndex>>,
+    def_path_hash_map: OnceCell<UnhashMap<DefPathHash, DefIndex>>,
     /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
     alloc_decoding_state: AllocDecodingState,
-    /// The `DepNodeIndex` of the `DepNode` representing this upstream crate.
-    /// It is initialized on the first access in `get_crate_dep_node_index()`.
-    /// Do not access the value directly, as it might not have been initialized yet.
-    /// The field must always be initialized to `DepNodeIndex::INVALID`.
-    dep_node_index: AtomicCell<DepNodeIndex>,
     /// Caches decoded `DefKey`s.
     def_key_cache: Lock<FxHashMap<DefIndex, DefKey>>,
     /// Caches decoded `DefPathHash`es.
@@ -720,21 +715,25 @@
         &self.raw_proc_macros.unwrap()[pos]
     }
 
-    fn item_ident(&self, item_index: DefIndex, sess: &Session) -> Ident {
+    fn try_item_ident(&self, item_index: DefIndex, sess: &Session) -> Result<Ident, String> {
         let name = self
             .def_key(item_index)
             .disambiguated_data
             .data
             .get_opt_name()
-            .expect("no name in item_ident");
+            .ok_or_else(|| format!("Missing opt name for {:?}", item_index))?;
         let span = self
             .root
             .tables
             .ident_span
             .get(self, item_index)
-            .map(|data| data.decode((self, sess)))
-            .unwrap_or_else(|| panic!("Missing ident span for {:?} ({:?})", name, item_index));
-        Ident::new(name, span)
+            .ok_or_else(|| format!("Missing ident span for {:?} ({:?})", name, item_index))?
+            .decode((self, sess));
+        Ok(Ident::new(name, span))
+    }
+
+    fn item_ident(&self, item_index: DefIndex, sess: &Session) -> Ident {
+        self.try_item_ident(item_index, sess).unwrap()
     }
 
     fn def_kind(&self, index: DefIndex) -> DefKind {
@@ -1055,19 +1054,15 @@
 
         // Iterate over all children.
         let macros_only = self.dep_kind.lock().macros_only();
-        let children = self.root.tables.children.get(self, id).unwrap_or_else(Lazy::empty);
-        for child_index in children.decode((self, sess)) {
-            if macros_only {
-                continue;
-            }
+        if !macros_only {
+            let children = self.root.tables.children.get(self, id).unwrap_or_else(Lazy::empty);
 
-            // Get the item.
-            if let Some(child_kind) = self.maybe_kind(child_index) {
-                match child_kind {
-                    EntryKind::MacroDef(..) => {}
-                    _ if macros_only => continue,
-                    _ => {}
-                }
+            for child_index in children.decode((self, sess)) {
+                // Get the item.
+                let child_kind = match self.maybe_kind(child_index) {
+                    Some(child_kind) => child_kind,
+                    None => continue,
+                };
 
                 // Hand off the item to the callback.
                 match child_kind {
@@ -1102,8 +1097,8 @@
                 }
 
                 let def_key = self.def_key(child_index);
-                let span = self.get_span(child_index, sess);
                 if def_key.disambiguated_data.data.get_opt_name().is_some() {
+                    let span = self.get_span(child_index, sess);
                     let kind = self.def_kind(child_index);
                     let ident = self.item_ident(child_index, sess);
                     let vis = self.get_visibility(child_index);
@@ -1137,9 +1132,8 @@
                                 // within the crate. We only need this for fictive constructors,
                                 // for other constructors correct visibilities
                                 // were already encoded in metadata.
-                                let attrs: Vec<_> =
-                                    self.get_item_attrs(def_id.index, sess).collect();
-                                if sess.contains_name(&attrs, sym::non_exhaustive) {
+                                let mut attrs = self.get_item_attrs(def_id.index, sess);
+                                if attrs.any(|item| item.has_name(sym::non_exhaustive)) {
                                     let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
                                     vis = ty::Visibility::Restricted(crate_def_id);
                                 }
@@ -1164,6 +1158,10 @@
         }
     }
 
+    fn is_ctfe_mir_available(&self, id: DefIndex) -> bool {
+        self.root.tables.mir_for_ctfe.get(self, id).is_some()
+    }
+
     fn is_item_mir_available(&self, id: DefIndex) -> bool {
         self.root.tables.mir.get(self, id).is_some()
     }
@@ -1187,6 +1185,17 @@
             .decode((self, tcx))
     }
 
+    fn get_mir_for_ctfe(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
+        self.root
+            .tables
+            .mir_for_ctfe
+            .get(self, id)
+            .unwrap_or_else(|| {
+                bug!("get_mir_for_ctfe: missing MIR for `{:?}`", self.local_def_id(id))
+            })
+            .decode((self, tcx))
+    }
+
     fn get_mir_abstract_const(
         &self,
         tcx: TyCtxt<'tcx>,
@@ -1345,15 +1354,14 @@
             return &[];
         }
 
-        // Do a reverse lookup beforehand to avoid touching the crate_num
-        // hash map in the loop below.
-        let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) {
-            Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)),
-            Some(None) => return &[],
-            None => None,
-        };
+        if let Some(def_id) = filter {
+            // Do a reverse lookup beforehand to avoid touching the crate_num
+            // hash map in the loop below.
+            let filter = match self.reverse_translate_def_id(def_id) {
+                Some(def_id) => (def_id.krate.as_u32(), def_id.index),
+                None => return &[],
+            };
 
-        if let Some(filter) = filter {
             if let Some(impls) = self.trait_impls.get(&filter) {
                 tcx.arena.alloc_from_iter(
                     impls.decode(self).map(|(idx, simplified_self_ty)| {
@@ -1560,7 +1568,7 @@
         // stored in this crate.
         let map = self.cdata.def_path_hash_map.get_or_init(|| {
             let end_id = self.root.tables.def_path_hashes.size() as u32;
-            let mut map = FxHashMap::with_capacity_and_hasher(end_id as usize, Default::default());
+            let mut map = UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default());
             for i in 0..end_id {
                 let def_index = DefIndex::from_u32(i);
                 // There may be gaps in the encoded table if we're decoding a proc-macro crate
@@ -1597,31 +1605,6 @@
         self.def_path_hash_unlocked(index, &mut def_path_hashes)
     }
 
-    /// Get the `DepNodeIndex` corresponding this crate. The result of this
-    /// method is cached in the `dep_node_index` field.
-    fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex {
-        let mut dep_node_index = self.dep_node_index.load();
-
-        if unlikely!(dep_node_index == DepNodeIndex::INVALID) {
-            // We have not cached the DepNodeIndex for this upstream crate yet,
-            // so use the dep-graph to find it out and cache it.
-            // Note that multiple threads can enter this block concurrently.
-            // That is fine because the DepNodeIndex remains constant
-            // throughout the whole compilation session, and multiple stores
-            // would always write the same value.
-
-            let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX);
-            let dep_node =
-                DepNode::from_def_path_hash(def_path_hash, dep_graph::DepKind::CrateMetadata);
-
-            dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node);
-            assert!(dep_node_index != DepNodeIndex::INVALID);
-            self.dep_node_index.store(dep_node_index);
-        }
-
-        dep_node_index
-    }
-
     /// Imports the source_map from an external crate into the source_map of the crate
     /// currently being compiled (the "local crate").
     ///
@@ -1838,7 +1821,6 @@
             source_map_import_info: OnceCell::new(),
             def_path_hash_map: Default::default(),
             alloc_decoding_state,
-            dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
             cnum,
             cnum_map,
             dependencies,
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index b7f2288..17ce4a5 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -44,13 +44,16 @@
                 let ($def_id, $other) = def_id_arg.into_args();
                 assert!(!$def_id.is_local());
 
-                let $cdata = CStore::from_tcx($tcx).get_crate_data($def_id.krate);
-
-                if $tcx.dep_graph.is_fully_enabled() {
-                    let crate_dep_node_index = $cdata.get_crate_dep_node_index($tcx);
-                    $tcx.dep_graph.read_index(crate_dep_node_index);
+                // External query providers call `crate_hash` in order to register a dependency
+                // on the crate metadata. The exception is `crate_hash` itself, which obviously
+                // doesn't need to do this (and can't, as it would cause a query cycle).
+                use rustc_middle::dep_graph::DepKind;
+                if DepKind::$name != DepKind::crate_hash && $tcx.dep_graph.is_fully_enabled() {
+                    $tcx.ensure().crate_hash($def_id.krate);
                 }
 
+                let $cdata = CStore::from_tcx($tcx).get_crate_data($def_id.krate);
+
                 $compute
             })*
 
@@ -115,6 +118,7 @@
         })
     }
     optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) }
+    mir_for_ctfe => { tcx.arena.alloc(cdata.get_mir_for_ctfe(tcx, def_id.index)) }
     promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) }
     mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) }
     unused_generic_params => { cdata.get_unused_generic_params(def_id.index) }
@@ -128,6 +132,9 @@
     generator_kind => { cdata.generator_kind(def_id.index) }
     def_kind => { cdata.def_kind(def_id.index) }
     def_span => { cdata.get_span(def_id.index, &tcx.sess) }
+    def_ident_span => {
+        cdata.try_item_ident(def_id.index, &tcx.sess).ok().map(|ident| ident.span)
+    }
     lookup_stability => {
         cdata.get_stability(def_id.index).map(|s| tcx.intern_stability(s))
     }
@@ -145,6 +152,7 @@
     impl_parent => { cdata.get_parent_impl(def_id.index) }
     trait_of_item => { cdata.get_trait_of_item(def_id.index) }
     is_mir_available => { cdata.is_item_mir_available(def_id.index) }
+    is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
 
     dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) }
     is_panic_runtime => { cdata.root.panic_runtime }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 4dfe3e8..5e26742 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -46,7 +46,7 @@
 
     lazy_state: LazyState,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
-    predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
+    predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
 
     interpret_allocs: FxIndexSet<interpret::AllocId>,
 
@@ -66,6 +66,11 @@
     required_source_files: Option<GrowableBitSet<usize>>,
     is_proc_macro: bool,
     hygiene_ctxt: &'a HygieneEncodeContext,
+
+    // Determines if MIR used for code generation will be included in the crate
+    // metadata. When emitting only metadata (e.g., cargo check), we can avoid
+    // generating optimized MIR altogether.
+    emit_codegen_mir: bool,
 }
 
 /// If the current crate is a proc-macro, returns early with `Lazy:empty()`.
@@ -308,7 +313,7 @@
 
 impl<'a, 'tcx> FingerprintEncoder for EncodeContext<'a, 'tcx> {
     fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
-        f.encode_opaque(&mut self.opaque)
+        self.opaque.encode_fingerprint(f)
     }
 }
 
@@ -323,7 +328,7 @@
         &mut self.type_shorthands
     }
 
-    fn predicate_shorthands(&mut self) -> &mut FxHashMap<rustc_middle::ty::Predicate<'tcx>, usize> {
+    fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
         &mut self.predicate_shorthands
     }
 
@@ -694,7 +699,7 @@
             println!("       lang item bytes: {}", lang_item_bytes);
             println!(" diagnostic item bytes: {}", diagnostic_item_bytes);
             println!("          native bytes: {}", native_lib_bytes);
-            println!("         source_map bytes: {}", source_map_bytes);
+            println!("      source_map bytes: {}", source_map_bytes);
             println!("            impl bytes: {}", impl_bytes);
             println!("    exp. symbols bytes: {}", exported_symbols_bytes);
             println!("  def-path table bytes: {}", def_path_table_bytes);
@@ -758,8 +763,6 @@
         self.encode_generics(def_id);
         self.encode_explicit_predicates(def_id);
         self.encode_inferred_outlives(def_id);
-        self.encode_optimized_mir(def_id.expect_local());
-        self.encode_promoted_mir(def_id.expect_local());
     }
 
     fn encode_enum_variant_ctor(&mut self, def: &ty::AdtDef, index: VariantIdx) {
@@ -789,8 +792,11 @@
         self.encode_generics(def_id);
         self.encode_explicit_predicates(def_id);
         self.encode_inferred_outlives(def_id);
-        self.encode_optimized_mir(def_id.expect_local());
-        self.encode_promoted_mir(def_id.expect_local());
+        let opt_mir = tcx.sess.opts.debugging_opts.always_encode_mir || self.emit_codegen_mir;
+        if opt_mir {
+            self.encode_optimized_mir(def_id.expect_local());
+        }
+        self.encode_mir_for_ctfe(def_id.expect_local());
     }
 
     fn encode_info_for_mod(&mut self, id: hir::HirId, md: &hir::Mod<'_>, attrs: &[ast::Attribute]) {
@@ -896,8 +902,11 @@
         self.encode_generics(def_id);
         self.encode_explicit_predicates(def_id);
         self.encode_inferred_outlives(def_id);
-        self.encode_optimized_mir(def_id.expect_local());
-        self.encode_promoted_mir(def_id.expect_local());
+        let opt_mir = tcx.sess.opts.debugging_opts.always_encode_mir || self.emit_codegen_mir;
+        if opt_mir {
+            self.encode_optimized_mir(def_id.expect_local());
+        }
+        self.encode_mir_for_ctfe(def_id.expect_local());
     }
 
     fn encode_generics(&mut self, def_id: DefId) {
@@ -1015,13 +1024,32 @@
         self.encode_inferred_outlives(def_id);
 
         // This should be kept in sync with `PrefetchVisitor.visit_trait_item`.
-        self.encode_optimized_mir(def_id.expect_local());
-        self.encode_promoted_mir(def_id.expect_local());
+        match trait_item.kind {
+            ty::AssocKind::Type => {}
+            ty::AssocKind::Const => {
+                if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id.expect_local()) {
+                    self.encode_mir_for_ctfe(def_id.expect_local());
+                    self.encode_promoted_mir(def_id.expect_local());
+                }
+            }
+            ty::AssocKind::Fn => {
+                let opt_mir =
+                    tcx.sess.opts.debugging_opts.always_encode_mir || self.emit_codegen_mir;
+                if opt_mir {
+                    if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id.expect_local()) {
+                        self.encode_optimized_mir(def_id.expect_local());
+                        self.encode_promoted_mir(def_id.expect_local());
+                    }
+                }
+            }
+        }
     }
 
-    fn metadata_output_only(&self) -> bool {
-        // MIR optimisation can be skipped when we're just interested in the metadata.
-        !self.tcx.sess.opts.output_types.should_codegen()
+    fn should_encode_fn_opt_mir(&self, def_id: DefId) -> bool {
+        self.tcx.sess.opts.debugging_opts.always_encode_mir
+            || (self.emit_codegen_mir
+                && (self.tcx.generics_of(def_id).requires_monomorphization(self.tcx)
+                    || self.tcx.codegen_fn_attrs(def_id).requests_inline()))
     }
 
     fn encode_info_for_impl_item(&mut self, def_id: DefId) {
@@ -1089,23 +1117,24 @@
 
         // The following part should be kept in sync with `PrefetchVisitor.visit_impl_item`.
 
-        let mir = match ast_item.kind {
-            hir::ImplItemKind::Const(..) => true,
+        let (mir, mir_const) = match ast_item.kind {
+            hir::ImplItemKind::Const(..) => (false, true),
             hir::ImplItemKind::Fn(ref sig, _) => {
-                let generics = self.tcx.generics_of(def_id);
-                let needs_inline = (generics.requires_monomorphization(self.tcx)
-                    || tcx.codegen_fn_attrs(def_id).requests_inline())
-                    && !self.metadata_output_only();
+                let opt_mir = self.should_encode_fn_opt_mir(def_id);
                 let is_const_fn = sig.header.constness == hir::Constness::Const;
-                let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
-                needs_inline || is_const_fn || always_encode_mir
+                (opt_mir, is_const_fn)
             }
-            hir::ImplItemKind::TyAlias(..) => false,
+            hir::ImplItemKind::TyAlias(..) => (false, false),
         };
         if mir {
             self.encode_optimized_mir(def_id.expect_local());
+        }
+        if mir || mir_const {
             self.encode_promoted_mir(def_id.expect_local());
         }
+        if mir_const {
+            self.encode_mir_for_ctfe(def_id.expect_local());
+        }
     }
 
     fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[Ident]> {
@@ -1116,28 +1145,34 @@
         self.lazy(param_names.iter())
     }
 
+    fn encode_mir_for_ctfe(&mut self, def_id: LocalDefId) {
+        debug!("EntryBuilder::encode_mir_for_ctfe({:?})", def_id);
+        record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- self.tcx.mir_for_ctfe(def_id));
+
+        let unused = self.tcx.unused_generic_params(def_id);
+        if !unused.is_empty() {
+            record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
+        }
+
+        let abstract_const = self.tcx.mir_abstract_const(def_id);
+        if let Ok(Some(abstract_const)) = abstract_const {
+            record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const);
+        }
+    }
+
     fn encode_optimized_mir(&mut self, def_id: LocalDefId) {
-        debug!("EntryBuilder::encode_mir({:?})", def_id);
-        if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
-            record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id));
+        debug!("EntryBuilder::encode_optimized_mir({:?})", def_id);
+        record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id));
 
-            let unused = self.tcx.unused_generic_params(def_id);
-            if !unused.is_empty() {
-                record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
-            }
-
-            let abstract_const = self.tcx.mir_abstract_const(def_id);
-            if let Ok(Some(abstract_const)) = abstract_const {
-                record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const);
-            }
+        let unused = self.tcx.unused_generic_params(def_id);
+        if !unused.is_empty() {
+            record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
         }
     }
 
     fn encode_promoted_mir(&mut self, def_id: LocalDefId) {
         debug!("EncodeContext::encode_promoted_mir({:?})", def_id);
-        if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
-            record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id));
-        }
+        record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id));
     }
 
     // Encodes the inherent implementations of a structure, enumeration, or trait.
@@ -1259,7 +1294,7 @@
                     is_non_exhaustive: variant.is_field_list_non_exhaustive(),
                 }), adt_def.repr)
             }
-            hir::ItemKind::Impl { defaultness, .. } => {
+            hir::ItemKind::Impl(hir::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 {
@@ -1406,22 +1441,25 @@
 
         // The following part should be kept in sync with `PrefetchVisitor.visit_item`.
 
-        let mir = match item.kind {
-            hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true,
+        let (mir, const_mir) = match item.kind {
+            hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => (false, true),
             hir::ItemKind::Fn(ref sig, ..) => {
-                let generics = tcx.generics_of(def_id);
-                let needs_inline = (generics.requires_monomorphization(tcx)
-                    || tcx.codegen_fn_attrs(def_id).requests_inline())
-                    && !self.metadata_output_only();
-                let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
-                needs_inline || sig.header.constness == hir::Constness::Const || always_encode_mir
+                let opt_mir = self.should_encode_fn_opt_mir(def_id);
+                let is_const_fn = sig.header.constness == hir::Constness::Const;
+                // We don't need the optimized MIR for const fns.
+                (opt_mir, is_const_fn)
             }
-            _ => false,
+            _ => (false, false),
         };
         if mir {
             self.encode_optimized_mir(def_id.expect_local());
+        }
+        if mir || const_mir {
             self.encode_promoted_mir(def_id.expect_local());
         }
+        if const_mir {
+            self.encode_mir_for_ctfe(def_id.expect_local());
+        }
     }
 
     /// Serialize the text of exported macros
@@ -1469,8 +1507,14 @@
             record!(self.tables.fn_sig[def_id] <- substs.as_closure().sig());
         }
         self.encode_generics(def_id.to_def_id());
-        self.encode_optimized_mir(def_id);
-        self.encode_promoted_mir(def_id);
+        let opt_mir = // FIXME: Optimized MIR is necessary to determine the layout of generators.
+            matches!(ty.kind(), ty::Generator(..))
+            || self.tcx.sess.opts.debugging_opts.always_encode_mir
+            || self.emit_codegen_mir;
+        if opt_mir {
+            self.encode_optimized_mir(def_id);
+            self.encode_promoted_mir(def_id);
+        }
     }
 
     fn encode_info_for_anon_const(&mut self, def_id: LocalDefId) {
@@ -1486,7 +1530,7 @@
         self.encode_generics(def_id.to_def_id());
         self.encode_explicit_predicates(def_id.to_def_id());
         self.encode_inferred_outlives(def_id.to_def_id());
-        self.encode_optimized_mir(def_id);
+        self.encode_mir_for_ctfe(def_id);
         self.encode_promoted_mir(def_id);
     }
 
@@ -1834,7 +1878,7 @@
                         EntryKind::ConstParam,
                         true,
                     );
-                    // FIXME(const_generics:defaults)
+                    // FIXME(const_generics_defaults)
                 }
             }
         }
@@ -1951,6 +1995,12 @@
 }
 
 impl<'tcx> PrefetchVisitor<'tcx> {
+    fn prefetch_ctfe_mir(&self, def_id: LocalDefId) {
+        if self.mir_keys.contains(&def_id) {
+            self.tcx.ensure().mir_for_ctfe(def_id);
+            self.tcx.ensure().promoted_mir(def_id);
+        }
+    }
     fn prefetch_mir(&self, def_id: LocalDefId) {
         if self.mir_keys.contains(&def_id) {
             self.tcx.ensure().optimized_mir(def_id);
@@ -1965,16 +2015,18 @@
         let tcx = self.tcx;
         match item.kind {
             hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => {
-                self.prefetch_mir(tcx.hir().local_def_id(item.hir_id))
+                self.prefetch_ctfe_mir(tcx.hir().local_def_id(item.hir_id))
             }
             hir::ItemKind::Fn(ref sig, ..) => {
                 let def_id = tcx.hir().local_def_id(item.hir_id);
-                let generics = tcx.generics_of(def_id.to_def_id());
-                let needs_inline = generics.requires_monomorphization(tcx)
+                let opt_mir = tcx.generics_of(def_id.to_def_id()).requires_monomorphization(tcx)
                     || tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline();
-                if needs_inline || sig.header.constness == hir::Constness::Const {
+                if opt_mir {
                     self.prefetch_mir(def_id)
                 }
+                if sig.header.constness == hir::Constness::Const {
+                    self.prefetch_ctfe_mir(def_id);
+                }
             }
             _ => (),
         }
@@ -1982,7 +2034,16 @@
 
     fn visit_trait_item(&self, trait_item: &'v hir::TraitItem<'v>) {
         // This should be kept in sync with `encode_info_for_trait_item`.
-        self.prefetch_mir(self.tcx.hir().local_def_id(trait_item.hir_id));
+        let def_id = self.tcx.hir().local_def_id(trait_item.hir_id);
+        match trait_item.kind {
+            hir::TraitItemKind::Type(..) => {}
+            hir::TraitItemKind::Const(..) => {
+                self.prefetch_ctfe_mir(def_id);
+            }
+            hir::TraitItemKind::Fn(..) => {
+                self.prefetch_mir(def_id);
+            }
+        }
     }
 
     fn visit_impl_item(&self, impl_item: &'v hir::ImplItem<'v>) {
@@ -1990,17 +2051,19 @@
         let tcx = self.tcx;
         match impl_item.kind {
             hir::ImplItemKind::Const(..) => {
-                self.prefetch_mir(tcx.hir().local_def_id(impl_item.hir_id))
+                self.prefetch_ctfe_mir(tcx.hir().local_def_id(impl_item.hir_id))
             }
             hir::ImplItemKind::Fn(ref sig, _) => {
                 let def_id = tcx.hir().local_def_id(impl_item.hir_id);
-                let generics = tcx.generics_of(def_id.to_def_id());
-                let needs_inline = generics.requires_monomorphization(tcx)
+                let opt_mir = tcx.generics_of(def_id.to_def_id()).requires_monomorphization(tcx)
                     || tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline();
                 let is_const_fn = sig.header.constness == hir::Constness::Const;
-                if needs_inline || is_const_fn {
+                if opt_mir {
                     self.prefetch_mir(def_id)
                 }
+                if is_const_fn {
+                    self.prefetch_ctfe_mir(def_id);
+                }
             }
             hir::ImplItemKind::TyAlias(..) => (),
         }
@@ -2094,6 +2157,7 @@
         required_source_files,
         is_proc_macro: tcx.sess.crate_types().contains(&CrateType::ProcMacro),
         hygiene_ctxt: &hygiene_ctxt,
+        emit_codegen_mir: tcx.sess.opts.output_types.should_codegen(),
     };
 
     // Encode the rustc version string in a predictable location.
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 5360617..59a8bc7 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -302,6 +302,7 @@
     // As an optimization, a missing entry indicates an empty `&[]`.
     explicit_item_bounds: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>,
     mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
+    mir_for_ctfe: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
     promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
     mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,
     unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index d954c8a..62f2874 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -29,9 +29,10 @@
 //!   contained no `DefId` for thing that had been removed.
 //!
 //! `DepNode` definition happens in the `define_dep_nodes!()` macro. This macro
-//! defines the `DepKind` enum and a corresponding `DepConstructor` enum. The
-//! `DepConstructor` enum links a `DepKind` to the parameters that are needed at
-//! runtime in order to construct a valid `DepNode` fingerprint.
+//! defines the `DepKind` enum. Each `DepKind` has its own parameters that are
+//! needed at runtime in order to construct a valid `DepNode` fingerprint.
+//! However, only `CompileCodegenUnit` is constructed explicitly (with
+//! `make_compile_codegen_unit`).
 //!
 //! Because the macro sees what parameters a given `DepKind` requires, it can
 //! "infer" some properties for each kind of `DepNode`:
@@ -44,32 +45,118 @@
 //!   `DefId` it was computed from. In other cases, too much information gets
 //!   lost during fingerprint computation.
 //!
-//! The `DepConstructor` enum, together with `DepNode::new()`, ensures that only
+//! `make_compile_codegen_unit`, together with `DepNode::new()`, ensures that only
 //! valid `DepNode` instances can be constructed. For example, the API does not
 //! allow for constructing parameterless `DepNode`s with anything other
 //! than a zeroed out fingerprint. More generally speaking, it relieves the
 //! user of the `DepNode` API of having to know how to compute the expected
 //! fingerprint for a given set of node parameters.
 
-use crate::mir::interpret::{GlobalId, LitToConstInput};
-use crate::traits;
-use crate::traits::query::{
-    CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
-    CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
-    CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
-};
-use crate::ty::subst::{GenericArg, SubstsRef};
-use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
+use crate::ty::TyCtxt;
 
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::definitions::DefPathHash;
 use rustc_hir::HirId;
 use rustc_span::symbol::Symbol;
+use rustc_span::DUMMY_SP;
 use std::hash::Hash;
 
 pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams};
 
+/// This struct stores metadata about each DepKind.
+///
+/// Information is retrieved by indexing the `DEP_KINDS` array using the integer value
+/// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual
+/// jump table instead of large matches.
+pub struct DepKindStruct {
+    /// Whether the DepNode has parameters (query keys).
+    pub(super) has_params: bool,
+
+    /// Anonymous queries cannot be replayed from one compiler invocation to the next.
+    /// When their result is needed, it is recomputed. They are useful for fine-grained
+    /// dependency tracking, and caching within one compiler invocation.
+    pub(super) is_anon: bool,
+
+    /// Eval-always queries do not track their dependencies, and are always recomputed, even if
+    /// their inputs have not changed since the last compiler invocation. The result is still
+    /// cached within one compiler invocation.
+    pub(super) is_eval_always: bool,
+
+    /// Whether the query key can be recovered from the hashed fingerprint.
+    /// See [DepNodeParams] trait for the behaviour of each key type.
+    // FIXME: Make this a simple boolean once DepNodeParams::can_reconstruct_query_key
+    // can be made a specialized associated const.
+    can_reconstruct_query_key: fn() -> bool,
+
+    /// The red/green evaluation system will try to mark a specific DepNode in the
+    /// dependency graph as green by recursively trying to mark the dependencies of
+    /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
+    /// where we don't know if it is red or green and we therefore actually have
+    /// to recompute its value in order to find out. Since the only piece of
+    /// information that we have at that point is the `DepNode` we are trying to
+    /// re-evaluate, we need some way to re-run a query from just that. This is what
+    /// `force_from_dep_node()` implements.
+    ///
+    /// In the general case, a `DepNode` consists of a `DepKind` and an opaque
+    /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
+    /// is usually constructed by computing a stable hash of the query-key that the
+    /// `DepNode` corresponds to. Consequently, it is not in general possible to go
+    /// back from hash to query-key (since hash functions are not reversible). For
+    /// this reason `force_from_dep_node()` is expected to fail from time to time
+    /// because we just cannot find out, from the `DepNode` alone, what the
+    /// corresponding query-key is and therefore cannot re-run the query.
+    ///
+    /// The system deals with this case letting `try_mark_green` fail which forces
+    /// the root query to be re-evaluated.
+    ///
+    /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
+    /// Fortunately, we can use some contextual information that will allow us to
+    /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
+    /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
+    /// valid `DefPathHash`. Since we also always build a huge table that maps every
+    /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
+    /// everything we need to re-run the query.
+    ///
+    /// Take the `mir_promoted` query as an example. Like many other queries, it
+    /// just has a single parameter: the `DefId` of the item it will compute the
+    /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
+    /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
+    /// is actually a `DefPathHash`, and can therefore just look up the corresponding
+    /// `DefId` in `tcx.def_path_hash_to_def_id`.
+    ///
+    /// When you implement a new query, it will likely have a corresponding new
+    /// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
+    /// a rule of thumb, if your query takes a `DefId` or `LocalDefId` as sole parameter,
+    /// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
+    /// add it to the "We don't have enough information to reconstruct..." group in
+    /// the match below.
+    pub(super) force_from_dep_node: fn(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool,
+
+    /// Invoke a query to put the on-disk cached value in memory.
+    pub(super) try_load_from_on_disk_cache: fn(TyCtxt<'_>, &DepNode),
+}
+
+impl std::ops::Deref for DepKind {
+    type Target = DepKindStruct;
+    fn deref(&self) -> &DepKindStruct {
+        &DEP_KINDS[*self as usize]
+    }
+}
+
+impl DepKind {
+    #[inline(always)]
+    pub fn can_reconstruct_query_key(&self) -> bool {
+        // Only fetch the DepKindStruct once.
+        let data: &DepKindStruct = &**self;
+        if data.is_anon {
+            return false;
+        }
+
+        (data.can_reconstruct_query_key)()
+    }
+}
+
 // erase!() just makes tokens go away. It's used to specify which macro argument
 // is repeated (i.e., which sub-expression of the macro we are in) but don't need
 // to actually use any of the arguments.
@@ -103,6 +190,120 @@
     ($($attr:ident $(($($attr_args:tt)*))* ),*) => ({$(is_eval_always_attr!($attr) | )* false});
 }
 
+#[allow(non_upper_case_globals)]
+pub mod dep_kind {
+    use super::*;
+    use crate::ty::query::{queries, query_keys};
+    use rustc_query_system::query::{force_query, QueryDescription};
+
+    // We use this for most things when incr. comp. is turned off.
+    pub const Null: DepKindStruct = DepKindStruct {
+        has_params: false,
+        is_anon: false,
+        is_eval_always: false,
+
+        can_reconstruct_query_key: || true,
+        force_from_dep_node: |_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node),
+        try_load_from_on_disk_cache: |_, _| {},
+    };
+
+    pub const TraitSelect: DepKindStruct = DepKindStruct {
+        has_params: false,
+        is_anon: true,
+        is_eval_always: false,
+
+        can_reconstruct_query_key: || true,
+        force_from_dep_node: |_, _| false,
+        try_load_from_on_disk_cache: |_, _| {},
+    };
+
+    pub const CompileCodegenUnit: DepKindStruct = DepKindStruct {
+        has_params: true,
+        is_anon: false,
+        is_eval_always: false,
+
+        can_reconstruct_query_key: || false,
+        force_from_dep_node: |_, _| false,
+        try_load_from_on_disk_cache: |_, _| {},
+    };
+
+    macro_rules! define_query_dep_kinds {
+        ($(
+            [$($attrs:tt)*]
+            $variant:ident $(( $tuple_arg_ty:ty $(,)? ))*
+        ,)*) => (
+            $(pub const $variant: DepKindStruct = {
+                const has_params: bool = $({ erase!($tuple_arg_ty); true } |)* false;
+                const is_anon: bool = contains_anon_attr!($($attrs)*);
+                const is_eval_always: bool = contains_eval_always_attr!($($attrs)*);
+
+                #[inline(always)]
+                fn can_reconstruct_query_key() -> bool {
+                    <query_keys::$variant<'_> as DepNodeParams<TyCtxt<'_>>>
+                        ::can_reconstruct_query_key()
+                }
+
+                fn recover<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<query_keys::$variant<'tcx>> {
+                    <query_keys::$variant<'_> as DepNodeParams<TyCtxt<'_>>>::recover(tcx, dep_node)
+                }
+
+                fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool {
+                    if is_anon {
+                        return false;
+                    }
+
+                    if !can_reconstruct_query_key() {
+                        return false;
+                    }
+
+                    if let Some(key) = recover(tcx, dep_node) {
+                        force_query::<queries::$variant<'_>, _>(
+                            tcx,
+                            key,
+                            DUMMY_SP,
+                            *dep_node
+                        );
+                        return true;
+                    }
+
+                    false
+                }
+
+                fn try_load_from_on_disk_cache(tcx: TyCtxt<'_>, dep_node: &DepNode) {
+                    if is_anon {
+                        return
+                    }
+
+                    if !can_reconstruct_query_key() {
+                        return
+                    }
+
+                    debug_assert!(tcx.dep_graph
+                                     .node_color(dep_node)
+                                     .map(|c| c.is_green())
+                                     .unwrap_or(false));
+
+                    let key = recover(tcx, dep_node).unwrap_or_else(|| panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash));
+                    if queries::$variant::cache_on_disk(tcx, &key, None) {
+                        let _ = tcx.$variant(key);
+                    }
+                }
+
+                DepKindStruct {
+                    has_params,
+                    is_anon,
+                    is_eval_always,
+                    can_reconstruct_query_key,
+                    force_from_dep_node,
+                    try_load_from_on_disk_cache,
+                }
+            };)*
+        );
+    }
+
+    rustc_dep_node_append!([define_query_dep_kinds!][]);
+}
+
 macro_rules! define_dep_nodes {
     (<$tcx:tt>
     $(
@@ -110,182 +311,19 @@
         $variant:ident $(( $tuple_arg_ty:ty $(,)? ))*
       ,)*
     ) => (
-        #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
+        static DEP_KINDS: &[DepKindStruct] = &[ $(dep_kind::$variant),* ];
+
+        /// This enum serves as an index into the `DEP_KINDS` array.
+        #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
         #[allow(non_camel_case_types)]
         pub enum DepKind {
             $($variant),*
         }
 
-        impl DepKind {
-            #[allow(unreachable_code)]
-            pub fn can_reconstruct_query_key<$tcx>(&self) -> bool {
-                match *self {
-                    $(
-                        DepKind :: $variant => {
-                            if contains_anon_attr!($($attrs)*) {
-                                return false;
-                            }
-
-                            // tuple args
-                            $({
-                                return <$tuple_arg_ty as DepNodeParams<TyCtxt<'_>>>
-                                    ::can_reconstruct_query_key();
-                            })*
-
-                            true
-                        }
-                    )*
-                }
-            }
-
-            pub fn is_anon(&self) -> bool {
-                match *self {
-                    $(
-                        DepKind :: $variant => { contains_anon_attr!($($attrs)*) }
-                    )*
-                }
-            }
-
-            pub fn is_eval_always(&self) -> bool {
-                match *self {
-                    $(
-                        DepKind :: $variant => { contains_eval_always_attr!($($attrs)*) }
-                    )*
-                }
-            }
-
-            #[allow(unreachable_code)]
-            pub fn has_params(&self) -> bool {
-                match *self {
-                    $(
-                        DepKind :: $variant => {
-                            // tuple args
-                            $({
-                                erase!($tuple_arg_ty);
-                                return true;
-                            })*
-
-                            false
-                        }
-                    )*
-                }
-            }
-        }
-
-        pub struct DepConstructor;
-
-        #[allow(non_camel_case_types)]
-        impl DepConstructor {
-            $(
-                #[inline(always)]
-                #[allow(unreachable_code, non_snake_case)]
-                pub fn $variant(_tcx: TyCtxt<'_>, $(arg: $tuple_arg_ty)*) -> DepNode {
-                    // tuple args
-                    $({
-                        erase!($tuple_arg_ty);
-                        return DepNode::construct(_tcx, DepKind::$variant, &arg)
-                    })*
-
-                    return DepNode::construct(_tcx, DepKind::$variant, &())
-                }
-            )*
-        }
-
-        pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>;
-
-        // We keep a lot of `DepNode`s in memory during compilation. It's not
-        // required that their size stay the same, but we don't want to change
-        // it inadvertently. This assert just ensures we're aware of any change.
-        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-        static_assert_size!(DepNode, 17);
-
-        #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
-        static_assert_size!(DepNode, 24);
-
-        pub trait DepNodeExt: Sized {
-            /// Construct a DepNode from the given DepKind and DefPathHash. This
-            /// method will assert that the given DepKind actually requires a
-            /// single DefId/DefPathHash parameter.
-            fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> Self;
-
-            /// Extracts the DefId corresponding to this DepNode. This will work
-            /// if two conditions are met:
-            ///
-            /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
-            /// 2. the item that the DefPath refers to exists in the current tcx.
-            ///
-            /// Condition (1) is determined by the DepKind variant of the
-            /// DepNode. Condition (2) might not be fulfilled if a DepNode
-            /// refers to something from the previous compilation session that
-            /// has been removed.
-            fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId>;
-
-            /// Used in testing
-            fn from_label_string(label: &str, def_path_hash: DefPathHash)
-                -> Result<Self, ()>;
-
-            /// Used in testing
-            fn has_label_string(label: &str) -> bool;
-        }
-
-        impl DepNodeExt for DepNode {
-            /// Construct a DepNode from the given DepKind and DefPathHash. This
-            /// method will assert that the given DepKind actually requires a
-            /// single DefId/DefPathHash parameter.
-            fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode {
-                debug_assert!(kind.can_reconstruct_query_key() && kind.has_params());
-                DepNode {
-                    kind,
-                    hash: def_path_hash.0.into(),
-                }
-            }
-
-            /// Extracts the DefId corresponding to this DepNode. This will work
-            /// if two conditions are met:
-            ///
-            /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
-            /// 2. the item that the DefPath refers to exists in the current tcx.
-            ///
-            /// Condition (1) is determined by the DepKind variant of the
-            /// DepNode. Condition (2) might not be fulfilled if a DepNode
-            /// refers to something from the previous compilation session that
-            /// has been removed.
-            fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> {
-                if self.kind.can_reconstruct_query_key() {
-                    tcx.queries.on_disk_cache.as_ref()?.def_path_hash_to_def_id(tcx, DefPathHash(self.hash.into()))
-                } else {
-                    None
-                }
-            }
-
-            /// Used in testing
-            fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result<DepNode, ()> {
-                let kind = match label {
-                    $(
-                        stringify!($variant) => DepKind::$variant,
-                    )*
-                    _ => return Err(()),
-                };
-
-                if !kind.can_reconstruct_query_key() {
-                    return Err(());
-                }
-
-                if kind.has_params() {
-                    Ok(DepNode::from_def_path_hash(def_path_hash, kind))
-                } else {
-                    Ok(DepNode::new_no_params(kind))
-                }
-            }
-
-            /// Used in testing
-            fn has_label_string(label: &str) -> bool {
-                match label {
-                    $(
-                        stringify!($variant) => true,
-                    )*
-                    _ => false,
-                }
+        fn dep_kind_from_label_string(label: &str) -> Result<DepKind, ()> {
+            match label {
+                $(stringify!($variant) => Ok(DepKind::$variant),)*
+                _ => Err(()),
             }
         }
 
@@ -304,16 +342,122 @@
     // We use this for most things when incr. comp. is turned off.
     [] Null,
 
-    // Represents metadata from an extern crate.
-    [eval_always] CrateMetadata(CrateNum),
-
     [anon] TraitSelect,
 
+    // WARNING: if `Symbol` is changed, make sure you update `make_compile_codegen_unit` below.
     [] CompileCodegenUnit(Symbol),
 ]);
 
+// WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys.
+// Be very careful changing this type signature!
+crate fn make_compile_codegen_unit(tcx: TyCtxt<'_>, name: Symbol) -> DepNode {
+    DepNode::construct(tcx, DepKind::CompileCodegenUnit, &name)
+}
+
+pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>;
+
+// We keep a lot of `DepNode`s in memory during compilation. It's not
+// required that their size stay the same, but we don't want to change
+// it inadvertently. This assert just ensures we're aware of any change.
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+static_assert_size!(DepNode, 17);
+
+#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+static_assert_size!(DepNode, 24);
+
+pub trait DepNodeExt: Sized {
+    /// Construct a DepNode from the given DepKind and DefPathHash. This
+    /// method will assert that the given DepKind actually requires a
+    /// single DefId/DefPathHash parameter.
+    fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> Self;
+
+    /// Extracts the DefId corresponding to this DepNode. This will work
+    /// if two conditions are met:
+    ///
+    /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
+    /// 2. the item that the DefPath refers to exists in the current tcx.
+    ///
+    /// Condition (1) is determined by the DepKind variant of the
+    /// DepNode. Condition (2) might not be fulfilled if a DepNode
+    /// refers to something from the previous compilation session that
+    /// has been removed.
+    fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId>;
+
+    /// Used in testing
+    fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result<Self, ()>;
+
+    /// Used in testing
+    fn has_label_string(label: &str) -> bool;
+}
+
+impl DepNodeExt for DepNode {
+    /// Construct a DepNode from the given DepKind and DefPathHash. This
+    /// method will assert that the given DepKind actually requires a
+    /// single DefId/DefPathHash parameter.
+    fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode {
+        debug_assert!(kind.can_reconstruct_query_key() && kind.has_params);
+        DepNode { kind, hash: def_path_hash.0.into() }
+    }
+
+    /// Extracts the DefId corresponding to this DepNode. This will work
+    /// if two conditions are met:
+    ///
+    /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
+    /// 2. the item that the DefPath refers to exists in the current tcx.
+    ///
+    /// Condition (1) is determined by the DepKind variant of the
+    /// DepNode. Condition (2) might not be fulfilled if a DepNode
+    /// refers to something from the previous compilation session that
+    /// has been removed.
+    fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> {
+        if self.kind.can_reconstruct_query_key() {
+            tcx.queries
+                .on_disk_cache
+                .as_ref()?
+                .def_path_hash_to_def_id(tcx, DefPathHash(self.hash.into()))
+        } else {
+            None
+        }
+    }
+
+    /// Used in testing
+    fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result<DepNode, ()> {
+        let kind = dep_kind_from_label_string(label)?;
+
+        if !kind.can_reconstruct_query_key() {
+            return Err(());
+        }
+
+        if kind.has_params {
+            Ok(DepNode::from_def_path_hash(def_path_hash, kind))
+        } else {
+            Ok(DepNode::new_no_params(kind))
+        }
+    }
+
+    /// Used in testing
+    fn has_label_string(label: &str) -> bool {
+        dep_kind_from_label_string(label).is_ok()
+    }
+}
+
+impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for () {
+    #[inline(always)]
+    fn can_reconstruct_query_key() -> bool {
+        true
+    }
+
+    fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint {
+        Fingerprint::ZERO
+    }
+
+    fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
+        Some(())
+    }
+}
+
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
-    #[inline]
+    #[inline(always)]
     fn can_reconstruct_query_key() -> bool {
         true
     }
@@ -342,7 +486,7 @@
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
-    #[inline]
+    #[inline(always)]
     fn can_reconstruct_query_key() -> bool {
         true
     }
@@ -361,7 +505,7 @@
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
-    #[inline]
+    #[inline(always)]
     fn can_reconstruct_query_key() -> bool {
         true
     }
@@ -381,7 +525,7 @@
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
-    #[inline]
+    #[inline(always)]
     fn can_reconstruct_query_key() -> bool {
         false
     }
@@ -406,7 +550,7 @@
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
-    #[inline]
+    #[inline(always)]
     fn can_reconstruct_query_key() -> bool {
         false
     }
diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs
index 728bfef..b88ffa2 100644
--- a/compiler/rustc_middle/src/dep_graph/mod.rs
+++ b/compiler/rustc_middle/src/dep_graph/mod.rs
@@ -1,5 +1,4 @@
 use crate::ich::StableHashingContext;
-use crate::ty::query::try_load_from_on_disk_cache;
 use crate::ty::{self, TyCtxt};
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sync::Lock;
@@ -9,13 +8,13 @@
 
 mod dep_node;
 
-pub(crate) use rustc_query_system::dep_graph::DepNodeParams;
 pub use rustc_query_system::dep_graph::{
     debug, hash_result, DepContext, DepNodeColor, DepNodeIndex, SerializedDepNodeIndex,
     WorkProduct, WorkProductId,
 };
 
-pub use dep_node::{label_strs, DepConstructor, DepKind, DepNode, DepNodeExt};
+crate use dep_node::make_compile_codegen_unit;
+pub use dep_node::{label_strs, DepKind, DepNode, DepNodeExt};
 
 pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepKind>;
 pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps<DepKind>;
@@ -26,18 +25,25 @@
 impl rustc_query_system::dep_graph::DepKind for DepKind {
     const NULL: Self = DepKind::Null;
 
-    fn is_eval_always(&self) -> bool {
-        DepKind::is_eval_always(self)
+    #[inline(always)]
+    fn can_reconstruct_query_key(&self) -> bool {
+        DepKind::can_reconstruct_query_key(self)
     }
 
+    #[inline(always)]
+    fn is_eval_always(&self) -> bool {
+        self.is_eval_always
+    }
+
+    #[inline(always)]
     fn has_params(&self) -> bool {
-        DepKind::has_params(self)
+        self.has_params
     }
 
     fn debug_node(node: &DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         write!(f, "{:?}", node.kind)?;
 
-        if !node.kind.has_params() && !node.kind.is_anon() {
+        if !node.kind.has_params && !node.kind.is_anon {
             return Ok(());
         }
 
@@ -81,10 +87,6 @@
             op(icx.task_deps)
         })
     }
-
-    fn can_reconstruct_query_key(&self) -> bool {
-        DepKind::can_reconstruct_query_key(self)
-    }
 }
 
 impl<'tcx> DepContext for TyCtxt<'tcx> {
@@ -114,20 +116,9 @@
         // be removed. https://github.com/rust-lang/rust/issues/62649 is one such
         // bug that must be fixed before removing this.
         match dep_node.kind {
-            DepKind::hir_owner | DepKind::hir_owner_nodes | DepKind::CrateMetadata => {
+            DepKind::hir_owner | DepKind::hir_owner_nodes => {
                 if let Some(def_id) = dep_node.extract_def_id(*self) {
-                    if def_id_corresponds_to_hir_dep_node(*self, def_id.expect_local()) {
-                        if dep_node.kind == DepKind::CrateMetadata {
-                            // The `DefPath` has corresponding node,
-                            // and that node should have been marked
-                            // either red or green in `data.colors`.
-                            bug!(
-                                "DepNode {:?} should have been \
-                             pre-marked as red or green but wasn't.",
-                                dep_node
-                            );
-                        }
-                    } else {
+                    if !def_id_corresponds_to_hir_dep_node(*self, def_id.expect_local()) {
                         // This `DefPath` does not have a
                         // corresponding `DepNode` (e.g. a
                         // struct field), and the ` DefPath`
@@ -153,7 +144,26 @@
         }
 
         debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node);
-        ty::query::force_from_dep_node(*self, dep_node)
+
+        // We must avoid ever having to call `force_from_dep_node()` for a
+        // `DepNode::codegen_unit`:
+        // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
+        // would always end up having to evaluate the first caller of the
+        // `codegen_unit` query that *is* reconstructible. This might very well be
+        // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
+        // to re-trigger calling the `codegen_unit` query with the right key. At
+        // that point we would already have re-done all the work we are trying to
+        // avoid doing in the first place.
+        // The solution is simple: Just explicitly call the `codegen_unit` query for
+        // each CGU, right after partitioning. This way `try_mark_green` will always
+        // hit the cache instead of having to go through `force_from_dep_node`.
+        // This assertion makes sure, we actually keep applying the solution above.
+        debug_assert!(
+            dep_node.kind != DepKind::codegen_unit,
+            "calling force_from_dep_node() on DepKind::codegen_unit"
+        );
+
+        (dep_node.kind.force_from_dep_node)(*self, dep_node)
     }
 
     fn has_errors_or_delayed_span_bugs(&self) -> bool {
@@ -166,7 +176,7 @@
 
     // Interactions with on_disk_cache
     fn try_load_from_on_disk_cache(&self, dep_node: &DepNode) {
-        try_load_from_on_disk_cache(*self, dep_node)
+        (dep_node.kind.try_load_from_on_disk_cache)(*self, dep_node)
     }
 
     fn load_diagnostics(&self, prev_dep_node_index: SerializedDepNodeIndex) -> Vec<Diagnostic> {
diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs
index 82cfca4..872fcb0 100644
--- a/compiler/rustc_middle/src/hir/map/collector.rs
+++ b/compiler/rustc_middle/src/hir/map/collector.rs
@@ -529,13 +529,22 @@
     }
 
     fn visit_macro_def(&mut self, macro_def: &'hir MacroDef<'hir>) {
-        self.with_dep_node_owner(macro_def.hir_id.owner, macro_def, |this, hash| {
-            this.insert_with_hash(
-                macro_def.span,
-                macro_def.hir_id,
-                Node::MacroDef(macro_def),
-                hash,
-            );
+        // Exported macros are visited directly from the crate root,
+        // so they do not have `parent_node` set.
+        // Find the correct enclosing module from their DefKey.
+        let def_key = self.definitions.def_key(macro_def.hir_id.owner);
+        let parent = def_key.parent.map_or(hir::CRATE_HIR_ID, |local_def_index| {
+            self.definitions.local_def_id_to_hir_id(LocalDefId { local_def_index })
+        });
+        self.with_parent(parent, |this| {
+            this.with_dep_node_owner(macro_def.hir_id.owner, macro_def, |this, hash| {
+                this.insert_with_hash(
+                    macro_def.span,
+                    macro_def.hir_id,
+                    Node::MacroDef(macro_def),
+                    hash,
+                );
+            })
         });
     }
 
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 09d5b10..06bb134 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -31,7 +31,7 @@
 impl<'hir> Entry<'hir> {
     fn parent_node(self) -> Option<HirId> {
         match self.node {
-            Node::Crate(_) | Node::MacroDef(_) => None,
+            Node::Crate(_) => None,
             _ => Some(self.parent),
         }
     }
@@ -505,7 +505,7 @@
                     | ItemKind::Union(_, generics)
                     | ItemKind::Trait(_, _, generics, ..)
                     | ItemKind::TraitAlias(generics, _)
-                    | ItemKind::Impl { generics, .. },
+                    | ItemKind::Impl(Impl { generics, .. }),
                 ..
             }) => Some(generics),
             _ => None,
@@ -658,12 +658,12 @@
         CRATE_HIR_ID
     }
 
-    /// When on a match arm tail expression or on a match arm, give back the enclosing `match`
-    /// expression.
+    /// When on an if expression, a match arm tail expression or a match arm, give back
+    /// the enclosing `if` or `match` expression.
     ///
-    /// Used by error reporting when there's a type error in a match arm caused by the `match`
+    /// Used by error reporting when there's a type error in an if or match arm caused by the
     /// expression needing to be unit.
-    pub fn get_match_if_cause(&self, hir_id: HirId) -> Option<&'hir Expr<'hir>> {
+    pub fn get_if_cause(&self, hir_id: HirId) -> Option<&'hir Expr<'hir>> {
         for (_, node) in self.parent_iter(hir_id) {
             match node {
                 Node::Item(_)
@@ -671,7 +671,9 @@
                 | Node::TraitItem(_)
                 | Node::ImplItem(_)
                 | Node::Stmt(Stmt { kind: StmtKind::Local(_), .. }) => break,
-                Node::Expr(expr @ Expr { kind: ExprKind::Match(..), .. }) => return Some(expr),
+                Node::Expr(expr @ Expr { kind: ExprKind::If(..) | ExprKind::Match(..), .. }) => {
+                    return Some(expr);
+                }
                 _ => {}
             }
         }
@@ -710,15 +712,10 @@
         let mut scope = id;
         loop {
             scope = self.get_enclosing_scope(scope).unwrap_or(CRATE_HIR_ID);
-            if scope == CRATE_HIR_ID {
-                return CRATE_HIR_ID;
-            }
-            match self.get(scope) {
-                Node::Block(_) => {}
-                _ => break,
+            if scope == CRATE_HIR_ID || !matches!(self.get(scope), Node::Block(_)) {
+                return scope;
             }
         }
-        scope
     }
 
     pub fn get_parent_did(&self, id: HirId) -> LocalDefId {
@@ -818,7 +815,7 @@
     /// Given a node ID, gets a list of attributes associated with the AST
     /// corresponding to the node-ID.
     pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] {
-        let attrs = self.find_entry(id).map(|entry| match entry.node {
+        self.find_entry(id).map_or(&[], |entry| match entry.node {
             Node::Param(a) => &a.attrs[..],
             Node::Local(l) => &l.attrs[..],
             Node::Item(i) => &i.attrs[..],
@@ -845,8 +842,7 @@
             | Node::Block(..)
             | Node::Lifetime(..)
             | Node::Visibility(..) => &[],
-        });
-        attrs.unwrap_or(&[])
+        })
     }
 
     /// Gets the span of the definition of the specified HIR node.
diff --git a/compiler/rustc_middle/src/ich/hcx.rs b/compiler/rustc_middle/src/ich/hcx.rs
index 084fe4c..addcb7a 100644
--- a/compiler/rustc_middle/src/ich/hcx.rs
+++ b/compiler/rustc_middle/src/ich/hcx.rs
@@ -12,7 +12,7 @@
 use rustc_session::Session;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
-use rustc_span::{BytePos, CachingSourceMapView, SourceFile};
+use rustc_span::{BytePos, CachingSourceMapView, SourceFile, SpanData};
 
 use rustc_span::def_id::{CrateNum, CRATE_DEF_INDEX};
 use smallvec::SmallVec;
@@ -248,6 +248,13 @@
     ) -> Option<(Lrc<SourceFile>, usize, BytePos)> {
         self.source_map().byte_pos_to_line_and_col(byte)
     }
+
+    fn span_data_to_lines_and_cols(
+        &mut self,
+        span: &SpanData,
+    ) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)> {
+        self.source_map().span_data_to_lines_and_cols(span)
+    }
 }
 
 pub fn hash_stable_trait_impls<'a>(
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 64d8501..80c87dd 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -46,7 +46,7 @@
 }
 
 /// A tuple of a lint level and its source.
-pub type LevelSource = (Level, LintLevelSource);
+pub type LevelAndSource = (Level, LintLevelSource);
 
 pub struct LintLevelSets {
     pub list: Vec<LintSet>,
@@ -57,11 +57,11 @@
     CommandLine {
         // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
         // flag.
-        specs: FxHashMap<LintId, LevelSource>,
+        specs: FxHashMap<LintId, LevelAndSource>,
     },
 
     Node {
-        specs: FxHashMap<LintId, LevelSource>,
+        specs: FxHashMap<LintId, LevelAndSource>,
         parent: u32,
     },
 }
@@ -75,9 +75,9 @@
         &self,
         lint: &'static Lint,
         idx: u32,
-        aux: Option<&FxHashMap<LintId, LevelSource>>,
+        aux: Option<&FxHashMap<LintId, LevelAndSource>>,
         sess: &Session,
-    ) -> LevelSource {
+    ) -> LevelAndSource {
         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
@@ -113,7 +113,7 @@
         &self,
         id: LintId,
         mut idx: u32,
-        aux: Option<&FxHashMap<LintId, LevelSource>>,
+        aux: Option<&FxHashMap<LintId, LevelAndSource>>,
     ) -> (Option<Level>, LintLevelSource) {
         if let Some(specs) = aux {
             if let Some(&(level, src)) = specs.get(&id) {
@@ -157,7 +157,7 @@
         lint: &'static Lint,
         id: HirId,
         session: &Session,
-    ) -> Option<LevelSource> {
+    ) -> Option<LevelAndSource> {
         self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session))
     }
 }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index a69555f..fab2f2c 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1745,18 +1745,14 @@
 
     /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
     /// a single deref of a local.
-    //
-    // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
+    #[inline(always)]
     pub fn local_or_deref_local(&self) -> Option<Local> {
-        match self.as_ref() {
-            PlaceRef { local, projection: [] }
-            | PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(local),
-            _ => None,
-        }
+        self.as_ref().local_or_deref_local()
     }
 
     /// If this place represents a local variable like `_X` with no
     /// projections, return `Some(_X)`.
+    #[inline(always)]
     pub fn as_local(&self) -> Option<Local> {
         self.as_ref().as_local()
     }
@@ -1770,6 +1766,7 @@
     /// As a concrete example, given the place a.b.c, this would yield:
     /// - (a, .b)
     /// - (a.b, .c)
+    ///
     /// Given a place without projections, the iterator is empty.
     pub fn iter_projections(
         self,
@@ -1790,8 +1787,6 @@
 impl<'tcx> PlaceRef<'tcx> {
     /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
     /// a single deref of a local.
-    //
-    // 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 { local, projection: [] }
@@ -1808,6 +1803,14 @@
             _ => None,
         }
     }
+
+    pub fn last_projection(&self) -> Option<(PlaceRef<'tcx>, PlaceElem<'tcx>)> {
+        if let &[ref proj_base @ .., elem] = self.projection {
+            Some((PlaceRef { local: self.local, projection: proj_base }, elem))
+        } else {
+            None
+        }
+    }
 }
 
 impl Debug for Place<'_> {
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 1e70f76..6d5d408 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -1,4 +1,4 @@
-use crate::dep_graph::{DepConstructor, DepNode, WorkProduct, WorkProductId};
+use crate::dep_graph::{DepNode, WorkProduct, WorkProductId};
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt};
 use rustc_attr::InlineAttr;
@@ -362,7 +362,7 @@
     }
 
     pub fn codegen_dep_node(&self, tcx: TyCtxt<'tcx>) -> DepNode {
-        DepConstructor::CompileCodegenUnit(tcx, self.name())
+        crate::dep_graph::make_compile_codegen_unit(tcx, self.name())
     }
 }
 
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 89a9309..a7b847f 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -439,18 +439,27 @@
     }
 
     #[inline]
-    pub fn optimized_mir_opt_const_arg(
+    pub fn optimized_mir_or_const_arg_mir(
         self,
         def: ty::WithOptConstParam<DefId>,
     ) -> &'tcx Body<'tcx> {
         if let Some((did, param_did)) = def.as_const_arg() {
-            self.optimized_mir_of_const_arg((did, param_did))
+            self.mir_for_ctfe_of_const_arg((did, param_did))
         } else {
             self.optimized_mir(def.did)
         }
     }
 
     #[inline]
+    pub fn mir_for_ctfe_opt_const_arg(self, def: ty::WithOptConstParam<DefId>) -> &'tcx Body<'tcx> {
+        if let Some((did, param_did)) = def.as_const_arg() {
+            self.mir_for_ctfe_of_const_arg((did, param_did))
+        } else {
+            self.mir_for_ctfe(def.did)
+        }
+    }
+
+    #[inline]
     pub fn mir_abstract_const_opt_const_arg(
         self,
         def: ty::WithOptConstParam<DefId>,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 1e836d0..00ee7b8 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -312,6 +312,20 @@
             desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key.did.to_def_id()) }
         }
 
+        query mir_for_ctfe(
+            key: DefId
+        ) -> &'tcx mir::Body<'tcx> {
+            desc { |tcx| "caching mir of `{}` for CTFE", tcx.def_path_str(key) }
+            cache_on_disk_if { key.is_local() }
+        }
+
+        query mir_for_ctfe_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> {
+            desc {
+                |tcx| "MIR for CTFE of the const argument `{}`",
+                tcx.def_path_str(key.0.to_def_id())
+            }
+        }
+
         query mir_promoted(key: ty::WithOptConstParam<LocalDefId>) ->
             (
                 &'tcx Steal<mir::Body<'tcx>>,
@@ -331,12 +345,6 @@
             desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key) }
             cache_on_disk_if { key.is_local() }
         }
-        query optimized_mir_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> {
-            desc {
-                |tcx| "optimizing MIR for the const argument `{}`",
-                tcx.def_path_str(key.0.to_def_id())
-            }
-        }
 
         /// Returns coverage summary info for a function, after executing the `InstrumentCoverage`
         /// MIR pass (assuming the -Zinstrument-coverage option is enabled).
@@ -873,6 +881,7 @@
         query def_kind(def_id: DefId) -> DefKind {
             desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) }
         }
+
         query def_span(def_id: DefId) -> Span {
             desc { |tcx| "looking up span for `{}`", tcx.def_path_str(def_id) }
             // FIXME(mw): DefSpans are not really inputs since they are derived from
@@ -882,15 +891,23 @@
             // regardless of HIR hashing.
             eval_always
         }
+
+        query def_ident_span(def_id: DefId) -> Option<Span> {
+            desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) }
+        }
+
         query lookup_stability(def_id: DefId) -> Option<&'tcx attr::Stability> {
             desc { |tcx| "looking up stability of `{}`", tcx.def_path_str(def_id) }
         }
+
         query lookup_const_stability(def_id: DefId) -> Option<&'tcx attr::ConstStability> {
             desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) }
         }
+
         query lookup_deprecation_entry(def_id: DefId) -> Option<DeprecationEntry> {
             desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) }
         }
+
         query item_attrs(def_id: DefId) -> &'tcx [ast::Attribute] {
             desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) }
         }
@@ -927,6 +944,9 @@
     }
 
     Codegen {
+        query is_ctfe_mir_available(key: DefId) -> bool {
+            desc { |tcx| "checking if item has ctfe mir available: `{}`", tcx.def_path_str(key) }
+        }
         query is_mir_available(key: DefId) -> bool {
             desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) }
         }
@@ -1220,6 +1240,8 @@
             eval_always
             desc { "looking up the disambiguator a crate" }
         }
+        // The macro which defines `rustc_metadata::provide_extern` depends on this query's name.
+        // Changing the name should cause a compiler error, but in case that changes, be aware.
         query crate_hash(_: CrateNum) -> Svh {
             eval_always
             desc { "looking up the hash a crate" }
@@ -1259,11 +1281,6 @@
     }
 
     Other {
-        query dllimport_foreign_items(_: CrateNum)
-            -> FxHashSet<DefId> {
-            storage(ArenaCacheSelector<'tcx>)
-            desc { "dllimport_foreign_items" }
-        }
         query is_dllimport_foreign_item(def_id: DefId) -> bool {
             desc { |tcx| "is_dllimport_foreign_item({})", tcx.def_path_str(def_id) }
         }
@@ -1294,7 +1311,7 @@
             desc { "looking up a named region" }
         }
         query is_late_bound_map(_: LocalDefId) ->
-            Option<&'tcx FxHashSet<ItemLocalId>> {
+            Option<(LocalDefId, &'tcx FxHashSet<ItemLocalId>)> {
             desc { "testing if a region is late bound" }
         }
         query object_lifetime_defaults_map(_: LocalDefId)
@@ -1308,6 +1325,15 @@
             eval_always
             desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
         }
+
+        /// Computes the set of modules from which this type is visibly uninhabited.
+        /// To check whether a type is uninhabited at all (not just from a given module), you could
+        /// check whether the forest is empty.
+        query type_uninhabited_from(
+            key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
+        ) -> ty::inhabitedness::DefIdForest {
+            desc { "computing the inhabitedness of `{:?}`", key }
+        }
     }
 
     Other {
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index df59469..a7b0ff4 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -43,27 +43,13 @@
     }
 }
 
-impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::Predicate<'tcx> {
+impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::PredicateKind<'tcx> {
     type Variant = ty::PredicateKind<'tcx>;
+
+    #[inline]
     fn variant(&self) -> &Self::Variant {
-        self.kind()
-    }
-}
-
-pub trait OpaqueEncoder: Encoder {
-    fn opaque(&mut self) -> &mut rustc_serialize::opaque::Encoder;
-    fn encoder_position(&self) -> usize;
-}
-
-impl OpaqueEncoder for rustc_serialize::opaque::Encoder {
-    #[inline]
-    fn opaque(&mut self) -> &mut rustc_serialize::opaque::Encoder {
         self
     }
-    #[inline]
-    fn encoder_position(&self) -> usize {
-        self.position()
-    }
 }
 
 pub trait TyEncoder<'tcx>: Encoder {
@@ -71,7 +57,7 @@
 
     fn position(&self) -> usize;
     fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize>;
-    fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::Predicate<'tcx>, usize>;
+    fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize>;
     fn encode_alloc_id(&mut self, alloc_id: &AllocId) -> Result<(), Self::Error>;
 }
 
@@ -134,9 +120,15 @@
     }
 }
 
+impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Binder<ty::PredicateKind<'tcx>> {
+    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+        encode_with_shorthand(e, &self.skip_binder(), TyEncoder::predicate_shorthands)
+    }
+}
+
 impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Predicate<'tcx> {
     fn encode(&self, e: &mut E) -> Result<(), E::Error> {
-        encode_with_shorthand(e, self, TyEncoder::predicate_shorthands)
+        self.kind().encode(e)
     }
 }
 
@@ -234,18 +226,24 @@
     }
 }
 
-impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> {
-    fn decode(decoder: &mut D) -> Result<ty::Predicate<'tcx>, D::Error> {
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Binder<ty::PredicateKind<'tcx>> {
+    fn decode(decoder: &mut D) -> Result<ty::Binder<ty::PredicateKind<'tcx>>, D::Error> {
         // Handle shorthands first, if we have an usize > 0x80.
-        let predicate_kind = if decoder.positioned_at_shorthand() {
+        Ok(ty::Binder::bind(if decoder.positioned_at_shorthand() {
             let pos = decoder.read_usize()?;
             assert!(pos >= SHORTHAND_OFFSET);
             let shorthand = pos - SHORTHAND_OFFSET;
 
-            decoder.with_position(shorthand, ty::PredicateKind::decode)
+            decoder.with_position(shorthand, ty::PredicateKind::decode)?
         } else {
-            ty::PredicateKind::decode(decoder)
-        }?;
+            ty::PredicateKind::decode(decoder)?
+        }))
+    }
+}
+
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> {
+    fn decode(decoder: &mut D) -> Result<ty::Predicate<'tcx>, D::Error> {
+        let predicate_kind = Decodable::decode(decoder)?;
         let predicate = decoder.tcx().mk_predicate(predicate_kind);
         Ok(predicate)
     }
@@ -473,3 +471,28 @@
         }
     }
 }
+
+macro_rules! impl_binder_encode_decode {
+    ($($t:ty),+ $(,)?) => {
+        $(
+            impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Binder<$t> {
+                fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+                    self.as_ref().skip_binder().encode(e)
+                }
+            }
+            impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Binder<$t> {
+                fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+                    Ok(ty::Binder::bind(Decodable::decode(decoder)?))
+                }
+            }
+        )*
+    }
+}
+
+impl_binder_encode_decode! {
+    &'tcx ty::List<Ty<'tcx>>,
+    ty::FnSig<'tcx>,
+    ty::ExistentialPredicate<'tcx>,
+    ty::TraitRef<'tcx>,
+    Vec<ty::GeneratorInteriorTypeCause<'tcx>>,
+}
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 0af884a..041c040 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -92,8 +92,7 @@
                 let item_id = tcx.hir().get_parent_node(hir_id);
                 let item_def_id = tcx.hir().local_def_id(item_id);
                 let generics = tcx.generics_of(item_def_id.to_def_id());
-                let index =
-                    generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id).to_def_id()];
+                let index = generics.param_def_id_to_index[&def_id];
                 let name = tcx.hir().name(hir_id);
                 ty::ConstKind::Param(ty::ParamConst::new(index, name))
             }
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index ecf2837..a2638d8 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -82,7 +82,7 @@
     /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
     /// unevaluated constant.
     pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
-        self.try_eval(tcx, param_env).and_then(Result::ok).map(ConstKind::Value).unwrap_or(self)
+        self.try_eval(tcx, param_env).and_then(Result::ok).map_or(self, ConstKind::Value)
     }
 
     #[inline]
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index b2db09c..1cbf761 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1,8 +1,9 @@
 //! Type context book-keeping.
 
 use crate::arena::Arena;
-use crate::dep_graph::{self, DepGraph, DepKind, DepNode, DepNodeExt};
+use crate::dep_graph::DepGraph;
 use crate::hir::exports::ExportMap;
+use crate::hir::place::Place as HirPlace;
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
 use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
@@ -17,9 +18,9 @@
 use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts};
 use crate::ty::TyKind::*;
 use crate::ty::{
-    self, AdtDef, AdtKind, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid, DefIdTree,
-    ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy, IntVar,
-    IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind,
+    self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid,
+    DefIdTree, ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy,
+    IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind,
     ProjectionTy, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar,
     TyVid, TypeAndMut, Visibility,
 };
@@ -37,8 +38,7 @@
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId};
-use rustc_hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::Definitions;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
@@ -47,6 +47,7 @@
 };
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
+use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
 use rustc_session::lint::{Level, Lint};
 use rustc_session::Session;
@@ -133,7 +134,7 @@
     }
 
     #[inline(never)]
-    fn intern_predicate(&self, kind: PredicateKind<'tcx>) -> &'tcx PredicateInner<'tcx> {
+    fn intern_predicate(&self, kind: Binder<PredicateKind<'tcx>>) -> &'tcx PredicateInner<'tcx> {
         self.predicate
             .intern(kind, |kind| {
                 let flags = super::flags::FlagComputation::for_predicate(kind);
@@ -379,7 +380,7 @@
 
     /// Records the reasons that we picked the kind of each closure;
     /// not all closures are present in the map.
-    closure_kind_origins: ItemLocalMap<(Span, Symbol)>,
+    closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
 
     /// For each fn, records the "liberated" types of its arguments
     /// and return type. Liberated means that all bound regions
@@ -642,11 +643,13 @@
         self.upvar_capture_map[&upvar_id]
     }
 
-    pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, Symbol)> {
+    pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
         LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
     }
 
-    pub fn closure_kind_origins_mut(&mut self) -> LocalTableInContextMut<'_, (Span, Symbol)> {
+    pub fn closure_kind_origins_mut(
+        &mut self,
+    ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
     }
 
@@ -1314,33 +1317,8 @@
         StableHashingContext::ignore_spans(self.sess, krate, self.definitions, &*self.cstore)
     }
 
-    // This method makes sure that we have a DepNode and a Fingerprint for
-    // every upstream crate. It needs to be called once right after the tcx is
-    // created.
-    // With full-fledged red/green, the method will probably become unnecessary
-    // as this will be done on-demand.
-    pub fn allocate_metadata_dep_nodes(self) {
-        // We cannot use the query versions of crates() and crate_hash(), since
-        // those would need the DepNodes that we are allocating here.
-        for cnum in self.cstore.crates_untracked() {
-            let def_path_hash = self.def_path_hash(DefId { krate: cnum, index: CRATE_DEF_INDEX });
-            let dep_node = DepNode::from_def_path_hash(def_path_hash, DepKind::CrateMetadata);
-            let crate_hash = self.cstore.crate_hash_untracked(cnum);
-            self.dep_graph.with_task(
-                dep_node,
-                self,
-                crate_hash,
-                |_, x| x, // No transformation needed
-                dep_graph::hash_result,
-            );
-        }
-    }
-
-    pub fn serialize_query_result_cache<E>(self, encoder: &mut E) -> Result<(), E::Error>
-    where
-        E: ty::codec::OpaqueEncoder,
-    {
-        self.queries.on_disk_cache.as_ref().map(|c| c.serialize(self, encoder)).unwrap_or(Ok(()))
+    pub fn serialize_query_result_cache(self, encoder: &mut FileEncoder) -> FileEncodeResult {
+        self.queries.on_disk_cache.as_ref().map_or(Ok(()), |c| c.serialize(self, encoder))
     }
 
     /// If `true`, we should use the MIR-based borrowck, but also
@@ -1973,8 +1951,8 @@
     }
 }
 
-impl<'tcx> Borrow<PredicateKind<'tcx>> for Interned<'tcx, PredicateInner<'tcx>> {
-    fn borrow<'a>(&'a self) -> &'a PredicateKind<'tcx> {
+impl<'tcx> Borrow<Binder<PredicateKind<'tcx>>> for Interned<'tcx, PredicateInner<'tcx>> {
+    fn borrow<'a>(&'a self) -> &'a Binder<PredicateKind<'tcx>> {
         &self.0.kind
     }
 }
@@ -2012,12 +1990,6 @@
     }
 }
 
-impl<'tcx> Borrow<PredicateKind<'tcx>> for Interned<'tcx, PredicateKind<'tcx>> {
-    fn borrow<'a>(&'a self) -> &'a PredicateKind<'tcx> {
-        &self.0
-    }
-}
-
 macro_rules! direct_interners {
     ($($name:ident: $method:ident($ty:ty),)+) => {
         $(impl<'tcx> PartialEq for Interned<'tcx, $ty> {
@@ -2116,8 +2088,8 @@
     }
 
     #[inline]
-    pub fn mk_predicate(self, kind: PredicateKind<'tcx>) -> Predicate<'tcx> {
-        let inner = self.interners.intern_predicate(kind);
+    pub fn mk_predicate(self, binder: Binder<PredicateKind<'tcx>>) -> Predicate<'tcx> {
+        let inner = self.interners.intern_predicate(binder);
         Predicate { inner }
     }
 
@@ -2125,9 +2097,9 @@
     pub fn reuse_or_mk_predicate(
         self,
         pred: Predicate<'tcx>,
-        kind: PredicateKind<'tcx>,
+        binder: Binder<PredicateKind<'tcx>>,
     ) -> Predicate<'tcx> {
-        if *pred.kind() != kind { self.mk_predicate(kind) } else { pred }
+        if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
     }
 
     pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> {
@@ -2603,7 +2575,8 @@
     }
 
     pub fn is_late_bound(self, id: HirId) -> bool {
-        self.is_late_bound_map(id.owner).map(|set| set.contains(&id.local_id)).unwrap_or(false)
+        self.is_late_bound_map(id.owner)
+            .map_or(false, |(owner, set)| owner == id.owner && set.contains(&id.local_id))
     }
 
     pub fn object_lifetime_defaults(self, id: HirId) -> Option<&'tcx [ObjectLifetimeDefault]> {
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 65703d0..3adcdbe 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -245,8 +245,8 @@
                 }
             }
 
-            match &param_spans[..] {
-                &[&param_span] => suggest_restrict(param_span.shrink_to_hi()),
+            match param_spans[..] {
+                [&param_span] => suggest_restrict(param_span.shrink_to_hi()),
                 _ => {
                     err.span_suggestion_verbose(
                         generics.where_clause.tail_span_for_suggestion(),
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index fe20925..f172790 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -829,7 +829,8 @@
                 }
             }
             Some(hir::Node::Item(hir::Item {
-                kind: hir::ItemKind::Impl { items, .. }, ..
+                kind: hir::ItemKind::Impl(hir::Impl { items, .. }),
+                ..
             })) => {
                 for item in &items[..] {
                     if let hir::AssocItemKind::Type = item.kind {
@@ -846,7 +847,7 @@
     }
 
     /// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref`
-    /// requirement, provide a strucuted suggestion to constrain it to a given type `ty`.
+    /// requirement, provide a structured suggestion to constrain it to a given type `ty`.
     fn constrain_generic_bound_associated_type_structured_suggestion(
         self,
         db: &mut DiagnosticBuilder<'_>,
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 4de3d15..6ecd1eb 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -22,9 +22,9 @@
         result
     }
 
-    pub fn for_predicate(kind: ty::PredicateKind<'_>) -> FlagComputation {
+    pub fn for_predicate(binder: ty::Binder<ty::PredicateKind<'_>>) -> FlagComputation {
         let mut result = FlagComputation::new();
-        result.add_predicate_kind(kind);
+        result.add_predicate(binder);
         result
     }
 
@@ -204,53 +204,46 @@
         }
     }
 
-    fn add_predicate_kind(&mut self, kind: ty::PredicateKind<'_>) {
-        match kind {
-            ty::PredicateKind::ForAll(binder) => {
-                self.bound_computation(binder, |computation, atom| {
-                    computation.add_predicate_atom(atom)
-                });
-            }
-            ty::PredicateKind::Atom(atom) => self.add_predicate_atom(atom),
-        }
+    fn add_predicate(&mut self, binder: ty::Binder<ty::PredicateKind<'_>>) {
+        self.bound_computation(binder, |computation, atom| computation.add_predicate_atom(atom));
     }
 
-    fn add_predicate_atom(&mut self, atom: ty::PredicateAtom<'_>) {
+    fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) {
         match atom {
-            ty::PredicateAtom::Trait(trait_pred, _constness) => {
+            ty::PredicateKind::Trait(trait_pred, _constness) => {
                 self.add_substs(trait_pred.trait_ref.substs);
             }
-            ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
+            ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
                 self.add_region(a);
                 self.add_region(b);
             }
-            ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, region)) => {
+            ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, region)) => {
                 self.add_ty(ty);
                 self.add_region(region);
             }
-            ty::PredicateAtom::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
+            ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
                 self.add_ty(a);
                 self.add_ty(b);
             }
-            ty::PredicateAtom::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
+            ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
                 self.add_projection_ty(projection_ty);
                 self.add_ty(ty);
             }
-            ty::PredicateAtom::WellFormed(arg) => {
+            ty::PredicateKind::WellFormed(arg) => {
                 self.add_substs(slice::from_ref(&arg));
             }
-            ty::PredicateAtom::ObjectSafe(_def_id) => {}
-            ty::PredicateAtom::ClosureKind(_def_id, substs, _kind) => {
+            ty::PredicateKind::ObjectSafe(_def_id) => {}
+            ty::PredicateKind::ClosureKind(_def_id, substs, _kind) => {
                 self.add_substs(substs);
             }
-            ty::PredicateAtom::ConstEvaluatable(_def_id, substs) => {
+            ty::PredicateKind::ConstEvaluatable(_def_id, substs) => {
                 self.add_substs(substs);
             }
-            ty::PredicateAtom::ConstEquate(expected, found) => {
+            ty::PredicateKind::ConstEquate(expected, found) => {
                 self.add_const(expected);
                 self.add_const(found);
             }
-            ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
+            ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
                 self.add_ty(ty);
             }
         }
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs b/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs
index d9aebfc..03c8963 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs
@@ -3,6 +3,9 @@
 use rustc_hir::CRATE_HIR_ID;
 use smallvec::SmallVec;
 use std::mem;
+use std::sync::Arc;
+
+use DefIdForest::*;
 
 /// Represents a forest of `DefId`s closed under the ancestor relation. That is,
 /// if a `DefId` representing a module is contained in the forest then all
@@ -11,45 +14,77 @@
 ///
 /// This is used to represent a set of modules in which a type is visibly
 /// uninhabited.
-#[derive(Clone)]
-pub struct DefIdForest {
-    /// The minimal set of `DefId`s required to represent the whole set.
-    /// If A and B are DefIds in the `DefIdForest`, and A is a descendant
-    /// of B, then only B will be in `root_ids`.
-    /// We use a `SmallVec` here because (for its use for caching inhabitedness)
-    /// it's rare that this will contain even two IDs.
-    root_ids: SmallVec<[DefId; 1]>,
+///
+/// We store the minimal set of `DefId`s required to represent the whole set. If A and B are
+/// `DefId`s in the `DefIdForest`, and A is a parent of B, then only A will be stored. When this is
+/// used with `type_uninhabited_from`, there will very rarely be more than one `DefId` stored.
+#[derive(Clone, HashStable)]
+pub enum DefIdForest {
+    Empty,
+    Single(DefId),
+    /// This variant is very rare.
+    /// Invariant: >1 elements
+    /// We use `Arc` because this is used in the output of a query.
+    Multiple(Arc<[DefId]>),
+}
+
+/// Tests whether a slice of roots contains a given DefId.
+#[inline]
+fn slice_contains(tcx: TyCtxt<'tcx>, slice: &[DefId], id: DefId) -> bool {
+    slice.iter().any(|root_id| tcx.is_descendant_of(id, *root_id))
 }
 
 impl<'tcx> DefIdForest {
     /// Creates an empty forest.
     pub fn empty() -> DefIdForest {
-        DefIdForest { root_ids: SmallVec::new() }
+        DefIdForest::Empty
     }
 
     /// Creates a forest consisting of a single tree representing the entire
     /// crate.
     #[inline]
     pub fn full(tcx: TyCtxt<'tcx>) -> DefIdForest {
-        let crate_id = tcx.hir().local_def_id(CRATE_HIR_ID);
-        DefIdForest::from_id(crate_id.to_def_id())
+        DefIdForest::from_id(tcx.hir().local_def_id(CRATE_HIR_ID).to_def_id())
     }
 
     /// Creates a forest containing a `DefId` and all its descendants.
     pub fn from_id(id: DefId) -> DefIdForest {
-        let mut root_ids = SmallVec::new();
-        root_ids.push(id);
-        DefIdForest { root_ids }
+        DefIdForest::Single(id)
+    }
+
+    fn as_slice(&self) -> &[DefId] {
+        match self {
+            Empty => &[],
+            Single(id) => std::slice::from_ref(id),
+            Multiple(root_ids) => root_ids,
+        }
+    }
+
+    // Only allocates in the rare `Multiple` case.
+    fn from_slice(root_ids: &[DefId]) -> DefIdForest {
+        match root_ids {
+            [] => Empty,
+            [id] => Single(*id),
+            _ => DefIdForest::Multiple(root_ids.into()),
+        }
     }
 
     /// Tests whether the forest is empty.
     pub fn is_empty(&self) -> bool {
-        self.root_ids.is_empty()
+        match self {
+            Empty => true,
+            Single(..) | Multiple(..) => false,
+        }
+    }
+
+    /// Iterate over the set of roots.
+    fn iter(&self) -> impl Iterator<Item = DefId> + '_ {
+        self.as_slice().iter().copied()
     }
 
     /// Tests whether the forest contains a given DefId.
     pub fn contains(&self, tcx: TyCtxt<'tcx>, id: DefId) -> bool {
-        self.root_ids.iter().any(|root_id| tcx.is_descendant_of(id, *root_id))
+        slice_contains(tcx, self.as_slice(), id)
     }
 
     /// Calculate the intersection of a collection of forests.
@@ -58,35 +93,28 @@
         I: IntoIterator<Item = DefIdForest>,
     {
         let mut iter = iter.into_iter();
-        let mut ret = if let Some(first) = iter.next() {
-            first
+        let mut ret: SmallVec<[_; 1]> = if let Some(first) = iter.next() {
+            SmallVec::from_slice(first.as_slice())
         } else {
             return DefIdForest::full(tcx);
         };
 
-        let mut next_ret = SmallVec::new();
-        let mut old_ret: SmallVec<[DefId; 1]> = SmallVec::new();
+        let mut next_ret: SmallVec<[_; 1]> = SmallVec::new();
         for next_forest in iter {
             // No need to continue if the intersection is already empty.
-            if ret.is_empty() {
-                break;
+            if ret.is_empty() || next_forest.is_empty() {
+                return DefIdForest::empty();
             }
 
-            for id in ret.root_ids.drain(..) {
-                if next_forest.contains(tcx, id) {
-                    next_ret.push(id);
-                } else {
-                    old_ret.push(id);
-                }
-            }
-            ret.root_ids.extend(old_ret.drain(..));
+            // We keep the elements in `ret` that are also in `next_forest`.
+            next_ret.extend(ret.iter().copied().filter(|&id| next_forest.contains(tcx, id)));
+            // We keep the elements in `next_forest` that are also in `ret`.
+            next_ret.extend(next_forest.iter().filter(|&id| slice_contains(tcx, &ret, id)));
 
-            next_ret.extend(next_forest.root_ids.into_iter().filter(|&id| ret.contains(tcx, id)));
-
-            mem::swap(&mut next_ret, &mut ret.root_ids);
-            next_ret.drain(..);
+            mem::swap(&mut next_ret, &mut ret);
+            next_ret.clear();
         }
-        ret
+        DefIdForest::from_slice(&ret)
     }
 
     /// Calculate the union of a collection of forests.
@@ -94,20 +122,26 @@
     where
         I: IntoIterator<Item = DefIdForest>,
     {
-        let mut ret = DefIdForest::empty();
-        let mut next_ret = SmallVec::new();
+        let mut ret: SmallVec<[_; 1]> = SmallVec::new();
+        let mut next_ret: SmallVec<[_; 1]> = SmallVec::new();
         for next_forest in iter {
-            next_ret.extend(ret.root_ids.drain(..).filter(|&id| !next_forest.contains(tcx, id)));
+            // Union with the empty set is a no-op.
+            if next_forest.is_empty() {
+                continue;
+            }
 
-            for id in next_forest.root_ids {
-                if !next_ret.contains(&id) {
+            // We add everything in `ret` that is not in `next_forest`.
+            next_ret.extend(ret.iter().copied().filter(|&id| !next_forest.contains(tcx, id)));
+            // We add everything in `next_forest` that we haven't added yet.
+            for id in next_forest.iter() {
+                if !slice_contains(tcx, &next_ret, id) {
                     next_ret.push(id);
                 }
             }
 
-            mem::swap(&mut next_ret, &mut ret.root_ids);
-            next_ret.drain(..);
+            mem::swap(&mut next_ret, &mut ret);
+            next_ret.clear();
         }
-        ret
+        DefIdForest::from_slice(&ret)
     }
 }
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 2f7707b..119cb13 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -6,7 +6,6 @@
 use crate::ty::{AdtDef, FieldDef, Ty, TyS, VariantDef};
 use crate::ty::{AdtKind, Visibility};
 use crate::ty::{DefId, SubstsRef};
-use rustc_data_structures::stack::ensure_sufficient_stack;
 
 mod def_id_forest;
 
@@ -187,34 +186,46 @@
 
 impl<'tcx> TyS<'tcx> {
     /// Calculates the forest of `DefId`s from which this type is visibly uninhabited.
-    fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> DefIdForest {
-        match *self.kind() {
-            Adt(def, substs) => {
-                ensure_sufficient_stack(|| def.uninhabited_from(tcx, substs, param_env))
-            }
+    fn uninhabited_from(
+        &'tcx self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> DefIdForest {
+        tcx.type_uninhabited_from(param_env.and(self))
+    }
+}
 
-            Never => DefIdForest::full(tcx),
+// Query provider for `type_uninhabited_from`.
+pub(crate) fn type_uninhabited_from<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
+) -> DefIdForest {
+    let ty = key.value;
+    let param_env = key.param_env;
+    match *ty.kind() {
+        Adt(def, substs) => def.uninhabited_from(tcx, substs, param_env),
 
-            Tuple(ref tys) => DefIdForest::union(
-                tcx,
-                tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx, param_env)),
-            ),
+        Never => DefIdForest::full(tcx),
 
-            Array(ty, len) => match len.try_eval_usize(tcx, param_env) {
-                Some(0) | None => DefIdForest::empty(),
-                // If the array is definitely non-empty, it's uninhabited if
-                // the type of its elements is uninhabited.
-                Some(1..) => ty.uninhabited_from(tcx, param_env),
-            },
+        Tuple(ref tys) => DefIdForest::union(
+            tcx,
+            tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx, param_env)),
+        ),
 
-            // References to uninitialised memory are valid for any type, including
-            // uninhabited types, in unsafe code, so we treat all references as
-            // inhabited.
-            // The precise semantics of inhabitedness with respect to references is currently
-            // undecided.
-            Ref(..) => DefIdForest::empty(),
+        Array(ty, len) => match len.try_eval_usize(tcx, param_env) {
+            Some(0) | None => DefIdForest::empty(),
+            // If the array is definitely non-empty, it's uninhabited if
+            // the type of its elements is uninhabited.
+            Some(1..) => ty.uninhabited_from(tcx, param_env),
+        },
 
-            _ => DefIdForest::empty(),
-        }
+        // References to uninitialised memory are valid for any type, including
+        // uninhabited types, in unsafe code, so we treat all references as
+        // inhabited.
+        // The precise semantics of inhabitedness with respect to references is currently
+        // undecided.
+        Ref(..) => DefIdForest::empty(),
+
+        _ => DefIdForest::empty(),
     }
 }
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 413c9cc..6ca5dcc 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -535,7 +535,7 @@
     } else {
         None
     };
-    let has_upvars = upvars_ty.map(|ty| ty.tuple_fields().count() > 0).unwrap_or(false);
+    let has_upvars = upvars_ty.map_or(false, |ty| ty.tuple_fields().count() > 0);
     debug!("polymorphize: upvars_ty={:?} has_upvars={:?}", upvars_ty, has_upvars);
 
     struct PolymorphizationFolder<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 4475d4e..195e840 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1466,10 +1466,12 @@
     ) -> Result<&'tcx Layout, LayoutError<'tcx>> {
         use SavedLocalEligibility::*;
         let tcx = self.tcx;
-
         let subst_field = |ty: Ty<'tcx>| ty.subst(tcx, substs);
 
-        let info = tcx.generator_layout(def_id);
+        let info = match tcx.generator_layout(def_id) {
+            None => return Err(LayoutError::Unknown(ty)),
+            Some(info) => info,
+        };
         let (ineligible_locals, assignments) = self.generator_saved_local_eligibility(&info);
 
         // Build a prefix layout, including "promoting" all ineligible
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 1fe1400..c6970df 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -17,7 +17,9 @@
 pub use self::Variance::*;
 
 use crate::hir::exports::ExportMap;
-use crate::hir::place::Place as HirPlace;
+use crate::hir::place::{
+    Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind,
+};
 use crate::ich::StableHashingContext;
 use crate::middle::cstore::CrateStoreDyn;
 use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
@@ -734,6 +736,43 @@
     pub info: CaptureInfo<'tcx>,
 }
 
+pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String {
+    let name = match place.base {
+        HirPlaceBase::Upvar(upvar_id) => tcx.hir().name(upvar_id.var_path.hir_id).to_string(),
+        _ => bug!("Capture_information should only contain upvars"),
+    };
+    let mut curr_string = name;
+
+    for (i, proj) in place.projections.iter().enumerate() {
+        match proj.kind {
+            HirProjectionKind::Deref => {
+                curr_string = format!("*{}", curr_string);
+            }
+            HirProjectionKind::Field(idx, variant) => match place.ty_before_projection(i).kind() {
+                ty::Adt(def, ..) => {
+                    curr_string = format!(
+                        "{}.{}",
+                        curr_string,
+                        def.variants[variant].fields[idx as usize].ident.name.as_str()
+                    );
+                }
+                ty::Tuple(_) => {
+                    curr_string = format!("{}.{}", curr_string, idx);
+                }
+                _ => {
+                    bug!(
+                        "Field projection applied to a type other than Adt or Tuple: {:?}.",
+                        place.ty_before_projection(i).kind()
+                    )
+                }
+            },
+            proj => bug!("{:?} unexpected because it isn't captured", proj),
+        }
+    }
+
+    curr_string.to_string()
+}
+
 /// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)
 /// for a particular capture as well as identifying the part of the source code
 /// that triggered this capture to occur.
@@ -801,6 +840,15 @@
             GenericParamDefKind::Const => "constant",
         }
     }
+    pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd {
+        match self {
+            GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime,
+            GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type,
+            GenericParamDefKind::Const => {
+                ast::ParamKindOrd::Const { unordered: tcx.features().const_generics }
+            }
+        }
+    }
 }
 
 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
@@ -862,19 +910,37 @@
         // We could cache this as a property of `GenericParamCount`, but
         // the aim is to refactor this away entirely eventually and the
         // presence of this method will be a constant reminder.
-        let mut own_counts: GenericParamCount = Default::default();
+        let mut own_counts = GenericParamCount::default();
 
         for param in &self.params {
             match param.kind {
                 GenericParamDefKind::Lifetime => own_counts.lifetimes += 1,
                 GenericParamDefKind::Type { .. } => own_counts.types += 1,
                 GenericParamDefKind::Const => own_counts.consts += 1,
-            };
+            }
         }
 
         own_counts
     }
 
+    pub fn own_defaults(&self) -> GenericParamCount {
+        let mut own_defaults = GenericParamCount::default();
+
+        for param in &self.params {
+            match param.kind {
+                GenericParamDefKind::Lifetime => (),
+                GenericParamDefKind::Type { has_default, .. } => {
+                    own_defaults.types += has_default as usize;
+                }
+                GenericParamDefKind::Const => {
+                    // FIXME(const_generics:defaults)
+                }
+            }
+        }
+
+        own_defaults
+    }
+
     pub fn requires_monomorphization(&self, tcx: TyCtxt<'tcx>) -> bool {
         if self.own_requires_monomorphization() {
             return true;
@@ -1003,14 +1069,14 @@
 
 #[derive(Debug)]
 crate struct PredicateInner<'tcx> {
-    kind: PredicateKind<'tcx>,
+    kind: Binder<PredicateKind<'tcx>>,
     flags: TypeFlags,
     /// See the comment for the corresponding field of [TyS].
     outer_exclusive_binder: ty::DebruijnIndex,
 }
 
 #[cfg(target_arch = "x86_64")]
-static_assert_size!(PredicateInner<'_>, 48);
+static_assert_size!(PredicateInner<'_>, 40);
 
 #[derive(Clone, Copy, Lift)]
 pub struct Predicate<'tcx> {
@@ -1033,59 +1099,9 @@
 impl<'tcx> Eq for Predicate<'tcx> {}
 
 impl<'tcx> Predicate<'tcx> {
-    #[inline(always)]
-    pub fn kind(self) -> &'tcx PredicateKind<'tcx> {
-        &self.inner.kind
-    }
-
-    /// Returns the inner `PredicateAtom`.
-    ///
-    /// The returned atom may contain unbound variables bound to binders skipped in this method.
-    /// It is safe to reapply binders to the given atom.
-    ///
-    /// Note that this method panics in case this predicate has unbound variables.
-    pub fn skip_binders(self) -> PredicateAtom<'tcx> {
-        match self.kind() {
-            &PredicateKind::ForAll(binder) => binder.skip_binder(),
-            &PredicateKind::Atom(atom) => {
-                debug_assert!(!atom.has_escaping_bound_vars());
-                atom
-            }
-        }
-    }
-
-    /// Returns the inner `PredicateAtom`.
-    ///
-    /// Note that this method does not check if the predicate has unbound variables.
-    ///
-    /// Rebinding the returned atom can causes the previously bound variables
-    /// to end up at the wrong binding level.
-    pub fn skip_binders_unchecked(self) -> PredicateAtom<'tcx> {
-        match self.kind() {
-            &PredicateKind::ForAll(binder) => binder.skip_binder(),
-            &PredicateKind::Atom(atom) => atom,
-        }
-    }
-
-    /// Converts this to a `Binder<PredicateAtom<'tcx>>`. If the value was an
-    /// `Atom`, then it is not allowed to contain escaping bound vars.
-    pub fn bound_atom(self) -> Binder<PredicateAtom<'tcx>> {
-        match self.kind() {
-            &PredicateKind::ForAll(binder) => binder,
-            &PredicateKind::Atom(atom) => {
-                debug_assert!(!atom.has_escaping_bound_vars());
-                Binder::dummy(atom)
-            }
-        }
-    }
-
-    /// Allows using a `Binder<PredicateAtom<'tcx>>` even if the given predicate previously
-    /// contained unbound variables by shifting these variables outwards.
-    pub fn bound_atom_with_opt_escaping(self, tcx: TyCtxt<'tcx>) -> Binder<PredicateAtom<'tcx>> {
-        match self.kind() {
-            &PredicateKind::ForAll(binder) => binder,
-            &PredicateKind::Atom(atom) => Binder::wrap_nonbinding(tcx, atom),
-        }
+    /// Gets the inner `Binder<PredicateKind<'tcx>>`.
+    pub fn kind(self) -> Binder<PredicateKind<'tcx>> {
+        self.inner.kind
     }
 }
 
@@ -1107,14 +1123,6 @@
 #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub enum PredicateKind<'tcx> {
-    /// `for<'a>: ...`
-    ForAll(Binder<PredicateAtom<'tcx>>),
-    Atom(PredicateAtom<'tcx>),
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable)]
-pub enum PredicateAtom<'tcx> {
     /// 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.
@@ -1160,21 +1168,6 @@
     TypeWellFormedFromEnv(Ty<'tcx>),
 }
 
-impl<'tcx> Binder<PredicateAtom<'tcx>> {
-    /// Wraps `self` with the given qualifier if this predicate has any unbound variables.
-    pub fn potentially_quantified(
-        self,
-        tcx: TyCtxt<'tcx>,
-        qualifier: impl FnOnce(Binder<PredicateAtom<'tcx>>) -> PredicateKind<'tcx>,
-    ) -> Predicate<'tcx> {
-        match self.no_bound_vars() {
-            Some(atom) => PredicateKind::Atom(atom),
-            None => qualifier(self),
-        }
-        .to_predicate(tcx)
-    }
-}
-
 /// The crate outlives map is computed during typeck and contains the
 /// outlives of every item in the local crate. You should not use it
 /// directly, because to do so will make your pass dependent on the
@@ -1260,13 +1253,9 @@
         // from the substitution and the value being substituted into, and
         // this trick achieves that).
         let substs = trait_ref.skip_binder().substs;
-        let pred = self.skip_binders();
+        let pred = self.kind().skip_binder();
         let new = pred.subst(tcx, substs);
-        if new != pred {
-            ty::Binder::bind(new).potentially_quantified(tcx, PredicateKind::ForAll)
-        } else {
-            self
-        }
+        tcx.reuse_or_mk_predicate(self, ty::Binder::bind(new))
     }
 }
 
@@ -1387,24 +1376,23 @@
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>;
 }
 
-impl ToPredicate<'tcx> for PredicateKind<'tcx> {
+impl ToPredicate<'tcx> for Binder<PredicateKind<'tcx>> {
     #[inline(always)]
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         tcx.mk_predicate(self)
     }
 }
 
-impl ToPredicate<'tcx> for PredicateAtom<'tcx> {
+impl ToPredicate<'tcx> for PredicateKind<'tcx> {
     #[inline(always)]
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        debug_assert!(!self.has_escaping_bound_vars(), "escaping bound vars for {:?}", self);
-        tcx.mk_predicate(PredicateKind::Atom(self))
+        tcx.mk_predicate(Binder::dummy(self))
     }
 }
 
 impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        PredicateAtom::Trait(ty::TraitPredicate { trait_ref: self.value }, self.constness)
+        PredicateKind::Trait(ty::TraitPredicate { trait_ref: self.value }, self.constness)
             .to_predicate(tcx)
     }
 }
@@ -1421,67 +1409,62 @@
 
 impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitPredicate<'tcx>> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        self.value
-            .map_bound(|value| PredicateAtom::Trait(value, self.constness))
-            .potentially_quantified(tcx, PredicateKind::ForAll)
+        self.value.map_bound(|value| PredicateKind::Trait(value, self.constness)).to_predicate(tcx)
     }
 }
 
 impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        self.map_bound(|value| PredicateAtom::RegionOutlives(value))
-            .potentially_quantified(tcx, PredicateKind::ForAll)
+        self.map_bound(PredicateKind::RegionOutlives).to_predicate(tcx)
     }
 }
 
 impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        self.map_bound(|value| PredicateAtom::TypeOutlives(value))
-            .potentially_quantified(tcx, PredicateKind::ForAll)
+        self.map_bound(PredicateKind::TypeOutlives).to_predicate(tcx)
     }
 }
 
 impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        self.map_bound(|value| PredicateAtom::Projection(value))
-            .potentially_quantified(tcx, PredicateKind::ForAll)
+        self.map_bound(PredicateKind::Projection).to_predicate(tcx)
     }
 }
 
 impl<'tcx> Predicate<'tcx> {
     pub fn to_opt_poly_trait_ref(self) -> Option<ConstnessAnd<PolyTraitRef<'tcx>>> {
-        let predicate = self.bound_atom();
+        let predicate = self.kind();
         match predicate.skip_binder() {
-            PredicateAtom::Trait(t, constness) => {
+            PredicateKind::Trait(t, constness) => {
                 Some(ConstnessAnd { constness, value: predicate.rebind(t.trait_ref) })
             }
-            PredicateAtom::Projection(..)
-            | PredicateAtom::Subtype(..)
-            | PredicateAtom::RegionOutlives(..)
-            | PredicateAtom::WellFormed(..)
-            | PredicateAtom::ObjectSafe(..)
-            | PredicateAtom::ClosureKind(..)
-            | PredicateAtom::TypeOutlives(..)
-            | PredicateAtom::ConstEvaluatable(..)
-            | PredicateAtom::ConstEquate(..)
-            | PredicateAtom::TypeWellFormedFromEnv(..) => None,
+            PredicateKind::Projection(..)
+            | PredicateKind::Subtype(..)
+            | PredicateKind::RegionOutlives(..)
+            | PredicateKind::WellFormed(..)
+            | PredicateKind::ObjectSafe(..)
+            | PredicateKind::ClosureKind(..)
+            | PredicateKind::TypeOutlives(..)
+            | PredicateKind::ConstEvaluatable(..)
+            | PredicateKind::ConstEquate(..)
+            | PredicateKind::TypeWellFormedFromEnv(..) => None,
         }
     }
 
     pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
-        let predicate = self.bound_atom();
+        let predicate = self.kind();
         match predicate.skip_binder() {
-            PredicateAtom::TypeOutlives(data) => Some(predicate.rebind(data)),
-            PredicateAtom::Trait(..)
-            | PredicateAtom::Projection(..)
-            | PredicateAtom::Subtype(..)
-            | PredicateAtom::RegionOutlives(..)
-            | PredicateAtom::WellFormed(..)
-            | PredicateAtom::ObjectSafe(..)
-            | PredicateAtom::ClosureKind(..)
-            | PredicateAtom::ConstEvaluatable(..)
-            | PredicateAtom::ConstEquate(..)
-            | PredicateAtom::TypeWellFormedFromEnv(..) => None,
+            PredicateKind::TypeOutlives(data) => Some(predicate.rebind(data)),
+            PredicateKind::Trait(..)
+            | PredicateKind::Projection(..)
+            | PredicateKind::Subtype(..)
+            | PredicateKind::RegionOutlives(..)
+            | PredicateKind::WellFormed(..)
+            | PredicateKind::ObjectSafe(..)
+            | PredicateKind::ClosureKind(..)
+            | PredicateKind::ConstEvaluatable(..)
+            | PredicateKind::ConstEquate(..)
+            | PredicateKind::TypeWellFormedFromEnv(..) => None,
         }
     }
 }
@@ -2888,19 +2871,11 @@
     }
 
     pub fn opt_associated_item(self, def_id: DefId) -> Option<&'tcx AssocItem> {
-        let is_associated_item = if let Some(def_id) = def_id.as_local() {
-            matches!(
-                self.hir().get(self.hir().local_def_id_to_hir_id(def_id)),
-                Node::TraitItem(_) | Node::ImplItem(_)
-            )
+        if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
+            Some(self.associated_item(def_id))
         } else {
-            matches!(
-                self.def_kind(def_id),
-                DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy
-            )
-        };
-
-        is_associated_item.then(|| self.associated_item(def_id))
+            None
+        }
     }
 
     pub fn field_index(self, hir_id: hir::HirId, typeck_results: &TypeckResults<'_>) -> usize {
@@ -3010,7 +2985,16 @@
     /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair.
     pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
         match instance {
-            ty::InstanceDef::Item(def) => self.optimized_mir_opt_const_arg(def),
+            ty::InstanceDef::Item(def) => match self.def_kind(def.did) {
+                DefKind::Const
+                | DefKind::Static
+                | DefKind::AssocConst
+                | DefKind::Ctor(..)
+                | DefKind::AnonConst => self.mir_for_ctfe_opt_const_arg(def),
+                // If the caller wants `mir_for_ctfe` of a function they should not be using
+                // `instance_mir`, so we'll assume const fn also wants the optimized version.
+                _ => self.optimized_mir_or_const_arg_mir(def),
+            },
             ty::InstanceDef::VtableShim(..)
             | ty::InstanceDef::ReifyShim(..)
             | ty::InstanceDef::Intrinsic(..)
@@ -3041,8 +3025,10 @@
         self.trait_def(trait_def_id).has_auto_impl
     }
 
-    pub fn generator_layout(self, def_id: DefId) -> &'tcx GeneratorLayout<'tcx> {
-        self.optimized_mir(def_id).generator_layout.as_ref().unwrap()
+    /// Returns layout of a generator. Layout might be unavailable if the
+    /// generator is tainted by errors.
+    pub fn generator_layout(self, def_id: DefId) -> Option<&'tcx GeneratorLayout<'tcx>> {
+        self.optimized_mir(def_id).generator_layout.as_ref()
     }
 
     /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
@@ -3146,6 +3132,7 @@
     *providers = ty::query::Providers {
         trait_impls_of: trait_def::trait_impls_of_provider,
         all_local_trait_impls: trait_def::all_local_trait_impls,
+        type_uninhabited_from: inhabitedness::type_uninhabited_from,
         ..*providers
     };
 }
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index c79e06b..77f1668 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -203,7 +203,7 @@
                                     self.tcx().type_of(param.def_id).subst(self.tcx(), substs),
                                 )
                     }
-                    ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
+                    ty::GenericParamDefKind::Const => false, // FIXME(const_generics_defaults)
                 }
             })
             .count();
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 8935727..8911de4 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -623,12 +623,8 @@
                     p!("impl");
                     for (predicate, _) in bounds {
                         let predicate = predicate.subst(self.tcx(), substs);
-                        // Note: We can't use `to_opt_poly_trait_ref` here as `predicate`
-                        // may contain unbound variables. We therefore do this manually.
-                        //
-                        // FIXME(lcnr): Find out why exactly this is the case :)
-                        let bound_predicate = predicate.bound_atom_with_opt_escaping(self.tcx());
-                        if let ty::PredicateAtom::Trait(pred, _) = bound_predicate.skip_binder() {
+                        let bound_predicate = predicate.kind();
+                        if let ty::PredicateKind::Trait(pred, _) = bound_predicate.skip_binder() {
                             let trait_ref = bound_predicate.rebind(pred.trait_ref);
                             // Don't print +Sized, but rather +?Sized if absent.
                             if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
@@ -2068,40 +2064,38 @@
     }
 
     ty::Predicate<'tcx> {
-        match self.kind() {
-            &ty::PredicateKind::Atom(atom) => p!(print(atom)),
-            ty::PredicateKind::ForAll(binder) => p!(print(binder)),
-        }
+        let binder = self.kind();
+        p!(print(binder))
     }
 
-    ty::PredicateAtom<'tcx> {
+    ty::PredicateKind<'tcx> {
         match *self {
-            ty::PredicateAtom::Trait(ref data, constness) => {
+            ty::PredicateKind::Trait(ref data, constness) => {
                 if let hir::Constness::Const = constness {
                     p!("const ");
                 }
                 p!(print(data))
             }
-            ty::PredicateAtom::Subtype(predicate) => p!(print(predicate)),
-            ty::PredicateAtom::RegionOutlives(predicate) => p!(print(predicate)),
-            ty::PredicateAtom::TypeOutlives(predicate) => p!(print(predicate)),
-            ty::PredicateAtom::Projection(predicate) => p!(print(predicate)),
-            ty::PredicateAtom::WellFormed(arg) => p!(print(arg), " well-formed"),
-            ty::PredicateAtom::ObjectSafe(trait_def_id) => {
+            ty::PredicateKind::Subtype(predicate) => p!(print(predicate)),
+            ty::PredicateKind::RegionOutlives(predicate) => p!(print(predicate)),
+            ty::PredicateKind::TypeOutlives(predicate) => p!(print(predicate)),
+            ty::PredicateKind::Projection(predicate) => p!(print(predicate)),
+            ty::PredicateKind::WellFormed(arg) => p!(print(arg), " well-formed"),
+            ty::PredicateKind::ObjectSafe(trait_def_id) => {
                 p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
             }
-            ty::PredicateAtom::ClosureKind(closure_def_id, _closure_substs, kind) => {
+            ty::PredicateKind::ClosureKind(closure_def_id, _closure_substs, kind) => {
                 p!("the closure `",
                 print_value_path(closure_def_id, &[]),
                 write("` implements the trait `{}`", kind))
             }
-            ty::PredicateAtom::ConstEvaluatable(def, substs) => {
+            ty::PredicateKind::ConstEvaluatable(def, substs) => {
                 p!("the constant `", print_value_path(def.did, substs), "` can be evaluated")
             }
-            ty::PredicateAtom::ConstEquate(c1, c2) => {
+            ty::PredicateKind::ConstEquate(c1, c2) => {
                 p!("the constant `", print(c1), "` equals `", print(c2), "`")
             }
-            ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
+            ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
                 p!("the type `", print(ty), "` is found in the environment")
             }
         }
diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs
index b269dd0..acfa58e 100644
--- a/compiler/rustc_middle/src/ty/query/mod.rs
+++ b/compiler/rustc_middle/src/ty/query/mod.rs
@@ -1,4 +1,4 @@
-use crate::dep_graph::{self, DepKind, DepNode, DepNodeParams};
+use crate::dep_graph;
 use crate::hir::exports::Export;
 use crate::hir::map;
 use crate::infer::canonical::{self, Canonical};
@@ -103,138 +103,6 @@
 
 rustc_query_append! { [define_queries!][<'tcx>] }
 
-/// The red/green evaluation system will try to mark a specific DepNode in the
-/// dependency graph as green by recursively trying to mark the dependencies of
-/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
-/// where we don't know if it is red or green and we therefore actually have
-/// to recompute its value in order to find out. Since the only piece of
-/// information that we have at that point is the `DepNode` we are trying to
-/// re-evaluate, we need some way to re-run a query from just that. This is what
-/// `force_from_dep_node()` implements.
-///
-/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
-/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
-/// is usually constructed by computing a stable hash of the query-key that the
-/// `DepNode` corresponds to. Consequently, it is not in general possible to go
-/// back from hash to query-key (since hash functions are not reversible). For
-/// this reason `force_from_dep_node()` is expected to fail from time to time
-/// because we just cannot find out, from the `DepNode` alone, what the
-/// corresponding query-key is and therefore cannot re-run the query.
-///
-/// The system deals with this case letting `try_mark_green` fail which forces
-/// the root query to be re-evaluated.
-///
-/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
-/// Fortunately, we can use some contextual information that will allow us to
-/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
-/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
-/// valid `DefPathHash`. Since we also always build a huge table that maps every
-/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
-/// everything we need to re-run the query.
-///
-/// Take the `mir_promoted` query as an example. Like many other queries, it
-/// just has a single parameter: the `DefId` of the item it will compute the
-/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
-/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
-/// is actually a `DefPathHash`, and can therefore just look up the corresponding
-/// `DefId` in `tcx.def_path_hash_to_def_id`.
-///
-/// When you implement a new query, it will likely have a corresponding new
-/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
-/// a rule of thumb, if your query takes a `DefId` or `LocalDefId` as sole parameter,
-/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
-/// add it to the "We don't have enough information to reconstruct..." group in
-/// the match below.
-pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool {
-    // We must avoid ever having to call `force_from_dep_node()` for a
-    // `DepNode::codegen_unit`:
-    // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
-    // would always end up having to evaluate the first caller of the
-    // `codegen_unit` query that *is* reconstructible. This might very well be
-    // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
-    // to re-trigger calling the `codegen_unit` query with the right key. At
-    // that point we would already have re-done all the work we are trying to
-    // avoid doing in the first place.
-    // The solution is simple: Just explicitly call the `codegen_unit` query for
-    // each CGU, right after partitioning. This way `try_mark_green` will always
-    // hit the cache instead of having to go through `force_from_dep_node`.
-    // This assertion makes sure, we actually keep applying the solution above.
-    debug_assert!(
-        dep_node.kind != DepKind::codegen_unit,
-        "calling force_from_dep_node() on DepKind::codegen_unit"
-    );
-
-    if !dep_node.kind.can_reconstruct_query_key() {
-        return false;
-    }
-
-    macro_rules! force_from_dep_node {
-        ($($(#[$attr:meta])* [$($modifiers:tt)*] $name:ident($K:ty),)*) => {
-            match dep_node.kind {
-                // These are inputs that are expected to be pre-allocated and that
-                // should therefore always be red or green already.
-                DepKind::CrateMetadata |
-
-                // These are anonymous nodes.
-                DepKind::TraitSelect |
-
-                // We don't have enough information to reconstruct the query key of
-                // these.
-                DepKind::CompileCodegenUnit |
-
-                // Forcing this makes no sense.
-                DepKind::Null => {
-                    bug!("force_from_dep_node: encountered {:?}", dep_node)
-                }
-
-                $(DepKind::$name => {
-                    debug_assert!(<$K as DepNodeParams<TyCtxt<'_>>>::can_reconstruct_query_key());
-
-                    if let Some(key) = <$K as DepNodeParams<TyCtxt<'_>>>::recover(tcx, dep_node) {
-                        force_query::<queries::$name<'_>, _>(
-                            tcx,
-                            key,
-                            DUMMY_SP,
-                            *dep_node
-                        );
-                        return true;
-                    }
-                })*
-            }
-        }
-    }
-
-    rustc_dep_node_append! { [force_from_dep_node!][] }
-
-    false
-}
-
-pub(crate) fn try_load_from_on_disk_cache<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) {
-    macro_rules! try_load_from_on_disk_cache {
-        ($($name:ident,)*) => {
-            match dep_node.kind {
-                $(DepKind::$name => {
-                    if <query_keys::$name<'tcx> as DepNodeParams<TyCtxt<'_>>>::can_reconstruct_query_key() {
-                        debug_assert!(tcx.dep_graph
-                                         .node_color(dep_node)
-                                         .map(|c| c.is_green())
-                                         .unwrap_or(false));
-
-                        let key = <query_keys::$name<'tcx> as DepNodeParams<TyCtxt<'_>>>::recover(tcx, dep_node).unwrap_or_else(|| panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash));
-                        if queries::$name::cache_on_disk(tcx, &key, None) {
-                            let _ = tcx.$name(key);
-                        }
-                    }
-                })*
-
-                _ => (),
-            }
-        }
-    }
-
-    rustc_cached_queries!(try_load_from_on_disk_cache!);
-}
-
 mod sealed {
     use super::{DefId, LocalDefId};
 
diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
index 8a1165b..cfe4700 100644
--- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
@@ -1,19 +1,23 @@
 use crate::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex};
 use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use crate::mir::{self, interpret};
-use crate::ty::codec::{OpaqueEncoder, RefDecodable, TyDecoder, TyEncoder};
+use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
 use crate::ty::context::TyCtxt;
 use crate::ty::{self, Ty};
 use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder, FingerprintEncoder};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
 use rustc_data_structures::thin_vec::ThinVec;
+use rustc_data_structures::unhash::UnhashMap;
 use rustc_errors::Diagnostic;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathHash;
 use rustc_hir::definitions::Definitions;
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
+use rustc_serialize::{
+    opaque::{self, FileEncodeResult, FileEncoder},
+    Decodable, Decoder, Encodable, Encoder,
+};
 use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::hygiene::{
     ExpnDataDecodeMode, ExpnDataEncodeMode, ExpnId, HygieneDecodeContext, HygieneEncodeContext,
@@ -28,8 +32,10 @@
 
 const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
 
-const TAG_VALID_SPAN: u8 = 0;
-const TAG_INVALID_SPAN: u8 = 1;
+// A normal span encoded with both location information and a `SyntaxContext`
+const TAG_FULL_SPAN: u8 = 0;
+// A partial span with no location information, encoded only with a `SyntaxContext`
+const TAG_PARTIAL_SPAN: u8 = 1;
 
 const TAG_SYNTAX_CONTEXT: u8 = 0;
 const TAG_EXPN_DATA: u8 = 1;
@@ -87,7 +93,7 @@
     // compilation session. This is used as an initial 'guess' when
     // we try to map a `DefPathHash` to its `DefId` in the current compilation
     // session.
-    foreign_def_path_hashes: FxHashMap<DefPathHash, RawDefId>,
+    foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
 
     // The *next* compilation sessison's `foreign_def_path_hashes` - at
     // the end of our current compilation session, this will get written
@@ -95,19 +101,19 @@
     // will become `foreign_def_path_hashes` of the next compilation session.
     // This stores any `DefPathHash` that we may need to map to a `DefId`
     // during the next compilation session.
-    latest_foreign_def_path_hashes: Lock<FxHashMap<DefPathHash, RawDefId>>,
+    latest_foreign_def_path_hashes: Lock<UnhashMap<DefPathHash, RawDefId>>,
 
     // Maps `DefPathHashes` to their corresponding `LocalDefId`s for all
     // local items in the current compilation session. This is only populated
     // when we are in incremental mode and have loaded a pre-existing cache
     // from disk, since this map is only used when deserializing a `DefPathHash`
     // from the incremental cache.
-    local_def_path_hash_to_def_id: FxHashMap<DefPathHash, LocalDefId>,
+    local_def_path_hash_to_def_id: UnhashMap<DefPathHash, LocalDefId>,
     // Caches all lookups of `DefPathHashes`, both for local and foreign
     // definitions. A definition from the previous compilation session
     // may no longer exist in the current compilation session, so
     // we use `Option<DefId>` so that we can cache a lookup failure.
-    def_path_hash_to_def_id_cache: Lock<FxHashMap<DefPathHash, Option<DefId>>>,
+    def_path_hash_to_def_id_cache: Lock<UnhashMap<DefPathHash, Option<DefId>>>,
 }
 
 // This type is used only for serialization and deserialization.
@@ -123,7 +129,7 @@
     syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
     // See `OnDiskCache.expn_data`
     expn_data: FxHashMap<u32, AbsoluteBytePos>,
-    foreign_def_path_hashes: FxHashMap<DefPathHash, RawDefId>,
+    foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
 }
 
 type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
@@ -160,8 +166,8 @@
     pub index: u32,
 }
 
-fn make_local_def_path_hash_map(definitions: &Definitions) -> FxHashMap<DefPathHash, LocalDefId> {
-    FxHashMap::from_iter(
+fn make_local_def_path_hash_map(definitions: &Definitions) -> UnhashMap<DefPathHash, LocalDefId> {
+    UnhashMap::from_iter(
         definitions
             .def_path_table()
             .all_def_path_hashes_and_def_ids(LOCAL_CRATE)
@@ -240,10 +246,11 @@
         }
     }
 
-    pub fn serialize<'tcx, E>(&self, tcx: TyCtxt<'tcx>, encoder: &mut E) -> Result<(), E::Error>
-    where
-        E: OpaqueEncoder,
-    {
+    pub fn serialize<'tcx>(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        encoder: &mut FileEncoder,
+    ) -> FileEncodeResult {
         // Serializing the `DepGraph` should not modify it.
         tcx.dep_graph.with_ignore(|| {
             // Allocate `SourceFileIndex`es.
@@ -297,14 +304,14 @@
             // Encode query results.
             let mut query_result_index = EncodedQueryResultIndex::new();
 
-            tcx.sess.time("encode_query_results", || {
+            tcx.sess.time("encode_query_results", || -> FileEncodeResult {
                 let enc = &mut encoder;
                 let qri = &mut query_result_index;
 
                 macro_rules! encode_queries {
                     ($($query:ident,)*) => {
                         $(
-                            encode_query_results::<ty::query::queries::$query<'_>, _>(
+                            encode_query_results::<ty::query::queries::$query<'_>>(
                                 tcx,
                                 enc,
                                 qri
@@ -323,15 +330,17 @@
                 .current_diagnostics
                 .borrow()
                 .iter()
-                .map(|(dep_node_index, diagnostics)| {
-                    let pos = AbsoluteBytePos::new(encoder.position());
-                    // Let's make sure we get the expected type here.
-                    let diagnostics: &EncodedDiagnostics = diagnostics;
-                    let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
-                    encoder.encode_tagged(dep_node_index, diagnostics)?;
+                .map(
+                    |(dep_node_index, diagnostics)| -> Result<_, <FileEncoder as Encoder>::Error> {
+                        let pos = AbsoluteBytePos::new(encoder.position());
+                        // Let's make sure we get the expected type here.
+                        let diagnostics: &EncodedDiagnostics = diagnostics;
+                        let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
+                        encoder.encode_tagged(dep_node_index, diagnostics)?;
 
-                    Ok((dep_node_index, pos))
-                })
+                        Ok((dep_node_index, pos))
+                    },
+                )
                 .collect::<Result<_, _>>()?;
 
             let interpret_alloc_index = {
@@ -374,13 +383,13 @@
 
             hygiene_encode_context.encode(
                 &mut encoder,
-                |encoder, index, ctxt_data| {
+                |encoder, index, ctxt_data| -> FileEncodeResult {
                     let pos = AbsoluteBytePos::new(encoder.position());
                     encoder.encode_tagged(TAG_SYNTAX_CONTEXT, ctxt_data)?;
                     syntax_contexts.insert(index, pos);
                     Ok(())
                 },
-                |encoder, index, expn_data| {
+                |encoder, index, expn_data| -> FileEncodeResult {
                     let pos = AbsoluteBytePos::new(encoder.position());
                     encoder.encode_tagged(TAG_EXPN_DATA, expn_data)?;
                     expn_ids.insert(index, pos);
@@ -409,7 +418,7 @@
 
             // Encode the position of the footer as the last 8 bytes of the
             // file so we know where to look for it.
-            IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder.opaque())?;
+            IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?;
 
             // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
             // of the footer must be the last thing in the data stream.
@@ -807,6 +816,15 @@
 
 crate::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
 
+// This ensures that the `Decodable<opaque::Decoder>::decode` specialization for `Vec<u8>` is used
+// when a `CacheDecoder` is passed to `Decodable::decode`. Unfortunately, we have to manually opt
+// into specializations this way, given how `CacheDecoder` and the decoding traits currently work.
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Vec<u8> {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        Decodable::decode(&mut d.opaque)
+    }
+}
+
 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for SyntaxContext {
     fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
         let syntax_contexts = decoder.syntax_contexts;
@@ -848,10 +866,11 @@
     fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
         let tag: u8 = Decodable::decode(decoder)?;
 
-        if tag == TAG_INVALID_SPAN {
-            return Ok(DUMMY_SP);
+        if tag == TAG_PARTIAL_SPAN {
+            let ctxt = SyntaxContext::decode(decoder)?;
+            return Ok(DUMMY_SP.with_ctxt(ctxt));
         } else {
-            debug_assert_eq!(tag, TAG_VALID_SPAN);
+            debug_assert_eq!(tag, TAG_FULL_SPAN);
         }
 
         let file_lo_index = SourceFileIndex::decode(decoder)?;
@@ -954,17 +973,28 @@
 
 //- ENCODING -------------------------------------------------------------------
 
+trait OpaqueEncoder: Encoder {
+    fn position(&self) -> usize;
+}
+
+impl OpaqueEncoder for FileEncoder {
+    #[inline]
+    fn position(&self) -> usize {
+        FileEncoder::position(self)
+    }
+}
+
 /// An encoder that can write to the incremental compilation cache.
 struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> {
     tcx: TyCtxt<'tcx>,
     encoder: &'a mut E,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
-    predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
+    predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
     interpret_allocs: FxIndexSet<interpret::AllocId>,
     source_map: CachingSourceMapView<'tcx>,
     file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>,
     hygiene_context: &'a HygieneEncodeContext,
-    latest_foreign_def_path_hashes: FxHashMap<DefPathHash, RawDefId>,
+    latest_foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
 }
 
 impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E>
@@ -995,9 +1025,9 @@
     }
 }
 
-impl<'a, 'tcx> FingerprintEncoder for CacheEncoder<'a, 'tcx, rustc_serialize::opaque::Encoder> {
-    fn encode_fingerprint(&mut self, f: &Fingerprint) -> opaque::EncodeResult {
-        f.encode_opaque(self.encoder)
+impl<'a, 'tcx, E: OpaqueEncoder> FingerprintEncoder for CacheEncoder<'a, 'tcx, E> {
+    fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), E::Error> {
+        self.encoder.encode_fingerprint(f)
     }
 }
 
@@ -1030,24 +1060,29 @@
 {
     fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
         if *self == DUMMY_SP {
-            return TAG_INVALID_SPAN.encode(s);
+            TAG_PARTIAL_SPAN.encode(s)?;
+            return SyntaxContext::root().encode(s);
         }
 
         let span_data = self.data();
-        let (file_lo, line_lo, col_lo) = match s.source_map.byte_pos_to_line_and_col(span_data.lo) {
-            Some(pos) => pos,
-            None => return TAG_INVALID_SPAN.encode(s),
+        let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo);
+        let partial_span = match &pos {
+            Some((file_lo, _, _)) => !file_lo.contains(span_data.hi),
+            None => true,
         };
 
-        if !file_lo.contains(span_data.hi) {
-            return TAG_INVALID_SPAN.encode(s);
+        if partial_span {
+            TAG_PARTIAL_SPAN.encode(s)?;
+            return span_data.ctxt.encode(s);
         }
 
+        let (file_lo, line_lo, col_lo) = pos.unwrap();
+
         let len = span_data.hi - span_data.lo;
 
         let source_file_index = s.source_file_index(file_lo);
 
-        TAG_VALID_SPAN.encode(s)?;
+        TAG_FULL_SPAN.encode(s)?;
         source_file_index.encode(s)?;
         line_lo.encode(s)?;
         col_lo.encode(s)?;
@@ -1063,12 +1098,12 @@
     const CLEAR_CROSS_CRATE: bool = false;
 
     fn position(&self) -> usize {
-        self.encoder.encoder_position()
+        self.encoder.position()
     }
     fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
         &mut self.type_shorthands
     }
-    fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::Predicate<'tcx>, usize> {
+    fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
         &mut self.predicate_shorthands
     }
     fn encode_alloc_id(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
@@ -1149,6 +1184,16 @@
     }
 }
 
+// This ensures that the `Encodable<opaque::FileEncoder>::encode` specialization for byte slices
+// is used when a `CacheEncoder` having an `opaque::FileEncoder` is passed to `Encodable::encode`.
+// Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder`
+// and the encoding traits currently work.
+impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx, FileEncoder>> for [u8] {
+    fn encode(&self, e: &mut CacheEncoder<'a, 'tcx, FileEncoder>) -> FileEncodeResult {
+        self.encode(e.encoder)
+    }
+}
+
 // An integer that will always encode to 8 bytes.
 struct IntEncodedWithFixedSize(u64);
 
@@ -1156,8 +1201,8 @@
     pub const ENCODED_SIZE: usize = 8;
 }
 
-impl Encodable<opaque::Encoder> for IntEncodedWithFixedSize {
-    fn encode(&self, e: &mut opaque::Encoder) -> Result<(), !> {
+impl<E: OpaqueEncoder> Encodable<E> for IntEncodedWithFixedSize {
+    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
         let start_pos = e.position();
         for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE {
             ((self.0 >> (i * 8)) as u8).encode(e)?;
@@ -1185,15 +1230,14 @@
     }
 }
 
-fn encode_query_results<'a, 'tcx, Q, E>(
+fn encode_query_results<'a, 'tcx, Q>(
     tcx: TyCtxt<'tcx>,
-    encoder: &mut CacheEncoder<'a, 'tcx, E>,
+    encoder: &mut CacheEncoder<'a, 'tcx, FileEncoder>,
     query_result_index: &mut EncodedQueryResultIndex,
-) -> Result<(), E::Error>
+) -> FileEncodeResult
 where
     Q: super::QueryDescription<TyCtxt<'tcx>> + super::QueryAccessors<TyCtxt<'tcx>>,
-    Q::Value: Encodable<CacheEncoder<'a, 'tcx, E>>,
-    E: 'a + OpaqueEncoder,
+    Q::Value: Encodable<CacheEncoder<'a, 'tcx, FileEncoder>>,
 {
     let _timer = tcx
         .sess
@@ -1210,7 +1254,7 @@
 
                 // Record position of the cache entry.
                 query_result_index
-                    .push((dep_node, AbsoluteBytePos::new(encoder.encoder.opaque().position())));
+                    .push((dep_node, AbsoluteBytePos::new(encoder.encoder.position())));
 
                 // Encode the type check tables with the `SerializedDepNodeIndex`
                 // as tag.
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 7a1ca6a..44c173e 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -231,37 +231,28 @@
 impl fmt::Debug for ty::PredicateKind<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
-            ty::PredicateKind::ForAll(binder) => write!(f, "ForAll({:?})", binder),
-            ty::PredicateKind::Atom(atom) => write!(f, "{:?}", atom),
-        }
-    }
-}
-
-impl fmt::Debug for ty::PredicateAtom<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            ty::PredicateAtom::Trait(ref a, constness) => {
+            ty::PredicateKind::Trait(ref a, constness) => {
                 if let hir::Constness::Const = constness {
                     write!(f, "const ")?;
                 }
                 a.fmt(f)
             }
-            ty::PredicateAtom::Subtype(ref pair) => pair.fmt(f),
-            ty::PredicateAtom::RegionOutlives(ref pair) => pair.fmt(f),
-            ty::PredicateAtom::TypeOutlives(ref pair) => pair.fmt(f),
-            ty::PredicateAtom::Projection(ref pair) => pair.fmt(f),
-            ty::PredicateAtom::WellFormed(data) => write!(f, "WellFormed({:?})", data),
-            ty::PredicateAtom::ObjectSafe(trait_def_id) => {
+            ty::PredicateKind::Subtype(ref pair) => pair.fmt(f),
+            ty::PredicateKind::RegionOutlives(ref pair) => pair.fmt(f),
+            ty::PredicateKind::TypeOutlives(ref pair) => pair.fmt(f),
+            ty::PredicateKind::Projection(ref pair) => pair.fmt(f),
+            ty::PredicateKind::WellFormed(data) => write!(f, "WellFormed({:?})", data),
+            ty::PredicateKind::ObjectSafe(trait_def_id) => {
                 write!(f, "ObjectSafe({:?})", trait_def_id)
             }
-            ty::PredicateAtom::ClosureKind(closure_def_id, closure_substs, kind) => {
+            ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
                 write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
             }
-            ty::PredicateAtom::ConstEvaluatable(def_id, substs) => {
+            ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
                 write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
             }
-            ty::PredicateAtom::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
-            ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
+            ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
+            ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
                 write!(f, "TypeWellFormedFromEnv({:?})", ty)
             }
         }
@@ -485,46 +476,36 @@
     type Lifted = ty::PredicateKind<'tcx>;
     fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
         match self {
-            ty::PredicateKind::ForAll(binder) => tcx.lift(binder).map(ty::PredicateKind::ForAll),
-            ty::PredicateKind::Atom(atom) => tcx.lift(atom).map(ty::PredicateKind::Atom),
-        }
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for ty::PredicateAtom<'a> {
-    type Lifted = ty::PredicateAtom<'tcx>;
-    fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        match self {
-            ty::PredicateAtom::Trait(data, constness) => {
-                tcx.lift(data).map(|data| ty::PredicateAtom::Trait(data, constness))
+            ty::PredicateKind::Trait(data, constness) => {
+                tcx.lift(data).map(|data| ty::PredicateKind::Trait(data, constness))
             }
-            ty::PredicateAtom::Subtype(data) => tcx.lift(data).map(ty::PredicateAtom::Subtype),
-            ty::PredicateAtom::RegionOutlives(data) => {
-                tcx.lift(data).map(ty::PredicateAtom::RegionOutlives)
+            ty::PredicateKind::Subtype(data) => tcx.lift(data).map(ty::PredicateKind::Subtype),
+            ty::PredicateKind::RegionOutlives(data) => {
+                tcx.lift(data).map(ty::PredicateKind::RegionOutlives)
             }
-            ty::PredicateAtom::TypeOutlives(data) => {
-                tcx.lift(data).map(ty::PredicateAtom::TypeOutlives)
+            ty::PredicateKind::TypeOutlives(data) => {
+                tcx.lift(data).map(ty::PredicateKind::TypeOutlives)
             }
-            ty::PredicateAtom::Projection(data) => {
-                tcx.lift(data).map(ty::PredicateAtom::Projection)
+            ty::PredicateKind::Projection(data) => {
+                tcx.lift(data).map(ty::PredicateKind::Projection)
             }
-            ty::PredicateAtom::WellFormed(ty) => tcx.lift(ty).map(ty::PredicateAtom::WellFormed),
-            ty::PredicateAtom::ClosureKind(closure_def_id, closure_substs, kind) => {
+            ty::PredicateKind::WellFormed(ty) => tcx.lift(ty).map(ty::PredicateKind::WellFormed),
+            ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
                 tcx.lift(closure_substs).map(|closure_substs| {
-                    ty::PredicateAtom::ClosureKind(closure_def_id, closure_substs, kind)
+                    ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind)
                 })
             }
-            ty::PredicateAtom::ObjectSafe(trait_def_id) => {
-                Some(ty::PredicateAtom::ObjectSafe(trait_def_id))
+            ty::PredicateKind::ObjectSafe(trait_def_id) => {
+                Some(ty::PredicateKind::ObjectSafe(trait_def_id))
             }
-            ty::PredicateAtom::ConstEvaluatable(def_id, substs) => {
-                tcx.lift(substs).map(|substs| ty::PredicateAtom::ConstEvaluatable(def_id, substs))
+            ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
+                tcx.lift(substs).map(|substs| ty::PredicateKind::ConstEvaluatable(def_id, substs))
             }
-            ty::PredicateAtom::ConstEquate(c1, c2) => {
-                tcx.lift((c1, c2)).map(|(c1, c2)| ty::PredicateAtom::ConstEquate(c1, c2))
+            ty::PredicateKind::ConstEquate(c1, c2) => {
+                tcx.lift((c1, c2)).map(|(c1, c2)| ty::PredicateKind::ConstEquate(c1, c2))
             }
-            ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
-                tcx.lift(ty).map(ty::PredicateAtom::TypeWellFormedFromEnv)
+            ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
+                tcx.lift(ty).map(ty::PredicateKind::TypeWellFormedFromEnv)
             }
         }
     }
@@ -1036,12 +1017,12 @@
 
 impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
     fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        let new = ty::PredicateKind::super_fold_with(self.inner.kind, folder);
+        let new = self.inner.kind.fold_with(folder);
         folder.tcx().reuse_or_mk_predicate(self, new)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        ty::PredicateKind::super_visit_with(&self.inner.kind, visitor)
+        self.inner.kind.visit_with(visitor)
     }
 
     fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 744c7a5..e53977b 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -605,7 +605,7 @@
     #[inline]
     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();
+        let num_variants = tcx.generator_layout(def_id).unwrap().variant_fields.len();
         VariantIdx::new(0)..VariantIdx::new(num_variants)
     }
 
@@ -666,7 +666,7 @@
         def_id: DefId,
         tcx: TyCtxt<'tcx>,
     ) -> impl Iterator<Item = impl Iterator<Item = Ty<'tcx>> + Captures<'tcx>> {
-        let layout = tcx.generator_layout(def_id);
+        let layout = tcx.generator_layout(def_id).unwrap();
         layout.variant_fields.iter().map(move |variant| {
             variant.iter().map(move |field| layout.field_tys[*field].subst(tcx, self.substs))
         })
@@ -955,7 +955,9 @@
 /// erase, or otherwise "discharge" these bound vars, we change the
 /// type from `Binder<T>` to just `T` (see
 /// e.g., `liberate_late_bound_regions`).
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
+///
+/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 pub struct Binder<T>(T);
 
 impl<T> Binder<T> {
diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs
index 0903ef5..e79adcd 100644
--- a/compiler/rustc_middle/src/util/bug.rs
+++ b/compiler/rustc_middle/src/util/bug.rs
@@ -21,6 +21,7 @@
     opt_span_bug_fmt(Some(span), args, Location::caller());
 }
 
+#[track_caller]
 fn opt_span_bug_fmt<S: Into<MultiSpan>>(
     span: Option<S>,
     args: fmt::Arguments<'_>,
diff --git a/compiler/rustc_mir/src/borrow_check/borrow_set.rs b/compiler/rustc_mir/src/borrow_check/borrow_set.rs
index b4299fb..288eda3 100644
--- a/compiler/rustc_mir/src/borrow_check/borrow_set.rs
+++ b/compiler/rustc_mir/src/borrow_check/borrow_set.rs
@@ -149,7 +149,7 @@
     }
 
     crate fn activations_at_location(&self, location: Location) -> &[BorrowIndex] {
-        self.activation_map.get(&location).map(|activations| &activations[..]).unwrap_or(&[])
+        self.activation_map.get(&location).map_or(&[], |activations| &activations[..])
     }
 
     crate fn len(&self) -> usize {
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
index 1474c7a..8f41bfa 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
@@ -141,6 +141,7 @@
             self.add_moved_or_invoked_closure_note(location, used_place, &mut err);
 
             let mut is_loop_move = false;
+            let mut in_pattern = false;
 
             for move_site in &move_site_vec {
                 let move_out = self.move_data.moves[(*move_site).moi];
@@ -151,95 +152,88 @@
 
                 let move_msg = if move_spans.for_closure() { " into closure" } else { "" };
 
+                let loop_message = if location == move_out.source || move_site.traversed_back_edge {
+                    ", in previous iteration of loop"
+                } else {
+                    ""
+                };
+
                 if location == move_out.source {
-                    err.span_label(
-                        span,
-                        format!(
-                            "value {}moved{} here, in previous iteration of loop",
-                            partially_str, move_msg
-                        ),
-                    );
                     is_loop_move = true;
-                } else if move_site.traversed_back_edge {
+                }
+
+                if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = move_spans {
+                    let place_name = self
+                        .describe_place(moved_place.as_ref())
+                        .map(|n| format!("`{}`", n))
+                        .unwrap_or_else(|| "value".to_owned());
+                    match kind {
+                        FnSelfUseKind::FnOnceCall => {
+                            err.span_label(
+                                fn_call_span,
+                                &format!(
+                                    "{} {}moved due to this call{}",
+                                    place_name, partially_str, loop_message
+                                ),
+                            );
+                            err.span_note(
+                                var_span,
+                                "this value implements `FnOnce`, which causes it to be moved when called",
+                            );
+                        }
+                        FnSelfUseKind::Operator { self_arg } => {
+                            err.span_label(
+                                fn_call_span,
+                                &format!(
+                                    "{} {}moved due to usage in operator{}",
+                                    place_name, partially_str, loop_message
+                                ),
+                            );
+                            if self.fn_self_span_reported.insert(fn_span) {
+                                err.span_note(
+                                    self_arg.span,
+                                    "calling this operator moves the left-hand side",
+                                );
+                            }
+                        }
+                        FnSelfUseKind::Normal { self_arg, implicit_into_iter } => {
+                            if implicit_into_iter {
+                                err.span_label(
+                                    fn_call_span,
+                                    &format!(
+                                        "{} {}moved due to this implicit call to `.into_iter()`{}",
+                                        place_name, partially_str, loop_message
+                                    ),
+                                );
+                            } else {
+                                err.span_label(
+                                    fn_call_span,
+                                    &format!(
+                                        "{} {}moved due to this method call{}",
+                                        place_name, partially_str, loop_message
+                                    ),
+                                );
+                            }
+                            // Avoid pointing to the same function in multiple different
+                            // error messages
+                            if self.fn_self_span_reported.insert(self_arg.span) {
+                                err.span_note(
+                                    self_arg.span,
+                                    &format!("this function takes ownership of the receiver `self`, which moves {}", place_name)
+                                );
+                            }
+                        }
+                        // Deref::deref takes &self, which cannot cause a move
+                        FnSelfUseKind::DerefCoercion { .. } => unreachable!(),
+                    }
+                } else {
                     err.span_label(
                         move_span,
-                        format!(
-                            "value {}moved{} here, in previous iteration of loop",
-                            partially_str, move_msg
-                        ),
+                        format!("value {}moved{} here{}", partially_str, move_msg, loop_message),
                     );
-                } else {
-                    if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } =
-                        move_spans
-                    {
-                        let place_name = self
-                            .describe_place(moved_place.as_ref())
-                            .map(|n| format!("`{}`", n))
-                            .unwrap_or_else(|| "value".to_owned());
-                        match kind {
-                            FnSelfUseKind::FnOnceCall => {
-                                err.span_label(
-                                    fn_call_span,
-                                    &format!(
-                                        "{} {}moved due to this call",
-                                        place_name, partially_str
-                                    ),
-                                );
-                                err.span_note(
-                                    var_span,
-                                    "this value implements `FnOnce`, which causes it to be moved when called",
-                                );
-                            }
-                            FnSelfUseKind::Operator { self_arg } => {
-                                err.span_label(
-                                    fn_call_span,
-                                    &format!(
-                                        "{} {}moved due to usage in operator",
-                                        place_name, partially_str
-                                    ),
-                                );
-                                if self.fn_self_span_reported.insert(fn_span) {
-                                    err.span_note(
-                                        self_arg.span,
-                                        "calling this operator moves the left-hand side",
-                                    );
-                                }
-                            }
-                            FnSelfUseKind::Normal { self_arg, implicit_into_iter } => {
-                                if implicit_into_iter {
-                                    err.span_label(
-                                        fn_call_span,
-                                        &format!(
-                                            "{} {}moved due to this implicit call to `.into_iter()`",
-                                            place_name, partially_str
-                                        ),
-                                    );
-                                } else {
-                                    err.span_label(
-                                        fn_call_span,
-                                        &format!(
-                                            "{} {}moved due to this method call",
-                                            place_name, partially_str
-                                        ),
-                                    );
-                                }
-                                // Avoid pointing to the same function in multiple different
-                                // error messages
-                                if self.fn_self_span_reported.insert(self_arg.span) {
-                                    err.span_note(
-                                        self_arg.span,
-                                        &format!("this function consumes the receiver `self` by taking ownership of it, which moves {}", place_name)
-                                    );
-                                }
-                            }
-                            // Deref::deref takes &self, which cannot cause a move
-                            FnSelfUseKind::DerefCoercion { .. } => unreachable!(),
-                        }
-                    } else {
-                        err.span_label(
-                            move_span,
-                            format!("value {}moved{} here", partially_str, move_msg),
-                        );
+                    // If the move error occurs due to a loop, don't show
+                    // another message for the same span
+                    if loop_message.is_empty() {
                         move_spans.var_span_label(
                             &mut err,
                             format!(
@@ -250,6 +244,7 @@
                         );
                     }
                 }
+
                 if let UseSpans::PatUse(span) = move_spans {
                     err.span_suggestion_verbose(
                         span.shrink_to_lo(),
@@ -262,6 +257,7 @@
                         "ref ".to_string(),
                         Applicability::MachineApplicable,
                     );
+                    in_pattern = true;
                 }
 
                 if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() {
@@ -293,9 +289,7 @@
                 );
             }
 
-            let ty =
-                Place::ty_from(used_place.local, used_place.projection, self.body, self.infcx.tcx)
-                    .ty;
+            let ty = PlaceRef::ty(&used_place, self.body, self.infcx.tcx).ty;
             let needs_note = match ty.kind() {
                 ty::Closure(id, _) => {
                     let tables = self.infcx.tcx.typeck(id.expect_local());
@@ -310,7 +304,8 @@
             let place = &self.move_data.move_paths[mpi].place;
             let ty = place.ty(self.body, self.infcx.tcx).ty;
 
-            if is_loop_move {
+            // If we're in pattern, we do nothing in favor of the previous suggestion (#80913).
+            if is_loop_move & !in_pattern {
                 if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
                     // We have a `&mut` ref, we need to reborrow on each iteration (#62112).
                     err.span_suggestion_verbose(
@@ -732,8 +727,8 @@
     ) -> (String, String, String, String) {
         // Define a small closure that we can use to check if the type of a place
         // is a union.
-        let union_ty = |place_base, place_projection| {
-            let ty = Place::ty_from(place_base, place_projection, self.body, self.infcx.tcx).ty;
+        let union_ty = |place_base| {
+            let ty = PlaceRef::ty(&place_base, self.body, self.infcx.tcx).ty;
             ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty)
         };
 
@@ -751,15 +746,10 @@
                 // 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 { local, projection } = first_borrowed_place;
-
-                let mut cursor = projection.as_ref();
-                while let [proj_base @ .., elem] = cursor {
-                    cursor = proj_base;
-
+                for (place_base, elem) in first_borrowed_place.iter_projections().rev() {
                     match elem {
-                        ProjectionElem::Field(field, _) if union_ty(local, proj_base).is_some() => {
-                            return Some((PlaceRef { local, projection: proj_base }, field));
+                        ProjectionElem::Field(field, _) if union_ty(place_base).is_some() => {
+                            return Some((place_base, field));
                         }
                         _ => {}
                     }
@@ -769,23 +759,12 @@
             .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 { local, ref projection } = second_borrowed_place;
-
-                let mut cursor = &projection[..];
-                while let [proj_base @ .., elem] = cursor {
-                    cursor = proj_base;
-
+                for (place_base, elem) in second_borrowed_place.iter_projections().rev() {
                     if let ProjectionElem::Field(field, _) = elem {
-                        if let Some(union_ty) = union_ty(local, proj_base) {
-                            if field != target_field
-                                && local == target_base.local
-                                && proj_base == target_base.projection
-                            {
+                        if let Some(union_ty) = union_ty(place_base) {
+                            if field != target_field && place_base == target_base {
                                 return Some((
-                                    self.describe_any_place(PlaceRef {
-                                        local,
-                                        projection: proj_base,
-                                    }),
+                                    self.describe_any_place(place_base),
                                     self.describe_any_place(first_borrowed_place.as_ref()),
                                     self.describe_any_place(second_borrowed_place.as_ref()),
                                     union_ty.to_string(),
@@ -1342,21 +1321,30 @@
             Applicability::MachineApplicable,
         );
 
-        let msg = match category {
+        match category {
             ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => {
-                format!("{} is returned here", kind)
+                let msg = format!("{} is returned here", kind);
+                err.span_note(constraint_span, &msg);
             }
             ConstraintCategory::CallArgument => {
                 fr_name.highlight_region_name(&mut err);
-                format!("function requires argument type to outlive `{}`", fr_name)
+                if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) {
+                    err.note(
+                        "async blocks are not executed immediately and must either take a \
+                    reference or ownership of outside variables they use",
+                    );
+                } else {
+                    let msg = format!("function requires argument type to outlive `{}`", fr_name);
+                    err.span_note(constraint_span, &msg);
+                }
             }
             _ => bug!(
                 "report_escaping_closure_capture called with unexpected constraint \
                  category: `{:?}`",
                 category
             ),
-        };
-        err.span_note(constraint_span, &msg);
+        }
+
         err
     }
 
@@ -1628,20 +1616,17 @@
 
     fn classify_drop_access_kind(&self, place: PlaceRef<'tcx>) -> StorageDeadOrDrop<'tcx> {
         let tcx = self.infcx.tcx;
-        match place.projection {
-            [] => StorageDeadOrDrop::LocalStorageDead,
-            [proj_base @ .., elem] => {
+        match place.last_projection() {
+            None => StorageDeadOrDrop::LocalStorageDead,
+            Some((place_base, elem)) => {
                 // FIXME(spastorino) make this iterate
-                let base_access = self.classify_drop_access_kind(PlaceRef {
-                    local: place.local,
-                    projection: proj_base,
-                });
+                let base_access = self.classify_drop_access_kind(place_base);
                 match elem {
                     ProjectionElem::Deref => match base_access {
                         StorageDeadOrDrop::LocalStorageDead
                         | StorageDeadOrDrop::BoxedStorageDead => {
                             assert!(
-                                Place::ty_from(place.local, proj_base, self.body, tcx).ty.is_box(),
+                                place_base.ty(self.body, tcx).ty.is_box(),
                                 "Drop of value behind a reference or raw pointer"
                             );
                             StorageDeadOrDrop::BoxedStorageDead
@@ -1649,7 +1634,7 @@
                         StorageDeadOrDrop::Destructor(_) => base_access,
                     },
                     ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
-                        let base_ty = Place::ty_from(place.local, proj_base, self.body, tcx).ty;
+                        let base_ty = place_base.ty(self.body, tcx).ty;
                         match base_ty.kind() {
                             ty::Adt(def, _) if def.has_dtor(tcx) => {
                                 // Report the outermost adt with a destructor
@@ -1664,7 +1649,6 @@
                             _ => base_access,
                         }
                     }
-
                     ProjectionElem::ConstantIndex { .. }
                     | ProjectionElem::Subslice { .. }
                     | ProjectionElem::Index(_) => base_access,
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
index eccb616..a3d09c3 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
@@ -75,7 +75,7 @@
                     LaterUseKind::FakeLetRead => "stored here",
                     LaterUseKind::Other => "used here",
                 };
-                if !borrow_span.map(|sp| sp.overlaps(var_or_use_span)).unwrap_or(false) {
+                if !borrow_span.map_or(false, |sp| sp.overlaps(var_or_use_span)) {
                     err.span_label(
                         var_or_use_span,
                         format!("{}borrow later {}", borrow_desc, message),
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
index 4ebc1cd..6d98bf5 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
@@ -103,7 +103,7 @@
                         let did = did.expect_local();
                         let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
 
-                        if let Some((span, name)) =
+                        if let Some((span, hir_place)) =
                             self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
                         {
                             diag.span_note(
@@ -111,7 +111,7 @@
                                 &format!(
                                     "closure cannot be invoked more than once because it moves the \
                                     variable `{}` out of its environment",
-                                    name,
+                                    ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
                                 ),
                             );
                             return;
@@ -127,7 +127,7 @@
                 let did = did.expect_local();
                 let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
 
-                if let Some((span, name)) =
+                if let Some((span, hir_place)) =
                     self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
                 {
                     diag.span_note(
@@ -135,7 +135,7 @@
                         &format!(
                             "closure cannot be moved more than once as it is not `Copy` due to \
                              moving the variable `{}` out of its environment",
-                            name
+                            ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
                         ),
                     );
                 }
@@ -338,8 +338,7 @@
                     self.describe_field(PlaceRef { local, projection: proj_base }, field)
                 }
                 ProjectionElem::Downcast(_, variant_index) => {
-                    let base_ty =
-                        Place::ty_from(place.local, place.projection, self.body, self.infcx.tcx).ty;
+                    let base_ty = place.ty(self.body, self.infcx.tcx).ty;
                     self.describe_field_from_ty(&base_ty, field, Some(*variant_index))
                 }
                 ProjectionElem::Field(_, field_type) => {
@@ -473,7 +472,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.local, deref_base.projection, self.body, tcx).ty;
+        let base_ty = deref_base.ty(self.body, tcx).ty;
         if base_ty.is_unsafe_ptr() {
             BorrowedContentSource::DerefRawPointer
         } else if base_ty.is_mutable_ptr() {
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs
index b1cebbd..350e0d0 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs
@@ -302,7 +302,7 @@
             .find_map(|p| self.is_upvar_field_projection(p));
 
         let deref_base = match deref_target_place.projection.as_ref() {
-            &[ref proj_base @ .., ProjectionElem::Deref] => {
+            [proj_base @ .., ProjectionElem::Deref] => {
                 PlaceRef { local: deref_target_place.local, projection: &proj_base }
             }
             _ => bug!("deref_target_place is not a deref projection"),
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
index 78da43c..ab83fc8 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
@@ -590,8 +590,8 @@
 
                     let mut found = false;
                     for (bound, _) in bounds {
-                        if let ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(_, r)) =
-                            bound.skip_binders()
+                        if let ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_, r)) =
+                            bound.kind().skip_binder()
                         {
                             let r = r.subst(self.infcx.tcx, substs);
                             if let ty::RegionKind::ReStatic = r {
diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs
index 44044d5..006e050 100644
--- a/compiler/rustc_mir/src/borrow_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/mod.rs
@@ -1740,20 +1740,18 @@
 
         self.check_if_full_path_is_moved(location, desired_action, place_span, flow_state);
 
-        if let [base_proj @ .., ProjectionElem::Subslice { from, to, from_end: false }] =
-            place_span.0.projection
+        if let Some((place_base, ProjectionElem::Subslice { from, to, from_end: false })) =
+            place_span.0.last_projection()
         {
-            let place_ty =
-                Place::ty_from(place_span.0.local, base_proj, self.body(), self.infcx.tcx);
+            let place_ty = PlaceRef::ty(&place_base, self.body(), self.infcx.tcx);
             if let ty::Array(..) = place_ty.ty.kind() {
-                let array_place = PlaceRef { local: place_span.0.local, projection: base_proj };
                 self.check_if_subslice_element_is_moved(
                     location,
                     desired_action,
-                    (array_place, place_span.1),
+                    (place_base, place_span.1),
                     maybe_uninits,
-                    *from,
-                    *to,
+                    from,
+                    to,
                 );
                 return;
             }
@@ -1825,10 +1823,7 @@
         debug!("check_if_assigned_path_is_moved place: {:?}", place);
 
         // None case => assigning to `x` does not require `x` be initialized.
-        let mut cursor = &*place.projection.as_ref();
-        while let [proj_base @ .., elem] = cursor {
-            cursor = proj_base;
-
+        for (place_base, elem) in place.iter_projections().rev() {
             match elem {
                 ProjectionElem::Index(_/*operand*/) |
                 ProjectionElem::ConstantIndex { .. } |
@@ -1843,10 +1838,7 @@
                 ProjectionElem::Deref => {
                     self.check_if_full_path_is_moved(
                         location, InitializationRequiringAction::Use,
-                        (PlaceRef {
-                            local: place.local,
-                            projection: proj_base,
-                        }, span), flow_state);
+                        (place_base, span), flow_state);
                     // (base initialized; no need to
                     // recur further)
                     break;
@@ -1862,15 +1854,12 @@
                     // assigning to `P.f` requires `P` itself
                     // be already initialized
                     let tcx = self.infcx.tcx;
-                    let base_ty = Place::ty_from(place.local, proj_base, self.body(), tcx).ty;
+                    let base_ty = PlaceRef::ty(&place_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 {
-                                    local: place.local,
-                                    projection: proj_base,
-                                }, span), flow_state);
+                                (place_base, span), flow_state);
 
                             // (base initialized; no need to
                             // recur further)
@@ -1880,10 +1869,7 @@
                         // Once `let s; s.x = V; read(s.x);`,
                         // is allowed, remove this match arm.
                         ty::Adt(..) | ty::Tuple(..) => {
-                            check_parent_of_field(self, location, PlaceRef {
-                                local: place.local,
-                                projection: proj_base,
-                            }, span, flow_state);
+                            check_parent_of_field(self, location, place_base, span, flow_state);
 
                             // rust-lang/rust#21232, #54499, #54986: during period where we reject
                             // partial initialization, do not complain about unnecessary `mut` on
@@ -1965,9 +1951,7 @@
                 // no move out from an earlier location) then this is an attempt at initialization
                 // of the union - we should error in that case.
                 let tcx = this.infcx.tcx;
-                if let ty::Adt(def, _) =
-                    Place::ty_from(base.local, base.projection, this.body(), tcx).ty.kind()
-                {
+                if let ty::Adt(def, _) = PlaceRef::ty(&base, this.body(), tcx).ty.kind() {
                     if def.is_union() {
                         if this.move_data.path_map[mpi].iter().any(|moi| {
                             this.move_data.moves[*moi].source.is_predecessor_of(location, this.body)
@@ -2162,9 +2146,9 @@
         place: PlaceRef<'tcx>,
         is_local_mutation_allowed: LocalMutationIsAllowed,
     ) -> Result<RootPlace<'tcx>, PlaceRef<'tcx>> {
-        match place {
-            PlaceRef { local, projection: [] } => {
-                let local = &self.body.local_decls[local];
+        match place.last_projection() {
+            None => {
+                let local = &self.body.local_decls[place.local];
                 match local.mutability {
                     Mutability::Not => match is_local_mutation_allowed {
                         LocalMutationIsAllowed::Yes => Ok(RootPlace {
@@ -2186,11 +2170,10 @@
                     }),
                 }
             }
-            PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
+            Some((place_base, elem)) => {
                 match elem {
                     ProjectionElem::Deref => {
-                        let base_ty =
-                            Place::ty_from(place.local, proj_base, self.body(), self.infcx.tcx).ty;
+                        let base_ty = PlaceRef::ty(&place_base, self.body(), self.infcx.tcx).ty;
 
                         // Check the kind of deref to decide
                         match base_ty.kind() {
@@ -2208,10 +2191,7 @@
                                             _ => LocalMutationIsAllowed::Yes,
                                         };
 
-                                        self.is_mutable(
-                                            PlaceRef { local: place.local, projection: proj_base },
-                                            mode,
-                                        )
+                                        self.is_mutable(place_base, mode)
                                     }
                                 }
                             }
@@ -2229,10 +2209,9 @@
                                 }
                             }
                             // `Box<T>` owns its content, so mutable if its location is mutable
-                            _ if base_ty.is_box() => self.is_mutable(
-                                PlaceRef { local: place.local, projection: proj_base },
-                                is_local_mutation_allowed,
-                            ),
+                            _ if base_ty.is_box() => {
+                                self.is_mutable(place_base, is_local_mutation_allowed)
+                            }
                             // Deref should only be for reference, pointers or boxes
                             _ => bug!("Deref of unexpected type: {:?}", base_ty),
                         }
@@ -2286,10 +2265,8 @@
                                     //     });
                                     // }
                                     // ```
-                                    let _ = self.is_mutable(
-                                        PlaceRef { local: place.local, projection: proj_base },
-                                        is_local_mutation_allowed,
-                                    )?;
+                                    let _ =
+                                        self.is_mutable(place_base, is_local_mutation_allowed)?;
                                     Ok(RootPlace {
                                         place_local: place.local,
                                         place_projection: place.projection,
@@ -2298,10 +2275,7 @@
                                 }
                             }
                         } else {
-                            self.is_mutable(
-                                PlaceRef { local: place.local, projection: proj_base },
-                                is_local_mutation_allowed,
-                            )
+                            self.is_mutable(place_base, is_local_mutation_allowed)
                         }
                     }
                 }
diff --git a/compiler/rustc_mir/src/borrow_check/path_utils.rs b/compiler/rustc_mir/src/borrow_check/path_utils.rs
index 9347295..fa3ae23 100644
--- a/compiler/rustc_mir/src/borrow_check/path_utils.rs
+++ b/compiler/rustc_mir/src/borrow_check/path_utils.rs
@@ -147,27 +147,25 @@
     place_ref: PlaceRef<'tcx>,
     body: &Body<'tcx>,
 ) -> Option<Field> {
-    let mut place_projection = place_ref.projection;
+    let mut place_ref = place_ref;
     let mut by_ref = false;
 
-    if let [proj_base @ .., ProjectionElem::Deref] = place_projection {
-        place_projection = proj_base;
+    if let Some((place_base, ProjectionElem::Deref)) = place_ref.last_projection() {
+        place_ref = place_base;
         by_ref = true;
     }
 
-    match place_projection {
-        [base @ .., ProjectionElem::Field(field, _ty)] => {
-            let base_ty = Place::ty_from(place_ref.local, base, body, tcx).ty;
-
+    match place_ref.last_projection() {
+        Some((place_base, ProjectionElem::Field(field, _ty))) => {
+            let base_ty = place_base.ty(body, tcx).ty;
             if (base_ty.is_closure() || base_ty.is_generator())
                 && (!by_ref || upvars[field.index()].by_ref)
             {
-                Some(*field)
+                Some(field)
             } else {
                 None
             }
         }
-
         _ => None,
     }
 }
diff --git a/compiler/rustc_mir/src/borrow_check/prefixes.rs b/compiler/rustc_mir/src/borrow_check/prefixes.rs
index 6c5d422..cf04c55 100644
--- a/compiler/rustc_mir/src/borrow_check/prefixes.rs
+++ b/compiler/rustc_mir/src/borrow_check/prefixes.rs
@@ -10,7 +10,7 @@
 use super::MirBorrowckCtxt;
 
 use rustc_hir as hir;
-use rustc_middle::mir::{Body, Place, PlaceRef, ProjectionElem};
+use rustc_middle::mir::{Body, PlaceRef, ProjectionElem};
 use rustc_middle::ty::{self, TyCtxt};
 
 pub trait IsPrefixOf<'tcx> {
@@ -67,24 +67,23 @@
         // downcasts here, but may return a base of a downcast).
 
         'cursor: loop {
-            match &cursor {
-                PlaceRef { local: _, projection: [] } => {
+            match cursor.last_projection() {
+                None => {
                     self.next = None;
                     return Some(cursor);
                 }
-                PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
+                Some((cursor_base, elem)) => {
                     match elem {
                         ProjectionElem::Field(_ /*field*/, _ /*ty*/) => {
                             // FIXME: add union handling
-                            self.next =
-                                Some(PlaceRef { local: cursor.local, projection: proj_base });
+                            self.next = Some(cursor_base);
                             return Some(cursor);
                         }
                         ProjectionElem::Downcast(..)
                         | ProjectionElem::Subslice { .. }
                         | ProjectionElem::ConstantIndex { .. }
                         | ProjectionElem::Index(_) => {
-                            cursor = PlaceRef { local: cursor.local, projection: proj_base };
+                            cursor = cursor_base;
                             continue 'cursor;
                         }
                         ProjectionElem::Deref => {
@@ -92,7 +91,7 @@
                         }
                     }
 
-                    assert_eq!(*elem, ProjectionElem::Deref);
+                    assert_eq!(elem, ProjectionElem::Deref);
 
                     match self.kind {
                         PrefixSet::Shallow => {
@@ -105,8 +104,7 @@
                         PrefixSet::All => {
                             // All prefixes: just blindly enqueue the base
                             // of the projection.
-                            self.next =
-                                Some(PlaceRef { local: cursor.local, projection: proj_base });
+                            self.next = Some(cursor_base);
                             return Some(cursor);
                         }
                         PrefixSet::Supporting => {
@@ -119,7 +117,7 @@
                     // derefs, except we stop at the deref of a shared
                     // reference.
 
-                    let ty = Place::ty_from(cursor.local, proj_base, self.body, self.tcx).ty;
+                    let ty = PlaceRef::ty(&cursor_base, self.body, self.tcx).ty;
                     match ty.kind() {
                         ty::RawPtr(_) | ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Not) => {
                             // don't continue traversing over derefs of raw pointers or shared
@@ -129,14 +127,12 @@
                         }
 
                         ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Mut) => {
-                            self.next =
-                                Some(PlaceRef { local: cursor.local, projection: proj_base });
+                            self.next = Some(cursor_base);
                             return Some(cursor);
                         }
 
                         ty::Adt(..) if ty.is_box() => {
-                            self.next =
-                                Some(PlaceRef { local: cursor.local, projection: proj_base });
+                            self.next = Some(cursor_base);
                             return Some(cursor);
                         }
 
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs
index b7d22fa..157959b 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs
@@ -39,10 +39,8 @@
             user_provided_sig = None;
         } else {
             let typeck_results = self.tcx().typeck(mir_def_id);
-            user_provided_sig = match typeck_results.user_provided_sigs.get(&mir_def_id.to_def_id())
-            {
-                None => None,
-                Some(user_provided_poly_sig) => {
+            user_provided_sig = typeck_results.user_provided_sigs.get(&mir_def_id.to_def_id()).map(
+                |user_provided_poly_sig| {
                     // Instantiate the canonicalized variables from
                     // user-provided signature (e.g., the `_` in the code
                     // above) with fresh variables.
@@ -54,18 +52,16 @@
                     // Replace the bound items in the fn sig with fresh
                     // variables, so that they represent the view from
                     // "inside" the closure.
-                    Some(
-                        self.infcx
-                            .replace_bound_vars_with_fresh_vars(
-                                body.span,
-                                LateBoundRegionConversionTime::FnCall,
-                                poly_sig,
-                            )
-                            .0,
-                    )
-                }
-            }
-        };
+                    self.infcx
+                        .replace_bound_vars_with_fresh_vars(
+                            body.span,
+                            LateBoundRegionConversionTime::FnCall,
+                            poly_sig,
+                        )
+                        .0
+                },
+            );
+        }
 
         debug!(
             "equate_inputs_and_outputs: normalized_input_tys = {:?}, local_decls = {:?}",
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
index 42cd050..fb9820e 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
@@ -1014,7 +1014,7 @@
                     }
 
                     self.prove_predicate(
-                        ty::PredicateAtom::WellFormed(inferred_ty.into()).to_predicate(self.tcx()),
+                        ty::PredicateKind::WellFormed(inferred_ty.into()).to_predicate(self.tcx()),
                         Locations::All(span),
                         ConstraintCategory::TypeAnnotation,
                     );
@@ -1266,7 +1266,7 @@
                     obligations.obligations.push(traits::Obligation::new(
                         ObligationCause::dummy(),
                         param_env,
-                        ty::PredicateAtom::WellFormed(revealed_ty.into()).to_predicate(infcx.tcx),
+                        ty::PredicateKind::WellFormed(revealed_ty.into()).to_predicate(infcx.tcx),
                     ));
                     obligations.add(
                         infcx
@@ -1611,7 +1611,7 @@
                 self.check_call_dest(body, term, &sig, destination, term_location);
 
                 self.prove_predicates(
-                    sig.inputs_and_output.iter().map(|ty| ty::PredicateAtom::WellFormed(ty.into())),
+                    sig.inputs_and_output.iter().map(|ty| ty::PredicateKind::WellFormed(ty.into())),
                     term_location.to_locations(),
                     ConstraintCategory::Boring,
                 );
@@ -1855,8 +1855,8 @@
                     self.assert_iscleanup(body, block_data, unwind, true);
                 }
             }
-            TerminatorKind::InlineAsm { ref destination, .. } => {
-                if let &Some(target) = destination {
+            TerminatorKind::InlineAsm { destination, .. } => {
+                if let Some(target) = destination {
                     self.assert_iscleanup(body, block_data, target, is_cleanup);
                 }
             }
@@ -2694,7 +2694,7 @@
         category: ConstraintCategory,
     ) {
         self.prove_predicates(
-            Some(ty::PredicateAtom::Trait(
+            Some(ty::PredicateKind::Trait(
                 ty::TraitPredicate { trait_ref },
                 hir::Constness::NotConst,
             )),
diff --git a/compiler/rustc_mir/src/borrow_check/universal_regions.rs b/compiler/rustc_mir/src/borrow_check/universal_regions.rs
index c1a0d98..02d951b 100644
--- a/compiler/rustc_mir/src/borrow_check/universal_regions.rs
+++ b/compiler/rustc_mir/src/borrow_check/universal_regions.rs
@@ -788,13 +788,13 @@
     fn_def_id: DefId,
     mut f: impl FnMut(ty::Region<'tcx>),
 ) {
-    if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) {
-        for late_bound in late_bounds.iter() {
-            let hir_id = HirId { owner: fn_def_id.expect_local(), local_id: *late_bound };
+    if let Some((owner, late_bounds)) = tcx.is_late_bound_map(fn_def_id.expect_local()) {
+        for &late_bound in late_bounds.iter() {
+            let hir_id = HirId { owner, local_id: late_bound };
             let name = tcx.hir().name(hir_id);
             let region_def_id = tcx.hir().local_def_id(hir_id);
             let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion {
-                scope: fn_def_id,
+                scope: owner.to_def_id(),
                 bound_region: ty::BoundRegionKind::BrNamed(region_def_id.to_def_id(), name),
             }));
             f(liberated_region);
diff --git a/compiler/rustc_mir/src/const_eval/fn_queries.rs b/compiler/rustc_mir/src/const_eval/fn_queries.rs
index aca822a..8c18dfc 100644
--- a/compiler/rustc_mir/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_mir/src/const_eval/fn_queries.rs
@@ -126,7 +126,7 @@
     matches!(
         node,
         hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Impl { constness: hir::Constness::Const, .. },
+            kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
             ..
         })
     )
diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_mir/src/const_eval/machine.rs
index 72912dd..49126cf 100644
--- a/compiler/rustc_mir/src/const_eval/machine.rs
+++ b/compiler/rustc_mir/src/const_eval/machine.rs
@@ -13,6 +13,7 @@
 use rustc_session::Limit;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::{Align, Size};
+use rustc_target::spec::abi::Abi;
 
 use crate::interpret::{
     self, compile_time_machine, AllocId, Allocation, Frame, ImmTy, InterpCx, InterpResult, Memory,
@@ -200,9 +201,26 @@
 
     type MemoryExtra = MemoryExtra;
 
+    fn load_mir(
+        ecx: &InterpCx<'mir, 'tcx, Self>,
+        instance: ty::InstanceDef<'tcx>,
+    ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
+        match instance {
+            ty::InstanceDef::Item(def) => {
+                if ecx.tcx.is_ctfe_mir_available(def.did) {
+                    Ok(ecx.tcx.mir_for_ctfe_opt_const_arg(def))
+                } else {
+                    throw_unsup!(NoMirFor(def.did))
+                }
+            }
+            _ => Ok(ecx.tcx.instance_mir(instance)),
+        }
+    }
+
     fn find_mir_or_eval_fn(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
+        _abi: Abi,
         args: &[OpTy<'tcx>],
         _ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
         _unwind: Option<mir::BasicBlock>, // unwinding is not supported in consts
diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
index ab7fada..ee78ff0 100644
--- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
+++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
@@ -518,14 +518,10 @@
 
         // Check if we are assigning into a field of a union, if so, lookup the place
         // of the union so it is marked as initialized again.
-        if let [proj_base @ .., ProjectionElem::Field(_, _)] = place.projection {
-            if let ty::Adt(def, _) =
-                Place::ty_from(place.local, proj_base, self.builder.body, self.builder.tcx)
-                    .ty
-                    .kind()
-            {
+        if let Some((place_base, ProjectionElem::Field(_, _))) = place.last_projection() {
+            if let ty::Adt(def, _) = place_base.ty(self.builder.body, self.builder.tcx).ty.kind() {
                 if def.is_union() {
-                    place = PlaceRef { local: place.local, projection: proj_base }
+                    place = place_base;
                 }
             }
         }
diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs
index 3d95557..7e9594d 100644
--- a/compiler/rustc_mir/src/interpret/eval_context.rs
+++ b/compiler/rustc_mir/src/interpret/eval_context.rs
@@ -370,7 +370,7 @@
 
     #[inline(always)]
     pub fn cur_span(&self) -> Span {
-        self.stack().last().map(|f| f.current_span()).unwrap_or(self.tcx.span)
+        self.stack().last().map_or(self.tcx.span, |f| f.current_span())
     }
 
     #[inline(always)]
@@ -477,16 +477,7 @@
         if let Some(promoted) = promoted {
             return Ok(&self.tcx.promoted_mir_opt_const_arg(def)[promoted]);
         }
-        match instance {
-            ty::InstanceDef::Item(def) => {
-                if self.tcx.is_mir_available(def.did) {
-                    Ok(self.tcx.optimized_mir_opt_const_arg(def))
-                } else {
-                    throw_unsup!(NoMirFor(def.did))
-                }
-            }
-            _ => Ok(self.tcx.instance_mir(instance)),
-        }
+        M::load_mir(self, instance)
     }
 
     /// Call this on things you got out of the MIR (so it is as generic as the current
diff --git a/compiler/rustc_mir/src/interpret/machine.rs b/compiler/rustc_mir/src/interpret/machine.rs
index f50cc6c1..53ac62d 100644
--- a/compiler/rustc_mir/src/interpret/machine.rs
+++ b/compiler/rustc_mir/src/interpret/machine.rs
@@ -10,6 +10,7 @@
 use rustc_middle::ty::{self, Ty};
 use rustc_span::def_id::DefId;
 use rustc_target::abi::Size;
+use rustc_target::spec::abi::Abi;
 
 use super::{
     AllocId, Allocation, AllocationExtra, CheckInAllocMsg, Frame, ImmTy, InterpCx, InterpResult,
@@ -131,6 +132,16 @@
     /// Whether to enforce the validity invariant
     fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
 
+    /// Entry point for obtaining the MIR of anything that should get evaluated.
+    /// So not just functions and shims, but also const/static initializers, anonymous
+    /// constants, ...
+    fn load_mir(
+        ecx: &InterpCx<'mir, 'tcx, Self>,
+        instance: ty::InstanceDef<'tcx>,
+    ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
+        Ok(ecx.tcx.instance_mir(instance))
+    }
+
     /// Entry point to all function calls.
     ///
     /// Returns either the mir to use for the call, or `None` if execution should
@@ -144,6 +155,7 @@
     fn find_mir_or_eval_fn(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
+        abi: Abi,
         args: &[OpTy<'tcx, Self::PointerTag>],
         ret: Option<(PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
         unwind: Option<mir::BasicBlock>,
@@ -154,6 +166,7 @@
     fn call_extra_fn(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         fn_val: Self::ExtraFnVal,
+        abi: Abi,
         args: &[OpTy<'tcx, Self::PointerTag>],
         ret: Option<(PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
         unwind: Option<mir::BasicBlock>,
@@ -405,6 +418,7 @@
     fn call_extra_fn(
         _ecx: &mut InterpCx<$mir, $tcx, Self>,
         fn_val: !,
+        _abi: Abi,
         _args: &[OpTy<$tcx>],
         _ret: Option<(PlaceTy<$tcx>, mir::BasicBlock)>,
         _unwind: Option<mir::BasicBlock>,
diff --git a/compiler/rustc_mir/src/interpret/terminator.rs b/compiler/rustc_mir/src/interpret/terminator.rs
index a293132..575667f 100644
--- a/compiler/rustc_mir/src/interpret/terminator.rs
+++ b/compiler/rustc_mir/src/interpret/terminator.rs
@@ -219,7 +219,7 @@
         let instance = match fn_val {
             FnVal::Instance(instance) => instance,
             FnVal::Other(extra) => {
-                return M::call_extra_fn(self, extra, args, ret, unwind);
+                return M::call_extra_fn(self, extra, caller_abi, args, ret, unwind);
             }
         };
 
@@ -264,10 +264,11 @@
             | ty::InstanceDef::CloneShim(..)
             | ty::InstanceDef::Item(_) => {
                 // We need MIR for this fn
-                let body = match M::find_mir_or_eval_fn(self, instance, args, ret, unwind)? {
-                    Some(body) => body,
-                    None => return Ok(()),
-                };
+                let body =
+                    match M::find_mir_or_eval_fn(self, instance, caller_abi, args, ret, unwind)? {
+                        Some(body) => body,
+                        None => return Ok(()),
+                    };
 
                 self.push_stack_frame(
                     instance,
diff --git a/compiler/rustc_mir/src/interpret/util.rs b/compiler/rustc_mir/src/interpret/util.rs
index c2165db..89f34cd 100644
--- a/compiler/rustc_mir/src/interpret/util.rs
+++ b/compiler/rustc_mir/src/interpret/util.rs
@@ -47,8 +47,7 @@
                         let index = index
                             .try_into()
                             .expect("more generic parameters than can fit into a `u32`");
-                        let is_used =
-                            unused_params.contains(index).map(|unused| !unused).unwrap_or(true);
+                        let is_used = unused_params.contains(index).map_or(true, |unused| !unused);
                         // Only recurse when generic parameters in fns, closures and generators
                         // are used and require substitution.
                         match (is_used, subst.needs_subst()) {
diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs
index 6370ead..75f80f6 100644
--- a/compiler/rustc_mir/src/monomorphize/collector.rs
+++ b/compiler/rustc_mir/src/monomorphize/collector.rs
@@ -823,7 +823,7 @@
     }
 
     if !tcx.is_mir_available(def_id) {
-        bug!("cannot create local mono-item for {:?}", def_id)
+        bug!("no MIR available for {:?}", def_id);
     }
 
     true
@@ -1146,8 +1146,8 @@
     output: &mut Vec<Spanned<MonoItem<'tcx>>>,
 ) {
     match item.kind {
-        hir::ItemKind::Impl { ref generics, ref items, .. } => {
-            for param in generics.params {
+        hir::ItemKind::Impl(ref impl_) => {
+            for param in impl_.generics.params {
                 match param.kind {
                     hir::GenericParamKind::Lifetime { .. } => {}
                     hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => {
@@ -1167,7 +1167,7 @@
                 let param_env = ty::ParamEnv::reveal_all();
                 let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
                 let overridden_methods: FxHashSet<_> =
-                    items.iter().map(|iiref| iiref.ident.normalize_to_macros_2_0()).collect();
+                    impl_.items.iter().map(|iiref| iiref.ident.normalize_to_macros_2_0()).collect();
                 for method in tcx.provided_trait_methods(trait_ref.def_id) {
                     if overridden_methods.contains(&method.ident.normalize_to_macros_2_0()) {
                         continue;
diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs b/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs
index db6d3b2..b9fcd32 100644
--- a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs
+++ b/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs
@@ -247,8 +247,7 @@
             for (mono_item, linkage) in cgu.items() {
                 let symbol_name = mono_item.symbol_name(tcx).name;
                 let symbol_hash_start = symbol_name.rfind('h');
-                let symbol_hash =
-                    symbol_hash_start.map(|i| &symbol_name[i..]).unwrap_or("<no hash>");
+                let symbol_hash = symbol_hash_start.map_or("<no hash>", |i| &symbol_name[i..]);
 
                 debug!(
                     " - {} [{:?}] [{}] estimated size {}",
diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs
index 0ce1c5a..4ad71ab 100644
--- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs
+++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs
@@ -5,7 +5,7 @@
 //! generic parameters are unused (and eventually, in what ways generic parameters are used - only
 //! for their size, offset of a field, etc.).
 
-use rustc_hir::{def::DefKind, def_id::DefId};
+use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
 use rustc_index::bit_set::FiniteBitSet;
 use rustc_middle::mir::{
     visit::{TyContext, Visitor},
@@ -54,9 +54,17 @@
     }
 
     // Exit early when there is no MIR available.
-    if !tcx.is_mir_available(def_id) {
-        debug!("unused_generic_params: (no mir available) def_id={:?}", def_id);
-        return FiniteBitSet::new_empty();
+    let context = tcx.hir().body_const_context(def_id.expect_local());
+    match context {
+        Some(ConstContext::ConstFn) | None if !tcx.is_mir_available(def_id) => {
+            debug!("unused_generic_params: (no mir available) def_id={:?}", def_id);
+            return FiniteBitSet::new_empty();
+        }
+        Some(_) if !tcx.is_ctfe_mir_available(def_id) => {
+            debug!("unused_generic_params: (no ctfe mir available) def_id={:?}", def_id);
+            return FiniteBitSet::new_empty();
+        }
+        _ => {}
     }
 
     // Create a bitset with N rightmost ones for each parameter.
@@ -69,7 +77,12 @@
     debug!("unused_generic_params: (after default) unused_parameters={:?}", unused_parameters);
 
     // Visit MIR and accumululate used generic parameters.
-    let body = tcx.optimized_mir(def_id);
+    let body = match context {
+        // Const functions are actually called and should thus be considered for polymorphization
+        // via their runtime MIR
+        Some(ConstContext::ConstFn) | None => tcx.optimized_mir(def_id),
+        Some(_) => tcx.mir_for_ctfe(def_id),
+    };
     let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters };
     vis.visit_body(body);
     debug!("unused_generic_params: (after visitor) unused_parameters={:?}", unused_parameters);
diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs
index d2e65ab..9e90a75 100644
--- a/compiler/rustc_mir/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs
@@ -209,16 +209,61 @@
 }
 
 #[derive(Debug)]
+/// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow never escapes to
+/// the final value of the constant.
+pub struct TransientCellBorrow;
+impl NonConstOp for TransientCellBorrow {
+    fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
+        Status::Unstable(sym::const_refs_to_cell)
+    }
+    fn importance(&self) -> DiagnosticImportance {
+        // The cases that cannot possibly work will already emit a `CellBorrow`, so we should
+        // not additionally emit a feature gate error if activating the feature gate won't work.
+        DiagnosticImportance::Secondary
+    }
+    fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
+        feature_err(
+            &ccx.tcx.sess.parse_sess,
+            sym::const_refs_to_cell,
+            span,
+            "cannot borrow here, since the borrowed element may contain interior mutability",
+        )
+    }
+}
+
+#[derive(Debug)]
+/// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow might escape to
+/// the final value of the constant, and thus we cannot allow this (for now). We may allow
+/// it in the future for static items.
 pub struct CellBorrow;
 impl NonConstOp for CellBorrow {
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
-        struct_span_err!(
+        let mut err = struct_span_err!(
             ccx.tcx.sess,
             span,
             E0492,
-            "cannot borrow a constant which may contain \
-            interior mutability, create a static instead"
-        )
+            "{}s cannot refer to interior mutable data",
+            ccx.const_kind(),
+        );
+        err.span_label(
+            span,
+            format!("this borrow of an interior mutable value may end up in the final value"),
+        );
+        if let hir::ConstContext::Static(_) = ccx.const_kind() {
+            err.help(
+                "to fix this, the value can be extracted to a separate \
+                `static` item and then referenced",
+            );
+        }
+        if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
+            err.note(
+                "A constant containing interior mutable data behind a reference can allow you
+                 to modify that data. This would make multiple uses of a constant to be able to
+                 see different values and allow circumventing the `Send` and `Sync` requirements
+                 for shared mutable data, which is unsound.",
+            );
+        }
+        err
     }
 }
 
diff --git a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs
index c66d3ed..0ce1980 100644
--- a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs
@@ -174,14 +174,10 @@
 
         Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
             // Special-case reborrows to be more like a copy of the reference.
-            if let &[ref proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
-                let base_ty = Place::ty_from(place.local, proj_base, cx.body, cx.tcx).ty;
+            if let Some((place_base, ProjectionElem::Deref)) = place.as_ref().last_projection() {
+                let base_ty = place_base.ty(cx.body, cx.tcx).ty;
                 if let ty::Ref(..) = base_ty.kind() {
-                    return in_place::<Q, _>(
-                        cx,
-                        in_local,
-                        PlaceRef { local: place.local, projection: proj_base },
-                    );
+                    return in_place::<Q, _>(cx, in_local, place_base);
                 }
             }
 
@@ -209,9 +205,9 @@
     Q: Qualif,
     F: FnMut(Local) -> bool,
 {
-    let mut projection = place.projection;
-    while let &[ref proj_base @ .., proj_elem] = projection {
-        match proj_elem {
+    let mut place = place;
+    while let Some((place_base, elem)) = place.last_projection() {
+        match elem {
             ProjectionElem::Index(index) if in_local(index) => return true,
 
             ProjectionElem::Deref
@@ -222,16 +218,16 @@
             | ProjectionElem::Index(_) => {}
         }
 
-        let base_ty = Place::ty_from(place.local, proj_base, cx.body, cx.tcx);
-        let proj_ty = base_ty.projection_ty(cx.tcx, proj_elem).ty;
+        let base_ty = place_base.ty(cx.body, cx.tcx);
+        let proj_ty = base_ty.projection_ty(cx.tcx, elem).ty;
         if !Q::in_any_value_of_ty(cx, proj_ty) {
             return false;
         }
 
-        projection = proj_base;
+        place = place_base;
     }
 
-    assert!(projection.is_empty());
+    assert!(place.projection.is_empty());
     in_local(place.local)
 }
 
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
index 90688eb..3d81926 100644
--- a/compiler/rustc_mir/src/transform/check_consts/validation.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs
@@ -3,6 +3,7 @@
 use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorReported};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, HirId, LangItem};
+use rustc_index::bit_set::BitSet;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
@@ -188,6 +189,9 @@
     /// The span of the current statement.
     span: Span,
 
+    /// A set that stores for each local whether it has a `StorageDead` for it somewhere.
+    local_has_storage_dead: Option<BitSet<Local>>,
+
     error_emitted: Option<ErrorReported>,
     secondary_errors: Vec<Diagnostic>,
 }
@@ -206,6 +210,7 @@
             span: ccx.body.span,
             ccx,
             qualifs: Default::default(),
+            local_has_storage_dead: None,
             error_emitted: None,
             secondary_errors: Vec::new(),
         }
@@ -282,6 +287,27 @@
         }
     }
 
+    fn local_has_storage_dead(&mut self, local: Local) -> bool {
+        let ccx = self.ccx;
+        self.local_has_storage_dead
+            .get_or_insert_with(|| {
+                struct StorageDeads {
+                    locals: BitSet<Local>,
+                }
+                impl Visitor<'tcx> for StorageDeads {
+                    fn visit_statement(&mut self, stmt: &Statement<'tcx>, _: Location) {
+                        if let StatementKind::StorageDead(l) = stmt.kind {
+                            self.locals.insert(l);
+                        }
+                    }
+                }
+                let mut v = StorageDeads { locals: BitSet::new_empty(ccx.body.local_decls.len()) };
+                v.visit_body(ccx.body);
+                v.locals
+            })
+            .contains(local)
+    }
+
     pub fn qualifs_in_return_place(&mut self) -> ConstQualifs {
         self.qualifs.in_return_place(self.ccx, self.error_emitted)
     }
@@ -385,24 +411,24 @@
         loop {
             let predicates = tcx.predicates_of(current);
             for (predicate, _) in predicates.predicates {
-                match predicate.skip_binders() {
-                    ty::PredicateAtom::RegionOutlives(_)
-                    | ty::PredicateAtom::TypeOutlives(_)
-                    | ty::PredicateAtom::WellFormed(_)
-                    | ty::PredicateAtom::Projection(_)
-                    | ty::PredicateAtom::ConstEvaluatable(..)
-                    | ty::PredicateAtom::ConstEquate(..)
-                    | ty::PredicateAtom::TypeWellFormedFromEnv(..) => continue,
-                    ty::PredicateAtom::ObjectSafe(_) => {
+                match predicate.kind().skip_binder() {
+                    ty::PredicateKind::RegionOutlives(_)
+                    | ty::PredicateKind::TypeOutlives(_)
+                    | ty::PredicateKind::WellFormed(_)
+                    | ty::PredicateKind::Projection(_)
+                    | ty::PredicateKind::ConstEvaluatable(..)
+                    | ty::PredicateKind::ConstEquate(..)
+                    | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
+                    ty::PredicateKind::ObjectSafe(_) => {
                         bug!("object safe predicate on function: {:#?}", predicate)
                     }
-                    ty::PredicateAtom::ClosureKind(..) => {
+                    ty::PredicateKind::ClosureKind(..) => {
                         bug!("closure kind predicate on function: {:#?}", predicate)
                     }
-                    ty::PredicateAtom::Subtype(_) => {
+                    ty::PredicateKind::Subtype(_) => {
                         bug!("subtype predicate on function: {:#?}", predicate)
                     }
-                    ty::PredicateAtom::Trait(pred, constness) => {
+                    ty::PredicateKind::Trait(pred, constness) => {
                         if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
                             continue;
                         }
@@ -556,7 +582,29 @@
                 );
 
                 if borrowed_place_has_mut_interior {
-                    self.check_op(ops::CellBorrow);
+                    match self.const_kind() {
+                        // In a const fn all borrows are transient or point to the places given via
+                        // references in the arguments (so we already checked them with
+                        // TransientCellBorrow/CellBorrow as appropriate).
+                        // The borrow checker guarantees that no new non-transient borrows are created.
+                        // NOTE: Once we have heap allocations during CTFE we need to figure out
+                        // how to prevent `const fn` to create long-lived allocations that point
+                        // to (interior) mutable memory.
+                        hir::ConstContext::ConstFn => self.check_op(ops::TransientCellBorrow),
+                        _ => {
+                            // Locals with StorageDead are definitely not part of the final constant value, and
+                            // it is thus inherently safe to permit such locals to have their
+                            // address taken as we can't end up with a reference to them in the
+                            // final value.
+                            // Note: This is only sound if every local that has a `StorageDead` has a
+                            // `StorageDead` in every control flow path leading to a `return` terminator.
+                            if self.local_has_storage_dead(place.local) {
+                                self.check_op(ops::TransientCellBorrow);
+                            } else {
+                                self.check_op(ops::CellBorrow);
+                            }
+                        }
+                    }
                 }
             }
 
@@ -959,27 +1007,26 @@
     body: &Body<'tcx>,
     place: Place<'tcx>,
 ) -> Option<&'a [PlaceElem<'tcx>]> {
-    place.projection.split_last().and_then(|(outermost, inner)| {
-        if outermost != &ProjectionElem::Deref {
-            return None;
+    match place.as_ref().last_projection() {
+        Some((place_base, ProjectionElem::Deref)) => {
+            // 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 body.local_decls[place_base.local].is_ref_to_static() {
+                None
+            } else {
+                // 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_base.ty(body, tcx).ty;
+                match inner_ty.kind() {
+                    ty::Ref(..) => Some(place_base.projection),
+                    _ => None,
+                }
+            }
         }
-
-        // 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 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.local, inner, body, tcx).ty;
-        match inner_ty.kind() {
-            ty::Ref(..) => Some(inner),
-            _ => None,
-        }
-    })
+        _ => None,
+    }
 }
 
 fn is_int_bool_or_char(ty: Ty<'_>) -> bool {
diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs
index e64955c..bac47d0 100644
--- a/compiler/rustc_mir/src/transform/check_unsafety.rs
+++ b/compiler/rustc_mir/src/transform/check_unsafety.rs
@@ -223,13 +223,6 @@
         // Check for raw pointer `Deref`.
         for (base, proj) in place.iter_projections() {
             if proj == ProjectionElem::Deref {
-                let source_info = self.source_info; // Backup source_info so we can restore it later.
-                if base.projection.is_empty() && 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[place.local].source_info;
-                }
                 let base_ty = base.ty(self.body, self.tcx).ty;
                 if base_ty.is_unsafe_ptr() {
                     self.require_unsafe(
@@ -237,7 +230,6 @@
                         UnsafetyViolationDetails::DerefOfRawPointer,
                     )
                 }
-                self.source_info = source_info; // Restore backed-up source_info.
             }
         }
 
@@ -407,17 +399,13 @@
         place: Place<'tcx>,
         is_mut_use: bool,
     ) {
-        let mut cursor = place.projection.as_ref();
-        while let &[ref proj_base @ .., elem] = cursor {
-            cursor = proj_base;
-
+        for (place_base, elem) in place.iter_projections().rev() {
             match elem {
                 // Modifications behind a dereference don't affect the value of
                 // the pointer.
                 ProjectionElem::Deref => return,
                 ProjectionElem::Field(..) => {
-                    let ty =
-                        Place::ty_from(place.local, proj_base, &self.body.local_decls, self.tcx).ty;
+                    let ty = place_base.ty(&self.body.local_decls, self.tcx).ty;
                     if let ty::Adt(def, _) = ty.kind() {
                         if self.tcx.layout_scalar_valid_range(def.did)
                             != (Bound::Unbounded, Bound::Unbounded)
diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs
index 1d949e0..a311e26 100644
--- a/compiler/rustc_mir/src/transform/const_prop.rs
+++ b/compiler/rustc_mir/src/transform/const_prop.rs
@@ -25,6 +25,7 @@
 use rustc_session::lint;
 use rustc_span::{def_id::DefId, Span};
 use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TargetDataLayout};
+use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 
 use crate::const_eval::ConstEvalErr;
@@ -184,9 +185,17 @@
 
     type MemoryExtra = ();
 
+    fn load_mir(
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        _instance: ty::InstanceDef<'tcx>,
+    ) -> InterpResult<'tcx, &'tcx Body<'tcx>> {
+        throw_machine_stop_str!("calling functions isn't supported in ConstProp")
+    }
+
     fn find_mir_or_eval_fn(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _instance: ty::Instance<'tcx>,
+        _abi: Abi,
         _args: &[OpTy<'tcx>],
         _ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
         _unwind: Option<BasicBlock>,
diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir/src/transform/coverage/debug.rs
index b66e374..2cd0dc6 100644
--- a/compiler/rustc_mir/src/transform/coverage/debug.rs
+++ b/compiler/rustc_mir/src/transform/coverage/debug.rs
@@ -130,7 +130,7 @@
 pub(super) fn debug_options<'a>() -> &'a DebugOptions {
     static DEBUG_OPTIONS: SyncOnceCell<DebugOptions> = SyncOnceCell::new();
 
-    &DEBUG_OPTIONS.get_or_init(|| DebugOptions::from_env())
+    &DEBUG_OPTIONS.get_or_init(DebugOptions::from_env)
 }
 
 /// Parses and maintains coverage-specific debug options captured from the environment variable
@@ -430,7 +430,7 @@
         {
             bcb_to_coverage_spans_with_counters
                 .entry(bcb)
-                .or_insert_with(|| Vec::new())
+                .or_insert_with(Vec::new)
                 .push((coverage_span.clone(), counter_kind.clone()));
         }
     }
@@ -456,7 +456,7 @@
         if let Some(bcb_to_dependency_counters) = self.some_bcb_to_dependency_counters.as_mut() {
             bcb_to_dependency_counters
                 .entry(bcb)
-                .or_insert_with(|| Vec::new())
+                .or_insert_with(Vec::new)
                 .push(counter_kind.clone());
         }
     }
@@ -527,8 +527,8 @@
     pub fn add_expression_operands(&mut self, expression: &CoverageKind) {
         if let Some(used_expression_operands) = self.some_used_expression_operands.as_mut() {
             if let CoverageKind::Expression { id, lhs, rhs, .. } = *expression {
-                used_expression_operands.entry(lhs).or_insert_with(|| Vec::new()).push(id);
-                used_expression_operands.entry(rhs).or_insert_with(|| Vec::new()).push(id);
+                used_expression_operands.entry(lhs).or_insert_with(Vec::new).push(id);
+                used_expression_operands.entry(rhs).or_insert_with(Vec::new).push(id);
             }
         }
     }
diff --git a/compiler/rustc_mir/src/transform/coverage/graph.rs b/compiler/rustc_mir/src/transform/coverage/graph.rs
index b1a1bb9..e58b915 100644
--- a/compiler/rustc_mir/src/transform/coverage/graph.rs
+++ b/compiler/rustc_mir/src/transform/coverage/graph.rs
@@ -394,7 +394,7 @@
         let operand = counter_kind.as_operand_id();
         if let Some(replaced) = self
             .edge_from_bcbs
-            .get_or_insert_with(|| FxHashMap::default())
+            .get_or_insert_with(FxHashMap::default)
             .insert(from_bcb, counter_kind)
         {
             Error::from_string(format!(
diff --git a/compiler/rustc_mir/src/transform/coverage/query.rs b/compiler/rustc_mir/src/transform/coverage/query.rs
index aa34ae7..4b455a6 100644
--- a/compiler/rustc_mir/src/transform/coverage/query.rs
+++ b/compiler/rustc_mir/src/transform/coverage/query.rs
@@ -4,7 +4,7 @@
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::{self, Coverage, CoverageInfo, Location};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::def_id::DefId;
 
 /// The `query` provider for `CoverageInfo`, requested by `codegen_coverage()` (to inject each
@@ -112,7 +112,7 @@
 }
 
 fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo {
-    let mir_body = tcx.optimized_mir(def_id);
+    let mir_body = mir_body(tcx, def_id);
 
     let mut coverage_visitor = CoverageVisitor {
         // num_counters always has at least the `ZERO` counter.
@@ -129,8 +129,7 @@
 }
 
 fn covered_file_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Symbol> {
-    let mir_body = tcx.optimized_mir(def_id);
-    for bb_data in mir_body.basic_blocks().iter() {
+    for bb_data in mir_body(tcx, def_id).basic_blocks().iter() {
         for statement in bb_data.statements.iter() {
             if let StatementKind::Coverage(box ref coverage) = statement.kind {
                 if let Some(code_region) = coverage.code_region.as_ref() {
@@ -142,9 +141,17 @@
     None
 }
 
+/// This function ensures we obtain the correct MIR for the given item irrespective of
+/// whether that means const mir or runtime mir. For `const fn` this opts for runtime
+/// mir.
+fn mir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx mir::Body<'tcx> {
+    let id = ty::WithOptConstParam::unknown(def_id);
+    let def = ty::InstanceDef::Item(id);
+    tcx.instance_mir(def)
+}
+
 fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx CodeRegion> {
-    let mir_body: &'tcx mir::Body<'tcx> = tcx.optimized_mir(def_id);
-    mir_body
+    mir_body(tcx, def_id)
         .basic_blocks()
         .iter()
         .map(|data| {
diff --git a/compiler/rustc_mir/src/transform/function_item_references.rs b/compiler/rustc_mir/src/transform/function_item_references.rs
index 7c8c349..8d02ac6 100644
--- a/compiler/rustc_mir/src/transform/function_item_references.rs
+++ b/compiler/rustc_mir/src/transform/function_item_references.rs
@@ -5,7 +5,7 @@
 use rustc_middle::ty::{
     self,
     subst::{GenericArgKind, Subst, SubstsRef},
-    PredicateAtom, Ty, TyCtxt, TyS,
+    PredicateKind, Ty, TyCtxt, TyS,
 };
 use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES;
 use rustc_span::{symbol::sym, Span};
@@ -105,7 +105,7 @@
         let param_env = self.tcx.param_env(def_id);
         let bounds = param_env.caller_bounds();
         for bound in bounds {
-            if let Some(bound_ty) = self.is_pointer_trait(&bound.skip_binders()) {
+            if let Some(bound_ty) = self.is_pointer_trait(&bound.kind().skip_binder()) {
                 // Get the argument types as they appear in the function signature.
                 let arg_defs = self.tcx.fn_sig(def_id).skip_binder().inputs();
                 for (arg_num, arg_def) in arg_defs.iter().enumerate() {
@@ -131,8 +131,8 @@
     }
 
     /// If the given predicate is the trait `fmt::Pointer`, returns the bound parameter type.
-    fn is_pointer_trait(&self, bound: &PredicateAtom<'tcx>) -> Option<Ty<'tcx>> {
-        if let ty::PredicateAtom::Trait(predicate, _) = bound {
+    fn is_pointer_trait(&self, bound: &PredicateKind<'tcx>) -> Option<Ty<'tcx>> {
+        if let ty::PredicateKind::Trait(predicate, _) = bound {
             if self.tcx.is_diagnostic_item(sym::pointer_trait, predicate.def_id()) {
                 Some(predicate.trait_ref.self_ty())
             } else {
diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index 6e7575c..07e637b 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -41,6 +41,15 @@
             return;
         }
 
+        if tcx.sess.opts.debugging_opts.instrument_coverage {
+            // Since `Inline` happens after `InstrumentCoverage`, the function-specific coverage
+            // counters can be invalidated, such as by merging coverage counter statements from
+            // a pre-inlined function into a different function. This kind of change is invalid,
+            // so inlining must be skipped. Note: This check is performed here so inlining can
+            // be disabled without preventing other optimizations (regardless of `mir_opt_level`).
+            return;
+        }
+
         if inline(tcx, body) {
             debug!("running simplify cfg on {:?}", body.source);
             CfgSimplifier::new(body).simplify();
@@ -373,7 +382,7 @@
             // Cost of the var is the size in machine-words, if we know
             // it.
             if let Some(size) = type_size_of(tcx, self.param_env, ty) {
-                cost += (size / ptr_size) as usize;
+                cost += ((size + ptr_size - 1) / ptr_size) as usize;
             } else {
                 cost += UNKNOWN_SIZE_COST;
             }
@@ -742,11 +751,11 @@
     }
 
     fn visit_span(&mut self, span: &mut Span) {
+        let mut expn_data =
+            ExpnData::default(ExpnKind::Inlined, *span, self.tcx.sess.edition(), None);
+        expn_data.def_site = self.body_span;
         // Make sure that all spans track the fact that they were inlined.
-        *span = self.callsite_span.fresh_expansion(ExpnData {
-            def_site: self.body_span,
-            ..ExpnData::default(ExpnKind::Inlined, *span, self.tcx.sess.edition(), None)
-        });
+        *span = self.callsite_span.fresh_expansion(expn_data);
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs
index 990ca31..b0c7037 100644
--- a/compiler/rustc_mir/src/transform/instcombine.rs
+++ b/compiler/rustc_mir/src/transform/instcombine.rs
@@ -277,11 +277,9 @@
 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 { local, projection: &[ref proj_base @ .., ProjectionElem::Deref] } =
-                place.as_ref()
-            {
+            if let Some((place_base, ProjectionElem::Deref)) = place.as_ref().last_projection() {
                 // The dereferenced place must have type `&_`.
-                let ty = Place::ty_from(local, proj_base, self.body, self.tcx).ty;
+                let ty = place_base.ty(self.body, self.tcx).ty;
                 if let ty::Ref(_, _, Mutability::Not) = ty.kind() {
                     self.optimizations.and_stars.insert(location);
                 }
diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs
index 7f3b421..11f7e69 100644
--- a/compiler/rustc_mir/src/transform/mod.rs
+++ b/compiler/rustc_mir/src/transform/mod.rs
@@ -71,9 +71,11 @@
         },
         mir_promoted,
         mir_drops_elaborated_and_const_checked,
+        mir_for_ctfe,
+        mir_for_ctfe_of_const_arg,
         optimized_mir,
-        optimized_mir_of_const_arg,
         is_mir_available,
+        is_ctfe_mir_available: |tcx, did| is_mir_available(tcx, did),
         promoted_mir: |tcx, def_id| {
             let def_id = def_id.expect_local();
             if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
@@ -278,6 +280,7 @@
     tcx.alloc_steal_mir(body)
 }
 
+/// Compute the main MIR body and the list of MIR bodies of the promoteds.
 fn mir_promoted(
     tcx: TyCtxt<'tcx>,
     def: ty::WithOptConstParam<LocalDefId>,
@@ -319,6 +322,87 @@
     (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
 }
 
+/// Compute the MIR that is used during CTFE (and thus has no optimizations run on it)
+fn mir_for_ctfe<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Body<'tcx> {
+    let did = def_id.expect_local();
+    if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) {
+        tcx.mir_for_ctfe_of_const_arg(def)
+    } else {
+        tcx.arena.alloc(inner_mir_for_ctfe(tcx, ty::WithOptConstParam::unknown(did)))
+    }
+}
+
+/// Same as `mir_for_ctfe`, but used to get the MIR of a const generic parameter.
+/// The docs on `WithOptConstParam` explain this a bit more, but the TLDR is that
+/// we'd get cycle errors with `mir_for_ctfe`, because typeck would need to typeck
+/// the const parameter while type checking the main body, which in turn would try
+/// to type check the main body again.
+fn mir_for_ctfe_of_const_arg<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    (did, param_did): (LocalDefId, DefId),
+) -> &'tcx Body<'tcx> {
+    tcx.arena.alloc(inner_mir_for_ctfe(
+        tcx,
+        ty::WithOptConstParam { did, const_param_did: Some(param_did) },
+    ))
+}
+
+fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
+    // FIXME: don't duplicate this between the optimized_mir/mir_for_ctfe queries
+    if tcx.is_constructor(def.did.to_def_id()) {
+        // There's no reason to run all of the MIR passes on constructors when
+        // we can just output the MIR we want directly. This also saves const
+        // qualification and borrow checking the trouble of special casing
+        // constructors.
+        return shim::build_adt_ctor(tcx, def.did.to_def_id());
+    }
+
+    let context = tcx
+        .hir()
+        .body_const_context(def.did)
+        .expect("mir_for_ctfe should not be used for runtime functions");
+
+    let mut body = tcx.mir_drops_elaborated_and_const_checked(def).borrow().clone();
+
+    match context {
+        // Do not const prop functions, either they get executed at runtime or exported to metadata,
+        // so we run const prop on them, or they don't, in which case we const evaluate some control
+        // flow paths of the function and any errors in those paths will get emitted as const eval
+        // errors.
+        hir::ConstContext::ConstFn => {}
+        // Static items always get evaluated, so we can just let const eval see if any erroneous
+        // control flow paths get executed.
+        hir::ConstContext::Static(_) => {}
+        // Associated constants get const prop run so we detect common failure situations in the
+        // crate that defined the constant.
+        // Technically we want to not run on regular const items, but oli-obk doesn't know how to
+        // conveniently detect that at this point without looking at the HIR.
+        hir::ConstContext::Const => {
+            #[rustfmt::skip]
+            let optimizations: &[&dyn MirPass<'_>] = &[
+                &const_prop::ConstProp,
+            ];
+
+            #[rustfmt::skip]
+            run_passes(
+                tcx,
+                &mut body,
+                MirPhase::Optimization,
+                &[
+                    optimizations,
+                ],
+            );
+        }
+    }
+
+    debug_assert!(!body.has_free_regions(), "Free regions in MIR for CTFE");
+
+    body
+}
+
+/// Obtain just the main MIR (no promoteds) and run some cleanups on it. This also runs
+/// mir borrowck *before* doing so in order to ensure that borrowck can be run and doesn't
+/// end up missing the source MIR due to stealing happening.
 fn mir_drops_elaborated_and_const_checked<'tcx>(
     tcx: TyCtxt<'tcx>,
     def: ty::WithOptConstParam<LocalDefId>,
@@ -456,35 +540,32 @@
     );
 }
 
+/// Optimize the MIR and prepare it for codegen.
 fn optimized_mir<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx Body<'tcx> {
     let did = did.expect_local();
-    if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) {
-        tcx.optimized_mir_of_const_arg(def)
-    } else {
-        tcx.arena.alloc(inner_optimized_mir(tcx, ty::WithOptConstParam::unknown(did)))
-    }
+    assert_eq!(ty::WithOptConstParam::try_lookup(did, tcx), None);
+    tcx.arena.alloc(inner_optimized_mir(tcx, did))
 }
 
-fn optimized_mir_of_const_arg<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    (did, param_did): (LocalDefId, DefId),
-) -> &'tcx Body<'tcx> {
-    tcx.arena.alloc(inner_optimized_mir(
-        tcx,
-        ty::WithOptConstParam { did, const_param_did: Some(param_did) },
-    ))
-}
-
-fn inner_optimized_mir(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
-    if tcx.is_constructor(def.did.to_def_id()) {
+fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
+    if tcx.is_constructor(did.to_def_id()) {
         // There's no reason to run all of the MIR passes on constructors when
         // we can just output the MIR we want directly. This also saves const
         // qualification and borrow checking the trouble of special casing
         // constructors.
-        return shim::build_adt_ctor(tcx, def.did.to_def_id());
+        return shim::build_adt_ctor(tcx, did.to_def_id());
     }
 
-    let mut body = tcx.mir_drops_elaborated_and_const_checked(def).steal();
+    match tcx.hir().body_const_context(did) {
+        // Run the `mir_for_ctfe` query, which depends on `mir_drops_elaborated_and_const_checked`
+        // which we are going to steal below. Thus we need to run `mir_for_ctfe` first, so it
+        // computes and caches its result.
+        Some(hir::ConstContext::ConstFn) => tcx.ensure().mir_for_ctfe(did),
+        None => {}
+        Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other),
+    }
+    let mut body =
+        tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal();
     run_optimization_passes(tcx, &mut body);
 
     debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
@@ -492,6 +573,8 @@
     body
 }
 
+/// Fetch all the promoteds of an item and prepare their MIR bodies to be ready for
+/// constant evaluation once all substitutions become known.
 fn promoted_mir<'tcx>(
     tcx: TyCtxt<'tcx>,
     def: ty::WithOptConstParam<LocalDefId>,
@@ -510,7 +593,6 @@
 
     for body in &mut promoted {
         run_post_borrowck_cleanup_passes(tcx, body);
-        run_optimization_passes(tcx, body);
     }
 
     debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR");
diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs
index ea92e23..cac5abb 100644
--- a/compiler/rustc_mir/src/transform/promote_consts.rs
+++ b/compiler/rustc_mir/src/transform/promote_consts.rs
@@ -445,43 +445,50 @@
     }
 
     fn validate_place(&self, place: PlaceRef<'tcx>) -> Result<(), Unpromotable> {
-        match place {
-            PlaceRef { local, projection: [] } => self.validate_local(local),
-            PlaceRef { local, projection: [proj_base @ .., elem] } => {
+        match place.last_projection() {
+            None => self.validate_local(place.local),
+            Some((place_base, elem)) => {
                 // Validate topmost projection, then recurse.
-                match *elem {
+                match elem {
                     ProjectionElem::Deref => {
                         let mut promotable = false;
-                        // This is a special treatment for cases like *&STATIC where STATIC is a
-                        // global static variable.
-                        // This pattern is generated only when global static variables are directly
-                        // accessed and is qualified for promotion safely.
-                        if let TempState::Defined { location, .. } = self.temps[local] {
-                            let def_stmt =
-                                self.body[location.block].statements.get(location.statement_index);
-                            if let Some(Statement {
-                                kind:
-                                    StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(c)))),
-                                ..
-                            }) = def_stmt
+                        // The `is_empty` predicate is introduced to exclude the case
+                        // where the projection operations are [ .field, * ].
+                        // The reason is because promotion will be illegal if field
+                        // accesses precede the dereferencing.
+                        // Discussion can be found at
+                        // https://github.com/rust-lang/rust/pull/74945#discussion_r463063247
+                        // There may be opportunity for generalization, but this needs to be
+                        // accounted for.
+                        if place_base.projection.is_empty() {
+                            // This is a special treatment for cases like *&STATIC where STATIC is a
+                            // global static variable.
+                            // This pattern is generated only when global static variables are directly
+                            // accessed and is qualified for promotion safely.
+                            if let TempState::Defined { location, .. } =
+                                self.temps[place_base.local]
                             {
-                                if let Some(did) = c.check_static_ptr(self.tcx) {
-                                    // Evaluating a promoted may not read statics except if it got
-                                    // promoted from a static (this is a CTFE check). So we
-                                    // can only promote static accesses inside statics.
-                                    if let Some(hir::ConstContext::Static(..)) = self.const_kind {
-                                        // The `is_empty` predicate is introduced to exclude the case
-                                        // where the projection operations are [ .field, * ].
-                                        // The reason is because promotion will be illegal if field
-                                        // accesses precede the dereferencing.
-                                        // Discussion can be found at
-                                        // https://github.com/rust-lang/rust/pull/74945#discussion_r463063247
-                                        // There may be opportunity for generalization, but this needs to be
-                                        // accounted for.
-                                        if proj_base.is_empty()
-                                            && !self.tcx.is_thread_local_static(did)
+                                let def_stmt = self.body[location.block]
+                                    .statements
+                                    .get(location.statement_index);
+                                if let Some(Statement {
+                                    kind:
+                                        StatementKind::Assign(box (
+                                            _,
+                                            Rvalue::Use(Operand::Constant(c)),
+                                        )),
+                                    ..
+                                }) = def_stmt
+                                {
+                                    if let Some(did) = c.check_static_ptr(self.tcx) {
+                                        // Evaluating a promoted may not read statics except if it got
+                                        // promoted from a static (this is a CTFE check). So we
+                                        // can only promote static accesses inside statics.
+                                        if let Some(hir::ConstContext::Static(..)) = self.const_kind
                                         {
-                                            promotable = true;
+                                            if !self.tcx.is_thread_local_static(did) {
+                                                promotable = true;
+                                            }
                                         }
                                     }
                                 }
@@ -502,8 +509,7 @@
                     }
 
                     ProjectionElem::Field(..) => {
-                        let base_ty =
-                            Place::ty_from(place.local, proj_base, self.body, self.tcx).ty;
+                        let base_ty = place_base.ty(self.body, self.tcx).ty;
                         if let Some(def) = base_ty.ty_adt_def() {
                             // No promotion of union field accesses.
                             if def.is_union() {
@@ -513,7 +519,7 @@
                     }
                 }
 
-                self.validate_place(PlaceRef { local: place.local, projection: proj_base })
+                self.validate_place(place_base)
             }
         }
     }
@@ -660,13 +666,11 @@
             Rvalue::AddressOf(_, place) => {
                 // We accept `&raw *`, i.e., raw reborrows -- creating a raw pointer is
                 // no problem, only using it is.
-                if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
-                    let base_ty = Place::ty_from(place.local, proj_base, self.body, self.tcx).ty;
+                if let Some((place_base, ProjectionElem::Deref)) = place.as_ref().last_projection()
+                {
+                    let base_ty = place_base.ty(self.body, self.tcx).ty;
                     if let ty::Ref(..) = base_ty.kind() {
-                        return self.validate_place(PlaceRef {
-                            local: place.local,
-                            projection: proj_base,
-                        });
+                        return self.validate_place(place_base);
                     }
                 }
                 return Err(Unpromotable);
@@ -675,12 +679,12 @@
             Rvalue::Ref(_, kind, place) => {
                 // Special-case reborrows to be more like a copy of the reference.
                 let mut place_simplified = place.as_ref();
-                if let [proj_base @ .., ProjectionElem::Deref] = &place_simplified.projection {
-                    let base_ty =
-                        Place::ty_from(place_simplified.local, proj_base, self.body, self.tcx).ty;
+                if let Some((place_base, ProjectionElem::Deref)) =
+                    place_simplified.last_projection()
+                {
+                    let base_ty = place_base.ty(self.body, self.tcx).ty;
                     if let ty::Ref(..) = base_ty.kind() {
-                        place_simplified =
-                            PlaceRef { local: place_simplified.local, projection: proj_base };
+                        place_simplified = place_base;
                     }
                 }
 
diff --git a/compiler/rustc_mir/src/transform/simplify_try.rs b/compiler/rustc_mir/src/transform/simplify_try.rs
index a345988..05a8882 100644
--- a/compiler/rustc_mir/src/transform/simplify_try.rs
+++ b/compiler/rustc_mir/src/transform/simplify_try.rs
@@ -113,7 +113,7 @@
         test: impl Fn(&'a Statement<'tcx>) -> bool,
         mut action: impl FnMut(usize, &'a Statement<'tcx>),
     ) {
-        while stmt_iter.peek().map(|(_, stmt)| test(stmt)).unwrap_or(false) {
+        while stmt_iter.peek().map_or(false, |(_, stmt)| test(stmt)) {
             let (idx, stmt) = stmt_iter.next().unwrap();
 
             action(idx, stmt);
@@ -635,7 +635,7 @@
                     })
                     .peekable();
 
-                let bb_first = iter_bbs_reachable.peek().map(|(idx, _)| *idx).unwrap_or(&targets_and_values[0]);
+                let bb_first = iter_bbs_reachable.peek().map_or(&targets_and_values[0], |(idx, _)| *idx);
                 let mut all_successors_equivalent = StatementEquality::TrivialEqual;
 
                 // All successor basic blocks must be equal or contain statements that are pairwise considered equal.
diff --git a/compiler/rustc_mir/src/util/alignment.rs b/compiler/rustc_mir/src/util/alignment.rs
index a0728a6..f567c9c 100644
--- a/compiler/rustc_mir/src/util/alignment.rs
+++ b/compiler/rustc_mir/src/util/alignment.rs
@@ -38,15 +38,12 @@
 where
     L: HasLocalDecls<'tcx>,
 {
-    let mut cursor = place.projection.as_ref();
-    while let &[ref proj_base @ .., elem] = cursor {
-        cursor = proj_base;
-
+    for (place_base, elem) in place.iter_projections().rev() {
         match elem {
             // encountered a Deref, which is ABI-aligned
             ProjectionElem::Deref => break,
             ProjectionElem::Field(..) => {
-                let ty = Place::ty_from(place.local, proj_base, local_decls, tcx).ty;
+                let ty = place_base.ty(local_decls, tcx).ty;
                 match ty.kind() {
                     ty::Adt(def, _) if def.repr.packed() => return true,
                     _ => {}
diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs
index 89ce29b..7fc1c3a 100644
--- a/compiler/rustc_mir/src/util/pretty.rs
+++ b/compiler/rustc_mir/src/util/pretty.rs
@@ -273,8 +273,6 @@
 
     let mut first = true;
     for def_id in dump_mir_def_ids(tcx, single) {
-        let body = &tcx.optimized_mir(def_id);
-
         if first {
             first = false;
         } else {
@@ -282,11 +280,28 @@
             writeln!(w)?;
         }
 
-        write_mir_fn(tcx, body, &mut |_, _| Ok(()), w)?;
-
-        for body in tcx.promoted_mir(def_id) {
-            writeln!(w)?;
+        let render_body = |w: &mut dyn Write, body| -> io::Result<()> {
             write_mir_fn(tcx, body, &mut |_, _| Ok(()), w)?;
+
+            for body in tcx.promoted_mir(def_id) {
+                writeln!(w)?;
+                write_mir_fn(tcx, body, &mut |_, _| Ok(()), w)?;
+            }
+            Ok(())
+        };
+        match tcx.hir().body_const_context(def_id.expect_local()) {
+            None => render_body(w, tcx.optimized_mir(def_id))?,
+            // For `const fn` we want to render the optimized MIR. If you want the mir used in
+            // ctfe, you can dump the MIR after the `Deaggregator` optimization pass.
+            Some(rustc_hir::ConstContext::ConstFn) => {
+                render_body(w, tcx.optimized_mir(def_id))?;
+                writeln!(w)?;
+                writeln!(w, "// MIR FOR CTFE")?;
+                // Do not use `render_body`, as that would render the promoteds again, but these
+                // are shared between mir_for_ctfe and optimized_mir
+                write_mir_fn(tcx, tcx.mir_for_ctfe(def_id), &mut |_, _| Ok(()), w)?;
+            }
+            Some(_) => render_body(w, tcx.mir_for_ctfe(def_id))?,
         }
     }
     Ok(())
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index cf2e4e8..c11b8f7 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -531,6 +531,7 @@
             | ExprKind::Borrow { .. }
             | ExprKind::AddressOf { .. }
             | ExprKind::Match { .. }
+            | ExprKind::If { .. }
             | ExprKind::Loop { .. }
             | ExprKind::Block { .. }
             | ExprKind::Assign { .. }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 3f381f3..55bdbcf 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -251,6 +251,7 @@
             | ExprKind::StaticRef { .. }
             | ExprKind::Block { .. }
             | ExprKind::Match { .. }
+            | ExprKind::If { .. }
             | ExprKind::NeverToAny { .. }
             | ExprKind::Use { .. }
             | ExprKind::Borrow { .. }
diff --git a/compiler/rustc_mir_build/src/build/expr/category.rs b/compiler/rustc_mir_build/src/build/expr/category.rs
index 8561170..9320b58 100644
--- a/compiler/rustc_mir_build/src/build/expr/category.rs
+++ b/compiler/rustc_mir_build/src/build/expr/category.rs
@@ -45,6 +45,7 @@
 
             ExprKind::LogicalOp { .. }
             | ExprKind::Match { .. }
+            | ExprKind::If { .. }
             | ExprKind::NeverToAny { .. }
             | ExprKind::Use { .. }
             | ExprKind::Adt { .. }
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 0928179..639f2bb 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -10,9 +10,7 @@
 use rustc_hir as hir;
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, CanonicalUserTypeAnnotation};
-use rustc_span::symbol::sym;
-use rustc_target::spec::abi::Abi;
+use rustc_middle::ty::{CanonicalUserTypeAnnotation};
 
 use std::slice;
 
@@ -69,6 +67,40 @@
             ExprKind::Match { scrutinee, arms } => {
                 this.match_expr(destination, scope, expr_span, block, scrutinee, arms)
             }
+            ExprKind::If { cond, then, else_opt } => {
+                let place = unpack!(block = this.as_temp(block, Some(this.local_scope()), cond, Mutability::Mut));
+                let operand = Operand::Move(Place::from(place));
+
+                let mut then_block = this.cfg.start_new_block();
+                let mut else_block = this.cfg.start_new_block();
+                let term = TerminatorKind::if_(this.hir.tcx(), operand, then_block, else_block);
+                this.cfg.terminate(block, source_info, term);
+
+                unpack!(then_block = this.into(destination, scope, then_block, then));
+                else_block = if let Some(else_opt) = else_opt {
+                    unpack!(this.into(destination, None, else_block, else_opt))
+                } else {
+                    // Body of the `if` expression without an `else` clause must return `()`, thus
+                    // we implicitly generate a `else {}` if it is not specified.
+                    let correct_si = this.source_info(expr_span.shrink_to_hi());
+                    this.cfg.push_assign_unit(else_block, correct_si, destination, this.hir.tcx());
+                    else_block
+                };
+
+                let join_block = this.cfg.start_new_block();
+                this.cfg.terminate(
+                    then_block,
+                    source_info,
+                    TerminatorKind::Goto { target: join_block },
+                );
+                this.cfg.terminate(
+                    else_block,
+                    source_info,
+                    TerminatorKind::Goto { target: join_block },
+                );
+
+                join_block.unit()
+            },
             ExprKind::NeverToAny { source } => {
                 let source = this.hir.mirror(source);
                 let is_call = matches!(source.kind, ExprKind::Call { .. } | ExprKind::InlineAsm { .. });
@@ -185,79 +217,41 @@
                     },
                 )
             }
-            ExprKind::Call { ty, fun, args, from_hir_call, fn_span } => {
-                let intrinsic = match *ty.kind() {
-                    ty::FnDef(def_id, _) => {
-                        let f = ty.fn_sig(this.hir.tcx());
-                        if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic {
-                            Some(this.hir.tcx().item_name(def_id))
-                        } else {
-                            None
-                        }
-                    }
-                    _ => None,
-                };
+            ExprKind::Call { ty: _, fun, args, from_hir_call, fn_span } => {
                 let fun = unpack!(block = this.as_local_operand(block, fun));
-                if let Some(sym::move_val_init) = intrinsic {
-                    // `move_val_init` has "magic" semantics - the second argument is
-                    // always evaluated "directly" into the first one.
+                let args: Vec<_> = args
+                    .into_iter()
+                    .map(|arg| unpack!(block = this.as_local_call_operand(block, arg)))
+                    .collect();
 
-                    let mut args = args.into_iter();
-                    let ptr = args.next().expect("0 arguments to `move_val_init`");
-                    let val = args.next().expect("1 argument to `move_val_init`");
-                    assert!(args.next().is_none(), ">2 arguments to `move_val_init`");
+                let success = this.cfg.start_new_block();
 
-                    let ptr = this.hir.mirror(ptr);
-                    let ptr_ty = ptr.ty;
-                    // Create an *internal* temp for the pointer, so that unsafety
-                    // checking won't complain about the raw pointer assignment.
-                    let ptr_temp = this
-                        .local_decls
-                        .push(LocalDecl::with_source_info(ptr_ty, source_info).internal());
-                    let ptr_temp = Place::from(ptr_temp);
-                    // No need for a scope, ptr_temp doesn't need drop
-                    let block = unpack!(this.into(ptr_temp, None, block, ptr));
-                    // Maybe we should provide a scope here so that
-                    // `move_val_init` wouldn't leak on panic even with an
-                    // arbitrary `val` expression, but `schedule_drop`,
-                    // borrowck and drop elaboration all prevent us from
-                    // dropping `ptr_temp.deref()`.
-                    this.into(this.hir.tcx().mk_place_deref(ptr_temp), None, block, val)
-                } else {
-                    let args: Vec<_> = args
-                        .into_iter()
-                        .map(|arg| unpack!(block = this.as_local_call_operand(block, arg)))
-                        .collect();
+                this.record_operands_moved(&args);
 
-                    let success = this.cfg.start_new_block();
+                debug!("into_expr: fn_span={:?}", fn_span);
 
-                    this.record_operands_moved(&args);
-
-                    debug!("into_expr: fn_span={:?}", fn_span);
-
-                    this.cfg.terminate(
-                        block,
-                        source_info,
-                        TerminatorKind::Call {
-                            func: fun,
-                            args,
-                            cleanup: None,
-                            // FIXME(varkor): replace this with an uninhabitedness-based check.
-                            // This requires getting access to the current module to call
-                            // `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
-                            destination: if expr.ty.is_never() {
-                                None
-                            } else {
-                                Some((destination, success))
-                            },
-                            from_hir_call,
-                            fn_span,
+                this.cfg.terminate(
+                    block,
+                    source_info,
+                    TerminatorKind::Call {
+                        func: fun,
+                        args,
+                        cleanup: None,
+                        // FIXME(varkor): replace this with an uninhabitedness-based check.
+                        // This requires getting access to the current module to call
+                        // `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
+                        destination: if expr.ty.is_never() {
+                            None
+                        } else {
+                            Some((destination, success))
                         },
-                    );
-                    this.diverge_from(block);
-                    schedule_drop(this);
-                    success.unit()
-                }
+                        from_hir_call,
+                        fn_span,
+                    },
+                );
+                this.diverge_from(block);
+                schedule_drop(this);
+                success.unit()
             }
             ExprKind::Use { source } => this.into(destination, scope, block, source),
             ExprKind::Borrow { arg, borrow_kind } => {
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 417f9bd..5954587 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -537,6 +537,11 @@
             },
             Err(err) => bug!("invalid loop id for continue: {}", err),
         },
+        hir::ExprKind::If(cond, then, else_opt) => ExprKind::If {
+            cond: cond.to_ref(),
+            then: then.to_ref(),
+            else_opt: else_opt.map(|el| el.to_ref()),
+        },
         hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match {
             scrutinee: discr.to_ref(),
             arms: arms.iter().map(|a| convert_arm(cx, a)).collect(),
@@ -813,8 +818,7 @@
             let item_id = cx.tcx.hir().get_parent_node(hir_id);
             let item_def_id = cx.tcx.hir().local_def_id(item_id);
             let generics = cx.tcx.generics_of(item_def_id);
-            let local_def_id = cx.tcx.hir().local_def_id(hir_id);
-            let index = generics.param_def_id_to_index[&local_def_id.to_def_id()];
+            let index = generics.param_def_id_to_index[&def_id];
             let name = cx.tcx.hir().name(hir_id);
             let val = ty::ConstKind::Param(ty::ParamConst::new(index, name));
             ExprKind::Literal {
diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs
index ace9cad..ed3d392 100644
--- a/compiler/rustc_mir_build/src/thir/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/mod.rs
@@ -139,6 +139,11 @@
     Box {
         value: ExprRef<'tcx>,
     },
+    If {
+        cond: ExprRef<'tcx>,
+        then: ExprRef<'tcx>,
+        else_opt: Option<ExprRef<'tcx>>,
+    },
     Call {
         ty: Ty<'tcx>,
         fun: ExprRef<'tcx>,
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index db817b3..3977068 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -403,7 +403,7 @@
         match is_useful {
             NotUseful => {
                 match source {
-                    hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar => bug!(),
+                    hir::MatchSource::WhileDesugar => bug!(),
 
                     hir::MatchSource::IfLetDesugar { .. } | hir::MatchSource::WhileLetDesugar => {
                         // Check which arm we're on.
@@ -503,6 +503,11 @@
             ));
         }
     }
+    if let ty::Ref(_, sub_ty, _) = scrut_ty.kind() {
+        if cx.tcx.is_ty_uninhabited_from(cx.module, sub_ty, cx.param_env) {
+            err.note("references are always considered inhabited");
+        }
+    }
     err.emit();
 }
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 83fee38..d7c08a2 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -952,7 +952,7 @@
     assert!(rows.iter().all(|r| r.len() == v.len()));
 
     // FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).
-    let ty = matrix.heads().next().map(|r| r.ty).unwrap_or(v.head().ty);
+    let ty = matrix.heads().next().map_or(v.head().ty, |r| r.ty);
     let pcx = PatCtxt { cx, ty, span: v.head().span, is_top_level };
 
     debug!("is_useful_expand_first_col: ty={:#?}, expanding {:#?}", pcx.ty, v.head());
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 9abffba..62fd693 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -236,7 +236,6 @@
 pub fn nt_to_tokenstream(
     nt: &Nonterminal,
     sess: &ParseSess,
-    span: Span,
     synthesize_tokens: CanSynthesizeMissingTokens,
 ) -> TokenStream {
     // A `Nonterminal` is often a parsed AST item. At this point we now
@@ -256,11 +255,18 @@
         |tokens: Option<&LazyTokenStream>| tokens.as_ref().map(|t| t.create_token_stream());
 
     let tokens = match *nt {
-        Nonterminal::NtItem(ref item) => {
-            prepend_attrs(sess, &item.attrs, nt, span, item.tokens.as_ref())
-        }
+        Nonterminal::NtItem(ref item) => prepend_attrs(sess, &item.attrs, nt, item.tokens.as_ref()),
         Nonterminal::NtBlock(ref block) => convert_tokens(block.tokens.as_ref()),
-        Nonterminal::NtStmt(ref stmt) => prepend_attrs(sess, stmt.attrs(), nt, span, stmt.tokens()),
+        Nonterminal::NtStmt(ref stmt) => {
+            let do_prepend = |tokens| prepend_attrs(sess, stmt.attrs(), nt, tokens);
+            if let ast::StmtKind::Empty = stmt.kind {
+                let tokens: TokenStream =
+                    tokenstream::TokenTree::token(token::Semi, stmt.span).into();
+                do_prepend(Some(&LazyTokenStream::new(tokens)))
+            } else {
+                do_prepend(stmt.tokens())
+            }
+        }
         Nonterminal::NtPat(ref pat) => convert_tokens(pat.tokens.as_ref()),
         Nonterminal::NtTy(ref ty) => convert_tokens(ty.tokens.as_ref()),
         Nonterminal::NtIdent(ident, is_raw) => {
@@ -277,31 +283,29 @@
             if expr.tokens.is_none() {
                 debug!("missing tokens for expr {:?}", expr);
             }
-            prepend_attrs(sess, &expr.attrs, nt, span, expr.tokens.as_ref())
+            prepend_attrs(sess, &expr.attrs, nt, expr.tokens.as_ref())
         }
     };
 
     if let Some(tokens) = tokens {
         return tokens;
     } else if matches!(synthesize_tokens, CanSynthesizeMissingTokens::Yes) {
-        return fake_token_stream(sess, nt, span);
+        return fake_token_stream(sess, nt);
     } else {
-        let pretty = rustc_ast_pretty::pprust::nonterminal_to_string_no_extra_parens(&nt);
-        panic!("Missing tokens at {:?} for nt {:?}", span, pretty);
+        panic!("Missing tokens for nt {:?}", pprust::nonterminal_to_string(nt));
     }
 }
 
-pub fn fake_token_stream(sess: &ParseSess, nt: &Nonterminal, span: Span) -> TokenStream {
+pub fn fake_token_stream(sess: &ParseSess, nt: &Nonterminal) -> TokenStream {
     let source = pprust::nonterminal_to_string(nt);
     let filename = FileName::macro_expansion_source_code(&source);
-    parse_stream_from_source_str(filename, source, sess, Some(span))
+    parse_stream_from_source_str(filename, source, sess, Some(nt.span()))
 }
 
 fn prepend_attrs(
     sess: &ParseSess,
     attrs: &[ast::Attribute],
     nt: &Nonterminal,
-    span: Span,
     tokens: Option<&tokenstream::LazyTokenStream>,
 ) -> Option<tokenstream::TokenStream> {
     if attrs.is_empty() {
@@ -312,7 +316,7 @@
         // FIXME: Correctly handle tokens for inner attributes.
         // For now, we fall back to reparsing the original AST node
         if attr.style == ast::AttrStyle::Inner {
-            return Some(fake_token_stream(sess, nt, span));
+            return Some(fake_token_stream(sess, nt));
         }
         builder.push(attr.tokens());
     }
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index fae09fa..1b26fb3 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -89,7 +89,7 @@
             inner_parse_policy, self.token
         );
         let lo = self.token.span;
-        let ((item, style, span), tokens) = self.collect_tokens(|this| {
+        self.collect_tokens(|this| {
             if this.eat(&token::Pound) {
                 let style = if this.eat(&token::Not) {
                     ast::AttrStyle::Inner
@@ -107,15 +107,13 @@
                     this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy);
                 }
 
-                Ok((item, style, attr_sp))
+                Ok(attr::mk_attr_from_item(item, None, style, attr_sp))
             } else {
                 let token_str = pprust::token_to_string(&this.token);
                 let msg = &format!("expected `#`, found `{}`", token_str);
                 Err(this.struct_span_err(this.token.span, msg))
             }
-        })?;
-
-        Ok(attr::mk_attr_from_item(item, tokens, style, span))
+        })
     }
 
     pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy<'_>) {
@@ -165,13 +163,7 @@
                 let args = this.parse_attr_args()?;
                 Ok(ast::AttrItem { path, args, tokens: None })
             };
-            if capture_tokens {
-                let (mut item, tokens) = self.collect_tokens(do_parse)?;
-                item.tokens = tokens;
-                item
-            } else {
-                do_parse(self)?
-            }
+            if capture_tokens { self.collect_tokens(do_parse) } else { do_parse(self) }?
         })
     }
 
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 98c7b9a..35435bae 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -511,7 +511,7 @@
         //
         // `x.foo::<u32>>>(3)`
         let parsed_angle_bracket_args =
-            segment.args.as_ref().map(|args| args.is_angle_bracketed()).unwrap_or(false);
+            segment.args.as_ref().map_or(false, |args| args.is_angle_bracketed());
 
         debug!(
             "check_trailing_angle_brackets: parsed_angle_bracket_args={:?}",
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index b147f42..6db415e 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -15,6 +15,7 @@
 use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{Applicability, DiagnosticBuilder, PResult};
+use rustc_span::edition::LATEST_STABLE_EDITION;
 use rustc_span::source_map::{self, Span, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Pos};
@@ -471,7 +472,8 @@
     /// Parses a prefix-unary-operator expr.
     fn parse_prefix_expr(&mut self, attrs: Option<AttrVec>) -> PResult<'a, P<Expr>> {
         let attrs = self.parse_or_use_outer_attributes(attrs)?;
-        self.maybe_collect_tokens(super::attr::maybe_needs_tokens(&attrs), |this| {
+        let needs_tokens = super::attr::maybe_needs_tokens(&attrs);
+        let do_parse = |this: &mut Parser<'a>| {
             let lo = this.token.span;
             // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
             let (hi, ex) = match this.token.uninterpolate().kind {
@@ -487,7 +489,8 @@
                 _ => return this.parse_dot_or_call_expr(Some(attrs)),
             }?;
             Ok(this.mk_expr(lo.to(hi), ex, attrs))
-        })
+        };
+        if needs_tokens { self.collect_tokens(do_parse) } else { do_parse(self) }
     }
 
     fn parse_prefix_expr_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
@@ -1124,20 +1127,6 @@
         }
     }
 
-    fn maybe_collect_tokens(
-        &mut self,
-        needs_tokens: bool,
-        f: impl FnOnce(&mut Self) -> PResult<'a, P<Expr>>,
-    ) -> PResult<'a, P<Expr>> {
-        if needs_tokens {
-            let (mut expr, tokens) = self.collect_tokens(f)?;
-            expr.tokens = tokens;
-            Ok(expr)
-        } else {
-            f(self)
-        }
-    }
-
     fn parse_lit_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let lo = self.token.span;
         match self.parse_opt_lit() {
@@ -1598,10 +1587,6 @@
         } else {
             Async::No
         };
-        if let Async::Yes { span, .. } = asyncness {
-            // Feature-gate `async ||` closures.
-            self.sess.gated_spans.gate(sym::async_closure, span);
-        }
 
         let capture_clause = self.parse_capture_clause()?;
         let decl = self.parse_fn_block_decl()?;
@@ -1618,6 +1603,11 @@
             }
         };
 
+        if let Async::Yes { span, .. } = asyncness {
+            // Feature-gate `async ||` closures.
+            self.sess.gated_spans.gate(sym::async_closure, span);
+        }
+
         Ok(self.mk_expr(
             lo.to(body.span),
             ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)),
@@ -2108,8 +2098,8 @@
 
         let mut async_block_err = |e: &mut DiagnosticBuilder<'_>, span: Span| {
             recover_async = true;
-            e.span_label(span, "`async` blocks are only allowed in the 2018 edition");
-            e.help("set `edition = \"2018\"` in `Cargo.toml`");
+            e.span_label(span, "`async` blocks are only allowed in Rust 2018 or later");
+            e.help(&format!("set `edition = \"{}\"` in `Cargo.toml`", LATEST_STABLE_EDITION));
             e.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
         };
 
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 860e630..42a1337 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -5,7 +5,7 @@
     self as ast, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause,
 };
 use rustc_errors::PResult;
-use rustc_span::symbol::kw;
+use rustc_span::symbol::{kw, sym};
 
 impl<'a> Parser<'a> {
     /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
@@ -56,12 +56,26 @@
         self.expect(&token::Colon)?;
         let ty = self.parse_ty()?;
 
+        // Parse optional const generics default value, taking care of feature gating the spans
+        // with the unstable syntax mechanism.
+        let default = if self.eat(&token::Eq) {
+            // The gated span goes from the `=` to the end of the const argument that follows (and
+            // which could be a block expression).
+            let start = self.prev_token.span;
+            let const_arg = self.parse_const_arg()?;
+            let span = start.to(const_arg.value.span);
+            self.sess.gated_spans.gate(sym::const_generics_defaults, span);
+            Some(const_arg)
+        } else {
+            None
+        };
+
         Ok(GenericParam {
             ident,
             id: ast::DUMMY_NODE_ID,
             attrs: preceding_attrs.into(),
             bounds: Vec::new(),
-            kind: GenericParamKind::Const { ty, kw_span: const_span },
+            kind: GenericParamKind::Const { ty, kw_span: const_span, default },
             is_placeholder: false,
         })
     }
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index c6669f0..810ae61 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -16,7 +16,7 @@
 use rustc_ast::{MacArgs, MacCall, MacDelimiter};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, PResult, StashKey};
-use rustc_span::edition::Edition;
+use rustc_span::edition::{Edition, LATEST_STABLE_EDITION};
 use rustc_span::source_map::{self, Span};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 
@@ -125,19 +125,7 @@
             item
         };
 
-        let (mut item, tokens) = if needs_tokens {
-            let (item, tokens) = self.collect_tokens(parse_item)?;
-            (item, tokens)
-        } else {
-            (parse_item(self)?, None)
-        };
-        if let Some(item) = &mut item {
-            // If we captured tokens during parsing (due to encountering an `NtItem`),
-            // use those instead
-            if item.tokens.is_none() {
-                item.tokens = tokens;
-            }
-        }
+        let item = if needs_tokens { self.collect_tokens(parse_item) } else { parse_item(self) }?;
 
         self.unclosed_delims.append(&mut unclosed_delims);
         Ok(item)
@@ -220,7 +208,22 @@
         let info = if self.eat_keyword(kw::Use) {
             // USE ITEM
             let tree = self.parse_use_tree()?;
-            self.expect_semi()?;
+
+            // If wildcard or glob-like brace syntax doesn't have `;`,
+            // the user may not know `*` or `{}` should be the last.
+            if let Err(mut e) = self.expect_semi() {
+                match tree.kind {
+                    UseTreeKind::Glob => {
+                        e.note("the wildcard token must be last on the path").emit();
+                    }
+                    UseTreeKind::Nested(..) => {
+                        e.note("glob-like brace syntax must be last on the path").emit();
+                    }
+                    _ => (),
+                }
+                return Err(e);
+            }
+
             (Ident::invalid(), ItemKind::Use(P(tree)))
         } else if self.check_fn_front_matter() {
             // FUNCTION ITEM
@@ -1667,9 +1670,9 @@
     fn ban_async_in_2015(&self, span: Span) {
         if span.rust_2015() {
             let diag = self.diagnostic();
-            struct_span_err!(diag, span, E0670, "`async fn` is not permitted in the 2015 edition")
-                .span_label(span, "to use `async fn`, switch to Rust 2018")
-                .help("set `edition = \"2018\"` in `Cargo.toml`")
+            struct_span_err!(diag, span, E0670, "`async fn` is not permitted in Rust 2015")
+                .span_label(span, "to use `async fn`, switch to Rust 2018 or later")
+                .help(&format!("set `edition = \"{}\"` in `Cargo.toml`", LATEST_STABLE_EDITION))
                 .note("for more on editions, read https://doc.rust-lang.org/edition-guide")
                 .emit();
         }
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 1062000..5d7ea5b 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -12,7 +12,6 @@
 use crate::lexer::UnmatchedBrace;
 pub use diagnostics::AttemptLocalParseRecovery;
 use diagnostics::Error;
-pub use pat::OrPatNonterminalMode;
 pub use path::PathStyle;
 
 use rustc_ast::ptr::P;
@@ -20,8 +19,8 @@
 use rustc_ast::tokenstream::{self, DelimSpan, LazyTokenStream, Spacing};
 use rustc_ast::tokenstream::{CreateTokenStream, TokenStream, TokenTree, TreeAndSpacing};
 use rustc_ast::DUMMY_NODE_ID;
-use rustc_ast::{self as ast, AnonConst, AttrStyle, AttrVec, Const, CrateSugar, Extern, Unsafe};
-use rustc_ast::{Async, Expr, ExprKind, MacArgs, MacDelimiter, Mutability, StrLit};
+use rustc_ast::{self as ast, AnonConst, AttrStyle, AttrVec, Const, CrateSugar, Extern, HasTokens};
+use rustc_ast::{Async, Expr, ExprKind, MacArgs, MacDelimiter, Mutability, StrLit, Unsafe};
 use rustc_ast::{Visibility, VisibilityKind};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::sync::Lrc;
@@ -984,8 +983,8 @@
                         _ => self.sess.gated_spans.gate(sym::extended_key_value_attributes, span),
                     }
 
-                    let token = token::Interpolated(Lrc::new(token::NtExpr(expr)));
-                    MacArgs::Eq(eq_span, TokenTree::token(token, span).into())
+                    let token_kind = token::Interpolated(Lrc::new(token::NtExpr(expr)));
+                    MacArgs::Eq(eq_span, Token::new(token_kind, span))
                 } else {
                     MacArgs::Empty
                 }
@@ -1235,14 +1234,22 @@
     /// This restriction shouldn't be an issue in practice,
     /// since this function is used to record the tokens for
     /// a parsed AST item, which always has matching delimiters.
-    pub fn collect_tokens<R>(
+    pub fn collect_tokens<R: HasTokens>(
         &mut self,
         f: impl FnOnce(&mut Self) -> PResult<'a, R>,
-    ) -> PResult<'a, (R, Option<LazyTokenStream>)> {
+    ) -> PResult<'a, R> {
         let start_token = (self.token.clone(), self.token_spacing);
-        let cursor_snapshot = self.token_cursor.clone();
+        let cursor_snapshot = TokenCursor {
+            frame: self.token_cursor.frame.clone(),
+            // We only ever capture tokens within our current frame,
+            // so we can just use an empty frame stack
+            stack: vec![],
+            desugar_doc_comments: self.token_cursor.desugar_doc_comments,
+            num_next_calls: self.token_cursor.num_next_calls,
+            append_unglued_token: self.token_cursor.append_unglued_token.clone(),
+        };
 
-        let ret = f(self)?;
+        let mut ret = f(self)?;
 
         // Produces a `TokenStream` on-demand. Using `cursor_snapshot`
         // and `num_calls`, we can reconstruct the `TokenStream` seen
@@ -1312,7 +1319,8 @@
             trailing_semi: false,
             append_unglued_token: self.token_cursor.append_unglued_token.clone(),
         };
-        Ok((ret, Some(LazyTokenStream::new(lazy_impl))))
+        ret.finalize_tokens(LazyTokenStream::new(lazy_impl));
+        Ok(ret)
     }
 
     /// `::{` or `::*`
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index a6b9ac1..97d0c0d 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -4,7 +4,7 @@
 use rustc_errors::PResult;
 use rustc_span::symbol::{kw, Ident};
 
-use crate::parser::pat::{GateOr, OrPatNonterminalMode, RecoverComma};
+use crate::parser::pat::{GateOr, RecoverComma};
 use crate::parser::{FollowedByType, Parser, PathStyle};
 
 impl<'a> Parser<'a> {
@@ -12,11 +12,7 @@
     ///
     /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
     /// token. Be conservative (return true) if not sure.
-    pub fn nonterminal_may_begin_with(
-        kind: NonterminalKind,
-        token: &Token,
-        or_pat_mode: OrPatNonterminalMode,
-    ) -> bool {
+    pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool {
         /// Checks whether the non-terminal may contain a single (non-keyword) identifier.
         fn may_be_ident(nt: &token::Nonterminal) -> bool {
             match *nt {
@@ -62,7 +58,7 @@
                 },
                 _ => false,
             },
-            NonterminalKind::Pat => match token.kind {
+            NonterminalKind::Pat2018 { .. } | NonterminalKind::Pat2021 { .. } => match token.kind {
                 token::Ident(..) |                  // box, ref, mut, and other identifiers (can stricten)
                 token::OpenDelim(token::Paren) |    // tuple pattern
                 token::OpenDelim(token::Bracket) |  // slice pattern
@@ -76,7 +72,7 @@
                 token::Lt |                         // path (UFCS constant)
                 token::BinOp(token::Shl) => true,   // path (double UFCS)
                 // leading vert `|` or-pattern
-                token::BinOp(token::Or) =>  matches!(or_pat_mode, OrPatNonterminalMode::TopPat),
+                token::BinOp(token::Or) =>  matches!(kind, NonterminalKind::Pat2021 {..}),
                 token::Interpolated(ref nt) => may_be_ident(nt),
                 _ => false,
             },
@@ -94,11 +90,7 @@
     }
 
     /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`).
-    pub fn parse_nonterminal(
-        &mut self,
-        kind: NonterminalKind,
-        or_pat_mode: OrPatNonterminalMode,
-    ) -> PResult<'a, Nonterminal> {
+    pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonterminal> {
         // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
         // needs to have them force-captured here.
         // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
@@ -107,79 +99,34 @@
         // we always capture tokens for any `Nonterminal` which needs them.
         Ok(match kind {
             NonterminalKind::Item => match self.collect_tokens(|this| this.parse_item())? {
-                (Some(mut item), tokens) => {
-                    // If we captured tokens during parsing (due to outer attributes),
-                    // use those.
-                    if item.tokens.is_none() {
-                        item.tokens = tokens;
-                    }
-                    token::NtItem(item)
-                }
-                (None, _) => {
+                Some(item) => token::NtItem(item),
+                None => {
                     return Err(self.struct_span_err(self.token.span, "expected an item keyword"));
                 }
             },
             NonterminalKind::Block => {
-                let (mut block, tokens) = self.collect_tokens(|this| this.parse_block())?;
-                // We have have eaten an NtBlock, which could already have tokens
-                if block.tokens.is_none() {
-                    block.tokens = tokens;
-                }
-                token::NtBlock(block)
+                token::NtBlock(self.collect_tokens(|this| this.parse_block())?)
             }
-            NonterminalKind::Stmt => {
-                let (stmt, tokens) = self.collect_tokens(|this| this.parse_stmt())?;
-                match stmt {
-                    Some(mut s) => {
-                        if s.tokens().is_none() {
-                            s.set_tokens(tokens);
-                        }
-                        token::NtStmt(s)
-                    }
-                    None => {
-                        return Err(self.struct_span_err(self.token.span, "expected a statement"));
-                    }
+            NonterminalKind::Stmt => match self.collect_tokens(|this| this.parse_stmt())? {
+                Some(s) => token::NtStmt(s),
+                None => {
+                    return Err(self.struct_span_err(self.token.span, "expected a statement"));
                 }
-            }
-            NonterminalKind::Pat => {
-                let (mut pat, tokens) = self.collect_tokens(|this| match or_pat_mode {
-                    OrPatNonterminalMode::TopPat => {
+            },
+            NonterminalKind::Pat2018 { .. } | NonterminalKind::Pat2021 { .. } => {
+                token::NtPat(self.collect_tokens(|this| match kind {
+                    NonterminalKind::Pat2018 { .. } => this.parse_pat(None),
+                    NonterminalKind::Pat2021 { .. } => {
                         this.parse_top_pat(GateOr::Yes, RecoverComma::No)
                     }
-                    OrPatNonterminalMode::NoTopAlt => this.parse_pat(None),
-                })?;
-                // We have have eaten an NtPat, which could already have tokens
-                if pat.tokens.is_none() {
-                    pat.tokens = tokens;
-                }
-                token::NtPat(pat)
+                    _ => unreachable!(),
+                })?)
             }
-            NonterminalKind::Expr => {
-                let (mut expr, tokens) = self.collect_tokens(|this| this.parse_expr())?;
-                // If we captured tokens during parsing (due to outer attributes),
-                // use those.
-                if expr.tokens.is_none() {
-                    expr.tokens = tokens;
-                }
-                token::NtExpr(expr)
-            }
+            NonterminalKind::Expr => token::NtExpr(self.collect_tokens(|this| this.parse_expr())?),
             NonterminalKind::Literal => {
-                let (mut lit, tokens) =
-                    self.collect_tokens(|this| this.parse_literal_maybe_minus())?;
-                // We have have eaten a nonterminal, which  could already have tokens
-                if lit.tokens.is_none() {
-                    lit.tokens = tokens;
-                }
-                token::NtLiteral(lit)
+                token::NtLiteral(self.collect_tokens(|this| this.parse_literal_maybe_minus())?)
             }
-            NonterminalKind::Ty => {
-                let (mut ty, tokens) = self.collect_tokens(|this| this.parse_ty())?;
-                // We have an eaten an NtTy, which could already have tokens
-                if ty.tokens.is_none() {
-                    ty.tokens = tokens;
-                }
-                token::NtTy(ty)
-            }
+            NonterminalKind::Ty => token::NtTy(self.collect_tokens(|this| this.parse_ty())?),
             // this could be handled like a token, since it is one
             NonterminalKind::Ident => {
                 if let Some((ident, is_raw)) = get_macro_ident(&self.token) {
@@ -192,32 +139,15 @@
                 }
             }
             NonterminalKind::Path => {
-                let (mut path, tokens) =
-                    self.collect_tokens(|this| this.parse_path(PathStyle::Type))?;
-                // We have have eaten an NtPath, which could already have tokens
-                if path.tokens.is_none() {
-                    path.tokens = tokens;
-                }
-                token::NtPath(path)
+                token::NtPath(self.collect_tokens(|this| this.parse_path(PathStyle::Type))?)
             }
             NonterminalKind::Meta => {
-                let (mut attr, tokens) = self.collect_tokens(|this| this.parse_attr_item(false))?;
-                // We may have eaten a nonterminal, which could already have tokens
-                if attr.tokens.is_none() {
-                    attr.tokens = tokens;
-                }
-                token::NtMeta(P(attr))
+                token::NtMeta(P(self.collect_tokens(|this| this.parse_attr_item(false))?))
             }
             NonterminalKind::TT => token::NtTT(self.parse_token_tree()),
-            NonterminalKind::Vis => {
-                let (mut vis, tokens) =
-                    self.collect_tokens(|this| this.parse_visibility(FollowedByType::Yes))?;
-                // We may have etan an `NtVis`, which could already have tokens
-                if vis.tokens.is_none() {
-                    vis.tokens = tokens;
-                }
-                token::NtVis(vis)
-            }
+            NonterminalKind::Vis => token::NtVis(
+                self.collect_tokens(|this| this.parse_visibility(FollowedByType::Yes))?,
+            ),
             NonterminalKind::Lifetime => {
                 if self.check_lifetime() {
                     token::NtLifetime(self.expect_lifetime().ident)
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 1da371e..456e326 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -31,13 +31,6 @@
     No,
 }
 
-/// Used when parsing a non-terminal (see `parse_nonterminal`) to determine if `:pat` should match
-/// `top_pat` or `pat<no_top_alt>`. See issue <https://github.com/rust-lang/rust/pull/78935>.
-pub enum OrPatNonterminalMode {
-    TopPat,
-    NoTopAlt,
-}
-
 impl<'a> Parser<'a> {
     /// Parses a pattern.
     ///
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 60a47ca..dd36122 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -230,10 +230,11 @@
                 } else {
                     // `(T, U) -> R`
                     let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
+                    let inputs_span = lo.to(self.prev_token.span);
                     let span = ident.span.to(self.prev_token.span);
                     let output =
                         self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
-                    ParenthesizedArgs { inputs, output, span }.into()
+                    ParenthesizedArgs { span, inputs, inputs_span, output }.into()
                 };
 
                 PathSegment { ident, args, id: ast::DUMMY_NODE_ID }
@@ -515,6 +516,23 @@
         }
     }
 
+    /// Parse a const argument, e.g. `<3>`. It is assumed the angle brackets will be parsed by
+    /// the caller.
+    pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> {
+        // Parse const argument.
+        let value = if let token::OpenDelim(token::Brace) = self.token.kind {
+            self.parse_block_expr(
+                None,
+                self.token.span,
+                BlockCheckMode::Default,
+                ast::AttrVec::new(),
+            )?
+        } else {
+            self.handle_unambiguous_unbraced_const_arg()?
+        };
+        Ok(AnonConst { id: ast::DUMMY_NODE_ID, value })
+    }
+
     /// Parse a generic argument in a path segment.
     /// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
     fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
@@ -524,17 +542,7 @@
             GenericArg::Lifetime(self.expect_lifetime())
         } else if self.check_const_arg() {
             // Parse const argument.
-            let value = if let token::OpenDelim(token::Brace) = self.token.kind {
-                self.parse_block_expr(
-                    None,
-                    self.token.span,
-                    BlockCheckMode::Default,
-                    ast::AttrVec::new(),
-                )?
-            } else {
-                self.handle_unambiguous_unbraced_const_arg()?
-            };
-            GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })
+            GenericArg::Const(self.parse_const_arg()?)
         } else if self.check_type() {
             // Parse type argument.
             match self.parse_ty() {
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 2942747..641b292 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -89,15 +89,7 @@
         };
 
         let stmt = if has_attrs {
-            let (mut stmt, tokens) = self.collect_tokens(parse_stmt_inner)?;
-            if let Some(stmt) = &mut stmt {
-                // If we already have tokens (e.g. due to encounting an `NtStmt`),
-                // use those instead.
-                if stmt.tokens().is_none() {
-                    stmt.set_tokens(tokens);
-                }
-            }
-            stmt
+            self.collect_tokens(parse_stmt_inner)?
         } else {
             parse_stmt_inner(self)?
         };
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index f4bb961..2137272 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -2,7 +2,7 @@
 
 use crate::parse_in;
 
-use rustc_ast::tokenstream::DelimSpan;
+use rustc_ast::tokenstream::{DelimSpan, TokenTree};
 use rustc_ast::{self as ast, Attribute, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
 use rustc_errors::{Applicability, PResult};
 use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
@@ -45,7 +45,8 @@
         kind: match &item.args {
             MacArgs::Empty => MetaItemKind::Word,
             MacArgs::Eq(_, t) => {
-                let v = parse_in(sess, t.clone(), "name value", |p| p.parse_unsuffixed_lit())?;
+                let t = TokenTree::Token(t.clone()).into();
+                let v = parse_in(sess, t, "name value", |p| p.parse_unsuffixed_lit())?;
                 MetaItemKind::NameValue(v)
             }
             MacArgs::Delimited(dspan, delim, t) => {
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 25e3e67..f7b16bd 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -347,7 +347,7 @@
         let mut pos = pos;
         // This handles the raw string case, the raw argument is the number of #
         // in r###"..."### (we need to add one because of the `r`).
-        let raw = self.style.map(|raw| raw + 1).unwrap_or(0);
+        let raw = self.style.map_or(0, |raw| raw + 1);
         for skip in &self.skips {
             if pos > *skip {
                 pos += 1;
@@ -814,7 +814,7 @@
         skips
     }
 
-    let r_start = str_style.map(|r| r + 1).unwrap_or(0);
+    let r_start = str_style.map_or(0, |r| r + 1);
     let r_end = str_style.unwrap_or(0);
     let s = &snippet[r_start + 1..snippet.len() - r_end - 1];
     (find_skips(s, str_style.is_some()), true)
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index aeaa862..ac73ba7 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -32,7 +32,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 { ref of_trait, .. } => of_trait.is_some(),
+                hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(),
                 _ => bug!("parent of an ImplItem must be an Impl"),
             };
             if containing_impl_is_for_trait {
@@ -310,7 +310,7 @@
                 .sess
                 .struct_span_err(
                     meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
-                    &format!("{:?} character isn't allowed in `#[doc(alias = \"...\")]`", c,),
+                    &format!("{:?} character isn't allowed in `#[doc(alias = \"...\")]`", c),
                 )
                 .emit();
             return false;
@@ -343,7 +343,7 @@
                 // We can't link to trait impl's consts.
                 let err = "associated constant in trait implementation block";
                 match containing_item.kind {
-                    ItemKind::Impl { of_trait: Some(_), .. } => Some(err),
+                    ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => Some(err),
                     _ => None,
                 }
             }
@@ -358,6 +358,17 @@
                 .emit();
             return false;
         }
+        let item_name = self.tcx.hir().name(hir_id);
+        if &*item_name.as_str() == doc_alias {
+            self.tcx
+                .sess
+                .struct_span_err(
+                    meta.span(),
+                    &format!("`#[doc(alias = \"...\")]` is the same as the item's name"),
+                )
+                .emit();
+            return false;
+        }
         true
     }
 
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 2d6bbff..c887a86 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -49,9 +49,7 @@
 
             // All other expressions are allowed.
             Self::Loop(Loop | While | WhileLet)
-            | Self::Match(
-                WhileDesugar | WhileLetDesugar | Normal | IfDesugar { .. } | IfLetDesugar { .. },
-            ) => &[],
+            | Self::Match(WhileDesugar | WhileLetDesugar | Normal | IfLetDesugar { .. }) => &[],
         };
 
         Some(gates)
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index c4fb0cf..80a24c9 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -396,7 +396,7 @@
                     }
                 }
             }
-            hir::ItemKind::Impl { ref of_trait, items, .. } => {
+            hir::ItemKind::Impl(hir::Impl { ref of_trait, items, .. }) => {
                 if of_trait.is_some() {
                     self.worklist.push(item.hir_id);
                 }
diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_passes/src/intrinsicck.rs
index 711e8e8..ee90e9c 100644
--- a/compiler/rustc_passes/src/intrinsicck.rs
+++ b/compiler/rustc_passes/src/intrinsicck.rs
@@ -78,7 +78,7 @@
                 return;
             }
 
-            // Special-case transmutting from `typeof(function)` and
+            // Special-case transmuting from `typeof(function)` and
             // `Option<typeof(function)>` to present a clearer error.
             let from = unpack_option_like(self.tcx, from);
             if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (from.kind(), sk_to) {
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index fcea1b2..6202cc3 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -419,7 +419,7 @@
             }
 
             // live nodes required for interesting control flow:
-            hir::ExprKind::Match(..) | hir::ExprKind::Loop(..) => {
+            hir::ExprKind::If(..) | hir::ExprKind::Match(..) | hir::ExprKind::Loop(..) => {
                 self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span));
                 intravisit::walk_expr(self, expr);
             }
@@ -846,6 +846,29 @@
             // at the label ident
             hir::ExprKind::Loop(ref blk, _, _) => self.propagate_through_loop(expr, &blk, succ),
 
+            hir::ExprKind::If(ref cond, ref then, ref else_opt) => {
+                //
+                //     (cond)
+                //       |
+                //       v
+                //     (expr)
+                //     /   \
+                //    |     |
+                //    v     v
+                //  (then)(els)
+                //    |     |
+                //    v     v
+                //   (  succ  )
+                //
+                let else_ln =
+                    self.propagate_through_opt_expr(else_opt.as_ref().map(|e| &**e), succ);
+                let then_ln = self.propagate_through_expr(&then, succ);
+                let ln = self.live_node(expr.hir_id, expr.span);
+                self.init_from_succ(ln, else_ln);
+                self.merge_from_succ(ln, then_ln);
+                self.propagate_through_expr(&cond, ln)
+            }
+
             hir::ExprKind::Match(ref e, arms, _) => {
                 //
                 //      (e)
@@ -1336,6 +1359,7 @@
         | hir::ExprKind::Tup(..)
         | hir::ExprKind::Binary(..)
         | hir::ExprKind::Cast(..)
+        | hir::ExprKind::If(..)
         | hir::ExprKind::DropTemps(..)
         | hir::ExprKind::Unary(..)
         | hir::ExprKind::Ret(..)
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index 5b50ef8..93fb23c 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -149,7 +149,7 @@
 fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId, body: &'tcx hir::Body<'tcx>, fn_span: Span) {
     let mut this = CheckInlineAssembly { tcx, items: Vec::new() };
     this.visit_body(body);
-    if let &[(ItemKind::Asm, _)] = &this.items[..] {
+    if let [(ItemKind::Asm, _)] = this.items[..] {
         // Ok.
     } else {
         tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, fn_span, |lint| {
@@ -201,6 +201,7 @@
             | ExprKind::Type(..)
             | ExprKind::Loop(..)
             | ExprKind::Match(..)
+            | ExprKind::If(..)
             | ExprKind::Closure(..)
             | ExprKind::Assign(..)
             | ExprKind::AssignOp(..)
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index fde83af..b237671 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -349,7 +349,9 @@
         }
 
         // We need only trait impls here, not inherent impls, and only non-exported ones
-        if let hir::ItemKind::Impl { of_trait: Some(ref trait_ref), ref items, .. } = item.kind {
+        if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), ref items, .. }) =
+            item.kind
+        {
             if !self.access_levels.is_reachable(item.hir_id) {
                 // FIXME(#53488) remove `let`
                 let tcx = self.tcx;
diff --git a/compiler/rustc_passes/src/region.rs b/compiler/rustc_passes/src/region.rs
index 1af79ab..91421d7 100644
--- a/compiler/rustc_passes/src/region.rs
+++ b/compiler/rustc_passes/src/region.rs
@@ -241,6 +241,17 @@
                 terminating(r.hir_id.local_id);
             }
 
+            hir::ExprKind::If(ref expr, ref then, Some(ref otherwise)) => {
+                terminating(expr.hir_id.local_id);
+                terminating(then.hir_id.local_id);
+                terminating(otherwise.hir_id.local_id);
+            }
+
+            hir::ExprKind::If(ref expr, ref then, None) => {
+                terminating(expr.hir_id.local_id);
+                terminating(then.hir_id.local_id);
+            }
+
             hir::ExprKind::Loop(ref body, _, _) => {
                 terminating(body.hir_id.local_id);
             }
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 3c2462a..4a3d6ec 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -330,11 +330,12 @@
             // 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 { of_trait: None, .. } | hir::ItemKind::ForeignMod { .. } => {
+            hir::ItemKind::Impl(hir::Impl { of_trait: None, .. })
+            | hir::ItemKind::ForeignMod { .. } => {
                 self.in_trait_impl = false;
                 kind = AnnotationKind::Container;
             }
-            hir::ItemKind::Impl { of_trait: Some(_), .. } => {
+            hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => {
                 self.in_trait_impl = true;
                 kind = AnnotationKind::DeprecationProhibited;
             }
@@ -443,7 +444,7 @@
 
     fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
         let kind = match &p.kind {
-            // FIXME(const_generics:defaults)
+            // FIXME(const_generics_defaults)
             hir::GenericParamKind::Type { default, .. } if default.is_some() => {
                 AnnotationKind::Container
             }
@@ -503,7 +504,7 @@
         // optional. They inherit stability from their parents when unannotated.
         if !matches!(
             i.kind,
-            hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod { .. }
+            hir::ItemKind::Impl(hir::Impl { of_trait: None, .. }) | hir::ItemKind::ForeignMod { .. }
         ) {
             self.check_missing_stability(i.hir_id, i.span);
         }
@@ -672,7 +673,7 @@
             // 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 { of_trait: Some(ref t), self_ty, items, .. } => {
+            hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => {
                 if self.tcx.features().staged_api {
                     // If this impl block has an #[unstable] attribute, give an
                     // error if all involved types and traits are stable, because
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 1bcfdf0..66206ca 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -100,19 +100,19 @@
     }
 
     fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<V::BreakTy> {
-        match predicate.skip_binders() {
-            ty::PredicateAtom::Trait(ty::TraitPredicate { trait_ref }, _) => {
+        match predicate.kind().skip_binder() {
+            ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref }, _) => {
                 self.visit_trait(trait_ref)
             }
-            ty::PredicateAtom::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
+            ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
                 ty.visit_with(self)?;
                 self.visit_trait(projection_ty.trait_ref(self.def_id_visitor.tcx()))
             }
-            ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => {
+            ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => {
                 ty.visit_with(self)
             }
-            ty::PredicateAtom::RegionOutlives(..) => ControlFlow::CONTINUE,
-            ty::PredicateAtom::ConstEvaluatable(..)
+            ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE,
+            ty::PredicateKind::ConstEvaluatable(..)
                 if self.def_id_visitor.tcx().features().const_evaluatable_checked =>
             {
                 // FIXME(const_evaluatable_checked): If the constant used here depends on a
@@ -632,9 +632,9 @@
                     }
                 }
             }
-            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() {
+            hir::ItemKind::Impl(ref impl_) => {
+                for impl_item_ref in impl_.items {
+                    if impl_.of_trait.is_some() || impl_item_ref.vis.node.is_pub() {
                         self.update(impl_item_ref.id.hir_id, item_level);
                     }
                 }
@@ -736,11 +736,11 @@
                 }
             }
             // Visit everything except for private impl items.
-            hir::ItemKind::Impl { items, .. } => {
+            hir::ItemKind::Impl(ref impl_) => {
                 if item_level.is_some() {
                     self.reach(item.hir_id, item_level).generics().predicates().ty().trait_ref();
 
-                    for impl_item_ref in items {
+                    for impl_item_ref in impl_.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)
@@ -832,10 +832,15 @@
     }
 
     fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
+        // Non-opaque macros cannot make other items more accessible than they already are.
         if attr::find_transparency(&self.tcx.sess, &md.attrs, md.ast.macro_rules).0
             != Transparency::Opaque
         {
-            self.update(md.hir_id, Some(AccessLevel::Public));
+            // `#[macro_export]`-ed `macro_rules!` are `Public` since they
+            // ignore their containing path to always appear at the crate root.
+            if md.ast.macro_rules {
+                self.update(md.hir_id, Some(AccessLevel::Public));
+            }
             return;
         }
 
@@ -1445,7 +1450,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 { generics: ref g, ref of_trait, ref self_ty, items, .. } => {
+            hir::ItemKind::Impl(ref impl_) => {
                 // `impl [... for] Private` is never visible.
                 let self_contains_private;
                 // `impl [... for] Public<...>`, but not `impl [... for]
@@ -1460,7 +1465,7 @@
                         at_outer_type: true,
                         outer_type_is_public_path: false,
                     };
-                    visitor.visit_ty(&self_ty);
+                    visitor.visit_ty(&impl_.self_ty);
                     self_contains_private = visitor.contains_private;
                     self_is_public_path = visitor.outer_type_is_public_path;
                 }
@@ -1468,7 +1473,7 @@
                 // Miscellaneous info about the impl:
 
                 // `true` iff this is `impl Private for ...`.
-                let not_private_trait = of_trait.as_ref().map_or(
+                let not_private_trait = impl_.of_trait.as_ref().map_or(
                     true, // no trait counts as public trait
                     |tr| {
                         let did = tr.path.res.def_id();
@@ -1489,8 +1494,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 = of_trait.is_some()
-                    || items.iter().any(|impl_item_ref| {
+                let trait_or_some_public_method = impl_.of_trait.is_some()
+                    || impl_.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::Fn(..) => {
@@ -1501,11 +1506,11 @@
                     });
 
                 if !self_contains_private && not_private_trait && trait_or_some_public_method {
-                    intravisit::walk_generics(self, g);
+                    intravisit::walk_generics(self, &impl_.generics);
 
-                    match of_trait {
+                    match impl_.of_trait {
                         None => {
-                            for impl_item_ref in items {
+                            for impl_item_ref in impl_.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
@@ -1526,7 +1531,7 @@
                                 }
                             }
                         }
-                        Some(tr) => {
+                        Some(ref tr) => {
                             // Any private types in a trait impl fall into three
                             // categories.
                             // 1. mentioned in the trait definition
@@ -1543,7 +1548,7 @@
                             intravisit::walk_path(self, &tr.path);
 
                             // Those in 3. are warned with this call.
-                            for impl_item_ref in items {
+                            for impl_item_ref in impl_.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);
@@ -1551,11 +1556,11 @@
                             }
                         }
                     }
-                } else if of_trait.is_none() && self_is_public_path {
+                } else if impl_.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 items {
+                    for impl_item_ref in impl_.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 {
@@ -1572,7 +1577,7 @@
                         }
                     }
                     if found_pub_static {
-                        intravisit::walk_generics(self, g)
+                        intravisit::walk_generics(self, &impl_.generics)
                     }
                 }
                 return;
@@ -1965,11 +1970,11 @@
             // 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 of_trait, items, .. } => {
+            hir::ItemKind::Impl(ref impl_) => {
                 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 items {
-                    let impl_item_vis = if of_trait.is_none() {
+                for impl_item_ref in impl_.items {
+                    let impl_item_vis = if impl_.of_trait.is_none() {
                         min(
                             tcx.visibility(tcx.hir().local_def_id(impl_item_ref.id.hir_id)),
                             impl_vis,
@@ -2027,7 +2032,7 @@
                 Node::ImplItem(impl_item) => {
                     match tcx.hir().get(tcx.hir().get_parent_item(hir_id)) {
                         Node::Item(hir::Item {
-                            kind: hir::ItemKind::Impl { of_trait: Some(tr), .. },
+                            kind: hir::ItemKind::Impl(hir::Impl { of_trait: Some(tr), .. }),
                             ..
                         }) => tr.path.res.opt_def_id().map_or_else(
                             || {
diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs
index ff52fda..64aba87 100644
--- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs
@@ -153,12 +153,6 @@
     }
 }
 
-impl<Ctxt: DepContext> DepNodeParams<Ctxt> for () {
-    fn to_fingerprint(&self, _: Ctxt) -> Fingerprint {
-        Fingerprint::ZERO
-    }
-}
-
 /// A "work product" corresponds to a `.o` (or other) file that we
 /// save in between runs. These IDs do not have a `DefId` but rather
 /// some independent path or string that persists between runs without
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 605d7ae..151e056 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -953,7 +953,7 @@
     // Returns true if the given node has been marked as green during the
     // current compilation session. Used in various assertions
     pub fn is_green(&self, dep_node: &DepNode<K>) -> bool {
-        self.node_color(dep_node).map(|c| c.is_green()).unwrap_or(false)
+        self.node_color(dep_node).map_or(false, |c| c.is_green())
     }
 
     // This method loads all on-disk cacheable query results into memory, so
diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs
index da0b5aa..b1c9016 100644
--- a/compiler/rustc_query_system/src/dep_graph/mod.rs
+++ b/compiler/rustc_query_system/src/dep_graph/mod.rs
@@ -61,7 +61,7 @@
 }
 
 /// Describe the different families of dependency nodes.
-pub trait DepKind: Copy + fmt::Debug + Eq + Ord + Hash {
+pub trait DepKind: Copy + fmt::Debug + Eq + Hash {
     const NULL: Self;
 
     /// Return whether this kind always require evaluation.
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 426f5bb..d17af61 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -566,7 +566,6 @@
     assert!(new_hash == old_hash, "found unstable fingerprints for {:?}", dep_node,);
 }
 
-#[inline(always)]
 fn force_query_with_job<C, CTX>(
     tcx: CTX,
     key: C::Key,
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index c5f783e..4ab14c1 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -96,7 +96,7 @@
 
     /// Walks up the tree of definitions starting at `def_id`,
     /// stopping at the first `DefKind::Mod` encountered
-    fn nearest_mod_parent(&mut self, def_id: DefId) -> Module<'a> {
+    fn nearest_parent_mod(&mut self, def_id: DefId) -> Module<'a> {
         let def_key = self.cstore().def_key(def_id);
 
         let mut parent_id = DefId {
@@ -115,7 +115,7 @@
         self.get_module(parent_id)
     }
 
-    crate fn get_module(&mut self, def_id: DefId) -> Module<'a> {
+    pub fn get_module(&mut self, def_id: DefId) -> Module<'a> {
         // If this is a local module, it will be in `module_map`, no need to recalculate it.
         if let Some(def_id) = def_id.as_local() {
             return self.module_map[&def_id];
@@ -137,7 +137,7 @@
                 .get_opt_name()
                 .expect("given a DefId that wasn't a module");
 
-            let parent = Some(self.nearest_mod_parent(def_id));
+            let parent = Some(self.nearest_parent_mod(def_id));
             (name, parent)
         };
 
@@ -179,7 +179,7 @@
             // so this hopefully won't be a problem.
             //
             // See https://github.com/rust-lang/rust/pull/77984#issuecomment-712445508
-            self.nearest_mod_parent(def_id)
+            self.nearest_parent_mod(def_id)
         }
     }
 
@@ -266,7 +266,7 @@
                 } else {
                     // If it's not in an enum, its visibility is restricted to the `mod` item
                     // that it's defined in.
-                    Ok(ty::Visibility::Restricted(self.parent_scope.module.normal_ancestor_id))
+                    Ok(ty::Visibility::Restricted(self.parent_scope.module.nearest_parent_mod))
                 }
             }
             ast::VisibilityKind::Restricted { ref path, id, .. } => {
@@ -803,7 +803,7 @@
                 let module = self.r.new_module(
                     parent,
                     module_kind,
-                    parent.normal_ancestor_id,
+                    parent.nearest_parent_mod,
                     expansion,
                     item.span,
                 );
@@ -878,7 +878,7 @@
                 let module = self.r.new_module(
                     parent,
                     module_kind,
-                    parent.normal_ancestor_id,
+                    parent.nearest_parent_mod,
                     expansion,
                     item.span,
                 );
@@ -921,7 +921,7 @@
             let module = self.r.new_module(
                 parent,
                 ModuleKind::Block(block.id),
-                parent.normal_ancestor_id,
+                parent.nearest_parent_mod,
                 expansion,
                 block.span,
             );
@@ -1298,26 +1298,31 @@
     method!(visit_ty: ast::Ty, ast::TyKind::MacCall, walk_ty);
 
     fn visit_item(&mut self, item: &'b Item) {
-        let macro_use = match item.kind {
+        let orig_module_scope = self.parent_scope.module;
+        self.parent_scope.macro_rules = match item.kind {
             ItemKind::MacroDef(..) => {
-                self.parent_scope.macro_rules = self.define_macro(item);
-                return;
+                let macro_rules_scope = self.define_macro(item);
+                visit::walk_item(self, item);
+                macro_rules_scope
             }
             ItemKind::MacCall(..) => {
-                self.parent_scope.macro_rules = self.visit_invoc_in_module(item.id);
-                return;
+                let macro_rules_scope = self.visit_invoc_in_module(item.id);
+                visit::walk_item(self, item);
+                macro_rules_scope
             }
-            ItemKind::Mod(..) => self.contains_macro_use(&item.attrs),
-            _ => false,
+            _ => {
+                let orig_macro_rules_scope = self.parent_scope.macro_rules;
+                self.build_reduced_graph_for_item(item);
+                visit::walk_item(self, item);
+                match item.kind {
+                    ItemKind::Mod(..) if self.contains_macro_use(&item.attrs) => {
+                        self.parent_scope.macro_rules
+                    }
+                    _ => orig_macro_rules_scope,
+                }
+            }
         };
-        let orig_current_module = self.parent_scope.module;
-        let orig_current_macro_rules_scope = self.parent_scope.macro_rules;
-        self.build_reduced_graph_for_item(item);
-        visit::walk_item(self, item);
-        self.parent_scope.module = orig_current_module;
-        if !macro_use {
-            self.parent_scope.macro_rules = orig_current_macro_rules_scope;
-        }
+        self.parent_scope.module = orig_module_scope;
     }
 
     fn visit_stmt(&mut self, stmt: &'b ast::Stmt) {
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 48bce88..727d6ab 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -91,7 +91,10 @@
                 DefPathData::ValueNs(i.ident.name)
             }
             ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.name),
-            ItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
+            ItemKind::MacCall(..) => {
+                visit::walk_item(self, i);
+                return self.visit_macro_invoc(i.id);
+            }
             ItemKind::GlobalAsm(..) => DefPathData::Misc,
             ItemKind::Use(..) => {
                 return visit::walk_item(self, i);
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 809de9b..69fb687 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -398,14 +398,30 @@
                 err.help("use the `|| { ... }` closure form instead");
                 err
             }
-            ResolutionError::AttemptToUseNonConstantValueInConstant => {
+            ResolutionError::AttemptToUseNonConstantValueInConstant(ident, sugg, current) => {
                 let mut err = struct_span_err!(
                     self.session,
                     span,
                     E0435,
                     "attempt to use a non-constant value in a constant"
                 );
-                err.span_label(span, "non-constant value");
+                // let foo =...
+                //     ^^^ given this Span
+                // ------- get this Span to have an applicable suggestion
+                let sp =
+                    self.session.source_map().span_extend_to_prev_str(ident.span, current, true);
+                if sp.lo().0 == 0 {
+                    err.span_label(ident.span, &format!("this would need to be a `{}`", sugg));
+                } else {
+                    let sp = sp.with_lo(BytePos(sp.lo().0 - current.len() as u32));
+                    err.span_suggestion(
+                        sp,
+                        &format!("consider using `{}` instead of `{}`", sugg, current),
+                        format!("{} {}", sugg, ident),
+                        Applicability::MaybeIncorrect,
+                    );
+                    err.span_label(span, "non-constant value");
+                }
                 err
             }
             ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => {
@@ -595,7 +611,8 @@
         filter_fn: &impl Fn(Res) -> bool,
     ) -> Option<TypoSuggestion> {
         let mut suggestions = Vec::new();
-        self.visit_scopes(scope_set, parent_scope, ident, |this, scope, use_prelude, _| {
+        let ctxt = ident.span.ctxt();
+        self.visit_scopes(scope_set, parent_scope, ctxt, |this, scope, use_prelude, _| {
             match scope {
                 Scope::DeriveHelpers(expn_id) => {
                     let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
@@ -666,7 +683,7 @@
                     ));
                 }
                 Scope::BuiltinAttrs => {
-                    let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin);
+                    let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(kw::Empty));
                     if filter_fn(res) {
                         suggestions.extend(
                             BUILTIN_ATTRIBUTES
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index dd1874d..97e556f 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -14,7 +14,6 @@
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use rustc_ast::*;
-use rustc_ast::{unwrap_or, walk_list};
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::DiagnosticId;
@@ -92,6 +91,12 @@
     No,
 }
 
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+crate enum ConstantItemKind {
+    Const,
+    Static,
+}
+
 /// The rib kind restricts certain accesses,
 /// e.g. to a `Res::Local` of an outer item.
 #[derive(Copy, Clone, Debug)]
@@ -119,7 +124,7 @@
     ///
     /// The `bool` indicates if this constant may reference generic parameters
     /// and is used to only allow generic parameters to be used in trivial constant expressions.
-    ConstantItemRibKind(bool),
+    ConstantItemRibKind(bool, Option<(Ident, ConstantItemKind)>),
 
     /// We passed through a module.
     ModuleRibKind(Module<'a>),
@@ -145,7 +150,7 @@
             NormalRibKind
             | ClosureOrAsyncRibKind
             | FnItemRibKind
-            | ConstantItemRibKind(_)
+            | ConstantItemRibKind(..)
             | ModuleRibKind(_)
             | MacroDefinition(_)
             | ConstParamTyRibKind => false,
@@ -262,52 +267,60 @@
 
     crate fn is_expected(self, res: Res) -> bool {
         match self {
-            PathSource::Type => matches!(res, Res::Def(
+            PathSource::Type => matches!(
+                res,
+                Res::Def(
                     DefKind::Struct
-                    | DefKind::Union
-                    | DefKind::Enum
-                    | DefKind::Trait
-                    | DefKind::TraitAlias
-                    | DefKind::TyAlias
-                    | DefKind::AssocTy
-                    | DefKind::TyParam
-                    | DefKind::OpaqueTy
-                    | DefKind::ForeignTy,
+                        | DefKind::Union
+                        | DefKind::Enum
+                        | DefKind::Trait
+                        | DefKind::TraitAlias
+                        | DefKind::TyAlias
+                        | DefKind::AssocTy
+                        | DefKind::TyParam
+                        | DefKind::OpaqueTy
+                        | DefKind::ForeignTy,
                     _,
-                )
-                | Res::PrimTy(..)
-                | Res::SelfTy(..)),
+                ) | Res::PrimTy(..)
+                    | Res::SelfTy(..)
+            ),
             PathSource::Trait(AliasPossibility::No) => matches!(res, Res::Def(DefKind::Trait, _)),
             PathSource::Trait(AliasPossibility::Maybe) => {
                 matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _))
             }
-            PathSource::Expr(..) => matches!(res, Res::Def(
+            PathSource::Expr(..) => matches!(
+                res,
+                Res::Def(
                     DefKind::Ctor(_, CtorKind::Const | CtorKind::Fn)
-                    | DefKind::Const
-                    | DefKind::Static
-                    | DefKind::Fn
-                    | DefKind::AssocFn
-                    | DefKind::AssocConst
-                    | DefKind::ConstParam,
+                        | DefKind::Const
+                        | DefKind::Static
+                        | DefKind::Fn
+                        | DefKind::AssocFn
+                        | DefKind::AssocConst
+                        | DefKind::ConstParam,
                     _,
-                )
-                | Res::Local(..)
-                | Res::SelfCtor(..)),
-            PathSource::Pat => matches!(res, Res::Def(
+                ) | Res::Local(..)
+                    | Res::SelfCtor(..)
+            ),
+            PathSource::Pat => matches!(
+                res,
+                Res::Def(
                     DefKind::Ctor(_, CtorKind::Const) | DefKind::Const | DefKind::AssocConst,
                     _,
-                )
-                | Res::SelfCtor(..)),
+                ) | Res::SelfCtor(..)
+            ),
             PathSource::TupleStruct(..) => res.expected_in_tuple_struct_pat(),
-            PathSource::Struct => matches!(res, Res::Def(
+            PathSource::Struct => matches!(
+                res,
+                Res::Def(
                     DefKind::Struct
-                    | DefKind::Union
-                    | DefKind::Variant
-                    | DefKind::TyAlias
-                    | DefKind::AssocTy,
+                        | DefKind::Union
+                        | DefKind::Variant
+                        | DefKind::TyAlias
+                        | DefKind::AssocTy,
                     _,
-                )
-                | Res::SelfTy(..)),
+                ) | Res::SelfTy(..)
+            ),
             PathSource::TraitItem(ns) => match res {
                 Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) if ns == ValueNS => true,
                 Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
@@ -586,7 +599,8 @@
                     // Allow all following defaults to refer to this type parameter.
                     default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
                 }
-                GenericParamKind::Const { ref ty, kw_span: _ } => {
+                GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
+                    // FIXME(const_generics_defaults): handle `default` value here
                     for bound in &param.bounds {
                         self.visit_param_bound(bound);
                     }
@@ -633,7 +647,7 @@
                             // Note that we might not be inside of an repeat expression here,
                             // but considering that `IsRepeatExpr` is only relevant for
                             // non-trivial constants this is doesn't matter.
-                            self.with_constant_rib(IsRepeatExpr::No, true, |this| {
+                            self.with_constant_rib(IsRepeatExpr::No, true, None, |this| {
                                 this.smart_resolve_path(
                                     ty.id,
                                     qself.as_ref(),
@@ -842,7 +856,7 @@
                 | ClosureOrAsyncRibKind
                 | FnItemRibKind
                 | ItemRibKind(..)
-                | ConstantItemRibKind(_)
+                | ConstantItemRibKind(..)
                 | ModuleRibKind(..)
                 | ForwardTyParamBanRibKind
                 | ConstParamTyRibKind => {
@@ -969,6 +983,7 @@
                                             this.with_constant_rib(
                                                 IsRepeatExpr::No,
                                                 true,
+                                                None,
                                                 |this| this.visit_expr(expr),
                                             );
                                         }
@@ -1011,11 +1026,19 @@
                 self.with_item_rib(HasGenericParams::No, |this| {
                     this.visit_ty(ty);
                     if let Some(expr) = expr {
+                        let constant_item_kind = match item.kind {
+                            ItemKind::Const(..) => ConstantItemKind::Const,
+                            ItemKind::Static(..) => ConstantItemKind::Static,
+                            _ => unreachable!(),
+                        };
                         // We already forbid generic params because of the above item rib,
                         // so it doesn't matter whether this is a trivial constant.
-                        this.with_constant_rib(IsRepeatExpr::No, true, |this| {
-                            this.visit_expr(expr)
-                        });
+                        this.with_constant_rib(
+                            IsRepeatExpr::No,
+                            true,
+                            Some((item.ident, constant_item_kind)),
+                            |this| this.visit_expr(expr),
+                        );
                     }
                 });
             }
@@ -1117,15 +1140,16 @@
         &mut self,
         is_repeat: IsRepeatExpr,
         is_trivial: bool,
+        item: Option<(Ident, ConstantItemKind)>,
         f: impl FnOnce(&mut Self),
     ) {
         debug!("with_constant_rib: is_repeat={:?} is_trivial={}", is_repeat, is_trivial);
-        self.with_rib(ValueNS, ConstantItemRibKind(is_trivial), |this| {
+        self.with_rib(ValueNS, ConstantItemRibKind(is_trivial, item), |this| {
             this.with_rib(
                 TypeNS,
-                ConstantItemRibKind(is_repeat == IsRepeatExpr::Yes || is_trivial),
+                ConstantItemRibKind(is_repeat == IsRepeatExpr::Yes || is_trivial, item),
                 |this| {
-                    this.with_label_rib(ConstantItemRibKind(is_trivial), f);
+                    this.with_label_rib(ConstantItemRibKind(is_trivial, item), f);
                 },
             )
         });
@@ -1265,6 +1289,7 @@
                                             this.with_constant_rib(
                                                 IsRepeatExpr::No,
                                                 true,
+                                                None,
                                                 |this| {
                                                     visit::walk_assoc_item(
                                                         this,
@@ -1774,7 +1799,7 @@
             if this.should_report_errs() {
                 let (err, candidates) = this.smart_resolve_report_errors(path, span, source, res);
 
-                let def_id = this.parent_scope.module.normal_ancestor_id;
+                let def_id = this.parent_scope.module.nearest_parent_mod;
                 let instead = res.is_some();
                 let suggestion =
                     if res.is_none() { this.report_missing_type_error(path) } else { None };
@@ -1842,7 +1867,7 @@
 
             drop(parent_err);
 
-            let def_id = this.parent_scope.module.normal_ancestor_id;
+            let def_id = this.parent_scope.module.nearest_parent_mod;
 
             if this.should_report_errs() {
                 this.r.use_injections.push(UseError {
@@ -1885,7 +1910,7 @@
                 // it needs to be added to the trait map.
                 if ns == ValueNS {
                     let item_name = path.last().unwrap().ident;
-                    let traits = self.get_traits_containing_item(item_name, ns);
+                    let traits = self.traits_in_scope(item_name, ns);
                     self.r.trait_map.insert(id, traits);
                 }
 
@@ -1899,7 +1924,7 @@
                     {
                         // Check if we wrote `str::from_utf8` instead of `std::str::from_utf8`
                         let item_span =
-                            path.iter().last().map(|segment| segment.ident.span).unwrap_or(span);
+                            path.iter().last().map_or(span, |segment| segment.ident.span);
 
                         let mut hm = self.r.session.confused_type_with_std_module.borrow_mut();
                         hm.insert(item_span, span);
@@ -1921,8 +1946,7 @@
             _ => report_errors(self, None),
         };
 
-        if let PathSource::TraitItem(..) = source {
-        } else {
+        if !matches!(source, PathSource::TraitItem(..)) {
             // Avoid recording definition of `A::B` in `<T as A>::B::C`.
             self.r.record_partial_res(id, partial_res);
         }
@@ -2199,6 +2223,7 @@
         self.with_constant_rib(
             is_repeat,
             constant.value.is_potential_trivial_const_param(),
+            None,
             |this| {
                 visit::walk_anon_const(this, constant);
             },
@@ -2345,12 +2370,12 @@
                 // field, we need to add any trait methods we find that match
                 // the field name so that we can do some nice error reporting
                 // later on in typeck.
-                let traits = self.get_traits_containing_item(ident, ValueNS);
+                let traits = self.traits_in_scope(ident, ValueNS);
                 self.r.trait_map.insert(expr.id, traits);
             }
             ExprKind::MethodCall(ref segment, ..) => {
                 debug!("(recording candidate traits for expr) recording traits for {}", expr.id);
-                let traits = self.get_traits_containing_item(segment.ident, ValueNS);
+                let traits = self.traits_in_scope(segment.ident, ValueNS);
                 self.r.trait_map.insert(expr.id, traits);
             }
             _ => {
@@ -2359,60 +2384,13 @@
         }
     }
 
-    fn get_traits_containing_item(
-        &mut self,
-        mut ident: Ident,
-        ns: Namespace,
-    ) -> Vec<TraitCandidate> {
-        debug!("(getting traits containing item) looking for '{}'", ident.name);
-
-        let mut found_traits = Vec::new();
-        // Look for the current trait.
-        if let Some((module, _)) = self.current_trait_ref {
-            if self
-                .r
-                .resolve_ident_in_module(
-                    ModuleOrUniformRoot::Module(module),
-                    ident,
-                    ns,
-                    &self.parent_scope,
-                    false,
-                    module.span,
-                )
-                .is_ok()
-            {
-                let def_id = module.def_id().unwrap();
-                found_traits.push(TraitCandidate { def_id, import_ids: smallvec![] });
-            }
-        }
-
-        ident.span = ident.span.normalize_to_macros_2_0();
-        let mut search_module = self.parent_scope.module;
-        loop {
-            self.r.get_traits_in_module_containing_item(
-                ident,
-                ns,
-                search_module,
-                &mut found_traits,
-                &self.parent_scope,
-            );
-            search_module =
-                unwrap_or!(self.r.hygienic_lexical_parent(search_module, &mut ident.span), break);
-        }
-
-        if let Some(prelude) = self.r.prelude {
-            if !search_module.no_implicit_prelude {
-                self.r.get_traits_in_module_containing_item(
-                    ident,
-                    ns,
-                    prelude,
-                    &mut found_traits,
-                    &self.parent_scope,
-                );
-            }
-        }
-
-        found_traits
+    fn traits_in_scope(&mut self, ident: Ident, ns: Namespace) -> Vec<TraitCandidate> {
+        self.r.traits_in_scope(
+            self.current_trait_ref.as_ref().map(|(module, _)| *module),
+            &self.parent_scope,
+            ident.span.ctxt(),
+            Some((ident.name, ns)),
+        )
     }
 }
 
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 7d8f112..3945afb 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -180,7 +180,7 @@
             (
                 format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str),
                 if path_str == "async" && expected.starts_with("struct") {
-                    "`async` blocks are only allowed in the 2018 edition".to_string()
+                    "`async` blocks are only allowed in Rust 2018 or later".to_string()
                 } else {
                     format!("not found in {}", mod_str)
                 },
@@ -264,7 +264,7 @@
                 // The current function has a `self' parameter, but we were unable to resolve
                 // a reference to `self`. This can only happen if the `self` identifier we
                 // are resolving came from a different hygiene context.
-                if fn_kind.decl().inputs.get(0).map(|p| p.is_self()).unwrap_or(false) {
+                if fn_kind.decl().inputs.get(0).map_or(false, |p| p.is_self()) {
                     err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters");
                 } else {
                     let doesnt = if is_assoc_fn {
@@ -904,7 +904,7 @@
                     Applicability::MaybeIncorrect,
                 );
                 if path_str == "try" && span.rust_2015() {
-                    err.note("if you want the `try` keyword, you need to be in the 2018 edition");
+                    err.note("if you want the `try` keyword, you need Rust 2018 or later");
                 }
             }
             (Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => {
@@ -1452,8 +1452,7 @@
             }
         } else {
             let needs_placeholder = |def_id: DefId, kind: CtorKind| {
-                let has_no_fields =
-                    self.r.field_names.get(&def_id).map(|f| f.is_empty()).unwrap_or(false);
+                let has_no_fields = self.r.field_names.get(&def_id).map_or(false, |f| f.is_empty());
                 match kind {
                     CtorKind::Const => false,
                     CtorKind::Fn | CtorKind::Fictive if has_no_fields => false,
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index d5ba6f3..1be06a4 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -11,7 +11,8 @@
 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, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefIdMap, LOCAL_CRATE};
+use rustc_hir::hir_id::ItemLocalId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath};
 use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet, LifetimeParamKind};
@@ -20,6 +21,7 @@
 use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
+use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
 use std::borrow::Cow;
@@ -284,7 +286,7 @@
         resolve_lifetimes,
 
         named_region_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id),
-        is_late_bound_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&id),
+        is_late_bound_map,
         object_lifetime_defaults_map: |tcx, id| {
             tcx.resolve_lifetimes(LOCAL_CRATE).object_lifetime_defaults.get(&id)
         },
@@ -320,6 +322,32 @@
     rl
 }
 
+fn is_late_bound_map<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+) -> Option<(LocalDefId, &'tcx FxHashSet<ItemLocalId>)> {
+    match tcx.def_kind(def_id) {
+        DefKind::AnonConst => {
+            let mut def_id = tcx
+                .parent(def_id.to_def_id())
+                .unwrap_or_else(|| bug!("anon const or closure without a parent"));
+            // We search for the next outer anon const or fn here
+            // while skipping closures.
+            //
+            // Note that for `AnonConst` we still just recurse until we
+            // find a function body, but who cares :shrug:
+            while tcx.is_closure(def_id) {
+                def_id = tcx
+                    .parent(def_id)
+                    .unwrap_or_else(|| bug!("anon const or closure without a parent"));
+            }
+
+            tcx.is_late_bound_map(def_id.expect_local())
+        }
+        _ => tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&def_id).map(|lt| (def_id, lt)),
+    }
+}
+
 fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap {
     let krate = tcx.hir().krate();
     let mut map = NamedRegionMap {
@@ -409,11 +437,11 @@
             | hir::ItemKind::Union(_, ref generics)
             | hir::ItemKind::Trait(_, _, ref generics, ..)
             | hir::ItemKind::TraitAlias(ref generics, ..)
-            | hir::ItemKind::Impl { ref generics, .. } => {
+            | hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => {
                 self.missing_named_lifetime_spots.push(generics.into());
 
                 // Impls permit `'_` to be used and it is equivalent to "some fresh lifetime name".
-                // This is not true for other kinds of items.x
+                // This is not true for other kinds of items.
                 let track_lifetime_uses = matches!(item.kind, hir::ItemKind::Impl { .. });
                 // These kinds of items have only early-bound lifetime parameters.
                 let mut index = if sub_items_have_self_param(&item.kind) {
@@ -644,17 +672,17 @@
                             } else {
                                 bug!();
                             };
-                            if let hir::ParamName::Plain(param_name) = name {
-                                if param_name.name == kw::UnderscoreLifetime {
-                                    // Pick the elided lifetime "definition" if one exists
-                                    // and use it to make an elision scope.
-                                    self.lifetime_uses.insert(def_id, LifetimeUseSet::Many);
-                                    elision = Some(reg);
-                                } else {
-                                    lifetimes.insert(name, reg);
-                                }
+                            // We cannot predict what lifetimes are unused in opaque type.
+                            self.lifetime_uses.insert(def_id, LifetimeUseSet::Many);
+                            if let hir::ParamName::Plain(Ident {
+                                name: kw::UnderscoreLifetime,
+                                ..
+                            }) = name
+                            {
+                                // Pick the elided lifetime "definition" if one exists
+                                // and use it to make an elision scope.
+                                elision = Some(reg);
                             } else {
-                                self.lifetime_uses.insert(def_id, LifetimeUseSet::Many);
                                 lifetimes.insert(name, reg);
                             }
                         }
@@ -1433,7 +1461,7 @@
                     hir::TyKind::Path(ref qpath) => {
                         if let QPath::Resolved(_, path) = qpath {
                             let last_segment = &path.segments[path.segments.len() - 1];
-                            let generics = last_segment.generic_args();
+                            let generics = last_segment.args();
                             for arg in generics.args.iter() {
                                 if let GenericArg::Lifetime(lt) = arg {
                                     if lt.name.ident() == name {
@@ -1677,7 +1705,7 @@
             }
             match parent.kind {
                 hir::ItemKind::Trait(_, _, ref generics, ..)
-                | hir::ItemKind::Impl { ref generics, .. } => {
+                | hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => {
                     index += generics.params.len() as u32;
                 }
                 _ => {}
@@ -2102,7 +2130,7 @@
             }
 
             Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body), .. }) => {
-                if let hir::ItemKind::Impl { ref self_ty, ref items, .. } =
+                if let hir::ItemKind::Impl(hir::Impl { ref self_ty, ref items, .. }) =
                     self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
                 {
                     impl_self = Some(self_ty);
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index ca30d90..af53416 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -33,7 +33,7 @@
 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_expand::base::{SyntaxExtension, SyntaxExtensionKind};
 use rustc_hir::def::Namespace::*;
 use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX};
@@ -44,12 +44,13 @@
 use rustc_metadata::creader::{CStore, CrateLoader};
 use rustc_middle::hir::exports::ExportMap;
 use rustc_middle::middle::cstore::{CrateStore, MetadataLoaderDyn};
+use rustc_middle::span_bug;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, DefIdTree, ResolverOutputs};
-use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
 use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::Session;
+use rustc_span::edition::Edition;
 use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -64,7 +65,7 @@
 use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding};
 use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
 use imports::{Import, ImportKind, ImportResolver, NameResolution};
-use late::{HasGenericParams, PathSource, Rib, RibKind::*};
+use late::{ConstantItemKind, HasGenericParams, PathSource, Rib, RibKind::*};
 use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
 
 type Res = def::Res<NodeId>;
@@ -210,11 +211,15 @@
     /// Error E0434: can't capture dynamic environment in a fn item.
     CannotCaptureDynamicEnvironmentInFnItem,
     /// Error E0435: attempt to use a non-constant value in a constant.
-    AttemptToUseNonConstantValueInConstant,
+    AttemptToUseNonConstantValueInConstant(
+        Ident,
+        /* suggestion */ &'static str,
+        /* current */ &'static str,
+    ),
     /// Error E0530: `X` bindings cannot shadow `Y`s.
     BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>),
     /// Error E0128: type parameters with a default cannot use forward-declared identifiers.
-    ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
+    ForwardDeclaredTyParam, // FIXME(const_generics_defaults)
     /// ERROR E0770: the type of const parameters must not depend on other generic parameters.
     ParamInTyOfConstParam(Symbol),
     /// constant values inside of type parameter defaults must not depend on generic parameters.
@@ -422,7 +427,9 @@
     ///
     /// This could be:
     ///
-    /// * A normal module ‒ either `mod from_file;` or `mod from_block { }`.
+    /// * A normal module – either `mod from_file;` or `mod from_block { }` –
+    ///   or the crate root (which is conceptually a top-level module).
+    ///   Note that the crate root's [name][Self::name] will be [`kw::Empty`].
     /// * A trait or an enum (it implicitly contains associated types, methods and variant
     ///   constructors).
     Def(DefKind, DefId, Symbol),
@@ -456,28 +463,42 @@
 type Resolutions<'a> = RefCell<FxIndexMap<BindingKey, &'a RefCell<NameResolution<'a>>>>;
 
 /// One node in the tree of modules.
+///
+/// Note that a "module" in resolve is broader than a `mod` that you declare in Rust code. It may be one of these:
+///
+/// * `mod`
+/// * crate root (aka, top-level anonymous module)
+/// * `enum`
+/// * `trait`
+/// * curly-braced block with statements
+///
+/// You can use [`ModuleData::kind`] to determine the kind of module this is.
 pub struct ModuleData<'a> {
+    /// The direct parent module (it may not be a `mod`, however).
     parent: Option<Module<'a>>,
+    /// What kind of module this is, because this may not be a `mod`.
     kind: ModuleKind,
 
-    // The def id of the closest normal module (`mod`) ancestor (including this module).
-    normal_ancestor_id: DefId,
+    /// The [`DefId`] of the nearest `mod` item ancestor (which may be this module).
+    /// This may be the crate root.
+    nearest_parent_mod: DefId,
 
-    // Mapping between names and their (possibly in-progress) resolutions in this module.
-    // Resolutions in modules from other crates are not populated until accessed.
+    /// Mapping between names and their (possibly in-progress) resolutions in this module.
+    /// Resolutions in modules from other crates are not populated until accessed.
     lazy_resolutions: Resolutions<'a>,
-    // True if this is a module from other crate that needs to be populated on access.
+    /// True if this is a module from other crate that needs to be populated on access.
     populate_on_access: Cell<bool>,
 
-    // Macro invocations that can expand into items in this module.
+    /// Macro invocations that can expand into items in this module.
     unexpanded_invocations: RefCell<FxHashSet<ExpnId>>,
 
+    /// Whether `#[no_implicit_prelude]` is active.
     no_implicit_prelude: bool,
 
     glob_importers: RefCell<Vec<&'a Import<'a>>>,
     globs: RefCell<Vec<&'a Import<'a>>>,
 
-    // Used to memoize the traits in this module for faster searches through all traits in scope.
+    /// Used to memoize the traits in this module for faster searches through all traits in scope.
     traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>,
 
     /// Span of the module itself. Used for error reporting.
@@ -492,16 +513,16 @@
     fn new(
         parent: Option<Module<'a>>,
         kind: ModuleKind,
-        normal_ancestor_id: DefId,
+        nearest_parent_mod: DefId,
         expansion: ExpnId,
         span: Span,
     ) -> Self {
         ModuleData {
             parent,
             kind,
-            normal_ancestor_id,
+            nearest_parent_mod,
             lazy_resolutions: Default::default(),
-            populate_on_access: Cell::new(!normal_ancestor_id.is_local()),
+            populate_on_access: Cell::new(!nearest_parent_mod.is_local()),
             unexpanded_invocations: Default::default(),
             no_implicit_prelude: false,
             glob_importers: RefCell::new(Vec::new()),
@@ -743,10 +764,13 @@
     }
 
     fn is_variant(&self) -> bool {
-        matches!(self.kind, NameBindingKind::Res(
+        matches!(
+            self.kind,
+            NameBindingKind::Res(
                 Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..), _),
                 _,
-            ))
+            )
+        )
     }
 
     fn is_extern_crate(&self) -> bool {
@@ -850,7 +874,7 @@
 
 /// Used for better errors for E0773
 enum BuiltinMacroState {
-    NotYetSeen(SyntaxExtension),
+    NotYetSeen(SyntaxExtensionKind),
     AlreadySeen(Span),
 }
 
@@ -1028,7 +1052,7 @@
 impl<'a> ResolverArenas<'a> {
     fn alloc_module(&'a self, module: ModuleData<'a>) -> Module<'a> {
         let module = self.modules.alloc(module);
-        if module.def_id().map(|def_id| def_id.is_local()).unwrap_or(true) {
+        if module.def_id().map_or(true, |def_id| def_id.is_local()) {
             self.local_modules.borrow_mut().push(module);
         }
         module
@@ -1427,7 +1451,7 @@
     }
 
     fn is_builtin_macro(&mut self, res: Res) -> bool {
-        self.get_macro(res).map_or(false, |ext| ext.is_builtin)
+        self.get_macro(res).map_or(false, |ext| ext.builtin_name.is_some())
     }
 
     fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
@@ -1453,52 +1477,79 @@
         self.crate_loader.postprocess(krate);
     }
 
-    fn get_traits_in_module_containing_item(
+    pub fn traits_in_scope(
         &mut self,
-        ident: Ident,
-        ns: Namespace,
-        module: Module<'a>,
-        found_traits: &mut Vec<TraitCandidate>,
+        current_trait: Option<Module<'a>>,
         parent_scope: &ParentScope<'a>,
+        ctxt: SyntaxContext,
+        assoc_item: Option<(Symbol, Namespace)>,
+    ) -> Vec<TraitCandidate> {
+        let mut found_traits = Vec::new();
+
+        if let Some(module) = current_trait {
+            if self.trait_may_have_item(Some(module), assoc_item) {
+                let def_id = module.def_id().unwrap();
+                found_traits.push(TraitCandidate { def_id, import_ids: smallvec![] });
+            }
+        }
+
+        self.visit_scopes(ScopeSet::All(TypeNS, false), parent_scope, ctxt, |this, scope, _, _| {
+            match scope {
+                Scope::Module(module) => {
+                    this.traits_in_module(module, assoc_item, &mut found_traits);
+                }
+                Scope::StdLibPrelude => {
+                    if let Some(module) = this.prelude {
+                        this.traits_in_module(module, assoc_item, &mut found_traits);
+                    }
+                }
+                Scope::ExternPrelude | Scope::ToolPrelude | Scope::BuiltinTypes => {}
+                _ => unreachable!(),
+            }
+            None::<()>
+        });
+
+        found_traits
+    }
+
+    fn traits_in_module(
+        &mut self,
+        module: Module<'a>,
+        assoc_item: Option<(Symbol, Namespace)>,
+        found_traits: &mut Vec<TraitCandidate>,
     ) {
-        assert!(ns == TypeNS || ns == ValueNS);
         module.ensure_traits(self);
         let traits = module.traits.borrow();
-
-        for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
-            // Traits have pseudo-modules that can be used to search for the given ident.
-            if let Some(module) = binding.module() {
-                let mut ident = ident;
-                if ident.span.glob_adjust(module.expansion, binding.span).is_none() {
-                    continue;
-                }
-                if self
-                    .resolve_ident_in_module_unadjusted(
-                        ModuleOrUniformRoot::Module(module),
-                        ident,
-                        ns,
-                        parent_scope,
-                        false,
-                        module.span,
-                    )
-                    .is_ok()
-                {
-                    let import_ids = self.find_transitive_imports(&binding.kind, trait_name);
-                    let trait_def_id = module.def_id().unwrap();
-                    found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids });
-                }
-            } else if let Res::Def(DefKind::TraitAlias, _) = binding.res() {
-                // For now, just treat all trait aliases as possible candidates, since we don't
-                // know if the ident is somewhere in the transitive bounds.
-                let import_ids = self.find_transitive_imports(&binding.kind, trait_name);
-                let trait_def_id = binding.res().def_id();
-                found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids });
-            } else {
-                bug!("candidate is not trait or trait alias?")
+        for (trait_name, trait_binding) in traits.as_ref().unwrap().iter() {
+            if self.trait_may_have_item(trait_binding.module(), assoc_item) {
+                let def_id = trait_binding.res().def_id();
+                let import_ids = self.find_transitive_imports(&trait_binding.kind, *trait_name);
+                found_traits.push(TraitCandidate { def_id, import_ids });
             }
         }
     }
 
+    // List of traits in scope is pruned on best effort basis. We reject traits not having an
+    // associated item with the given name and namespace (if specified). This is a conservative
+    // optimization, proper hygienic type-based resolution of associated items is done in typeck.
+    // We don't reject trait aliases (`trait_module == None`) because we don't have access to their
+    // associated items.
+    fn trait_may_have_item(
+        &mut self,
+        trait_module: Option<Module<'a>>,
+        assoc_item: Option<(Symbol, Namespace)>,
+    ) -> bool {
+        match (trait_module, assoc_item) {
+            (Some(trait_module), Some((name, ns))) => {
+                self.resolutions(trait_module).borrow().iter().any(|resolution| {
+                    let (&BindingKey { ident: assoc_ident, ns: assoc_ns, .. }, _) = resolution;
+                    assoc_ns == ns && assoc_ident.name == name
+                })
+            }
+            _ => true,
+        }
+    }
+
     fn find_transitive_imports(
         &mut self,
         mut kind: &NameBindingKind<'_>,
@@ -1519,11 +1570,11 @@
         &self,
         parent: Module<'a>,
         kind: ModuleKind,
-        normal_ancestor_id: DefId,
+        nearest_parent_mod: DefId,
         expn_id: ExpnId,
         span: Span,
     ) -> Module<'a> {
-        let module = ModuleData::new(Some(parent), kind, normal_ancestor_id, expn_id, span);
+        let module = ModuleData::new(Some(parent), kind, nearest_parent_mod, expn_id, span);
         self.arenas.alloc_module(module)
     }
 
@@ -1610,8 +1661,13 @@
         &mut self,
         scope_set: ScopeSet,
         parent_scope: &ParentScope<'a>,
-        ident: Ident,
-        mut visitor: impl FnMut(&mut Self, Scope<'a>, /*use_prelude*/ bool, Ident) -> Option<T>,
+        ctxt: SyntaxContext,
+        mut visitor: impl FnMut(
+            &mut Self,
+            Scope<'a>,
+            /*use_prelude*/ bool,
+            SyntaxContext,
+        ) -> Option<T>,
     ) -> Option<T> {
         // General principles:
         // 1. Not controlled (user-defined) names should have higher priority than controlled names
@@ -1654,7 +1710,7 @@
         // 4c. Standard library prelude (de-facto closed, controlled).
         // 6. Language prelude: builtin attributes (closed, controlled).
 
-        let rust_2015 = ident.span.rust_2015();
+        let rust_2015 = ctxt.edition() == Edition::Edition2015;
         let (ns, macro_kind, is_absolute_path) = match scope_set {
             ScopeSet::All(ns, _) => (ns, None, false),
             ScopeSet::AbsolutePath(ns) => (ns, None, true),
@@ -1667,7 +1723,7 @@
             TypeNS | ValueNS => Scope::Module(module),
             MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
         };
-        let mut ident = ident.normalize_to_macros_2_0();
+        let mut ctxt = ctxt.normalize_to_macros_2_0();
         let mut use_prelude = !module.no_implicit_prelude;
 
         loop {
@@ -1703,7 +1759,7 @@
             };
 
             if visit {
-                if let break_result @ Some(..) = visitor(self, scope, use_prelude, ident) {
+                if let break_result @ Some(..) = visitor(self, scope, use_prelude, ctxt) {
                     return break_result;
                 }
             }
@@ -1733,17 +1789,17 @@
                 },
                 Scope::CrateRoot => match ns {
                     TypeNS => {
-                        ident.span.adjust(ExpnId::root());
+                        ctxt.adjust(ExpnId::root());
                         Scope::ExternPrelude
                     }
                     ValueNS | MacroNS => break,
                 },
                 Scope::Module(module) => {
                     use_prelude = !module.no_implicit_prelude;
-                    match self.hygienic_lexical_parent(module, &mut ident.span) {
+                    match self.hygienic_lexical_parent(module, &mut ctxt) {
                         Some(parent_module) => Scope::Module(parent_module),
                         None => {
-                            ident.span.adjust(ExpnId::root());
+                            ctxt.adjust(ExpnId::root());
                             match ns {
                                 TypeNS => Scope::ExternPrelude,
                                 ValueNS => Scope::StdLibPrelude,
@@ -1821,14 +1877,16 @@
             // Use the rib kind to determine whether we are resolving parameters
             // (macro 2.0 hygiene) or local variables (`macro_rules` hygiene).
             let rib_ident = if ribs[i].kind.contains_params() { normalized_ident } else { ident };
-            if let Some(res) = ribs[i].bindings.get(&rib_ident).cloned() {
+            if let Some((original_rib_ident_def, res)) = ribs[i].bindings.get_key_value(&rib_ident)
+            {
                 // The ident resolves to a type parameter or local variable.
                 return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs(
                     i,
                     rib_ident,
-                    res,
+                    *res,
                     record_used,
                     path_span,
+                    *original_rib_ident_def,
                     ribs,
                 )));
             }
@@ -1866,16 +1924,18 @@
         ident = normalized_ident;
         let mut poisoned = None;
         loop {
+            let mut span_data = ident.span.data();
             let opt_module = if let Some(node_id) = record_used_id {
                 self.hygienic_lexical_parent_with_compatibility_fallback(
                     module,
-                    &mut ident.span,
+                    &mut span_data.ctxt,
                     node_id,
                     &mut poisoned,
                 )
             } else {
-                self.hygienic_lexical_parent(module, &mut ident.span)
+                self.hygienic_lexical_parent(module, &mut span_data.ctxt)
             };
+            ident.span = span_data.span();
             module = unwrap_or!(opt_module, break);
             let adjusted_parent_scope = &ParentScope { module, ..*parent_scope };
             let result = self.resolve_ident_in_module_unadjusted(
@@ -1949,10 +2009,10 @@
     fn hygienic_lexical_parent(
         &mut self,
         module: Module<'a>,
-        span: &mut Span,
+        ctxt: &mut SyntaxContext,
     ) -> Option<Module<'a>> {
-        if !module.expansion.outer_expn_is_descendant_of(span.ctxt()) {
-            return Some(self.macro_def_scope(span.remove_mark()));
+        if !module.expansion.outer_expn_is_descendant_of(*ctxt) {
+            return Some(self.macro_def_scope(ctxt.remove_mark()));
         }
 
         if let ModuleKind::Block(..) = module.kind {
@@ -1965,11 +2025,11 @@
     fn hygienic_lexical_parent_with_compatibility_fallback(
         &mut self,
         module: Module<'a>,
-        span: &mut Span,
+        ctxt: &mut SyntaxContext,
         node_id: NodeId,
         poisoned: &mut Option<NodeId>,
     ) -> Option<Module<'a>> {
-        if let module @ Some(..) = self.hygienic_lexical_parent(module, span) {
+        if let module @ Some(..) = self.hygienic_lexical_parent(module, ctxt) {
             return module;
         }
 
@@ -1992,9 +2052,9 @@
                 // The macro is a proc macro derive
                 if let Some(def_id) = module.expansion.expn_data().macro_def_id {
                     let ext = self.get_macro_by_def_id(def_id);
-                    if !ext.is_builtin
+                    if ext.builtin_name.is_none()
                         && ext.macro_kind() == MacroKind::Derive
-                        && parent.expansion.outer_expn_is_descendant_of(span.ctxt())
+                        && parent.expansion.outer_expn_is_descendant_of(*ctxt)
                     {
                         *poisoned = Some(node_id);
                         return module.parent;
@@ -2116,7 +2176,7 @@
                 return self.graph_root;
             }
         };
-        let module = self.get_module(DefId { index: CRATE_DEF_INDEX, ..module.normal_ancestor_id });
+        let module = self.get_module(DefId { index: CRATE_DEF_INDEX, ..module.nearest_parent_mod });
         debug!(
             "resolve_crate_root({:?}): got module {:?} ({:?}) (ident.span = {:?})",
             ident,
@@ -2128,10 +2188,10 @@
     }
 
     fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> {
-        let mut module = self.get_module(module.normal_ancestor_id);
+        let mut module = self.get_module(module.nearest_parent_mod);
         while module.span.ctxt().normalize_to_macros_2_0() != *ctxt {
             let parent = module.parent.unwrap_or_else(|| self.macro_def_scope(ctxt.remove_mark()));
-            module = self.get_module(parent.normal_ancestor_id);
+            module = self.get_module(parent.nearest_parent_mod);
         }
         module
     }
@@ -2540,6 +2600,7 @@
         mut res: Res,
         record_used: bool,
         span: Span,
+        original_rib_ident_def: Ident,
         all_ribs: &[Rib<'a>],
     ) -> Res {
         const CG_BUG_STR: &str = "min_const_generics resolve check didn't stop compilation";
@@ -2586,10 +2647,32 @@
                                 res_err = Some(CannotCaptureDynamicEnvironmentInFnItem);
                             }
                         }
-                        ConstantItemRibKind(_) => {
+                        ConstantItemRibKind(_, item) => {
                             // Still doesn't deal with upvars
                             if record_used {
-                                self.report_error(span, AttemptToUseNonConstantValueInConstant);
+                                let (span, resolution_error) =
+                                    if let Some((ident, constant_item_kind)) = item {
+                                        let kind_str = match constant_item_kind {
+                                            ConstantItemKind::Const => "const",
+                                            ConstantItemKind::Static => "static",
+                                        };
+                                        (
+                                            span,
+                                            AttemptToUseNonConstantValueInConstant(
+                                                ident, "let", kind_str,
+                                            ),
+                                        )
+                                    } else {
+                                        (
+                                            rib_ident.span,
+                                            AttemptToUseNonConstantValueInConstant(
+                                                original_rib_ident_def,
+                                                "const",
+                                                "let",
+                                            ),
+                                        )
+                                    };
+                                self.report_error(span, resolution_error);
                             }
                             return Res::Err;
                         }
@@ -2625,7 +2708,7 @@
                             in_ty_param_default = true;
                             continue;
                         }
-                        ConstantItemRibKind(trivial) => {
+                        ConstantItemRibKind(trivial, _) => {
                             let features = self.session.features_untracked();
                             // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
                             if !(trivial
@@ -2718,7 +2801,7 @@
                             in_ty_param_default = true;
                             continue;
                         }
-                        ConstantItemRibKind(trivial) => {
+                        ConstantItemRibKind(trivial, _) => {
                             let features = self.session.features_untracked();
                             // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
                             if !(trivial
@@ -2793,7 +2876,7 @@
     }
 
     fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
-        vis.is_accessible_from(module.normal_ancestor_id, self)
+        vis.is_accessible_from(module.nearest_parent_mod, self)
     }
 
     fn set_binding_parent_module(&mut self, binding: &'a NameBinding<'a>, module: Module<'a>) {
@@ -2817,7 +2900,7 @@
             self.binding_parent_modules.get(&PtrKey(modularized)),
         ) {
             (Some(macro_rules), Some(modularized)) => {
-                macro_rules.normal_ancestor_id == modularized.normal_ancestor_id
+                macro_rules.nearest_parent_mod == modularized.nearest_parent_mod
                     && modularized.is_ancestor_of(macro_rules)
             }
             _ => false,
@@ -2975,7 +3058,7 @@
         let duplicate = new_binding.res().opt_def_id() == old_binding.res().opt_def_id();
         let has_dummy_span = new_binding.span.is_dummy() || old_binding.span.is_dummy();
         let from_item =
-            self.extern_prelude.get(&ident).map(|entry| entry.introduced_by_item).unwrap_or(true);
+            self.extern_prelude.get(&ident).map_or(true, |entry| entry.introduced_by_item);
         // Only suggest removing an import if both bindings are to the same def, if both spans
         // aren't dummy spans. Further, if both bindings are imports, then the ident must have
         // been introduced by a item.
@@ -3171,34 +3254,6 @@
         })
     }
 
-    /// This is equivalent to `get_traits_in_module_containing_item`, but without filtering by the associated item.
-    ///
-    /// This is used by rustdoc for intra-doc links.
-    pub fn traits_in_scope(&mut self, module_id: DefId) -> Vec<TraitCandidate> {
-        let module = self.get_module(module_id);
-        module.ensure_traits(self);
-        let traits = module.traits.borrow();
-        let to_candidate =
-            |this: &mut Self, &(trait_name, binding): &(Ident, &NameBinding<'_>)| TraitCandidate {
-                def_id: binding.res().def_id(),
-                import_ids: this.find_transitive_imports(&binding.kind, trait_name),
-            };
-
-        let mut candidates: Vec<_> =
-            traits.as_ref().unwrap().iter().map(|x| to_candidate(self, x)).collect();
-
-        if let Some(prelude) = self.prelude {
-            if !module.no_implicit_prelude {
-                prelude.ensure_traits(self);
-                candidates.extend(
-                    prelude.traits.borrow().as_ref().unwrap().iter().map(|x| to_candidate(self, x)),
-                );
-            }
-        }
-
-        candidates
-    }
-
     /// Rustdoc uses this to resolve things in a recoverable way. `ResolutionError<'a>`
     /// isn't something that can be returned because it can't be made to live that long,
     /// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 5ad7c83..5d6120c 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -14,7 +14,8 @@
 use rustc_data_structures::ptr_key::PtrKey;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::struct_span_err;
-use rustc_expand::base::{Indeterminate, InvocationRes, ResolverExpand, SyntaxExtension};
+use rustc_expand::base::{Indeterminate, InvocationRes, ResolverExpand};
+use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
 use rustc_expand::compile_declarative_macro;
 use rustc_expand::expand::{AstFragment, Invocation, InvocationKind};
 use rustc_feature::is_builtin_attr_name;
@@ -176,10 +177,11 @@
         parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion);
     }
 
-    fn register_builtin_macro(&mut self, ident: Ident, ext: SyntaxExtension) {
-        if self.builtin_macros.insert(ident.name, BuiltinMacroState::NotYetSeen(ext)).is_some() {
+    fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind) {
+        if self.builtin_macros.insert(name, BuiltinMacroState::NotYetSeen(ext)).is_some() {
             self.session
-                .span_err(ident.span, &format!("built-in macro `{}` was already defined", ident));
+                .diagnostic()
+                .bug(&format!("built-in macro `{}` was already registered", name));
         }
     }
 
@@ -285,7 +287,7 @@
                                 helper_attrs.extend(
                                     ext.helper_attrs.iter().map(|name| Ident::new(*name, span)),
                                 );
-                                if ext.is_derive_copy {
+                                if ext.builtin_name == Some(sym::Copy) {
                                     self.containers_deriving_copy.insert(invoc_id);
                                 }
                                 ext
@@ -328,7 +330,7 @@
             if after_derive {
                 self.session.span_err(span, "macro attributes must be placed before `#[derive]`");
             }
-            let normal_module_def_id = self.macro_def_scope(invoc_id).normal_ancestor_id;
+            let normal_module_def_id = self.macro_def_scope(invoc_id).nearest_parent_mod;
             self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id);
         }
 
@@ -618,8 +620,9 @@
         let break_result = self.visit_scopes(
             scope_set,
             parent_scope,
-            orig_ident,
-            |this, scope, use_prelude, ident| {
+            orig_ident.span.ctxt(),
+            |this, scope, use_prelude, ctxt| {
+                let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt));
                 let ok = |res, span, arenas| {
                     Ok((
                         (res, ty::Visibility::Public, span, ExpnId::root()).to_name_binding(arenas),
@@ -754,7 +757,11 @@
                     }
                     Scope::BuiltinAttrs => {
                         if is_builtin_attr_name(ident.name) {
-                            ok(Res::NonMacroAttr(NonMacroAttrKind::Builtin), DUMMY_SP, this.arenas)
+                            ok(
+                                Res::NonMacroAttr(NonMacroAttrKind::Builtin(ident.name)),
+                                DUMMY_SP,
+                                this.arenas,
+                            )
                         } else {
                             Err(Determinacy::Determined)
                         }
@@ -807,13 +814,15 @@
                             // Found another solution, if the first one was "weak", report an error.
                             let (res, innermost_res) = (binding.res(), innermost_binding.res());
                             if res != innermost_res {
-                                let builtin = Res::NonMacroAttr(NonMacroAttrKind::Builtin);
+                                let is_builtin = |res| {
+                                    matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Builtin(..)))
+                                };
                                 let derive_helper_compat =
                                     Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat);
 
                                 let ambiguity_error_kind = if is_import {
                                     Some(AmbiguityKind::Import)
-                                } else if innermost_res == builtin || res == builtin {
+                                } else if is_builtin(innermost_res) || is_builtin(res) {
                                     Some(AmbiguityKind::BuiltinAttr)
                                 } else if innermost_res == derive_helper_compat
                                     || res == derive_helper_compat
@@ -1089,14 +1098,14 @@
             edition,
         );
 
-        if result.is_builtin {
+        if let Some(builtin_name) = result.builtin_name {
             // The macro was marked with `#[rustc_builtin_macro]`.
-            if let Some(builtin_macro) = self.builtin_macros.get_mut(&item.ident.name) {
+            if let Some(builtin_macro) = self.builtin_macros.get_mut(&builtin_name) {
                 // The macro is a built-in, replace its expander function
                 // while still taking everything else from the source code.
                 // If we already loaded this builtin macro, give a better error message than 'no such builtin macro'.
                 match mem::replace(builtin_macro, BuiltinMacroState::AlreadySeen(item.span)) {
-                    BuiltinMacroState::NotYetSeen(ext) => result.kind = ext.kind,
+                    BuiltinMacroState::NotYetSeen(ext) => result.kind = ext,
                     BuiltinMacroState::AlreadySeen(span) => {
                         struct_span_err!(
                             self.session,
diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs
index 40d60a8..2834e7b 100644
--- a/compiler/rustc_save_analysis/src/dump_visitor.rs
+++ b/compiler/rustc_save_analysis/src/dump_visitor.rs
@@ -582,7 +582,7 @@
                 }
                 ref v => {
                     let mut value = format!("{}::{}", enum_data.name, name);
-                    if let &hir::VariantData::Tuple(ref fields, _) = v {
+                    if let hir::VariantData::Tuple(fields, _) = v {
                         value.push('(');
                         value.push_str(
                             &fields
@@ -631,14 +631,7 @@
         self.dumper.dump_def(&access, enum_data);
     }
 
-    fn process_impl(
-        &mut self,
-        item: &'tcx hir::Item<'tcx>,
-        generics: &'tcx hir::Generics<'tcx>,
-        trait_ref: &'tcx Option<hir::TraitRef<'tcx>>,
-        typ: &'tcx hir::Ty<'tcx>,
-        impl_items: &'tcx [hir::ImplItemRef<'tcx>],
-    ) {
+    fn process_impl(&mut self, item: &'tcx hir::Item<'tcx>, impl_: &'tcx hir::Impl<'tcx>) {
         if let Some(impl_data) = self.save_ctxt.get_item_data(item) {
             if !self.span.filter_generated(item.span) {
                 if let super::Data::RelationData(rel, imp) = impl_data {
@@ -652,12 +645,12 @@
 
         let map = &self.tcx.hir();
         self.nest_typeck_results(map.local_def_id(item.hir_id), |v| {
-            v.visit_ty(&typ);
-            if let &Some(ref trait_ref) = trait_ref {
+            v.visit_ty(&impl_.self_ty);
+            if let Some(trait_ref) = &impl_.of_trait {
                 v.process_path(trait_ref.hir_ref_id, &hir::QPath::Resolved(None, &trait_ref.path));
             }
-            v.process_generic_params(generics, "", item.hir_id);
-            for impl_item in impl_items {
+            v.process_generic_params(&impl_.generics, "", item.hir_id);
+            for impl_item in impl_.items {
                 v.process_impl_item(
                     map.impl_item(impl_item.id),
                     map.local_def_id(item.hir_id).to_def_id(),
@@ -1082,7 +1075,7 @@
                     );
                 }
 
-                if let &Some(ref default_ty) = default_ty {
+                if let Some(default_ty) = default_ty {
                     self.visit_ty(default_ty)
                 }
             }
@@ -1287,9 +1280,7 @@
                 self.process_struct(item, def, ty_params)
             }
             hir::ItemKind::Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
-            hir::ItemKind::Impl { ref generics, ref of_trait, ref self_ty, ref items, .. } => {
-                self.process_impl(item, generics, of_trait, &self_ty, items)
-            }
+            hir::ItemKind::Impl(ref impl_) => self.process_impl(item, impl_),
             hir::ItemKind::Trait(_, _, ref generics, ref trait_refs, methods) => {
                 self.process_trait(item, generics, trait_refs, methods)
             }
@@ -1343,9 +1334,12 @@
                         self.visit_ty(ty);
                     }
                 }
-                hir::GenericParamKind::Const { ref ty } => {
+                hir::GenericParamKind::Const { ref ty, ref default } => {
                     self.process_bounds(param.bounds);
                     self.visit_ty(ty);
+                    if let Some(default) = default {
+                        self.visit_anon_const(default);
+                    }
                 }
             }
         }
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index 056c0b3..1291233 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -318,7 +318,7 @@
                     attributes: lower_attributes(item.attrs.to_vec(), self),
                 }))
             }
-            hir::ItemKind::Impl { ref of_trait, ref self_ty, ref items, .. } => {
+            hir::ItemKind::Impl(hir::Impl { ref of_trait, ref self_ty, ref items, .. }) => {
                 if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = self_ty.kind {
                     // Common case impl for a struct or something basic.
                     if generated_code(path.span) {
@@ -410,7 +410,7 @@
             match self.tcx.impl_of_method(def_id) {
                 Some(impl_id) => match self.tcx.hir().get_if_local(impl_id) {
                     Some(Node::Item(item)) => match item.kind {
-                        hir::ItemKind::Impl { ref self_ty, .. } => {
+                        hir::ItemKind::Impl(hir::Impl { ref self_ty, .. }) => {
                             let hir = self.tcx.hir();
 
                             let mut qualname = String::from("<");
@@ -670,7 +670,7 @@
     ) -> Option<Ref> {
         // Returns true if the path is function type sugar, e.g., `Fn(A) -> B`.
         fn fn_type(seg: &hir::PathSegment<'_>) -> bool {
-            seg.args.map(|args| args.parenthesized).unwrap_or(false)
+            seg.args.map_or(false, |args| args.parenthesized)
         }
 
         let res = self.get_path_res(id);
diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs
index ff445d7..8ada7e3 100644
--- a/compiler/rustc_save_analysis/src/sig.rs
+++ b/compiler/rustc_save_analysis/src/sig.rs
@@ -501,7 +501,7 @@
 
                 Ok(sig)
             }
-            hir::ItemKind::Impl {
+            hir::ItemKind::Impl(hir::Impl {
                 unsafety,
                 polarity,
                 defaultness,
@@ -511,7 +511,7 @@
                 ref of_trait,
                 ref self_ty,
                 items: _,
-            } => {
+            }) => {
                 let mut text = String::new();
                 if let hir::Defaultness::Default { .. } = defaultness {
                     text.push_str("default ");
@@ -614,9 +614,12 @@
                 start: offset + text.len(),
                 end: offset + text.len() + param_text.as_str().len(),
             });
-            if let hir::GenericParamKind::Const { ref ty } = param.kind {
+            if let hir::GenericParamKind::Const { ref ty, ref default } = param.kind {
                 param_text.push_str(": ");
                 param_text.push_str(&ty_to_string(&ty));
+                if let Some(ref _default) = default {
+                    // FIXME(const_generics_defaults): push the `default` value here
+                }
             }
             if !param.bounds.is_empty() {
                 param_text.push_str(": ");
diff --git a/compiler/rustc_serialize/src/collection_impls.rs b/compiler/rustc_serialize/src/collection_impls.rs
index 3d274cb..ae6d27e 100644
--- a/compiler/rustc_serialize/src/collection_impls.rs
+++ b/compiler/rustc_serialize/src/collection_impls.rs
@@ -11,12 +11,8 @@
 
 impl<S: Encoder, A: Array<Item: Encodable<S>>> Encodable<S> for SmallVec<A> {
     fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_seq(self.len(), |s| {
-            for (i, e) in self.iter().enumerate() {
-                s.emit_seq_elt(i, |s| e.encode(s))?;
-            }
-            Ok(())
-        })
+        let slice: &[A::Item] = self;
+        slice.encode(s)
     }
 }
 
@@ -292,46 +288,28 @@
 
 impl<E: Encoder, T: Encodable<E>> Encodable<E> for Rc<[T]> {
     fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_seq(self.len(), |s| {
-            for (index, e) in self.iter().enumerate() {
-                s.emit_seq_elt(index, |s| e.encode(s))?;
-            }
-            Ok(())
-        })
+        let slice: &[T] = self;
+        slice.encode(s)
     }
 }
 
 impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<[T]> {
     fn decode(d: &mut D) -> Result<Rc<[T]>, D::Error> {
-        d.read_seq(|d, len| {
-            let mut vec = Vec::with_capacity(len);
-            for index in 0..len {
-                vec.push(d.read_seq_elt(index, |d| Decodable::decode(d))?);
-            }
-            Ok(vec.into())
-        })
+        let vec: Vec<T> = Decodable::decode(d)?;
+        Ok(vec.into())
     }
 }
 
 impl<E: Encoder, T: Encodable<E>> Encodable<E> for Arc<[T]> {
     fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_seq(self.len(), |s| {
-            for (index, e) in self.iter().enumerate() {
-                s.emit_seq_elt(index, |s| e.encode(s))?;
-            }
-            Ok(())
-        })
+        let slice: &[T] = self;
+        slice.encode(s)
     }
 }
 
 impl<D: Decoder, T: Decodable<D>> Decodable<D> for Arc<[T]> {
     fn decode(d: &mut D) -> Result<Arc<[T]>, D::Error> {
-        d.read_seq(|d, len| {
-            let mut vec = Vec::with_capacity(len);
-            for index in 0..len {
-                vec.push(d.read_seq_elt(index, |d| Decodable::decode(d))?);
-            }
-            Ok(vec.into())
-        })
+        let vec: Vec<T> = Decodable::decode(d)?;
+        Ok(vec.into())
     }
 }
diff --git a/compiler/rustc_serialize/src/leb128.rs b/compiler/rustc_serialize/src/leb128.rs
index 1fe6a30..ea2df80 100644
--- a/compiler/rustc_serialize/src/leb128.rs
+++ b/compiler/rustc_serialize/src/leb128.rs
@@ -1,16 +1,45 @@
+#![macro_use]
+
+macro_rules! max_leb128_len {
+    ($int_ty:ty) => {
+        // The longest LEB128 encoding for an integer uses 7 bits per byte.
+        (std::mem::size_of::<$int_ty>() * 8 + 6) / 7
+    };
+}
+
+// Returns the longest LEB128 encoding of all supported integer types.
+pub const fn max_leb128_len() -> usize {
+    max_leb128_len!(u128)
+}
+
 macro_rules! impl_write_unsigned_leb128 {
-    ($fn_name:ident, $int_ty:ident) => {
+    ($fn_name:ident, $int_ty:ty) => {
         #[inline]
-        pub fn $fn_name(out: &mut Vec<u8>, mut value: $int_ty) {
+        pub fn $fn_name(
+            out: &mut [::std::mem::MaybeUninit<u8>; max_leb128_len!($int_ty)],
+            mut value: $int_ty,
+        ) -> &[u8] {
+            let mut i = 0;
+
             loop {
                 if value < 0x80 {
-                    out.push(value as u8);
+                    unsafe {
+                        *out.get_unchecked_mut(i).as_mut_ptr() = value as u8;
+                    }
+
+                    i += 1;
                     break;
                 } else {
-                    out.push(((value & 0x7f) | 0x80) as u8);
+                    unsafe {
+                        *out.get_unchecked_mut(i).as_mut_ptr() = ((value & 0x7f) | 0x80) as u8;
+                    }
+
                     value >>= 7;
+                    i += 1;
                 }
             }
+
+            unsafe { ::std::mem::MaybeUninit::slice_assume_init_ref(&out.get_unchecked(..i)) }
         }
     };
 }
@@ -22,7 +51,7 @@
 impl_write_unsigned_leb128!(write_usize_leb128, usize);
 
 macro_rules! impl_read_unsigned_leb128 {
-    ($fn_name:ident, $int_ty:ident) => {
+    ($fn_name:ident, $int_ty:ty) => {
         #[inline]
         pub fn $fn_name(slice: &[u8]) -> ($int_ty, usize) {
             let mut result = 0;
@@ -49,62 +78,79 @@
 impl_read_unsigned_leb128!(read_u128_leb128, u128);
 impl_read_unsigned_leb128!(read_usize_leb128, usize);
 
-#[inline]
-/// encodes an integer using signed leb128 encoding and stores
-/// the result using a callback function.
-///
-/// The callback `write` is called once for each position
-/// that is to be written to with the byte to be encoded
-/// at that position.
-pub fn write_signed_leb128_to<W>(mut value: i128, mut write: W)
-where
-    W: FnMut(u8),
-{
-    loop {
-        let mut byte = (value as u8) & 0x7f;
-        value >>= 7;
-        let more =
-            !(((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && ((byte & 0x40) != 0)));
+macro_rules! impl_write_signed_leb128 {
+    ($fn_name:ident, $int_ty:ty) => {
+        #[inline]
+        pub fn $fn_name(
+            out: &mut [::std::mem::MaybeUninit<u8>; max_leb128_len!($int_ty)],
+            mut value: $int_ty,
+        ) -> &[u8] {
+            let mut i = 0;
 
-        if more {
-            byte |= 0x80; // Mark this byte to show that more bytes will follow.
+            loop {
+                let mut byte = (value as u8) & 0x7f;
+                value >>= 7;
+                let more = !(((value == 0) && ((byte & 0x40) == 0))
+                    || ((value == -1) && ((byte & 0x40) != 0)));
+
+                if more {
+                    byte |= 0x80; // Mark this byte to show that more bytes will follow.
+                }
+
+                unsafe {
+                    *out.get_unchecked_mut(i).as_mut_ptr() = byte;
+                }
+
+                i += 1;
+
+                if !more {
+                    break;
+                }
+            }
+
+            unsafe { ::std::mem::MaybeUninit::slice_assume_init_ref(&out.get_unchecked(..i)) }
         }
-
-        write(byte);
-
-        if !more {
-            break;
-        }
-    }
+    };
 }
 
-#[inline]
-pub fn write_signed_leb128(out: &mut Vec<u8>, value: i128) {
-    write_signed_leb128_to(value, |v| out.push(v))
-}
+impl_write_signed_leb128!(write_i16_leb128, i16);
+impl_write_signed_leb128!(write_i32_leb128, i32);
+impl_write_signed_leb128!(write_i64_leb128, i64);
+impl_write_signed_leb128!(write_i128_leb128, i128);
+impl_write_signed_leb128!(write_isize_leb128, isize);
 
-#[inline]
-pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i128, usize) {
-    let mut result = 0;
-    let mut shift = 0;
-    let mut position = start_position;
-    let mut byte;
+macro_rules! impl_read_signed_leb128 {
+    ($fn_name:ident, $int_ty:ty) => {
+        #[inline]
+        pub fn $fn_name(slice: &[u8]) -> ($int_ty, usize) {
+            let mut result = 0;
+            let mut shift = 0;
+            let mut position = 0;
+            let mut byte;
 
-    loop {
-        byte = data[position];
-        position += 1;
-        result |= i128::from(byte & 0x7F) << shift;
-        shift += 7;
+            loop {
+                byte = slice[position];
+                position += 1;
+                result |= <$int_ty>::from(byte & 0x7F) << shift;
+                shift += 7;
 
-        if (byte & 0x80) == 0 {
-            break;
+                if (byte & 0x80) == 0 {
+                    break;
+                }
+            }
+
+            if (shift < <$int_ty>::BITS) && ((byte & 0x40) != 0) {
+                // sign extend
+                result |= (!0 << shift);
+            }
+
+            (result, position)
         }
-    }
-
-    if (shift < 64) && ((byte & 0x40) != 0) {
-        // sign extend
-        result |= -(1 << shift);
-    }
-
-    (result, position - start_position)
+    };
 }
+
+impl_read_signed_leb128!(read_i16_leb128, i16);
+impl_read_signed_leb128!(read_i32_leb128, i32);
+impl_read_signed_leb128!(read_i64_leb128, i64);
+impl_read_signed_leb128!(read_i128_leb128, i128);
+impl_read_signed_leb128!(read_isize_leb128, isize);
diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs
index ac1cdc6..53c3adc 100644
--- a/compiler/rustc_serialize/src/lib.rs
+++ b/compiler/rustc_serialize/src/lib.rs
@@ -14,6 +14,12 @@
 #![feature(nll)]
 #![feature(associated_type_bounds)]
 #![cfg_attr(bootstrap, feature(min_const_generics))]
+#![feature(min_specialization)]
+#![feature(vec_spare_capacity)]
+#![feature(core_intrinsics)]
+#![feature(int_bits_const)]
+#![feature(maybe_uninit_slice)]
+#![feature(new_uninit)]
 #![cfg_attr(test, feature(test))]
 #![allow(rustc::internal)]
 
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 8b79c93..3e37fc8 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -1,6 +1,11 @@
-use crate::leb128::{self, read_signed_leb128, write_signed_leb128};
+use crate::leb128::{self, max_leb128_len};
 use crate::serialize;
 use std::borrow::Cow;
+use std::fs::File;
+use std::io::{self, Write};
+use std::mem::MaybeUninit;
+use std::path::Path;
+use std::ptr;
 
 // -----------------------------------------------------------------------------
 // Encoder
@@ -22,21 +27,34 @@
     }
 
     #[inline]
+    pub fn position(&self) -> usize {
+        self.data.len()
+    }
+
+    #[inline]
     pub fn emit_raw_bytes(&mut self, s: &[u8]) {
         self.data.extend_from_slice(s);
     }
 }
 
-macro_rules! write_uleb128 {
-    ($enc:expr, $value:expr, $fun:ident) => {{
-        leb128::$fun(&mut $enc.data, $value);
-        Ok(())
-    }};
-}
+macro_rules! write_leb128 {
+    ($enc:expr, $value:expr, $int_ty:ty, $fun:ident) => {{
+        const MAX_ENCODED_LEN: usize = max_leb128_len!($int_ty);
+        let old_len = $enc.data.len();
 
-macro_rules! write_sleb128 {
-    ($enc:expr, $value:expr) => {{
-        write_signed_leb128(&mut $enc.data, $value as i128);
+        if MAX_ENCODED_LEN > $enc.data.capacity() - old_len {
+            $enc.data.reserve(MAX_ENCODED_LEN);
+        }
+
+        // SAFETY: The above check and `reserve` ensures that there is enough
+        // room to write the encoded value to the vector's internal buffer.
+        unsafe {
+            let buf = &mut *($enc.data.as_mut_ptr().add(old_len)
+                as *mut [MaybeUninit<u8>; MAX_ENCODED_LEN]);
+            let encoded = leb128::$fun(buf, $value);
+            $enc.data.set_len(old_len + encoded.len());
+        }
+
         Ok(())
     }};
 }
@@ -51,27 +69,27 @@
 
     #[inline]
     fn emit_usize(&mut self, v: usize) -> EncodeResult {
-        write_uleb128!(self, v, write_usize_leb128)
+        write_leb128!(self, v, usize, write_usize_leb128)
     }
 
     #[inline]
     fn emit_u128(&mut self, v: u128) -> EncodeResult {
-        write_uleb128!(self, v, write_u128_leb128)
+        write_leb128!(self, v, u128, write_u128_leb128)
     }
 
     #[inline]
     fn emit_u64(&mut self, v: u64) -> EncodeResult {
-        write_uleb128!(self, v, write_u64_leb128)
+        write_leb128!(self, v, u64, write_u64_leb128)
     }
 
     #[inline]
     fn emit_u32(&mut self, v: u32) -> EncodeResult {
-        write_uleb128!(self, v, write_u32_leb128)
+        write_leb128!(self, v, u32, write_u32_leb128)
     }
 
     #[inline]
     fn emit_u16(&mut self, v: u16) -> EncodeResult {
-        write_uleb128!(self, v, write_u16_leb128)
+        write_leb128!(self, v, u16, write_u16_leb128)
     }
 
     #[inline]
@@ -82,27 +100,27 @@
 
     #[inline]
     fn emit_isize(&mut self, v: isize) -> EncodeResult {
-        write_sleb128!(self, v)
+        write_leb128!(self, v, isize, write_isize_leb128)
     }
 
     #[inline]
     fn emit_i128(&mut self, v: i128) -> EncodeResult {
-        write_sleb128!(self, v)
+        write_leb128!(self, v, i128, write_i128_leb128)
     }
 
     #[inline]
     fn emit_i64(&mut self, v: i64) -> EncodeResult {
-        write_sleb128!(self, v)
+        write_leb128!(self, v, i64, write_i64_leb128)
     }
 
     #[inline]
     fn emit_i32(&mut self, v: i32) -> EncodeResult {
-        write_sleb128!(self, v)
+        write_leb128!(self, v, i32, write_i32_leb128)
     }
 
     #[inline]
     fn emit_i16(&mut self, v: i16) -> EncodeResult {
-        write_sleb128!(self, v)
+        write_leb128!(self, v, i16, write_i16_leb128)
     }
 
     #[inline]
@@ -141,10 +159,354 @@
     }
 }
 
-impl Encoder {
+pub type FileEncodeResult = Result<(), io::Error>;
+
+// `FileEncoder` encodes data to file via fixed-size buffer.
+//
+// When encoding large amounts of data to a file, using `FileEncoder` may be
+// preferred over using `Encoder` to encode to a `Vec`, and then writing the
+// `Vec` to file, as the latter uses as much memory as there is encoded data,
+// while the former uses the fixed amount of memory allocated to the buffer.
+// `FileEncoder` also has the advantage of not needing to reallocate as data
+// is appended to it, but the disadvantage of requiring more error handling,
+// which has some runtime overhead.
+pub struct FileEncoder {
+    // The input buffer. For adequate performance, we need more control over
+    // buffering than `BufWriter` offers. If `BufWriter` ever offers a raw
+    // buffer access API, we can use it, and remove `buf` and `buffered`.
+    buf: Box<[MaybeUninit<u8>]>,
+    buffered: usize,
+    flushed: usize,
+    file: File,
+}
+
+impl FileEncoder {
+    pub fn new<P: AsRef<Path>>(path: P) -> io::Result<Self> {
+        const DEFAULT_BUF_SIZE: usize = 8192;
+        FileEncoder::with_capacity(path, DEFAULT_BUF_SIZE)
+    }
+
+    pub fn with_capacity<P: AsRef<Path>>(path: P, capacity: usize) -> io::Result<Self> {
+        // Require capacity at least as large as the largest LEB128 encoding
+        // here, so that we don't have to check or handle this on every write.
+        assert!(capacity >= max_leb128_len());
+
+        // Require capacity small enough such that some capacity checks can be
+        // done using guaranteed non-overflowing add rather than sub, which
+        // shaves an instruction off those code paths (on x86 at least).
+        assert!(capacity <= usize::MAX - max_leb128_len());
+
+        let file = File::create(path)?;
+
+        Ok(FileEncoder { buf: Box::new_uninit_slice(capacity), buffered: 0, flushed: 0, file })
+    }
+
     #[inline]
     pub fn position(&self) -> usize {
-        self.data.len()
+        // Tracking position this way instead of having a `self.position` field
+        // means that we don't have to update the position on every write call.
+        self.flushed + self.buffered
+    }
+
+    #[inline]
+    pub fn emit_raw_bytes(&mut self, s: &[u8]) -> FileEncodeResult {
+        self.write_all(s)
+    }
+
+    pub fn flush(&mut self) -> FileEncodeResult {
+        // This is basically a copy of `BufWriter::flush`. If `BufWriter` ever
+        // offers a raw buffer access API, we can use it, and remove this.
+
+        /// Helper struct to ensure the buffer is updated after all the writes
+        /// are complete. It tracks the number of written bytes and drains them
+        /// all from the front of the buffer when dropped.
+        struct BufGuard<'a> {
+            buffer: &'a mut [u8],
+            encoder_buffered: &'a mut usize,
+            encoder_flushed: &'a mut usize,
+            flushed: usize,
+        }
+
+        impl<'a> BufGuard<'a> {
+            fn new(
+                buffer: &'a mut [u8],
+                encoder_buffered: &'a mut usize,
+                encoder_flushed: &'a mut usize,
+            ) -> Self {
+                assert_eq!(buffer.len(), *encoder_buffered);
+                Self { buffer, encoder_buffered, encoder_flushed, flushed: 0 }
+            }
+
+            /// The unwritten part of the buffer
+            fn remaining(&self) -> &[u8] {
+                &self.buffer[self.flushed..]
+            }
+
+            /// Flag some bytes as removed from the front of the buffer
+            fn consume(&mut self, amt: usize) {
+                self.flushed += amt;
+            }
+
+            /// true if all of the bytes have been written
+            fn done(&self) -> bool {
+                self.flushed >= *self.encoder_buffered
+            }
+        }
+
+        impl Drop for BufGuard<'_> {
+            fn drop(&mut self) {
+                if self.flushed > 0 {
+                    if self.done() {
+                        *self.encoder_flushed += *self.encoder_buffered;
+                        *self.encoder_buffered = 0;
+                    } else {
+                        self.buffer.copy_within(self.flushed.., 0);
+                        *self.encoder_flushed += self.flushed;
+                        *self.encoder_buffered -= self.flushed;
+                    }
+                }
+            }
+        }
+
+        let mut guard = BufGuard::new(
+            unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[..self.buffered]) },
+            &mut self.buffered,
+            &mut self.flushed,
+        );
+
+        while !guard.done() {
+            match self.file.write(guard.remaining()) {
+                Ok(0) => {
+                    return Err(io::Error::new(
+                        io::ErrorKind::WriteZero,
+                        "failed to write the buffered data",
+                    ));
+                }
+                Ok(n) => guard.consume(n),
+                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
+                Err(e) => return Err(e),
+            }
+        }
+
+        Ok(())
+    }
+
+    #[inline]
+    fn capacity(&self) -> usize {
+        self.buf.len()
+    }
+
+    #[inline]
+    fn write_one(&mut self, value: u8) -> FileEncodeResult {
+        // We ensure this during `FileEncoder` construction.
+        debug_assert!(self.capacity() >= 1);
+
+        let mut buffered = self.buffered;
+
+        if std::intrinsics::unlikely(buffered >= self.capacity()) {
+            self.flush()?;
+            buffered = 0;
+        }
+
+        // SAFETY: The above check and `flush` ensures that there is enough
+        // room to write the input to the buffer.
+        unsafe {
+            *MaybeUninit::slice_as_mut_ptr(&mut self.buf).add(buffered) = value;
+        }
+
+        self.buffered = buffered + 1;
+
+        Ok(())
+    }
+
+    #[inline]
+    fn write_all(&mut self, buf: &[u8]) -> FileEncodeResult {
+        let capacity = self.capacity();
+        let buf_len = buf.len();
+
+        if std::intrinsics::likely(buf_len <= capacity) {
+            let mut buffered = self.buffered;
+
+            if std::intrinsics::unlikely(buf_len > capacity - buffered) {
+                self.flush()?;
+                buffered = 0;
+            }
+
+            // SAFETY: The above check and `flush` ensures that there is enough
+            // room to write the input to the buffer.
+            unsafe {
+                let src = buf.as_ptr();
+                let dst = MaybeUninit::slice_as_mut_ptr(&mut self.buf).add(buffered);
+                ptr::copy_nonoverlapping(src, dst, buf_len);
+            }
+
+            self.buffered = buffered + buf_len;
+
+            Ok(())
+        } else {
+            self.write_all_unbuffered(buf)
+        }
+    }
+
+    fn write_all_unbuffered(&mut self, mut buf: &[u8]) -> FileEncodeResult {
+        if self.buffered > 0 {
+            self.flush()?;
+        }
+
+        // This is basically a copy of `Write::write_all` but also updates our
+        // `self.flushed`. It's necessary because `Write::write_all` does not
+        // return the number of bytes written when an error is encountered, and
+        // without that, we cannot accurately update `self.flushed` on error.
+        while !buf.is_empty() {
+            match self.file.write(buf) {
+                Ok(0) => {
+                    return Err(io::Error::new(
+                        io::ErrorKind::WriteZero,
+                        "failed to write whole buffer",
+                    ));
+                }
+                Ok(n) => {
+                    buf = &buf[n..];
+                    self.flushed += n;
+                }
+                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
+                Err(e) => return Err(e),
+            }
+        }
+
+        Ok(())
+    }
+}
+
+impl Drop for FileEncoder {
+    fn drop(&mut self) {
+        let _result = self.flush();
+    }
+}
+
+macro_rules! file_encoder_write_leb128 {
+    ($enc:expr, $value:expr, $int_ty:ty, $fun:ident) => {{
+        const MAX_ENCODED_LEN: usize = max_leb128_len!($int_ty);
+
+        // We ensure this during `FileEncoder` construction.
+        debug_assert!($enc.capacity() >= MAX_ENCODED_LEN);
+
+        let mut buffered = $enc.buffered;
+
+        // This can't overflow. See assertion in `FileEncoder::with_capacity`.
+        if std::intrinsics::unlikely(buffered + MAX_ENCODED_LEN > $enc.capacity()) {
+            $enc.flush()?;
+            buffered = 0;
+        }
+
+        // SAFETY: The above check and flush ensures that there is enough
+        // room to write the encoded value to the buffer.
+        let buf = unsafe {
+            &mut *($enc.buf.as_mut_ptr().add(buffered) as *mut [MaybeUninit<u8>; MAX_ENCODED_LEN])
+        };
+
+        let encoded = leb128::$fun(buf, $value);
+        $enc.buffered = buffered + encoded.len();
+
+        Ok(())
+    }};
+}
+
+impl serialize::Encoder for FileEncoder {
+    type Error = io::Error;
+
+    #[inline]
+    fn emit_unit(&mut self) -> FileEncodeResult {
+        Ok(())
+    }
+
+    #[inline]
+    fn emit_usize(&mut self, v: usize) -> FileEncodeResult {
+        file_encoder_write_leb128!(self, v, usize, write_usize_leb128)
+    }
+
+    #[inline]
+    fn emit_u128(&mut self, v: u128) -> FileEncodeResult {
+        file_encoder_write_leb128!(self, v, u128, write_u128_leb128)
+    }
+
+    #[inline]
+    fn emit_u64(&mut self, v: u64) -> FileEncodeResult {
+        file_encoder_write_leb128!(self, v, u64, write_u64_leb128)
+    }
+
+    #[inline]
+    fn emit_u32(&mut self, v: u32) -> FileEncodeResult {
+        file_encoder_write_leb128!(self, v, u32, write_u32_leb128)
+    }
+
+    #[inline]
+    fn emit_u16(&mut self, v: u16) -> FileEncodeResult {
+        file_encoder_write_leb128!(self, v, u16, write_u16_leb128)
+    }
+
+    #[inline]
+    fn emit_u8(&mut self, v: u8) -> FileEncodeResult {
+        self.write_one(v)
+    }
+
+    #[inline]
+    fn emit_isize(&mut self, v: isize) -> FileEncodeResult {
+        file_encoder_write_leb128!(self, v, isize, write_isize_leb128)
+    }
+
+    #[inline]
+    fn emit_i128(&mut self, v: i128) -> FileEncodeResult {
+        file_encoder_write_leb128!(self, v, i128, write_i128_leb128)
+    }
+
+    #[inline]
+    fn emit_i64(&mut self, v: i64) -> FileEncodeResult {
+        file_encoder_write_leb128!(self, v, i64, write_i64_leb128)
+    }
+
+    #[inline]
+    fn emit_i32(&mut self, v: i32) -> FileEncodeResult {
+        file_encoder_write_leb128!(self, v, i32, write_i32_leb128)
+    }
+
+    #[inline]
+    fn emit_i16(&mut self, v: i16) -> FileEncodeResult {
+        file_encoder_write_leb128!(self, v, i16, write_i16_leb128)
+    }
+
+    #[inline]
+    fn emit_i8(&mut self, v: i8) -> FileEncodeResult {
+        let as_u8: u8 = unsafe { std::mem::transmute(v) };
+        self.emit_u8(as_u8)
+    }
+
+    #[inline]
+    fn emit_bool(&mut self, v: bool) -> FileEncodeResult {
+        self.emit_u8(if v { 1 } else { 0 })
+    }
+
+    #[inline]
+    fn emit_f64(&mut self, v: f64) -> FileEncodeResult {
+        let as_u64: u64 = v.to_bits();
+        self.emit_u64(as_u64)
+    }
+
+    #[inline]
+    fn emit_f32(&mut self, v: f32) -> FileEncodeResult {
+        let as_u32: u32 = v.to_bits();
+        self.emit_u32(as_u32)
+    }
+
+    #[inline]
+    fn emit_char(&mut self, v: char) -> FileEncodeResult {
+        self.emit_u32(v as u32)
+    }
+
+    #[inline]
+    fn emit_str(&mut self, v: &str) -> FileEncodeResult {
+        self.emit_usize(v.len())?;
+        self.emit_raw_bytes(v.as_bytes())
     }
 }
 
@@ -179,11 +541,19 @@
     }
 
     #[inline]
-    pub fn read_raw_bytes(&mut self, s: &mut [u8]) -> Result<(), String> {
+    pub fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), String> {
         let start = self.position;
         let end = start + s.len();
+        assert!(end <= self.data.len());
 
-        s.copy_from_slice(&self.data[start..end]);
+        // SAFETY: Both `src` and `dst` point to at least `s.len()` elements:
+        // `src` points to at least `s.len()` elements by above assert, and
+        // `dst` points to `s.len()` elements by derivation from `s`.
+        unsafe {
+            let src = self.data.as_ptr().add(start);
+            let dst = s.as_mut_ptr() as *mut u8;
+            ptr::copy_nonoverlapping(src, dst, s.len());
+        }
 
         self.position = end;
 
@@ -191,7 +561,7 @@
     }
 }
 
-macro_rules! read_uleb128 {
+macro_rules! read_leb128 {
     ($dec:expr, $fun:ident) => {{
         let (value, bytes_read) = leb128::$fun(&$dec.data[$dec.position..]);
         $dec.position += bytes_read;
@@ -199,14 +569,6 @@
     }};
 }
 
-macro_rules! read_sleb128 {
-    ($dec:expr, $t:ty) => {{
-        let (value, bytes_read) = read_signed_leb128($dec.data, $dec.position);
-        $dec.position += bytes_read;
-        Ok(value as $t)
-    }};
-}
-
 impl<'a> serialize::Decoder for Decoder<'a> {
     type Error = String;
 
@@ -217,22 +579,22 @@
 
     #[inline]
     fn read_u128(&mut self) -> Result<u128, Self::Error> {
-        read_uleb128!(self, read_u128_leb128)
+        read_leb128!(self, read_u128_leb128)
     }
 
     #[inline]
     fn read_u64(&mut self) -> Result<u64, Self::Error> {
-        read_uleb128!(self, read_u64_leb128)
+        read_leb128!(self, read_u64_leb128)
     }
 
     #[inline]
     fn read_u32(&mut self) -> Result<u32, Self::Error> {
-        read_uleb128!(self, read_u32_leb128)
+        read_leb128!(self, read_u32_leb128)
     }
 
     #[inline]
     fn read_u16(&mut self) -> Result<u16, Self::Error> {
-        read_uleb128!(self, read_u16_leb128)
+        read_leb128!(self, read_u16_leb128)
     }
 
     #[inline]
@@ -244,27 +606,27 @@
 
     #[inline]
     fn read_usize(&mut self) -> Result<usize, Self::Error> {
-        read_uleb128!(self, read_usize_leb128)
+        read_leb128!(self, read_usize_leb128)
     }
 
     #[inline]
     fn read_i128(&mut self) -> Result<i128, Self::Error> {
-        read_sleb128!(self, i128)
+        read_leb128!(self, read_i128_leb128)
     }
 
     #[inline]
     fn read_i64(&mut self) -> Result<i64, Self::Error> {
-        read_sleb128!(self, i64)
+        read_leb128!(self, read_i64_leb128)
     }
 
     #[inline]
     fn read_i32(&mut self) -> Result<i32, Self::Error> {
-        read_sleb128!(self, i32)
+        read_leb128!(self, read_i32_leb128)
     }
 
     #[inline]
     fn read_i16(&mut self) -> Result<i16, Self::Error> {
-        read_sleb128!(self, i16)
+        read_leb128!(self, read_i16_leb128)
     }
 
     #[inline]
@@ -276,7 +638,7 @@
 
     #[inline]
     fn read_isize(&mut self) -> Result<isize, Self::Error> {
-        read_sleb128!(self, isize)
+        read_leb128!(self, read_isize_leb128)
     }
 
     #[inline]
@@ -316,3 +678,43 @@
         err.to_string()
     }
 }
+
+// Specializations for contiguous byte sequences follow. The default implementations for slices
+// encode and decode each element individually. This isn't necessary for `u8` slices when using
+// opaque encoders and decoders, because each `u8` is unchanged by encoding and decoding.
+// Therefore, we can use more efficient implementations that process the entire sequence at once.
+
+// Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
+// since the default implementations call `encode` on their slices internally.
+impl serialize::Encodable<Encoder> for [u8] {
+    fn encode(&self, e: &mut Encoder) -> EncodeResult {
+        serialize::Encoder::emit_usize(e, self.len())?;
+        e.emit_raw_bytes(self);
+        Ok(())
+    }
+}
+
+impl serialize::Encodable<FileEncoder> for [u8] {
+    fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult {
+        serialize::Encoder::emit_usize(e, self.len())?;
+        e.emit_raw_bytes(self)
+    }
+}
+
+// Specialize decoding `Vec<u8>`. This specialization also applies to decoding `Box<[u8]>`s, etc.,
+// since the default implementations call `decode` to produce a `Vec<u8>` internally.
+impl<'a> serialize::Decodable<Decoder<'a>> for Vec<u8> {
+    fn decode(d: &mut Decoder<'a>) -> Result<Self, String> {
+        let len = serialize::Decoder::read_usize(d)?;
+
+        let mut v = Vec::with_capacity(len);
+        let buf = &mut v.spare_capacity_mut()[..len];
+        d.read_raw_bytes(buf)?;
+
+        unsafe {
+            v.set_len(len);
+        }
+
+        Ok(v)
+    }
+}
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index aa305f3..47aad5b 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -527,7 +527,7 @@
 }
 
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for [T] {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+    default fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?
@@ -545,7 +545,7 @@
 }
 
 impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> {
-    fn decode(d: &mut D) -> Result<Vec<T>, D::Error> {
+    default fn decode(d: &mut D) -> Result<Vec<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut v = Vec::with_capacity(len);
             for i in 0..len {
@@ -591,13 +591,8 @@
     [T]: ToOwned<Owned = Vec<T>>,
 {
     fn decode(d: &mut D) -> Result<Cow<'static, [T]>, D::Error> {
-        d.read_seq(|d, len| {
-            let mut v = Vec::with_capacity(len);
-            for i in 0..len {
-                v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?);
-            }
-            Ok(Cow::Owned(v))
-        })
+        let v: Vec<T> = Decodable::decode(d)?;
+        Ok(Cow::Owned(v))
     }
 }
 
diff --git a/compiler/rustc_serialize/tests/leb128.rs b/compiler/rustc_serialize/tests/leb128.rs
index b0f7e78..a2bcf2c 100644
--- a/compiler/rustc_serialize/tests/leb128.rs
+++ b/compiler/rustc_serialize/tests/leb128.rs
@@ -1,18 +1,36 @@
+#![feature(int_bits_const)]
+#![feature(maybe_uninit_slice)]
+#![feature(maybe_uninit_uninit_array)]
+
 use rustc_serialize::leb128::*;
+use std::mem::MaybeUninit;
 
 macro_rules! impl_test_unsigned_leb128 {
     ($test_name:ident, $write_fn_name:ident, $read_fn_name:ident, $int_ty:ident) => {
         #[test]
         fn $test_name() {
+            // Test 256 evenly spaced values of integer range,
+            // integer max value, and some "random" numbers.
+            let mut values = Vec::new();
+
+            let increment = (1 as $int_ty) << ($int_ty::BITS - 8);
+            values.extend((0..256).map(|i| $int_ty::MIN + i * increment));
+
+            values.push($int_ty::MAX);
+
+            values.extend(
+                (-500..500).map(|i| (i as $int_ty).wrapping_mul(0x12345789ABCDEFu64 as $int_ty)),
+            );
+
             let mut stream = Vec::new();
 
-            for x in 0..62 {
-                $write_fn_name(&mut stream, (3u64 << x) as $int_ty);
+            for &x in &values {
+                let mut buf = MaybeUninit::uninit_array();
+                stream.extend($write_fn_name(&mut buf, x));
             }
 
             let mut position = 0;
-            for x in 0..62 {
-                let expected = (3u64 << x) as $int_ty;
+            for &expected in &values {
                 let (actual, bytes_read) = $read_fn_name(&stream[position..]);
                 assert_eq!(expected, actual);
                 position += bytes_read;
@@ -28,18 +46,49 @@
 impl_test_unsigned_leb128!(test_u128_leb128, write_u128_leb128, read_u128_leb128, u128);
 impl_test_unsigned_leb128!(test_usize_leb128, write_usize_leb128, read_usize_leb128, usize);
 
-#[test]
-fn test_signed_leb128() {
-    let values: Vec<_> = (-500..500).map(|i| i * 0x12345789ABCDEF).collect();
-    let mut stream = Vec::new();
-    for &x in &values {
-        write_signed_leb128(&mut stream, x);
-    }
-    let mut pos = 0;
-    for &x in &values {
-        let (value, bytes_read) = read_signed_leb128(&mut stream, pos);
-        pos += bytes_read;
-        assert_eq!(x, value);
-    }
-    assert_eq!(pos, stream.len());
+macro_rules! impl_test_signed_leb128 {
+    ($test_name:ident, $write_fn_name:ident, $read_fn_name:ident, $int_ty:ident) => {
+        #[test]
+        fn $test_name() {
+            // Test 256 evenly spaced values of integer range,
+            // integer max value, and some "random" numbers.
+            let mut values = Vec::new();
+
+            let mut value = $int_ty::MIN;
+            let increment = (1 as $int_ty) << ($int_ty::BITS - 8);
+
+            for _ in 0..256 {
+                values.push(value);
+                // The addition in the last loop iteration overflows.
+                value = value.wrapping_add(increment);
+            }
+
+            values.push($int_ty::MAX);
+
+            values.extend(
+                (-500..500).map(|i| (i as $int_ty).wrapping_mul(0x12345789ABCDEFi64 as $int_ty)),
+            );
+
+            let mut stream = Vec::new();
+
+            for &x in &values {
+                let mut buf = MaybeUninit::uninit_array();
+                stream.extend($write_fn_name(&mut buf, x));
+            }
+
+            let mut position = 0;
+            for &expected in &values {
+                let (actual, bytes_read) = $read_fn_name(&stream[position..]);
+                assert_eq!(expected, actual);
+                position += bytes_read;
+            }
+            assert_eq!(stream.len(), position);
+        }
+    };
 }
+
+impl_test_signed_leb128!(test_i16_leb128, write_i16_leb128, read_i16_leb128, i16);
+impl_test_signed_leb128!(test_i32_leb128, write_i32_leb128, read_i32_leb128, i32);
+impl_test_signed_leb128!(test_i64_leb128, write_i64_leb128, read_i64_leb128, i64);
+impl_test_signed_leb128!(test_i128_leb128, write_i128_leb128, read_i128_leb128, i128);
+impl_test_signed_leb128!(test_isize_leb128, write_isize_leb128, read_isize_leb128, isize);
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index c9ddcbd..0cafdec 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -819,7 +819,7 @@
         }
     }
     ret.insert((sym::target_arch, Some(Symbol::intern(arch))));
-    ret.insert((sym::target_endian, Some(Symbol::intern(end))));
+    ret.insert((sym::target_endian, Some(Symbol::intern(end.as_str()))));
     ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz))));
     ret.insert((sym::target_env, Some(Symbol::intern(env))));
     ret.insert((sym::target_vendor, Some(Symbol::intern(vendor))));
@@ -1308,12 +1308,11 @@
         None => DEFAULT_EDITION,
     };
 
-    if !edition.is_stable() && !nightly_options::match_is_nightly_build(matches) {
+    if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) {
         early_error(
             ErrorOutputType::default(),
             &format!(
-                "edition {} is unstable and only \
-                     available for nightly builds of rustc.",
+                "edition {} is unstable and only available with -Z unstable-options.",
                 edition,
             ),
         )
@@ -1830,11 +1829,17 @@
         }
 
         if debugging_opts.mir_opt_level > 1 {
+            // Functions inlined during MIR transform can, at best, make it impossible to
+            // effectively cover inlined functions, and, at worst, break coverage map generation
+            // during LLVM codegen. For example, function counter IDs are only unique within a
+            // function. Inlining after these counters are injected can produce duplicate counters,
+            // resulting in an invalid coverage map (and ICE); so this option combination is not
+            // allowed.
             early_warn(
                 error_format,
                 &format!(
-                    "`-Z mir-opt-level={}` (any level > 1) enables function inlining, which \
-                    limits the effectiveness of `-Z instrument-coverage`.",
+                    "`-Z mir-opt-level={}` (or any level > 1) enables function inlining, which \
+                    is incompatible with `-Z instrument-coverage`. Inlining will be disabled.",
                     debugging_opts.mir_opt_level,
                 ),
             );
@@ -2167,6 +2172,7 @@
         SymbolManglingVersion, TrimmedDefPaths,
     };
     use crate::lint;
+    use crate::options::WasiExecModel;
     use crate::utils::NativeLibKind;
     use rustc_feature::UnstableFeatures;
     use rustc_span::edition::Edition;
@@ -2222,6 +2228,7 @@
     impl_dep_tracking_hash_via_hash!(Option<RelocModel>);
     impl_dep_tracking_hash_via_hash!(Option<CodeModel>);
     impl_dep_tracking_hash_via_hash!(Option<TlsModel>);
+    impl_dep_tracking_hash_via_hash!(Option<WasiExecModel>);
     impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
     impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);
     impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 81f79f4..30af65e 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -279,6 +279,7 @@
         pub const parse_tls_model: &str =
             "one of supported TLS models (`rustc --print tls-models`)";
         pub const parse_target_feature: &str = parse_string;
+        pub const parse_wasi_exec_model: &str = "either `command` or `reactor`";
     }
 
     #[allow(dead_code)]
@@ -722,6 +723,15 @@
                 None => false,
             }
         }
+
+        fn parse_wasi_exec_model(slot: &mut Option<WasiExecModel>, v: Option<&str>) -> bool {
+            match v {
+                Some("command")  => *slot = Some(WasiExecModel::Command),
+                Some("reactor") => *slot = Some(WasiExecModel::Reactor),
+                _ => return false,
+            }
+            true
+        }
     }
 ) }
 
@@ -1166,9 +1176,17 @@
         "in general, enable more debug printouts (default: no)"),
     verify_llvm_ir: bool = (false, parse_bool, [TRACKED],
         "verify LLVM IR (default: no)"),
+    wasi_exec_model: Option<WasiExecModel> = (None, parse_wasi_exec_model, [TRACKED],
+        "whether to build a wasi command or reactor"),
 
     // This list is in alphabetical order.
     //
     // If you add a new option, please update:
-    // - src/librustc_interface/tests.rs
+    // - compiler/rustc_interface/src/tests.rs
+}
+
+#[derive(Clone, Hash)]
+pub enum WasiExecModel {
+    Command,
+    Reactor,
 }
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 75faab1..6d01854 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -796,6 +796,14 @@
         self.opts.debugging_opts.tls_model.unwrap_or(self.target.tls_model)
     }
 
+    pub fn is_wasi_reactor(&self) -> bool {
+        self.target.options.os == "wasi"
+            && matches!(
+                self.opts.debugging_opts.wasi_exec_model,
+                Some(config::WasiExecModel::Reactor)
+            )
+    }
+
     pub fn must_not_eliminate_frame_pointers(&self) -> bool {
         // "mcount" function relies on stack pointer.
         // See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
@@ -1076,6 +1084,11 @@
         self.opts.edition >= Edition::Edition2018
     }
 
+    /// Are we allowed to use features from the Rust 2021 edition?
+    pub fn rust_2021(&self) -> bool {
+        self.opts.edition >= Edition::Edition2021
+    }
+
     pub fn edition(&self) -> Edition {
         self.opts.edition
     }
@@ -1345,7 +1358,7 @@
 
     let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
     let optimization_fuel = Lock::new(OptimizationFuel {
-        remaining: sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0),
+        remaining: sopts.debugging_opts.fuel.as_ref().map_or(0, |i| i.1),
         out_of_fuel: false,
     });
     let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
@@ -1517,6 +1530,7 @@
     }
 
     const ASAN_SUPPORTED_TARGETS: &[&str] = &[
+        "aarch64-apple-darwin",
         "aarch64-fuchsia",
         "aarch64-unknown-linux-gnu",
         "x86_64-apple-darwin",
@@ -1524,11 +1538,16 @@
         "x86_64-unknown-freebsd",
         "x86_64-unknown-linux-gnu",
     ];
-    const LSAN_SUPPORTED_TARGETS: &[&str] =
-        &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
+    const LSAN_SUPPORTED_TARGETS: &[&str] = &[
+        "aarch64-apple-darwin",
+        "aarch64-unknown-linux-gnu",
+        "x86_64-apple-darwin",
+        "x86_64-unknown-linux-gnu",
+    ];
     const MSAN_SUPPORTED_TARGETS: &[&str] =
         &["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
     const TSAN_SUPPORTED_TARGETS: &[&str] = &[
+        "aarch64-apple-darwin",
         "aarch64-unknown-linux-gnu",
         "x86_64-apple-darwin",
         "x86_64-unknown-freebsd",
diff --git a/compiler/rustc_span/src/analyze_source_file/tests.rs b/compiler/rustc_span/src/analyze_source_file/tests.rs
index cb418a4..66aefc9 100644
--- a/compiler/rustc_span/src/analyze_source_file/tests.rs
+++ b/compiler/rustc_span/src/analyze_source_file/tests.rs
@@ -12,7 +12,7 @@
             let (lines, multi_byte_chars, non_narrow_chars) =
                 analyze_source_file($text, BytePos($source_file_start_pos));
 
-            let expected_lines: Vec<BytePos> = $lines.into_iter().map(|pos| BytePos(pos)).collect();
+            let expected_lines: Vec<BytePos> = $lines.into_iter().map(BytePos).collect();
 
             assert_eq!(lines, expected_lines);
 
diff --git a/compiler/rustc_span/src/caching_source_map_view.rs b/compiler/rustc_span/src/caching_source_map_view.rs
index 15dd00f..8e21b9f 100644
--- a/compiler/rustc_span/src/caching_source_map_view.rs
+++ b/compiler/rustc_span/src/caching_source_map_view.rs
@@ -1,5 +1,5 @@
 use crate::source_map::SourceMap;
-use crate::{BytePos, SourceFile};
+use crate::{BytePos, SourceFile, SpanData};
 use rustc_data_structures::sync::Lrc;
 use std::ops::Range;
 
@@ -24,6 +24,32 @@
     file_index: usize,
 }
 
+impl CacheEntry {
+    #[inline]
+    fn update(
+        &mut self,
+        new_file_and_idx: Option<(Lrc<SourceFile>, usize)>,
+        pos: BytePos,
+        time_stamp: usize,
+    ) {
+        if let Some((file, file_idx)) = new_file_and_idx {
+            self.file = file;
+            self.file_index = file_idx;
+        }
+
+        let line_index = self.file.lookup_line(pos).unwrap();
+        let line_bounds = self.file.line_bounds(line_index);
+        self.line_number = line_index + 1;
+        self.line = line_bounds;
+        self.touch(time_stamp);
+    }
+
+    #[inline]
+    fn touch(&mut self, time_stamp: usize) {
+        self.time_stamp = time_stamp;
+    }
+}
+
 #[derive(Clone)]
 pub struct CachingSourceMapView<'sm> {
     source_map: &'sm SourceMap,
@@ -57,59 +83,202 @@
         self.time_stamp += 1;
 
         // Check if the position is in one of the cached lines
-        for cache_entry in self.line_cache.iter_mut() {
-            if cache_entry.line.contains(&pos) {
-                cache_entry.time_stamp = self.time_stamp;
+        let cache_idx = self.cache_entry_index(pos);
+        if cache_idx != -1 {
+            let cache_entry = &mut self.line_cache[cache_idx as usize];
+            cache_entry.touch(self.time_stamp);
 
-                return Some((
-                    cache_entry.file.clone(),
-                    cache_entry.line_number,
-                    pos - cache_entry.line.start,
-                ));
-            }
+            return Some((
+                cache_entry.file.clone(),
+                cache_entry.line_number,
+                pos - cache_entry.line.start,
+            ));
         }
 
         // No cache hit ...
-        let mut oldest = 0;
-        for index in 1..self.line_cache.len() {
-            if self.line_cache[index].time_stamp < self.line_cache[oldest].time_stamp {
-                oldest = index;
-            }
-        }
+        let oldest = self.oldest_cache_entry_index();
+
+        // If the entry doesn't point to the correct file, get the new file and index.
+        let new_file_and_idx = if !file_contains(&self.line_cache[oldest].file, pos) {
+            Some(self.file_for_position(pos)?)
+        } else {
+            None
+        };
 
         let cache_entry = &mut self.line_cache[oldest];
+        cache_entry.update(new_file_and_idx, pos, self.time_stamp);
 
-        // If the entry doesn't point to the correct file, fix it up
-        if !file_contains(&cache_entry.file, pos) {
-            let file_valid;
-            if self.source_map.files().len() > 0 {
-                let file_index = self.source_map.lookup_source_file_idx(pos);
-                let file = self.source_map.files()[file_index].clone();
+        Some((cache_entry.file.clone(), cache_entry.line_number, pos - cache_entry.line.start))
+    }
 
-                if file_contains(&file, pos) {
-                    cache_entry.file = file;
-                    cache_entry.file_index = file_index;
-                    file_valid = true;
-                } else {
-                    file_valid = false;
+    pub fn span_data_to_lines_and_cols(
+        &mut self,
+        span_data: &SpanData,
+    ) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)> {
+        self.time_stamp += 1;
+
+        // Check if lo and hi are in the cached lines.
+        let lo_cache_idx = self.cache_entry_index(span_data.lo);
+        let hi_cache_idx = self.cache_entry_index(span_data.hi);
+
+        if lo_cache_idx != -1 && hi_cache_idx != -1 {
+            // Cache hit for span lo and hi. Check if they belong to the same file.
+            let result = {
+                let lo = &self.line_cache[lo_cache_idx as usize];
+                let hi = &self.line_cache[hi_cache_idx as usize];
+
+                if lo.file_index != hi.file_index {
+                    return None;
                 }
-            } else {
-                file_valid = false;
+
+                (
+                    lo.file.clone(),
+                    lo.line_number,
+                    span_data.lo - lo.line.start,
+                    hi.line_number,
+                    span_data.hi - hi.line.start,
+                )
+            };
+
+            self.line_cache[lo_cache_idx as usize].touch(self.time_stamp);
+            self.line_cache[hi_cache_idx as usize].touch(self.time_stamp);
+
+            return Some(result);
+        }
+
+        // No cache hit or cache hit for only one of span lo and hi.
+        let oldest = if lo_cache_idx != -1 || hi_cache_idx != -1 {
+            let avoid_idx = if lo_cache_idx != -1 { lo_cache_idx } else { hi_cache_idx };
+            self.oldest_cache_entry_index_avoid(avoid_idx as usize)
+        } else {
+            self.oldest_cache_entry_index()
+        };
+
+        // If the entry doesn't point to the correct file, get the new file and index.
+        // Return early if the file containing beginning of span doesn't contain end of span.
+        let new_file_and_idx = if !file_contains(&self.line_cache[oldest].file, span_data.lo) {
+            let new_file_and_idx = self.file_for_position(span_data.lo)?;
+            if !file_contains(&new_file_and_idx.0, span_data.hi) {
+                return None;
             }
 
-            if !file_valid {
+            Some(new_file_and_idx)
+        } else {
+            let file = &self.line_cache[oldest].file;
+            if !file_contains(&file, span_data.hi) {
                 return None;
             }
+
+            None
+        };
+
+        // Update the cache entries.
+        let (lo_idx, hi_idx) = match (lo_cache_idx, hi_cache_idx) {
+            // Oldest cache entry is for span_data.lo line.
+            (-1, -1) => {
+                let lo = &mut self.line_cache[oldest];
+                lo.update(new_file_and_idx, span_data.lo, self.time_stamp);
+
+                if !lo.line.contains(&span_data.hi) {
+                    let new_file_and_idx = Some((lo.file.clone(), lo.file_index));
+                    let next_oldest = self.oldest_cache_entry_index_avoid(oldest);
+                    let hi = &mut self.line_cache[next_oldest];
+                    hi.update(new_file_and_idx, span_data.hi, self.time_stamp);
+                    (oldest, next_oldest)
+                } else {
+                    (oldest, oldest)
+                }
+            }
+            // Oldest cache entry is for span_data.lo line.
+            (-1, _) => {
+                let lo = &mut self.line_cache[oldest];
+                lo.update(new_file_and_idx, span_data.lo, self.time_stamp);
+                let hi = &mut self.line_cache[hi_cache_idx as usize];
+                hi.touch(self.time_stamp);
+                (oldest, hi_cache_idx as usize)
+            }
+            // Oldest cache entry is for span_data.hi line.
+            (_, -1) => {
+                let hi = &mut self.line_cache[oldest];
+                hi.update(new_file_and_idx, span_data.hi, self.time_stamp);
+                let lo = &mut self.line_cache[lo_cache_idx as usize];
+                lo.touch(self.time_stamp);
+                (lo_cache_idx as usize, oldest)
+            }
+            _ => {
+                panic!();
+            }
+        };
+
+        let lo = &self.line_cache[lo_idx];
+        let hi = &self.line_cache[hi_idx];
+
+        // Span lo and hi may equal line end when last line doesn't
+        // end in newline, hence the inclusive upper bounds below.
+        debug_assert!(span_data.lo >= lo.line.start);
+        debug_assert!(span_data.lo <= lo.line.end);
+        debug_assert!(span_data.hi >= hi.line.start);
+        debug_assert!(span_data.hi <= hi.line.end);
+        debug_assert!(lo.file.contains(span_data.lo));
+        debug_assert!(lo.file.contains(span_data.hi));
+        debug_assert_eq!(lo.file_index, hi.file_index);
+
+        Some((
+            lo.file.clone(),
+            lo.line_number,
+            span_data.lo - lo.line.start,
+            hi.line_number,
+            span_data.hi - hi.line.start,
+        ))
+    }
+
+    fn cache_entry_index(&self, pos: BytePos) -> isize {
+        for (idx, cache_entry) in self.line_cache.iter().enumerate() {
+            if cache_entry.line.contains(&pos) {
+                return idx as isize;
+            }
         }
 
-        let line_index = cache_entry.file.lookup_line(pos).unwrap();
-        let line_bounds = cache_entry.file.line_bounds(line_index);
+        -1
+    }
 
-        cache_entry.line_number = line_index + 1;
-        cache_entry.line = line_bounds;
-        cache_entry.time_stamp = self.time_stamp;
+    fn oldest_cache_entry_index(&self) -> usize {
+        let mut oldest = 0;
 
-        Some((cache_entry.file.clone(), cache_entry.line_number, pos - cache_entry.line.start))
+        for idx in 1..self.line_cache.len() {
+            if self.line_cache[idx].time_stamp < self.line_cache[oldest].time_stamp {
+                oldest = idx;
+            }
+        }
+
+        oldest
+    }
+
+    fn oldest_cache_entry_index_avoid(&self, avoid_idx: usize) -> usize {
+        let mut oldest = if avoid_idx != 0 { 0 } else { 1 };
+
+        for idx in 0..self.line_cache.len() {
+            if idx != avoid_idx
+                && self.line_cache[idx].time_stamp < self.line_cache[oldest].time_stamp
+            {
+                oldest = idx;
+            }
+        }
+
+        oldest
+    }
+
+    fn file_for_position(&self, pos: BytePos) -> Option<(Lrc<SourceFile>, usize)> {
+        if !self.source_map.files().is_empty() {
+            let file_idx = self.source_map.lookup_source_file_idx(pos);
+            let file = &self.source_map.files()[file_idx];
+
+            if file_contains(file, pos) {
+                return Some((file.clone(), file_idx));
+            }
+        }
+
+        None
     }
 }
 
diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs
index efbb0a2..a9200dd 100644
--- a/compiler/rustc_span/src/edition.rs
+++ b/compiler/rustc_span/src/edition.rs
@@ -20,20 +20,26 @@
     Edition2015,
     /// The 2018 edition
     Edition2018,
+    /// The 2021 ediiton
+    Edition2021,
 }
 
 // Must be in order from oldest to newest.
-pub const ALL_EDITIONS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018];
+pub const ALL_EDITIONS: &[Edition] =
+    &[Edition::Edition2015, Edition::Edition2018, Edition::Edition2021];
 
-pub const EDITION_NAME_LIST: &str = "2015|2018";
+pub const EDITION_NAME_LIST: &str = "2015|2018|2021";
 
 pub const DEFAULT_EDITION: Edition = Edition::Edition2015;
 
+pub const LATEST_STABLE_EDITION: Edition = Edition::Edition2018;
+
 impl fmt::Display for Edition {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let s = match *self {
             Edition::Edition2015 => "2015",
             Edition::Edition2018 => "2018",
+            Edition::Edition2021 => "2021",
         };
         write!(f, "{}", s)
     }
@@ -44,6 +50,7 @@
         match *self {
             Edition::Edition2015 => "rust_2015_compatibility",
             Edition::Edition2018 => "rust_2018_compatibility",
+            Edition::Edition2021 => "rust_2021_compatibility",
         }
     }
 
@@ -51,6 +58,7 @@
         match *self {
             Edition::Edition2015 => sym::rust_2015_preview,
             Edition::Edition2018 => sym::rust_2018_preview,
+            Edition::Edition2021 => sym::rust_2021_preview,
         }
     }
 
@@ -58,6 +66,7 @@
         match *self {
             Edition::Edition2015 => true,
             Edition::Edition2018 => true,
+            Edition::Edition2021 => false,
         }
     }
 }
@@ -68,6 +77,7 @@
         match s {
             "2015" => Ok(Edition::Edition2015),
             "2018" => Ok(Edition::Edition2018),
+            "2021" => Ok(Edition::Edition2021),
             _ => Err(()),
         }
     }
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index fdc0d22..1fb5642 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -622,6 +622,10 @@
     pub fn dollar_crate_name(self) -> Symbol {
         HygieneData::with(|data| data.syntax_context_data[self.0 as usize].dollar_crate_name)
     }
+
+    pub fn edition(self) -> Edition {
+        self.outer_expn_data().edition
+    }
 }
 
 impl fmt::Debug for SyntaxContext {
@@ -650,6 +654,20 @@
             self.with_ctxt(data.apply_mark(SyntaxContext::root(), expn_id, transparency))
         })
     }
+
+    /// Reuses the span but adds information like the kind of the desugaring and features that are
+    /// allowed inside this span.
+    pub fn mark_with_reason(
+        self,
+        allow_internal_unstable: Option<Lrc<[Symbol]>>,
+        reason: DesugaringKind,
+        edition: Edition,
+    ) -> Span {
+        self.fresh_expansion(ExpnData {
+            allow_internal_unstable,
+            ..ExpnData::default(ExpnKind::Desugaring(reason), self, edition, None)
+        })
+    }
 }
 
 /// A subset of properties from both macro definition and macro call available through global data.
@@ -699,7 +717,7 @@
     /// created locally - when our serialized metadata is decoded,
     /// foreign `ExpnId`s will have their `ExpnData` looked up
     /// from the crate specified by `Crate
-    pub krate: CrateNum,
+    krate: CrateNum,
     /// The raw that this `ExpnData` had in its original crate.
     /// An `ExpnData` can be created before being assigned an `ExpnId`,
     /// so this might be `None` until `set_expn_data` is called
@@ -707,13 +725,39 @@
     // two `ExpnData`s that differ only in their `orig_id` should
     // be considered equivalent.
     #[stable_hasher(ignore)]
-    pub orig_id: Option<u32>,
+    orig_id: Option<u32>,
 }
 
 // This would require special handling of `orig_id` and `parent`
 impl !PartialEq for ExpnData {}
 
 impl ExpnData {
+    pub fn new(
+        kind: ExpnKind,
+        parent: ExpnId,
+        call_site: Span,
+        def_site: Span,
+        allow_internal_unstable: Option<Lrc<[Symbol]>>,
+        allow_internal_unsafe: bool,
+        local_inner_macros: bool,
+        edition: Edition,
+        macro_def_id: Option<DefId>,
+    ) -> ExpnData {
+        ExpnData {
+            kind,
+            parent,
+            call_site,
+            def_site,
+            allow_internal_unstable,
+            allow_internal_unsafe,
+            local_inner_macros,
+            edition,
+            macro_def_id,
+            krate: LOCAL_CRATE,
+            orig_id: None,
+        }
+    }
+
     /// Constructs expansion data with default properties.
     pub fn default(
         kind: ExpnKind,
diff --git a/compiler/rustc_span/src/lev_distance/tests.rs b/compiler/rustc_span/src/lev_distance/tests.rs
index 7aa01cb..90e20af 100644
--- a/compiler/rustc_span/src/lev_distance/tests.rs
+++ b/compiler/rustc_span/src/lev_distance/tests.rs
@@ -4,7 +4,7 @@
 fn test_lev_distance() {
     use std::char::{from_u32, MAX};
     // Test bytelength agnosticity
-    for c in (0..MAX as u32).filter_map(|i| from_u32(i)).map(|i| i.to_string()) {
+    for c in (0..MAX as u32).filter_map(from_u32).map(|i| i.to_string()) {
         assert_eq!(lev_distance(&c[..], &c[..]), 0);
     }
 
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 8009530..50cb155 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -301,6 +301,10 @@
 
 impl SpanData {
     #[inline]
+    pub fn span(&self) -> Span {
+        Span::new(self.lo, self.hi, self.ctxt)
+    }
+    #[inline]
     pub fn with_lo(&self, lo: BytePos) -> Span {
         Span::new(lo, self.hi, self.ctxt)
     }
@@ -468,7 +472,7 @@
 
     /// Edition of the crate from which this span came.
     pub fn edition(self) -> edition::Edition {
-        self.ctxt().outer_expn_data().edition
+        self.ctxt().edition()
     }
 
     #[inline]
@@ -481,6 +485,11 @@
         self.edition() >= edition::Edition::Edition2018
     }
 
+    #[inline]
+    pub fn rust_2021(&self) -> bool {
+        self.edition() >= edition::Edition::Edition2021
+    }
+
     /// Returns the source callee.
     ///
     /// Returns `None` if the supplied span has no expansion trace,
@@ -1862,6 +1871,10 @@
         &mut self,
         byte: BytePos,
     ) -> Option<(Lrc<SourceFile>, usize, BytePos)>;
+    fn span_data_to_lines_and_cols(
+        &mut self,
+        span: &SpanData,
+    ) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)>;
 }
 
 impl<CTX> HashStable<CTX> for Span
@@ -1886,8 +1899,9 @@
             return;
         }
 
-        if *self == DUMMY_SP {
+        if self.is_dummy() {
             Hash::hash(&TAG_INVALID_SPAN, hasher);
+            self.ctxt().hash_stable(ctx, hasher);
             return;
         }
 
@@ -1895,22 +1909,8 @@
         // position that belongs to it, as opposed to hashing the first
         // position past it.
         let span = self.data();
-        let (file_lo, line_lo, col_lo) = match ctx.byte_pos_to_line_and_col(span.lo) {
-            Some(pos) => pos,
-            None => {
-                Hash::hash(&TAG_INVALID_SPAN, hasher);
-                span.ctxt.hash_stable(ctx, hasher);
-                return;
-            }
-        };
-
-        if !file_lo.contains(span.hi) {
-            Hash::hash(&TAG_INVALID_SPAN, hasher);
-            span.ctxt.hash_stable(ctx, hasher);
-            return;
-        }
-
-        let (_, line_hi, col_hi) = match ctx.byte_pos_to_line_and_col(span.hi) {
+        let (file, line_lo, col_lo, line_hi, col_hi) = match ctx.span_data_to_lines_and_cols(&span)
+        {
             Some(pos) => pos,
             None => {
                 Hash::hash(&TAG_INVALID_SPAN, hasher);
@@ -1922,7 +1922,7 @@
         Hash::hash(&TAG_VALID_SPAN, hasher);
         // We truncate the stable ID hash and line and column numbers. The chances
         // of causing a collision this way should be minimal.
-        Hash::hash(&(file_lo.name_hash as u64), hasher);
+        Hash::hash(&(file.name_hash as u64), hasher);
 
         // Hash both the length and the end location (line/column) of a span. If we
         // hash only the length, for example, then two otherwise equal spans with
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index fefc0cb..4e0ce0d 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -539,7 +539,7 @@
 
     pub fn is_line_before_span_empty(&self, sp: Span) -> bool {
         match self.span_to_prev_source(sp) {
-            Ok(s) => s.split('\n').last().map(|l| l.trim_start().is_empty()).unwrap_or(false),
+            Ok(s) => s.split('\n').last().map_or(false, |l| l.trim_start().is_empty()),
             Err(_) => false,
         }
     }
@@ -568,7 +568,7 @@
         // asserting that the line numbers here are all indeed 1-based.
         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);
+            let line_len = lo.file.get_line(line_index).map_or(0, |s| s.chars().count());
             lines.push(LineInfo { line_index, start_col, end_col: CharPos::from_usize(line_len) });
             start_col = CharPos::from_usize(0);
         }
@@ -582,9 +582,9 @@
     /// Extracts the source surrounding the given `Span` using the `extract_source` function. The
     /// extract function takes three arguments: a string slice containing the source, an index in
     /// the slice for the beginning of the span and an index in the slice for the end of the span.
-    fn span_to_source<F>(&self, sp: Span, extract_source: F) -> Result<String, SpanSnippetError>
+    fn span_to_source<F, T>(&self, sp: Span, extract_source: F) -> Result<T, SpanSnippetError>
     where
-        F: Fn(&str, usize, usize) -> Result<String, SpanSnippetError>,
+        F: Fn(&str, usize, usize) -> Result<T, SpanSnippetError>,
     {
         let local_begin = self.lookup_byte_offset(sp.lo());
         let local_end = self.lookup_byte_offset(sp.hi());
@@ -648,10 +648,10 @@
 
     /// Extends the given `Span` to just after the previous occurrence of `c`. Return the same span
     /// if no character could be found or if an error occurred while retrieving the code snippet.
-    pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span {
+    pub fn span_extend_to_prev_char(&self, sp: Span, c: char, accept_newlines: bool) -> Span {
         if let Ok(prev_source) = self.span_to_prev_source(sp) {
-            let prev_source = prev_source.rsplit(c).next().unwrap_or("").trim_start();
-            if !prev_source.is_empty() && !prev_source.contains('\n') {
+            let prev_source = prev_source.rsplit(c).next().unwrap_or("");
+            if !prev_source.is_empty() && (!prev_source.contains('\n') || accept_newlines) {
                 return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32));
             }
         }
@@ -671,7 +671,9 @@
             let pat = pat.to_owned() + ws;
             if let Ok(prev_source) = self.span_to_prev_source(sp) {
                 let prev_source = prev_source.rsplit(&pat).next().unwrap_or("").trim_start();
-                if !prev_source.is_empty() && (!prev_source.contains('\n') || accept_newlines) {
+                if prev_source.is_empty() && sp.lo().0 != 0 {
+                    return sp.with_lo(BytePos(sp.lo().0 - 1));
+                } else if !prev_source.contains('\n') || accept_newlines {
                     return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32));
                 }
             }
@@ -680,6 +682,25 @@
         sp
     }
 
+    /// Returns the source snippet as `String` after the given `Span`.
+    pub fn span_to_next_source(&self, sp: Span) -> Result<String, SpanSnippetError> {
+        self.span_to_source(sp, |src, _, end_index| {
+            src.get(end_index..).map(|s| s.to_string()).ok_or(SpanSnippetError::IllFormedSpan(sp))
+        })
+    }
+
+    /// Extends the given `Span` to just after the next occurrence of `c`.
+    pub fn span_extend_to_next_char(&self, sp: Span, c: char, accept_newlines: bool) -> Span {
+        if let Ok(next_source) = self.span_to_next_source(sp) {
+            let next_source = next_source.split(c).next().unwrap_or("");
+            if !next_source.is_empty() && (!next_source.contains('\n') || accept_newlines) {
+                return sp.with_hi(BytePos(sp.hi().0 + next_source.len() as u32));
+            }
+        }
+
+        sp
+    }
+
     /// Given a `Span`, tries to get a shorter span ending before the first occurrence of `char`
     /// `c`.
     pub fn span_until_char(&self, sp: Span, c: char) -> Span {
@@ -870,8 +891,10 @@
     }
 
     pub fn get_source_file(&self, filename: &FileName) -> Option<Lrc<SourceFile>> {
+        // Remap filename before lookup
+        let filename = self.path_mapping().map_filename_prefix(filename).0;
         for sf in self.files.borrow().source_files.iter() {
-            if *filename == sf.name {
+            if filename == sf.name {
                 return Some(sf.clone());
             }
         }
@@ -1039,4 +1062,15 @@
 
         (path, false)
     }
+
+    fn map_filename_prefix(&self, file: &FileName) -> (FileName, bool) {
+        match file {
+            FileName::Real(realfile) => {
+                let path = realfile.local_path();
+                let (path, mapped) = self.map_prefix(path.to_path_buf());
+                (FileName::Real(RealFileName::Named(path)), mapped)
+            }
+            other => (other.clone(), false),
+        }
+    }
 }
diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs
index b8459ee..3f22829 100644
--- a/compiler/rustc_span/src/source_map/tests.rs
+++ b/compiler/rustc_span/src/source_map/tests.rs
@@ -107,7 +107,7 @@
 fn span_from_selection(input: &str, selection: &str) -> Span {
     assert_eq!(input.len(), selection.len());
     let left_index = selection.find('~').unwrap() as u32;
-    let right_index = selection.rfind('~').map(|x| x as u32).unwrap_or(left_index);
+    let right_index = selection.rfind('~').map_or(left_index, |x| x as u32);
     Span::with_root_ctxt(BytePos(left_index), BytePos(right_index + 1))
 }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 7ca2ff4..63f95a3 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -368,6 +368,7 @@
         const_fn_transmute,
         const_fn_union,
         const_generics,
+        const_generics_defaults,
         const_if_match,
         const_impl_trait,
         const_in_array_repeat_expressions,
@@ -380,6 +381,7 @@
         const_ptr,
         const_raw_ptr_deref,
         const_raw_ptr_to_usize_cast,
+        const_refs_to_cell,
         const_slice_ptr,
         const_trait_bound_opt_out,
         const_trait_impl,
@@ -470,6 +472,7 @@
         dropck_parametricity,
         dylib,
         dyn_trait,
+        edition_macro_pats,
         eh_catch_typeinfo,
         eh_personality,
         emit_enum,
@@ -713,7 +716,6 @@
         more_struct_aliases,
         movbe_target_feature,
         move_ref_pattern,
-        move_val_init,
         mul,
         mul_assign,
         mul_with_overflow,
@@ -808,6 +810,8 @@
         partial_ord,
         passes,
         pat,
+        pat2018,
+        pat2021,
         path,
         pattern_parentheses,
         phantom_data,
@@ -920,6 +924,7 @@
         rust,
         rust_2015_preview,
         rust_2018_preview,
+        rust_2021_preview,
         rust_begin_unwind,
         rust_eh_catch_typeinfo,
         rust_eh_personality,
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 6356a7e..b0d5f34 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -56,7 +56,15 @@
     let hash = get_symbol_hash(tcx, instance, instance_ty, instantiating_crate);
 
     let mut printer = SymbolPrinter { tcx, path: SymbolPath::new(), keep_within_component: false }
-        .print_def_path(def_id, &[])
+        .print_def_path(
+            def_id,
+            if let ty::InstanceDef::DropGlue(_, _) = instance.def {
+                // Add the name of the dropped type to the symbol name
+                &*instance.substs
+            } else {
+                &[]
+            },
+        )
         .unwrap();
 
     if let ty::InstanceDef::VtableShim(..) = instance.def {
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 5de9a8d..a9e595d 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -605,10 +605,11 @@
             "nvptx64" => nvptx64::compute_abi_info(self),
             "hexagon" => hexagon::compute_abi_info(self),
             "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self),
-            "wasm32" if cx.target_spec().os != "emscripten" => {
-                wasm32_bindgen_compat::compute_abi_info(self)
-            }
-            "wasm32" | "asmjs" => wasm32::compute_abi_info(cx, self),
+            "wasm32" => match cx.target_spec().os.as_str() {
+                "emscripten" | "wasi" => wasm32::compute_abi_info(cx, self),
+                _ => wasm32_bindgen_compat::compute_abi_info(self),
+            },
+            "asmjs" => wasm32::compute_abi_info(cx, self),
             a => return Err(format!("unrecognized arch \"{}\" in target specification", a)),
         }
 
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index a43080b..93868be 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -4,11 +4,14 @@
 use crate::spec::Target;
 
 use std::convert::{TryFrom, TryInto};
+use std::fmt;
 use std::num::NonZeroUsize;
 use std::ops::{Add, AddAssign, Deref, Mul, Range, RangeInclusive, Sub};
+use std::str::FromStr;
 
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable_Generic;
+use rustc_serialize::json::{Json, ToJson};
 use rustc_span::Span;
 
 pub mod call;
@@ -152,22 +155,19 @@
         }
 
         // Perform consistency checks against the Target information.
-        let endian_str = match dl.endian {
-            Endian::Little => "little",
-            Endian::Big => "big",
-        };
-        if endian_str != target.endian {
+        if dl.endian != target.endian {
             return Err(format!(
                 "inconsistent target specification: \"data-layout\" claims \
-                                architecture is {}-endian, while \"target-endian\" is `{}`",
-                endian_str, target.endian
+                 architecture is {}-endian, while \"target-endian\" is `{}`",
+                dl.endian.as_str(),
+                target.endian.as_str(),
             ));
         }
 
         if dl.pointer_size.bits() != target.pointer_width.into() {
             return Err(format!(
                 "inconsistent target specification: \"data-layout\" claims \
-                                pointers are {}-bit, while \"target-pointer-width\" is `{}`",
+                 pointers are {}-bit, while \"target-pointer-width\" is `{}`",
                 dl.pointer_size.bits(),
                 target.pointer_width
             ));
@@ -234,26 +234,75 @@
     Big,
 }
 
+impl Endian {
+    pub fn as_str(&self) -> &'static str {
+        match self {
+            Self::Little => "little",
+            Self::Big => "big",
+        }
+    }
+}
+
+impl fmt::Debug for Endian {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(self.as_str())
+    }
+}
+
+impl FromStr for Endian {
+    type Err = String;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "little" => Ok(Self::Little),
+            "big" => Ok(Self::Big),
+            _ => Err(format!(r#"unknown endian: "{}""#, s)),
+        }
+    }
+}
+
+impl ToJson for Endian {
+    fn to_json(&self) -> Json {
+        self.as_str().to_json()
+    }
+}
+
 /// Size of a type in bytes.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
 #[derive(HashStable_Generic)]
 pub struct Size {
+    // The top 3 bits are ALWAYS zero.
     raw: u64,
 }
 
 impl Size {
     pub const ZERO: Size = Size { raw: 0 };
 
-    #[inline]
+    /// Rounds `bits` up to the next-higher byte boundary, if `bits` is
+    /// is not aligned.
     pub fn from_bits(bits: impl TryInto<u64>) -> Size {
         let bits = bits.try_into().ok().unwrap();
+
+        #[cold]
+        fn overflow(bits: u64) -> ! {
+            panic!("Size::from_bits({}) has overflowed", bits);
+        }
+
+        // This is the largest value of `bits` that does not cause overflow
+        // during rounding, and guarantees that the resulting number of bytes
+        // cannot cause overflow when multiplied by 8.
+        if bits > 0xffff_ffff_ffff_fff8 {
+            overflow(bits);
+        }
+
         // Avoid potential overflow from `bits + 7`.
-        Size::from_bytes(bits / 8 + ((bits % 8) + 7) / 8)
+        Size { raw: bits / 8 + ((bits % 8) + 7) / 8 }
     }
 
     #[inline]
     pub fn from_bytes(bytes: impl TryInto<u64>) -> Size {
-        Size { raw: bytes.try_into().ok().unwrap() }
+        let bytes: u64 = bytes.try_into().ok().unwrap();
+        Size { raw: bytes }
     }
 
     #[inline]
@@ -268,9 +317,7 @@
 
     #[inline]
     pub fn bits(self) -> u64 {
-        self.bytes().checked_mul(8).unwrap_or_else(|| {
-            panic!("Size::bits: {} bytes in bits doesn't fit in u64", self.bytes())
-        })
+        self.raw << 3
     }
 
     #[inline]
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
index c6586b7..255740c 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
@@ -1,5 +1,6 @@
 // Targets the Big endian Cortex-R4/R5 processor (ARMv7-R)
 
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
 use crate::spec::{Target, TargetOptions};
 
@@ -11,7 +12,7 @@
         arch: "arm".to_string(),
 
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
             executables: true,
             linker: Some("rust-lld".to_owned()),
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
index e3d4397..eb82e4d 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
@@ -1,5 +1,6 @@
 // Targets the Cortex-R4F/R5F processor (ARMv7-R)
 
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
 use crate::spec::{Target, TargetOptions};
 
@@ -11,7 +12,7 @@
         arch: "arm".to_string(),
 
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
             executables: true,
             linker: Some("rust-lld".to_owned()),
diff --git a/compiler/rustc_target/src/spec/crt_objects.rs b/compiler/rustc_target/src/spec/crt_objects.rs
index 76c0bf4..32da16a 100644
--- a/compiler/rustc_target/src/spec/crt_objects.rs
+++ b/compiler/rustc_target/src/spec/crt_objects.rs
@@ -5,15 +5,16 @@
 //! The `crtx` ones are generally distributed with libc and the `begin/end` ones with gcc.
 //! See <https://dev.gentoo.org/~vapier/crt.txt> for some more details.
 //!
-//! | Pre-link CRT objects | glibc                  | musl                   | bionic           | mingw             | wasi |
-//! |----------------------|------------------------|------------------------|------------------|-------------------|------|
-//! | dynamic-nopic-exe    | crt1, crti, crtbegin   | crt1, crti, crtbegin   | crtbegin_dynamic | crt2, crtbegin    | crt1 |
-//! | dynamic-pic-exe      | Scrt1, crti, crtbeginS | Scrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin    | crt1 |
-//! | static-nopic-exe     | crt1, crti, crtbeginT  | crt1, crti, crtbegin   | crtbegin_static  | crt2, crtbegin    | crt1 |
-//! | static-pic-exe       | rcrt1, crti, crtbeginS | rcrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin    | crt1 |
-//! | dynamic-dylib        | crti, crtbeginS        | crti, crtbeginS        | crtbegin_so      | dllcrt2, crtbegin | -    |
-//! | static-dylib (gcc)   | crti, crtbeginT        | crti, crtbeginS        | crtbegin_so      | dllcrt2, crtbegin | -    |
-//! | static-dylib (clang) | crti, crtbeginT        | N/A                    | crtbegin_static  | dllcrt2, crtbegin | -    |
+//! | Pre-link CRT objects | glibc                  | musl                   | bionic           | mingw             | wasi         |
+//! |----------------------|------------------------|------------------------|------------------|-------------------|--------------|
+//! | dynamic-nopic-exe    | crt1, crti, crtbegin   | crt1, crti, crtbegin   | crtbegin_dynamic | crt2, crtbegin    | crt1         |
+//! | dynamic-pic-exe      | Scrt1, crti, crtbeginS | Scrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin    | crt1         |
+//! | static-nopic-exe     | crt1, crti, crtbeginT  | crt1, crti, crtbegin   | crtbegin_static  | crt2, crtbegin    | crt1         |
+//! | static-pic-exe       | rcrt1, crti, crtbeginS | rcrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin    | crt1         |
+//! | dynamic-dylib        | crti, crtbeginS        | crti, crtbeginS        | crtbegin_so      | dllcrt2, crtbegin | -            |
+//! | static-dylib (gcc)   | crti, crtbeginT        | crti, crtbeginS        | crtbegin_so      | dllcrt2, crtbegin | -            |
+//! | static-dylib (clang) | crti, crtbeginT        | N/A                    | crtbegin_static  | dllcrt2, crtbegin | -            |
+//! | wasi-reactor-exe     | N/A                    | N/A                    | N/A              | N/A               | crt1-reactor |
 //!
 //! | Post-link CRT objects | glibc         | musl          | bionic         | mingw  | wasi |
 //! |-----------------------|---------------|---------------|----------------|--------|------|
@@ -105,6 +106,7 @@
         (LinkOutputKind::DynamicPicExe, &["crt1.o"]),
         (LinkOutputKind::StaticNoPicExe, &["crt1.o"]),
         (LinkOutputKind::StaticPicExe, &["crt1.o"]),
+        (LinkOutputKind::WasiReactorExe, &["crt1-reactor.o"]),
     ])
 }
 
diff --git a/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs
new file mode 100644
index 0000000..f329b2d
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs
@@ -0,0 +1,8 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+    let mut base = super::i686_unknown_linux_gnu::target();
+    base.cpu = "i386".to_string();
+    base.llvm_target = "i386-unknown-linux-gnu".to_string();
+    base
+}
diff --git a/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs
new file mode 100644
index 0000000..5d96a55
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs
@@ -0,0 +1,8 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+    let mut base = super::i686_unknown_linux_gnu::target();
+    base.cpu = "i486".to_string();
+    base.llvm_target = "i486-unknown-linux-gnu".to_string();
+    base
+}
diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
index daa0d9d..5339853 100644
--- a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -7,7 +8,7 @@
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
         arch: "mips64".to_string(),
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             // NOTE(mips64r2) matches C toolchain
             cpu: "mips64r2".to_string(),
             features: "+mips64r2".to_string(),
diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs
index db8d0c0..329fbd2 100644
--- a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs
+++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,6 +12,6 @@
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
         arch: "mips64".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs
index a7ec1f1..b41b28cb 100644
--- a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -7,7 +8,7 @@
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
         arch: "mips".to_string(),
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             cpu: "mips32r2".to_string(),
             features: "+mips32r2,+fpxx,+nooddspreg".to_string(),
             max_atomic_width: Some(32),
diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs
index 1ebe577..3713af4 100644
--- a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,6 +12,6 @@
         pointer_width: 32,
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
         arch: "mips".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs
index 2123d5e..042ec91 100644
--- a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs
+++ b/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -7,7 +8,7 @@
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
         arch: "mips".to_string(),
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             cpu: "mips32r2".to_string(),
             features: "+mips32r2,+soft-float".to_string(),
             max_atomic_width: Some(32),
diff --git a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs
index 11b3734..a81c90f 100644
--- a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -7,7 +8,7 @@
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
         arch: "mips".to_string(),
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             cpu: "mips32r6".to_string(),
             features: "+mips32r6".to_string(),
             max_atomic_width: Some(32),
diff --git a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
index 6282c9e..3bf837f 100644
--- a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -7,7 +8,7 @@
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
         arch: "mips64".to_string(),
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             // NOTE(mips64r6) matches C toolchain
             cpu: "mips64r6".to_string(),
             features: "+mips64r6".to_string(),
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 8d72df6..d283c25 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -34,6 +34,7 @@
 //! the target's settings, though `target-feature` and `link-args` will *add*
 //! to the list specified by the target, rather than replace.
 
+use crate::abi::Endian;
 use crate::spec::abi::{lookup as lookup_abi, Abi};
 use crate::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
 use rustc_serialize::json::{Json, ToJson};
@@ -407,6 +408,8 @@
     DynamicDylib,
     /// Dynamic library with bundled libc ("statically linked").
     StaticDylib,
+    /// WASI module with a lifetime past the _initialize entry point
+    WasiReactorExe,
 }
 
 impl LinkOutputKind {
@@ -418,6 +421,7 @@
             LinkOutputKind::StaticPicExe => "static-pic-exe",
             LinkOutputKind::DynamicDylib => "dynamic-dylib",
             LinkOutputKind::StaticDylib => "static-dylib",
+            LinkOutputKind::WasiReactorExe => "wasi-reactor-exe",
         }
     }
 
@@ -429,6 +433,7 @@
             "static-pic-exe" => LinkOutputKind::StaticPicExe,
             "dynamic-dylib" => LinkOutputKind::DynamicDylib,
             "static-dylib" => LinkOutputKind::StaticDylib,
+            "wasi-reactor-exe" => LinkOutputKind::WasiReactorExe,
             _ => return None,
         })
     }
@@ -705,8 +710,8 @@
     /// Whether the target is built-in or loaded from a custom target specification.
     pub is_builtin: bool,
 
-    /// String to use as the `target_endian` `cfg` variable. Defaults to "little".
-    pub endian: String,
+    /// Used as the `target_endian` `cfg` variable. Defaults to little endian.
+    pub endian: Endian,
     /// Width of c_int type. Defaults to "32".
     pub c_int_width: String,
     /// OS name to use for conditional compilation (`target_os`). Defaults to "none".
@@ -1010,7 +1015,7 @@
     fn default() -> TargetOptions {
         TargetOptions {
             is_builtin: false,
-            endian: "little".to_string(),
+            endian: Endian::Little,
             c_int_width: "32".to_string(),
             os: "none".to_string(),
             env: String::new(),
@@ -1377,7 +1382,7 @@
                         let kind = LinkOutputKind::from_str(&k).ok_or_else(|| {
                             format!("{}: '{}' is not a valid value for CRT object kind. \
                                      Use '(dynamic,static)-(nopic,pic)-exe' or \
-                                     '(dynamic,static)-dylib'", name, k)
+                                     '(dynamic,static)-dylib' or 'wasi-reactor-exe'", name, k)
                         })?;
 
                         let v = v.as_array().ok_or_else(||
@@ -1439,8 +1444,10 @@
             } );
         }
 
+        if let Some(s) = obj.find("target-endian").and_then(Json::as_string) {
+            base.endian = s.parse()?;
+        }
         key!(is_builtin, bool);
-        key!(endian = "target-endian");
         key!(c_int_width = "target-c-int-width");
         key!(os);
         key!(env);
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
index 626865a..3dddeb1 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,6 +12,6 @@
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64".to_string(),
         arch: "powerpc64".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
index 0332281..751022c 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, RelroLevel, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -15,6 +16,6 @@
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64".to_string(),
         arch: "powerpc64".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
index 2315397..546dfba 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,6 +12,6 @@
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64".to_string(),
         arch: "powerpc64".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
index 1c83e3e..bb55872 100644
--- a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,6 +12,6 @@
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64".to_string(),
         arch: "powerpc64".to_string(),
-        options: TargetOptions { endian: "big".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
index 3a92712..70dd0b2 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -10,6 +11,6 @@
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
index 105a0b2..66118b7 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -10,6 +11,6 @@
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
index 49d3294..679a3a2 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -10,6 +11,6 @@
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
index 387d6cd..1245098 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -10,10 +11,6 @@
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
-        options: TargetOptions {
-            endian: "big".to_string(),
-            mcount: "__mcount".to_string(),
-            ..base
-        },
+        options: TargetOptions { endian: Endian::Big, mcount: "__mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
index 20ffa07..bb943a8 100644
--- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,10 +12,6 @@
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
-        options: TargetOptions {
-            endian: "big".to_string(),
-            features: "+secure-plt".to_string(),
-            ..base
-        },
+        options: TargetOptions { endian: Endian::Big, features: "+secure-plt".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
index 0e713fc..4b4f118 100644
--- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
+++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -12,7 +13,7 @@
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             // feature msync would disable instruction 'fsync' which is not supported by fsl_p1p2
             features: "+secure-plt,+msync".to_string(),
             ..base
diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
index d6e8e6e..4eeea9b 100644
--- a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
@@ -1,8 +1,9 @@
+use crate::abi::Endian;
 use crate::spec::Target;
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.endian = "big".to_string();
+    base.endian = Endian::Big;
     // z10 is the oldest CPU supported by LLVM
     base.cpu = "z10".to_string();
     // FIXME: The data_layout string below and the ABI implementation in
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs
index e9b5520..e1aa488 100644
--- a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs
@@ -1,8 +1,9 @@
+use crate::abi::Endian;
 use crate::spec::Target;
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.endian = "big".to_string();
+    base.endian = Endian::Big;
     base.cpu = "v9".to_string();
     base.max_atomic_width = Some(64);
 
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
index c8e90f8..7d685c8 100644
--- a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,10 +12,6 @@
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64-S128".to_string(),
         arch: "sparc64".to_string(),
-        options: TargetOptions {
-            endian: "big".to_string(),
-            mcount: "__mcount".to_string(),
-            ..base
-        },
+        options: TargetOptions { endian: Endian::Big, mcount: "__mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
index 630ce61..63b13fa 100644
--- a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
@@ -1,8 +1,9 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target};
 
 pub fn target() -> Target {
     let mut base = super::openbsd_base::opts();
-    base.endian = "big".to_string();
+    base.endian = Endian::Big;
     base.cpu = "v9".to_string();
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
     base.max_atomic_width = Some(64);
diff --git a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
index aae186b..9e8fbff 100644
--- a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
@@ -1,8 +1,9 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target};
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.endian = "big".to_string();
+    base.endian = Endian::Big;
     base.cpu = "v9".to_string();
     base.max_atomic_width = Some(64);
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mv8plus".to_string());
diff --git a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
index 5f99e0b..9ac56ca 100644
--- a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
+++ b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
@@ -1,8 +1,9 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target};
 
 pub fn target() -> Target {
     let mut base = super::solaris_base::opts();
-    base.endian = "big".to_string();
+    base.endian = Endian::Big;
     base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
     // llvm calls this "v9"
     base.cpu = "v9".to_string();
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
index f5bc90e..25ba489 100644
--- a/compiler/rustc_trait_selection/src/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -1153,7 +1153,7 @@
         debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
 
         for predicate in &bounds {
-            if let ty::PredicateAtom::Projection(projection) = predicate.skip_binders() {
+            if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
                 if projection.ty.references_error() {
                     // No point on adding these obligations since there's a type error involved.
                     return ty_var;
@@ -1251,18 +1251,18 @@
     traits::elaborate_predicates(tcx, predicates)
         .filter_map(|obligation| {
             debug!("required_region_bounds(obligation={:?})", obligation);
-            match obligation.predicate.skip_binders() {
-                ty::PredicateAtom::Projection(..)
-                | ty::PredicateAtom::Trait(..)
-                | ty::PredicateAtom::Subtype(..)
-                | ty::PredicateAtom::WellFormed(..)
-                | ty::PredicateAtom::ObjectSafe(..)
-                | ty::PredicateAtom::ClosureKind(..)
-                | ty::PredicateAtom::RegionOutlives(..)
-                | ty::PredicateAtom::ConstEvaluatable(..)
-                | ty::PredicateAtom::ConstEquate(..)
-                | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
-                ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
+            match obligation.predicate.kind().skip_binder() {
+                ty::PredicateKind::Projection(..)
+                | ty::PredicateKind::Trait(..)
+                | ty::PredicateKind::Subtype(..)
+                | ty::PredicateKind::WellFormed(..)
+                | ty::PredicateKind::ObjectSafe(..)
+                | ty::PredicateKind::ClosureKind(..)
+                | ty::PredicateKind::RegionOutlives(..)
+                | ty::PredicateKind::ConstEvaluatable(..)
+                | ty::PredicateKind::ConstEquate(..)
+                | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
+                ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
                     // Search for a bound of the form `erased_self_ty
                     // : 'a`, but be wary of something like `for<'a>
                     // erased_self_ty : 'a` (we interpret a
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index fc6a9a7..6593c10 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -305,8 +305,8 @@
                 infcx.resolve_vars_if_possible(Obligation::new(dummy_cause.clone(), new_env, pred));
             let result = select.select(&obligation);
 
-            match &result {
-                &Ok(Some(ref impl_source)) => {
+            match result {
+                Ok(Some(ref impl_source)) => {
                     // If we see an explicit negative impl (e.g., `impl !Send for MyStruct`),
                     // we immediately bail out, since it's impossible for us to continue.
 
@@ -339,8 +339,8 @@
                         return None;
                     }
                 }
-                &Ok(None) => {}
-                &Err(SelectionError::Unimplemented) => {
+                Ok(None) => {}
+                Err(SelectionError::Unimplemented) => {
                     if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
                         already_visited.remove(&pred);
                         self.add_user_pred(
@@ -414,9 +414,9 @@
         let mut should_add_new = true;
         user_computed_preds.retain(|&old_pred| {
             if let (
-                ty::PredicateAtom::Trait(new_trait, _),
-                ty::PredicateAtom::Trait(old_trait, _),
-            ) = (new_pred.skip_binders(), old_pred.skip_binders())
+                ty::PredicateKind::Trait(new_trait, _),
+                ty::PredicateKind::Trait(old_trait, _),
+            ) = (new_pred.kind().skip_binder(), old_pred.kind().skip_binder())
             {
                 if new_trait.def_id() == old_trait.def_id() {
                     let new_substs = new_trait.trait_ref.substs;
@@ -633,18 +633,16 @@
             // We check this by calling is_of_param on the relevant types
             // from the various possible predicates
 
-            let bound_predicate = predicate.bound_atom();
+            let bound_predicate = predicate.kind();
             match bound_predicate.skip_binder() {
-                ty::PredicateAtom::Trait(p, _) => {
-                    if self.is_param_no_infer(p.trait_ref.substs)
-                        && !only_projections
-                        && is_new_pred
-                    {
-                        self.add_user_pred(computed_preds, predicate);
-                    }
+                ty::PredicateKind::Trait(p, _) => {
+                    // Add this to `predicates` so that we end up calling `select`
+                    // with it. If this predicate ends up being unimplemented,
+                    // then `evaluate_predicates` will handle adding it the `ParamEnv`
+                    // if possible.
                     predicates.push_back(bound_predicate.rebind(p));
                 }
-                ty::PredicateAtom::Projection(p) => {
+                ty::PredicateKind::Projection(p) => {
                     let p = bound_predicate.rebind(p);
                     debug!(
                         "evaluate_nested_obligations: examining projection predicate {:?}",
@@ -774,13 +772,13 @@
                         }
                     }
                 }
-                ty::PredicateAtom::RegionOutlives(binder) => {
+                ty::PredicateKind::RegionOutlives(binder) => {
                     let binder = bound_predicate.rebind(binder);
                     if select.infcx().region_outlives_predicate(&dummy_cause, binder).is_err() {
                         return false;
                     }
                 }
-                ty::PredicateAtom::TypeOutlives(binder) => {
+                ty::PredicateKind::TypeOutlives(binder) => {
                     let binder = bound_predicate.rebind(binder);
                     match (
                         binder.no_bound_vars(),
@@ -803,7 +801,7 @@
                         _ => {}
                     };
                 }
-                ty::PredicateAtom::ConstEquate(c1, c2) => {
+                ty::PredicateKind::ConstEquate(c1, c2) => {
                     let evaluate = |c: &'tcx ty::Const<'tcx>| {
                         if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val {
                             match select.infcx().const_eval_resolve(
@@ -863,7 +861,7 @@
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         (match r {
-            &ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
+            ty::ReVar(vid) => self.vid_to_region.get(vid).cloned(),
             _ => None,
         })
         .unwrap_or_else(|| r.super_fold_with(self))
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index fdb2361..ad229e0 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -41,8 +41,8 @@
             // We are looking at a generic abstract constant.
             Some(ct) => {
                 for pred in param_env.caller_bounds() {
-                    match pred.skip_binders() {
-                        ty::PredicateAtom::ConstEvaluatable(b_def, b_substs) => {
+                    match pred.kind().skip_binder() {
+                        ty::PredicateKind::ConstEvaluatable(b_def, b_substs) => {
                             debug!(
                                 "is_const_evaluatable: caller_bound={:?}, {:?}",
                                 b_def, b_substs
@@ -152,7 +152,7 @@
     if concrete.is_ok() && substs.has_param_types_or_consts() {
         match infcx.tcx.def_kind(def.did) {
             DefKind::AnonConst => {
-                let mir_body = infcx.tcx.optimized_mir_opt_const_arg(def);
+                let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(def);
 
                 if mir_body.is_polymorphic {
                     future_compat_lint();
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 1d82e73..3eeb503 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -256,9 +256,9 @@
                     return;
                 }
 
-                let bound_predicate = obligation.predicate.bound_atom();
+                let bound_predicate = obligation.predicate.kind();
                 match bound_predicate.skip_binder() {
-                    ty::PredicateAtom::Trait(trait_predicate, _) => {
+                    ty::PredicateKind::Trait(trait_predicate, _) => {
                         let trait_predicate = bound_predicate.rebind(trait_predicate);
                         let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
 
@@ -280,18 +280,10 @@
                         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 = self.tcx.get_diagnostic_item(sym::from_trait)
-                            == Some(trait_ref.def_id());
+                        let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id());
                         let is_unsize =
                             { Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait() };
-                        let (message, note) = if is_try && is_from {
+                        let (message, note) = if is_try_conversion {
                             (
                                 Some(format!(
                                     "`?` couldn't convert the error to `{}`",
@@ -319,7 +311,7 @@
                             ))
                         );
 
-                        if is_try && is_from {
+                        if is_try_conversion {
                             let none_error = self
                                 .tcx
                                 .get_diagnostic_item(sym::none_error)
@@ -525,14 +517,14 @@
                         err
                     }
 
-                    ty::PredicateAtom::Subtype(predicate) => {
+                    ty::PredicateKind::Subtype(predicate) => {
                         // Errors for Subtype predicates show up as
                         // `FulfillmentErrorCode::CodeSubtypeError`,
                         // not selection error.
                         span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
                     }
 
-                    ty::PredicateAtom::RegionOutlives(predicate) => {
+                    ty::PredicateKind::RegionOutlives(predicate) => {
                         let predicate = bound_predicate.rebind(predicate);
                         let predicate = self.resolve_vars_if_possible(predicate);
                         let err = self
@@ -549,7 +541,7 @@
                         )
                     }
 
-                    ty::PredicateAtom::Projection(..) | ty::PredicateAtom::TypeOutlives(..) => {
+                    ty::PredicateKind::Projection(..) | ty::PredicateKind::TypeOutlives(..) => {
                         let predicate = self.resolve_vars_if_possible(obligation.predicate);
                         struct_span_err!(
                             self.tcx.sess,
@@ -560,12 +552,12 @@
                         )
                     }
 
-                    ty::PredicateAtom::ObjectSafe(trait_def_id) => {
+                    ty::PredicateKind::ObjectSafe(trait_def_id) => {
                         let violations = self.tcx.object_safety_violations(trait_def_id);
                         report_object_safety_error(self.tcx, span, trait_def_id, violations)
                     }
 
-                    ty::PredicateAtom::ClosureKind(closure_def_id, closure_substs, kind) => {
+                    ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
                         let found_kind = self.closure_kind(closure_substs).unwrap();
                         let closure_span =
                             self.tcx.sess.source_map().guess_head_span(
@@ -597,23 +589,23 @@
                         if let Some(typeck_results) = self.in_progress_typeck_results {
                             let typeck_results = typeck_results.borrow();
                             match (found_kind, typeck_results.closure_kind_origins().get(hir_id)) {
-                                (ty::ClosureKind::FnOnce, Some((span, name))) => {
+                                (ty::ClosureKind::FnOnce, Some((span, place))) => {
                                     err.span_label(
                                         *span,
                                         format!(
                                             "closure is `FnOnce` because it moves the \
                                          variable `{}` out of its environment",
-                                            name
+                                            ty::place_to_string_for_capture(tcx, place)
                                         ),
                                     );
                                 }
-                                (ty::ClosureKind::FnMut, Some((span, name))) => {
+                                (ty::ClosureKind::FnMut, Some((span, place))) => {
                                     err.span_label(
                                         *span,
                                         format!(
                                             "closure is `FnMut` because it mutates the \
                                          variable `{}` here",
-                                            name
+                                            ty::place_to_string_for_capture(tcx, place)
                                         ),
                                     );
                                 }
@@ -625,7 +617,7 @@
                         return;
                     }
 
-                    ty::PredicateAtom::WellFormed(ty) => {
+                    ty::PredicateKind::WellFormed(ty) => {
                         if !self.tcx.sess.opts.debugging_opts.chalk {
                             // WF predicates cannot themselves make
                             // errors. They can only block due to
@@ -643,7 +635,7 @@
                         }
                     }
 
-                    ty::PredicateAtom::ConstEvaluatable(..) => {
+                    ty::PredicateKind::ConstEvaluatable(..) => {
                         // Errors for `ConstEvaluatable` predicates show up as
                         // `SelectionError::ConstEvalFailure`,
                         // not `Unimplemented`.
@@ -654,7 +646,7 @@
                         )
                     }
 
-                    ty::PredicateAtom::ConstEquate(..) => {
+                    ty::PredicateKind::ConstEquate(..) => {
                         // Errors for `ConstEquate` predicates show up as
                         // `SelectionError::ConstEvalFailure`,
                         // not `Unimplemented`.
@@ -665,7 +657,7 @@
                         )
                     }
 
-                    ty::PredicateAtom::TypeWellFormedFromEnv(..) => span_bug!(
+                    ty::PredicateKind::TypeWellFormedFromEnv(..) => span_bug!(
                         span,
                         "TypeWellFormedFromEnv predicate should only exist in the environment"
                     ),
@@ -838,7 +830,7 @@
                     .collect::<Vec<ArgKind>>(),
             ),
             Node::Ctor(ref variant_data) => {
-                let span = variant_data.ctor_hir_id().map(|id| hir.span(id)).unwrap_or(DUMMY_SP);
+                let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id));
                 let span = sm.guess_head_span(span);
                 (span, vec![ArgKind::empty(); variant_data.fields().len()])
             }
@@ -1077,9 +1069,9 @@
         }
 
         // FIXME: It should be possible to deal with `ForAll` in a cleaner way.
-        let bound_error = error.bound_atom();
-        let (cond, error) = match (cond.skip_binders(), bound_error.skip_binder()) {
-            (ty::PredicateAtom::Trait(..), ty::PredicateAtom::Trait(error, _)) => {
+        let bound_error = error.kind();
+        let (cond, error) = match (cond.kind().skip_binder(), bound_error.skip_binder()) {
+            (ty::PredicateKind::Trait(..), ty::PredicateKind::Trait(error, _)) => {
                 (cond, bound_error.rebind(error))
             }
             _ => {
@@ -1089,8 +1081,8 @@
         };
 
         for obligation in super::elaborate_predicates(self.tcx, std::iter::once(cond)) {
-            let bound_predicate = obligation.predicate.bound_atom();
-            if let ty::PredicateAtom::Trait(implication, _) = bound_predicate.skip_binder() {
+            let bound_predicate = obligation.predicate.kind();
+            if let ty::PredicateKind::Trait(implication, _) = bound_predicate.skip_binder() {
                 let error = error.to_poly_trait_ref();
                 let implication = bound_predicate.rebind(implication.trait_ref);
                 // FIXME: I'm just not taking associated types at all here.
@@ -1170,8 +1162,8 @@
             //
             // this can fail if the problem was higher-ranked, in which
             // cause I have no idea for a good error message.
-            let bound_predicate = predicate.bound_atom();
-            if let ty::PredicateAtom::Projection(data) = bound_predicate.skip_binder() {
+            let bound_predicate = predicate.kind();
+            if let ty::PredicateKind::Projection(data) = bound_predicate.skip_binder() {
                 let mut selcx = SelectionContext::new(self);
                 let (data, _) = self.replace_bound_vars_with_fresh_vars(
                     obligation.cause.span,
@@ -1368,7 +1360,7 @@
         code: &ObligationCauseCode<'tcx>,
     ) -> Option<(String, Option<Span>)> {
         match code {
-            &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
+            ObligationCauseCode::BuiltinDerivedObligation(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),
@@ -1460,9 +1452,9 @@
             return;
         }
 
-        let bound_predicate = predicate.bound_atom();
+        let bound_predicate = predicate.kind();
         let mut err = match bound_predicate.skip_binder() {
-            ty::PredicateAtom::Trait(data, _) => {
+            ty::PredicateKind::Trait(data, _) => {
                 let trait_ref = bound_predicate.rebind(data.trait_ref);
                 debug!("trait_ref {:?}", trait_ref);
 
@@ -1567,7 +1559,7 @@
                 err
             }
 
-            ty::PredicateAtom::WellFormed(arg) => {
+            ty::PredicateKind::WellFormed(arg) => {
                 // Same hacky approach as above to avoid deluging user
                 // with error messages.
                 if arg.references_error() || self.tcx.sess.has_errors() {
@@ -1577,7 +1569,7 @@
                 self.emit_inference_failure_err(body_id, span, arg, ErrorCode::E0282)
             }
 
-            ty::PredicateAtom::Subtype(data) => {
+            ty::PredicateKind::Subtype(data) => {
                 if data.references_error() || self.tcx.sess.has_errors() {
                     // no need to overload user in such cases
                     return;
@@ -1587,7 +1579,7 @@
                 assert!(a.is_ty_var() && b.is_ty_var());
                 self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282)
             }
-            ty::PredicateAtom::Projection(data) => {
+            ty::PredicateKind::Projection(data) => {
                 let trait_ref = bound_predicate.rebind(data).to_poly_trait_ref(self.tcx);
                 let self_ty = trait_ref.skip_binder().self_ty();
                 let ty = data.ty;
@@ -1717,9 +1709,10 @@
         obligation: &PredicateObligation<'tcx>,
     ) {
         let (pred, item_def_id, span) =
-            match (obligation.predicate.skip_binders(), obligation.cause.code.peel_derives()) {
+            match (obligation.predicate.kind().skip_binder(), obligation.cause.code.peel_derives())
+            {
                 (
-                    ty::PredicateAtom::Trait(pred, _),
+                    ty::PredicateKind::Trait(pred, _),
                     &ObligationCauseCode::BindingObligation(item_def_id, span),
                 ) => (pred, item_def_id, span),
                 _ => return,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 79fea83..1830aaa 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -393,7 +393,7 @@
                 hir::Node::Item(hir::Item {
                     kind:
                         hir::ItemKind::Trait(_, _, generics, _, _)
-                        | hir::ItemKind::Impl { generics, .. },
+                        | hir::ItemKind::Impl(hir::Impl { generics, .. }),
                     ..
                 }) if projection.is_some() => {
                     // Missing restriction on associated type of type parameter (unmet projection).
@@ -416,7 +416,7 @@
                         | hir::ItemKind::Enum(_, generics)
                         | hir::ItemKind::Union(_, generics)
                         | hir::ItemKind::Trait(_, _, generics, ..)
-                        | hir::ItemKind::Impl { generics, .. }
+                        | hir::ItemKind::Impl(hir::Impl { generics, .. })
                         | hir::ItemKind::Fn(_, generics, _)
                         | hir::ItemKind::TyAlias(_, generics)
                         | hir::ItemKind::TraitAlias(generics, _)
@@ -1292,8 +1292,8 @@
         // the type. The last generator (`outer_generator` below) 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.skip_binders() {
-            ty::PredicateAtom::Trait(p, _) => (Some(p.trait_ref), Some(p.self_ty())),
+        let (mut trait_ref, mut target_ty) = match obligation.predicate.kind().skip_binder() {
+            ty::PredicateKind::Trait(p, _) => (Some(p.trait_ref), Some(p.self_ty())),
             _ => (None, None),
         };
         let mut generator = None;
@@ -2278,6 +2278,12 @@
                     self.visit_expr(expr);
                 }
             }
+            hir::ExprKind::If(_, then, else_opt) if self.in_block_tail => {
+                self.visit_expr(then);
+                if let Some(el) = else_opt {
+                    self.visit_expr(el);
+                }
+            }
             hir::ExprKind::Match(_, arms, _) if self.in_block_tail => {
                 for arm in arms {
                     self.visit_expr(arm.body);
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index a04f816..d4ced20 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -345,12 +345,13 @@
 
         let infcx = self.selcx.infcx();
 
-        match *obligation.predicate.kind() {
-            ty::PredicateKind::ForAll(binder) => match binder.skip_binder() {
+        let binder = obligation.predicate.kind();
+        match binder.no_bound_vars() {
+            None => match binder.skip_binder() {
                 // Evaluation will discard candidates using the leak check.
                 // This means we need to pass it the bound version of our
                 // predicate.
-                ty::PredicateAtom::Trait(trait_ref, _constness) => {
+                ty::PredicateKind::Trait(trait_ref, _constness) => {
                     let trait_obligation = obligation.with(binder.rebind(trait_ref));
 
                     self.process_trait_obligation(
@@ -359,7 +360,7 @@
                         &mut pending_obligation.stalled_on,
                     )
                 }
-                ty::PredicateAtom::Projection(data) => {
+                ty::PredicateKind::Projection(data) => {
                     let project_obligation = obligation.with(binder.rebind(data));
 
                     self.process_projection_obligation(
@@ -367,25 +368,25 @@
                         &mut pending_obligation.stalled_on,
                     )
                 }
-                ty::PredicateAtom::RegionOutlives(_)
-                | ty::PredicateAtom::TypeOutlives(_)
-                | ty::PredicateAtom::WellFormed(_)
-                | ty::PredicateAtom::ObjectSafe(_)
-                | ty::PredicateAtom::ClosureKind(..)
-                | ty::PredicateAtom::Subtype(_)
-                | ty::PredicateAtom::ConstEvaluatable(..)
-                | ty::PredicateAtom::ConstEquate(..) => {
+                ty::PredicateKind::RegionOutlives(_)
+                | ty::PredicateKind::TypeOutlives(_)
+                | ty::PredicateKind::WellFormed(_)
+                | ty::PredicateKind::ObjectSafe(_)
+                | ty::PredicateKind::ClosureKind(..)
+                | ty::PredicateKind::Subtype(_)
+                | ty::PredicateKind::ConstEvaluatable(..)
+                | ty::PredicateKind::ConstEquate(..) => {
                     let pred = infcx.replace_bound_vars_with_placeholders(binder);
                     ProcessResult::Changed(mk_pending(vec![
                         obligation.with(pred.to_predicate(self.selcx.tcx())),
                     ]))
                 }
-                ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+                ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                     bug!("TypeWellFormedFromEnv is only used for Chalk")
                 }
             },
-            ty::PredicateKind::Atom(atom) => match atom {
-                ty::PredicateAtom::Trait(data, _) => {
+            Some(pred) => match pred {
+                ty::PredicateKind::Trait(data, _) => {
                     let trait_obligation = obligation.with(Binder::dummy(data));
 
                     self.process_trait_obligation(
@@ -395,14 +396,14 @@
                     )
                 }
 
-                ty::PredicateAtom::RegionOutlives(data) => {
+                ty::PredicateKind::RegionOutlives(data) => {
                     match infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data)) {
                         Ok(()) => ProcessResult::Changed(vec![]),
                         Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)),
                     }
                 }
 
-                ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(t_a, r_b)) => {
+                ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(t_a, r_b)) => {
                     if self.register_region_obligations {
                         self.selcx.infcx().register_region_obligation_with_cause(
                             t_a,
@@ -413,7 +414,7 @@
                     ProcessResult::Changed(vec![])
                 }
 
-                ty::PredicateAtom::Projection(ref data) => {
+                ty::PredicateKind::Projection(ref data) => {
                     let project_obligation = obligation.with(Binder::dummy(*data));
 
                     self.process_projection_obligation(
@@ -422,7 +423,7 @@
                     )
                 }
 
-                ty::PredicateAtom::ObjectSafe(trait_def_id) => {
+                ty::PredicateKind::ObjectSafe(trait_def_id) => {
                     if !self.selcx.tcx().is_object_safe(trait_def_id) {
                         ProcessResult::Error(CodeSelectionError(Unimplemented))
                     } else {
@@ -430,7 +431,7 @@
                     }
                 }
 
-                ty::PredicateAtom::ClosureKind(_, closure_substs, kind) => {
+                ty::PredicateKind::ClosureKind(_, closure_substs, kind) => {
                     match self.selcx.infcx().closure_kind(closure_substs) {
                         Some(closure_kind) => {
                             if closure_kind.extends(kind) {
@@ -443,7 +444,7 @@
                     }
                 }
 
-                ty::PredicateAtom::WellFormed(arg) => {
+                ty::PredicateKind::WellFormed(arg) => {
                     match wf::obligations(
                         self.selcx.infcx(),
                         obligation.param_env,
@@ -461,7 +462,7 @@
                     }
                 }
 
-                ty::PredicateAtom::Subtype(subtype) => {
+                ty::PredicateKind::Subtype(subtype) => {
                     match self.selcx.infcx().subtype_predicate(
                         &obligation.cause,
                         obligation.param_env,
@@ -487,7 +488,7 @@
                     }
                 }
 
-                ty::PredicateAtom::ConstEvaluatable(def_id, substs) => {
+                ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
                     match const_evaluatable::is_const_evaluatable(
                         self.selcx.infcx(),
                         def_id,
@@ -507,7 +508,7 @@
                     }
                 }
 
-                ty::PredicateAtom::ConstEquate(c1, c2) => {
+                ty::PredicateKind::ConstEquate(c1, c2) => {
                     debug!(?c1, ?c2, "equating consts");
                     if self.selcx.tcx().features().const_evaluatable_checked {
                         // FIXME: we probably should only try to unify abstract constants
@@ -593,7 +594,7 @@
                         }
                     }
                 }
-                ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+                ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                     bug!("TypeWellFormedFromEnv is only used for Chalk")
                 }
             },
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 9c894e9..dbc40a2 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -324,7 +324,7 @@
     // TypeOutlives predicates - these are normally used by regionck.
     let outlives_predicates: Vec<_> = predicates
         .drain_filter(|predicate| {
-            matches!(predicate.skip_binders(), ty::PredicateAtom::TypeOutlives(..))
+            matches!(predicate.kind().skip_binder(), ty::PredicateKind::TypeOutlives(..))
         })
         .collect();
 
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 8b6e30f..a972361 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -273,12 +273,12 @@
 ) -> Option<Span> {
     let self_ty = tcx.types.self_param;
     let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into());
-    match predicate.skip_binders() {
-        ty::PredicateAtom::Trait(ref data, _) => {
+    match predicate.kind().skip_binder() {
+        ty::PredicateKind::Trait(ref data, _) => {
             // In the case of a trait predicate, we can skip the "self" type.
             if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
         }
-        ty::PredicateAtom::Projection(ref data) => {
+        ty::PredicateKind::Projection(ref data) => {
             // And similarly for projections. This should be redundant with
             // the previous check because any projection should have a
             // matching `Trait` predicate with the same inputs, but we do
@@ -300,15 +300,15 @@
                 None
             }
         }
-        ty::PredicateAtom::WellFormed(..)
-        | ty::PredicateAtom::ObjectSafe(..)
-        | ty::PredicateAtom::TypeOutlives(..)
-        | ty::PredicateAtom::RegionOutlives(..)
-        | ty::PredicateAtom::ClosureKind(..)
-        | ty::PredicateAtom::Subtype(..)
-        | ty::PredicateAtom::ConstEvaluatable(..)
-        | ty::PredicateAtom::ConstEquate(..)
-        | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
+        ty::PredicateKind::WellFormed(..)
+        | ty::PredicateKind::ObjectSafe(..)
+        | ty::PredicateKind::TypeOutlives(..)
+        | ty::PredicateKind::RegionOutlives(..)
+        | ty::PredicateKind::ClosureKind(..)
+        | ty::PredicateKind::Subtype(..)
+        | ty::PredicateKind::ConstEvaluatable(..)
+        | ty::PredicateKind::ConstEquate(..)
+        | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
     }
 }
 
@@ -328,20 +328,20 @@
     let predicates = tcx.predicates_of(def_id);
     let predicates = predicates.instantiate_identity(tcx).predicates;
     elaborate_predicates(tcx, predicates.into_iter()).any(|obligation| {
-        match obligation.predicate.skip_binders() {
-            ty::PredicateAtom::Trait(ref trait_pred, _) => {
+        match obligation.predicate.kind().skip_binder() {
+            ty::PredicateKind::Trait(ref trait_pred, _) => {
                 trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
             }
-            ty::PredicateAtom::Projection(..)
-            | ty::PredicateAtom::Subtype(..)
-            | ty::PredicateAtom::RegionOutlives(..)
-            | ty::PredicateAtom::WellFormed(..)
-            | ty::PredicateAtom::ObjectSafe(..)
-            | ty::PredicateAtom::ClosureKind(..)
-            | ty::PredicateAtom::TypeOutlives(..)
-            | ty::PredicateAtom::ConstEvaluatable(..)
-            | ty::PredicateAtom::ConstEquate(..)
-            | ty::PredicateAtom::TypeWellFormedFromEnv(..) => false,
+            ty::PredicateKind::Projection(..)
+            | ty::PredicateKind::Subtype(..)
+            | ty::PredicateKind::RegionOutlives(..)
+            | ty::PredicateKind::WellFormed(..)
+            | ty::PredicateKind::ObjectSafe(..)
+            | ty::PredicateKind::ClosureKind(..)
+            | ty::PredicateKind::TypeOutlives(..)
+            | ty::PredicateKind::ConstEvaluatable(..)
+            | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
         }
     })
 }
@@ -843,7 +843,7 @@
         }
 
         fn visit_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
-            if let ty::PredicateAtom::ConstEvaluatable(def, substs) = pred.skip_binders() {
+            if let ty::PredicateKind::ConstEvaluatable(def, substs) = pred.kind().skip_binder() {
                 // FIXME(const_evaluatable_checked): We should probably deduplicate the logic for
                 // `AbstractConst`s here, it might make sense to change `ConstEvaluatable` to
                 // take a `ty::Const` instead.
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index fa05264..75ff931 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -625,7 +625,7 @@
         .obligations
         .iter()
         .filter(|obligation| {
-            let bound_predicate = obligation.predicate.bound_atom();
+            let bound_predicate = obligation.predicate.kind();
             match bound_predicate.skip_binder() {
                 // We found a `T: Foo<X = U>` predicate, let's check
                 // if `U` references any unresolved type
@@ -636,7 +636,7 @@
                 // indirect obligations (e.g., we project to `?0`,
                 // but we have `T: Foo<X = ?1>` and `?1: Bar<X =
                 // ?0>`).
-                ty::PredicateAtom::Projection(data) => {
+                ty::PredicateKind::Projection(data) => {
                     infcx.unresolved_type_vars(&bound_predicate.rebind(data.ty)).is_some()
                 }
 
@@ -917,8 +917,8 @@
     let infcx = selcx.infcx();
     for predicate in env_predicates {
         debug!(?predicate);
-        let bound_predicate = predicate.bound_atom();
-        if let ty::PredicateAtom::Projection(data) = predicate.skip_binders() {
+        let bound_predicate = predicate.kind();
+        if let ty::PredicateKind::Projection(data) = predicate.kind().skip_binder() {
             let data = bound_predicate.rebind(data);
             let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
 
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
index 93ddcb6..de538c6 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
@@ -15,7 +15,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 ty::PredicateAtom::Trait(trait_ref, _) = key.value.predicate.skip_binders() {
+        if let ty::PredicateKind::Trait(trait_ref, _) = key.value.predicate.kind().skip_binder() {
             if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
                 if trait_ref.def_id() == sized_def_id {
                     if trait_ref.self_ty().is_trivially_sized(tcx) {
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 030c291..3015188 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -432,7 +432,7 @@
             .predicates
             .into_iter()
         {
-            if let ty::PredicateAtom::Trait(..) = super_trait.skip_binders() {
+            if let ty::PredicateKind::Trait(..) = super_trait.kind().skip_binder() {
                 let normalized_super_trait = normalize_with_depth_to(
                     self,
                     obligation.param_env,
@@ -641,7 +641,7 @@
             obligations.push(Obligation::new(
                 obligation.cause.clone(),
                 obligation.param_env,
-                ty::PredicateAtom::ClosureKind(closure_def_id, substs, kind)
+                ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)
                     .to_predicate(self.tcx()),
             ));
         }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index a8f8144..614a551 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -69,16 +69,16 @@
 
     pub fn intercrate_ambiguity_hint(&self) -> String {
         match self {
-            &IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => {
-                let self_desc = if let &Some(ref ty) = self_desc {
+            IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } => {
+                let self_desc = if let Some(ty) = self_desc {
                     format!(" for type `{}`", ty)
                 } else {
                     String::new()
                 };
                 format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc)
             }
-            &IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => {
-                let self_desc = if let &Some(ref ty) = self_desc {
+            IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc } => {
+                let self_desc = if let Some(ty) = self_desc {
                     format!(" for type `{}`", ty)
                 } else {
                     String::new()
@@ -89,7 +89,7 @@
                     trait_desc, self_desc
                 )
             }
-            &IntercrateAmbiguityCause::ReservationImpl { ref message } => message.clone(),
+            IntercrateAmbiguityCause::ReservationImpl { message } => message.clone(),
         }
     }
 }
@@ -454,16 +454,16 @@
         }
 
         let result = ensure_sufficient_stack(|| {
-            let bound_predicate = obligation.predicate.bound_atom();
+            let bound_predicate = obligation.predicate.kind();
             match bound_predicate.skip_binder() {
-                ty::PredicateAtom::Trait(t, _) => {
+                ty::PredicateKind::Trait(t, _) => {
                     let t = bound_predicate.rebind(t);
                     debug_assert!(!t.has_escaping_bound_vars());
                     let obligation = obligation.with(t);
                     self.evaluate_trait_predicate_recursively(previous_stack, obligation)
                 }
 
-                ty::PredicateAtom::Subtype(p) => {
+                ty::PredicateKind::Subtype(p) => {
                     let p = bound_predicate.rebind(p);
                     // Does this code ever run?
                     match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
@@ -479,7 +479,7 @@
                     }
                 }
 
-                ty::PredicateAtom::WellFormed(arg) => match wf::obligations(
+                ty::PredicateKind::WellFormed(arg) => match wf::obligations(
                     self.infcx,
                     obligation.param_env,
                     obligation.cause.body_id,
@@ -494,12 +494,12 @@
                     None => Ok(EvaluatedToAmbig),
                 },
 
-                ty::PredicateAtom::TypeOutlives(..) | ty::PredicateAtom::RegionOutlives(..) => {
+                ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::RegionOutlives(..) => {
                     // We do not consider region relationships when evaluating trait matches.
                     Ok(EvaluatedToOkModuloRegions)
                 }
 
-                ty::PredicateAtom::ObjectSafe(trait_def_id) => {
+                ty::PredicateKind::ObjectSafe(trait_def_id) => {
                     if self.tcx().is_object_safe(trait_def_id) {
                         Ok(EvaluatedToOk)
                     } else {
@@ -507,7 +507,7 @@
                     }
                 }
 
-                ty::PredicateAtom::Projection(data) => {
+                ty::PredicateKind::Projection(data) => {
                     let data = bound_predicate.rebind(data);
                     let project_obligation = obligation.with(data);
                     match project::poly_project_and_unify_type(self, &project_obligation) {
@@ -528,7 +528,7 @@
                     }
                 }
 
-                ty::PredicateAtom::ClosureKind(_, closure_substs, kind) => {
+                ty::PredicateKind::ClosureKind(_, closure_substs, kind) => {
                     match self.infcx.closure_kind(closure_substs) {
                         Some(closure_kind) => {
                             if closure_kind.extends(kind) {
@@ -541,7 +541,7 @@
                     }
                 }
 
-                ty::PredicateAtom::ConstEvaluatable(def_id, substs) => {
+                ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
                     match const_evaluatable::is_const_evaluatable(
                         self.infcx,
                         def_id,
@@ -555,7 +555,7 @@
                     }
                 }
 
-                ty::PredicateAtom::ConstEquate(c1, c2) => {
+                ty::PredicateKind::ConstEquate(c1, c2) => {
                     debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts");
 
                     let evaluate = |c: &'tcx ty::Const<'tcx>| {
@@ -598,7 +598,7 @@
                         }
                     }
                 }
-                ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+                ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                     bug!("TypeWellFormedFromEnv is only used for chalk")
                 }
             }
@@ -845,8 +845,8 @@
     }
 
     fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
-        let result = match predicate.skip_binders() {
-            ty::PredicateAtom::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()),
+        let result = match predicate.kind().skip_binder() {
+            ty::PredicateKind::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()),
             _ => false,
         };
         debug!(?predicate, ?result, "coinductive_predicate");
@@ -1174,8 +1174,8 @@
             .iter()
             .enumerate()
             .filter_map(|(idx, bound)| {
-                let bound_predicate = bound.bound_atom();
-                if let ty::PredicateAtom::Trait(pred, _) = bound_predicate.skip_binder() {
+                let bound_predicate = bound.kind();
+                if let ty::PredicateKind::Trait(pred, _) = bound_predicate.skip_binder() {
                     let bound = bound_predicate.rebind(pred.trait_ref);
                     if self.infcx.probe(|_| {
                         match self.match_normalize_trait_ref(
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 3f58fd7..e6ef9b1 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -106,28 +106,28 @@
     };
 
     // It's ok to skip the binder here because wf code is prepared for it
-    match predicate.skip_binders() {
-        ty::PredicateAtom::Trait(t, _) => {
+    match predicate.kind().skip_binder() {
+        ty::PredicateKind::Trait(t, _) => {
             wf.compute_trait_ref(&t.trait_ref, Elaborate::None);
         }
-        ty::PredicateAtom::RegionOutlives(..) => {}
-        ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
+        ty::PredicateKind::RegionOutlives(..) => {}
+        ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
             wf.compute(ty.into());
         }
-        ty::PredicateAtom::Projection(t) => {
+        ty::PredicateKind::Projection(t) => {
             wf.compute_projection(t.projection_ty);
             wf.compute(t.ty.into());
         }
-        ty::PredicateAtom::WellFormed(arg) => {
+        ty::PredicateKind::WellFormed(arg) => {
             wf.compute(arg);
         }
-        ty::PredicateAtom::ObjectSafe(_) => {}
-        ty::PredicateAtom::ClosureKind(..) => {}
-        ty::PredicateAtom::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ }) => {
+        ty::PredicateKind::ObjectSafe(_) => {}
+        ty::PredicateKind::ClosureKind(..) => {}
+        ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ }) => {
             wf.compute(a.into());
             wf.compute(b.into());
         }
-        ty::PredicateAtom::ConstEvaluatable(def, substs) => {
+        ty::PredicateKind::ConstEvaluatable(def, substs) => {
             let obligations = wf.nominal_obligations(def.did, substs);
             wf.out.extend(obligations);
 
@@ -135,11 +135,11 @@
                 wf.compute(arg);
             }
         }
-        ty::PredicateAtom::ConstEquate(c1, c2) => {
+        ty::PredicateKind::ConstEquate(c1, c2) => {
             wf.compute(c1.into());
             wf.compute(c2.into());
         }
-        ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+        ty::PredicateKind::TypeWellFormedFromEnv(..) => {
             bug!("TypeWellFormedFromEnv is only used for Chalk")
         }
     }
@@ -199,7 +199,7 @@
         trait_ref, item, cause, pred
     );
     let items = match item {
-        Some(hir::Item { kind: hir::ItemKind::Impl { items, .. }, .. }) => items,
+        Some(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.items,
         _ => return,
     };
     let fix_span =
@@ -209,8 +209,8 @@
         };
 
     // It is fine to skip the binder as we don't care about regions here.
-    match pred.skip_binders() {
-        ty::PredicateAtom::Projection(proj) => {
+    match pred.kind().skip_binder() {
+        ty::PredicateKind::Projection(proj) => {
             // The obligation comes not from the current `impl` nor the `trait` being implemented,
             // but rather from a "second order" obligation, where an associated type has a
             // projection coming from another associated type. See
@@ -225,7 +225,7 @@
                 }
             }
         }
-        ty::PredicateAtom::Trait(pred, _) => {
+        ty::PredicateKind::Trait(pred, _) => {
             // An associated item obligation born out of the `trait` failed to be met. An example
             // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
             debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
@@ -333,7 +333,9 @@
                     let mut new_cause = cause.clone();
                     // The first subst is the self ty - use the correct span for it.
                     if i == 0 {
-                        if let Some(hir::ItemKind::Impl { self_ty, .. }) = item.map(|i| &i.kind) {
+                        if let Some(hir::ItemKind::Impl(hir::Impl { self_ty, .. })) =
+                            item.map(|i| &i.kind)
+                        {
                             new_cause.make_mut().span = self_ty.span;
                         }
                     }
@@ -341,7 +343,7 @@
                         new_cause,
                         depth,
                         param_env,
-                        ty::PredicateAtom::WellFormed(arg).to_predicate(tcx),
+                        ty::PredicateKind::WellFormed(arg).to_predicate(tcx),
                     )
                 }),
         );
@@ -391,7 +393,7 @@
                         cause.clone(),
                         depth,
                         param_env,
-                        ty::PredicateAtom::WellFormed(arg).to_predicate(tcx),
+                        ty::PredicateKind::WellFormed(arg).to_predicate(tcx),
                     )
                 }),
         );
@@ -434,7 +436,7 @@
                             let obligations = self.nominal_obligations(def.did, substs);
                             self.out.extend(obligations);
 
-                            let predicate = ty::PredicateAtom::ConstEvaluatable(def, substs)
+                            let predicate = ty::PredicateKind::ConstEvaluatable(def, substs)
                                 .to_predicate(self.tcx());
                             let cause = self.cause(traits::MiscObligation);
                             self.out.push(traits::Obligation::with_depth(
@@ -458,7 +460,7 @@
                                     cause,
                                     self.recursion_depth,
                                     self.param_env,
-                                    ty::PredicateAtom::WellFormed(resolved_constant.into())
+                                    ty::PredicateKind::WellFormed(resolved_constant.into())
                                         .to_predicate(self.tcx()),
                                 ));
                             }
@@ -545,7 +547,7 @@
                             cause,
                             depth,
                             param_env,
-                            ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(rty, r))
+                            ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(rty, r))
                                 .to_predicate(self.tcx()),
                         ));
                     }
@@ -635,7 +637,7 @@
                                 cause.clone(),
                                 depth,
                                 param_env,
-                                ty::PredicateAtom::ObjectSafe(did).to_predicate(tcx),
+                                ty::PredicateKind::ObjectSafe(did).to_predicate(tcx),
                             )
                         }));
                     }
@@ -662,7 +664,7 @@
                             cause,
                             self.recursion_depth,
                             param_env,
-                            ty::PredicateAtom::WellFormed(ty.into()).to_predicate(self.tcx()),
+                            ty::PredicateKind::WellFormed(ty.into()).to_predicate(self.tcx()),
                         ));
                     } else {
                         // Yes, resolved, proceed with the result.
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 8aa68e5..48d4705 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -81,39 +81,36 @@
         interner: &RustInterner<'tcx>,
     ) -> chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'tcx>>> {
         let clauses = self.environment.into_iter().map(|predicate| {
-            let (predicate, binders, _named_regions) = collect_bound_vars(
-                interner,
-                interner.tcx,
-                predicate.bound_atom_with_opt_escaping(interner.tcx),
-            );
+            let (predicate, binders, _named_regions) =
+                collect_bound_vars(interner, interner.tcx, predicate.kind());
             let consequence = match predicate {
-                ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
+                ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
                     chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty(ty.lower_into(interner)))
                 }
-                ty::PredicateAtom::Trait(predicate, _) => chalk_ir::DomainGoal::FromEnv(
+                ty::PredicateKind::Trait(predicate, _) => chalk_ir::DomainGoal::FromEnv(
                     chalk_ir::FromEnv::Trait(predicate.trait_ref.lower_into(interner)),
                 ),
-                ty::PredicateAtom::RegionOutlives(predicate) => chalk_ir::DomainGoal::Holds(
+                ty::PredicateKind::RegionOutlives(predicate) => chalk_ir::DomainGoal::Holds(
                     chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
                         a: predicate.0.lower_into(interner),
                         b: predicate.1.lower_into(interner),
                     }),
                 ),
-                ty::PredicateAtom::TypeOutlives(predicate) => chalk_ir::DomainGoal::Holds(
+                ty::PredicateKind::TypeOutlives(predicate) => chalk_ir::DomainGoal::Holds(
                     chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
                         ty: predicate.0.lower_into(interner),
                         lifetime: predicate.1.lower_into(interner),
                     }),
                 ),
-                ty::PredicateAtom::Projection(predicate) => chalk_ir::DomainGoal::Holds(
+                ty::PredicateKind::Projection(predicate) => chalk_ir::DomainGoal::Holds(
                     chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)),
                 ),
-                ty::PredicateAtom::WellFormed(..)
-                | ty::PredicateAtom::ObjectSafe(..)
-                | ty::PredicateAtom::ClosureKind(..)
-                | ty::PredicateAtom::Subtype(..)
-                | ty::PredicateAtom::ConstEvaluatable(..)
-                | ty::PredicateAtom::ConstEquate(..) => bug!("unexpected predicate {}", predicate),
+                ty::PredicateKind::WellFormed(..)
+                | ty::PredicateKind::ObjectSafe(..)
+                | ty::PredicateKind::ClosureKind(..)
+                | ty::PredicateKind::Subtype(..)
+                | ty::PredicateKind::ConstEvaluatable(..)
+                | ty::PredicateKind::ConstEquate(..) => bug!("unexpected predicate {}", predicate),
             };
             let value = chalk_ir::ProgramClauseImplication {
                 consequence,
@@ -136,19 +133,16 @@
 
 impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predicate<'tcx> {
     fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::GoalData<RustInterner<'tcx>> {
-        let (predicate, binders, _named_regions) = collect_bound_vars(
-            interner,
-            interner.tcx,
-            self.bound_atom_with_opt_escaping(interner.tcx),
-        );
+        let (predicate, binders, _named_regions) =
+            collect_bound_vars(interner, interner.tcx, self.kind());
 
         let value = match predicate {
-            ty::PredicateAtom::Trait(predicate, _) => {
+            ty::PredicateKind::Trait(predicate, _) => {
                 chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
                     chalk_ir::WhereClause::Implemented(predicate.trait_ref.lower_into(interner)),
                 ))
             }
-            ty::PredicateAtom::RegionOutlives(predicate) => {
+            ty::PredicateKind::RegionOutlives(predicate) => {
                 chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
                     chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
                         a: predicate.0.lower_into(interner),
@@ -156,7 +150,7 @@
                     }),
                 ))
             }
-            ty::PredicateAtom::TypeOutlives(predicate) => {
+            ty::PredicateKind::TypeOutlives(predicate) => {
                 chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
                     chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
                         ty: predicate.0.lower_into(interner),
@@ -164,12 +158,12 @@
                     }),
                 ))
             }
-            ty::PredicateAtom::Projection(predicate) => {
+            ty::PredicateKind::Projection(predicate) => {
                 chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
                     chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)),
                 ))
             }
-            ty::PredicateAtom::WellFormed(arg) => match arg.unpack() {
+            ty::PredicateKind::WellFormed(arg) => match arg.unpack() {
                 GenericArgKind::Type(ty) => match ty.kind() {
                     // FIXME(chalk): In Chalk, a placeholder is WellFormed if it
                     // `FromEnv`. However, when we "lower" Params, we don't update
@@ -189,7 +183,7 @@
                 GenericArgKind::Lifetime(lt) => bug!("unexpect well formed predicate: {:?}", lt),
             },
 
-            ty::PredicateAtom::ObjectSafe(t) => chalk_ir::GoalData::DomainGoal(
+            ty::PredicateKind::ObjectSafe(t) => chalk_ir::GoalData::DomainGoal(
                 chalk_ir::DomainGoal::ObjectSafe(chalk_ir::TraitId(t)),
             ),
 
@@ -197,13 +191,13 @@
             //
             // We can defer this, but ultimately we'll want to express
             // some of these in terms of chalk operations.
-            ty::PredicateAtom::ClosureKind(..)
-            | ty::PredicateAtom::Subtype(..)
-            | ty::PredicateAtom::ConstEvaluatable(..)
-            | ty::PredicateAtom::ConstEquate(..) => {
+            ty::PredicateKind::ClosureKind(..)
+            | ty::PredicateKind::Subtype(..)
+            | ty::PredicateKind::ConstEvaluatable(..)
+            | ty::PredicateKind::ConstEquate(..) => {
                 chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner))
             }
-            ty::PredicateAtom::TypeWellFormedFromEnv(ty) => chalk_ir::GoalData::DomainGoal(
+            ty::PredicateKind::TypeWellFormedFromEnv(ty) => chalk_ir::GoalData::DomainGoal(
                 chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty(ty.lower_into(interner))),
             ),
         };
@@ -573,38 +567,35 @@
         self,
         interner: &RustInterner<'tcx>,
     ) -> Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>> {
-        let (predicate, binders, _named_regions) = collect_bound_vars(
-            interner,
-            interner.tcx,
-            self.bound_atom_with_opt_escaping(interner.tcx),
-        );
+        let (predicate, binders, _named_regions) =
+            collect_bound_vars(interner, interner.tcx, self.kind());
         let value = match predicate {
-            ty::PredicateAtom::Trait(predicate, _) => {
+            ty::PredicateKind::Trait(predicate, _) => {
                 Some(chalk_ir::WhereClause::Implemented(predicate.trait_ref.lower_into(interner)))
             }
-            ty::PredicateAtom::RegionOutlives(predicate) => {
+            ty::PredicateKind::RegionOutlives(predicate) => {
                 Some(chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
                     a: predicate.0.lower_into(interner),
                     b: predicate.1.lower_into(interner),
                 }))
             }
-            ty::PredicateAtom::TypeOutlives(predicate) => {
+            ty::PredicateKind::TypeOutlives(predicate) => {
                 Some(chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
                     ty: predicate.0.lower_into(interner),
                     lifetime: predicate.1.lower_into(interner),
                 }))
             }
-            ty::PredicateAtom::Projection(predicate) => {
+            ty::PredicateKind::Projection(predicate) => {
                 Some(chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)))
             }
-            ty::PredicateAtom::WellFormed(_ty) => None,
+            ty::PredicateKind::WellFormed(_ty) => None,
 
-            ty::PredicateAtom::ObjectSafe(..)
-            | ty::PredicateAtom::ClosureKind(..)
-            | ty::PredicateAtom::Subtype(..)
-            | ty::PredicateAtom::ConstEvaluatable(..)
-            | ty::PredicateAtom::ConstEquate(..)
-            | ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+            ty::PredicateKind::ObjectSafe(..)
+            | ty::PredicateKind::ClosureKind(..)
+            | ty::PredicateKind::Subtype(..)
+            | ty::PredicateKind::ConstEvaluatable(..)
+            | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                 bug!("unexpected predicate {}", &self)
             }
         };
@@ -707,32 +698,29 @@
         self,
         interner: &RustInterner<'tcx>,
     ) -> Option<chalk_solve::rust_ir::QuantifiedInlineBound<RustInterner<'tcx>>> {
-        let (predicate, binders, _named_regions) = collect_bound_vars(
-            interner,
-            interner.tcx,
-            self.bound_atom_with_opt_escaping(interner.tcx),
-        );
+        let (predicate, binders, _named_regions) =
+            collect_bound_vars(interner, interner.tcx, self.kind());
         match predicate {
-            ty::PredicateAtom::Trait(predicate, _) => Some(chalk_ir::Binders::new(
+            ty::PredicateKind::Trait(predicate, _) => Some(chalk_ir::Binders::new(
                 binders,
                 chalk_solve::rust_ir::InlineBound::TraitBound(
                     predicate.trait_ref.lower_into(interner),
                 ),
             )),
-            ty::PredicateAtom::Projection(predicate) => Some(chalk_ir::Binders::new(
+            ty::PredicateKind::Projection(predicate) => Some(chalk_ir::Binders::new(
                 binders,
                 chalk_solve::rust_ir::InlineBound::AliasEqBound(predicate.lower_into(interner)),
             )),
-            ty::PredicateAtom::TypeOutlives(_predicate) => None,
-            ty::PredicateAtom::WellFormed(_ty) => None,
+            ty::PredicateKind::TypeOutlives(_predicate) => None,
+            ty::PredicateKind::WellFormed(_ty) => None,
 
-            ty::PredicateAtom::RegionOutlives(..)
-            | ty::PredicateAtom::ObjectSafe(..)
-            | ty::PredicateAtom::ClosureKind(..)
-            | ty::PredicateAtom::Subtype(..)
-            | ty::PredicateAtom::ConstEvaluatable(..)
-            | ty::PredicateAtom::ConstEquate(..)
-            | ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+            ty::PredicateKind::RegionOutlives(..)
+            | ty::PredicateKind::ObjectSafe(..)
+            | ty::PredicateKind::ClosureKind(..)
+            | ty::PredicateKind::Subtype(..)
+            | ty::PredicateKind::ConstEvaluatable(..)
+            | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                 bug!("unexpected predicate {}", &self)
             }
         }
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index 97017fb..90ba902 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -94,27 +94,27 @@
         // region relationships.
         implied_bounds.extend(obligations.into_iter().flat_map(|obligation| {
             assert!(!obligation.has_escaping_bound_vars());
-            match obligation.predicate.kind() {
-                &ty::PredicateKind::ForAll(..) => vec![],
-                &ty::PredicateKind::Atom(atom) => match atom {
-                    ty::PredicateAtom::Trait(..)
-                    | ty::PredicateAtom::Subtype(..)
-                    | ty::PredicateAtom::Projection(..)
-                    | ty::PredicateAtom::ClosureKind(..)
-                    | ty::PredicateAtom::ObjectSafe(..)
-                    | ty::PredicateAtom::ConstEvaluatable(..)
-                    | ty::PredicateAtom::ConstEquate(..)
-                    | ty::PredicateAtom::TypeWellFormedFromEnv(..) => vec![],
-                    ty::PredicateAtom::WellFormed(arg) => {
+            match obligation.predicate.kind().no_bound_vars() {
+                None => vec![],
+                Some(pred) => match pred {
+                    ty::PredicateKind::Trait(..)
+                    | ty::PredicateKind::Subtype(..)
+                    | ty::PredicateKind::Projection(..)
+                    | ty::PredicateKind::ClosureKind(..)
+                    | ty::PredicateKind::ObjectSafe(..)
+                    | ty::PredicateKind::ConstEvaluatable(..)
+                    | ty::PredicateKind::ConstEquate(..)
+                    | ty::PredicateKind::TypeWellFormedFromEnv(..) => vec![],
+                    ty::PredicateKind::WellFormed(arg) => {
                         wf_args.push(arg);
                         vec![]
                     }
 
-                    ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
+                    ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
                         vec![OutlivesBound::RegionSubRegion(r_b, r_a)]
                     }
 
-                    ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty_a, r_b)) => {
+                    ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, r_b)) => {
                         let ty_a = infcx.resolve_vars_if_possible(ty_a);
                         let mut components = smallvec![];
                         tcx.push_outlives_components(ty_a, &mut components);
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index 4841e42..1213e55 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -46,16 +46,16 @@
 }
 
 fn not_outlives_predicate(p: &ty::Predicate<'tcx>) -> bool {
-    match p.skip_binders() {
-        ty::PredicateAtom::RegionOutlives(..) | ty::PredicateAtom::TypeOutlives(..) => false,
-        ty::PredicateAtom::Trait(..)
-        | ty::PredicateAtom::Projection(..)
-        | ty::PredicateAtom::WellFormed(..)
-        | ty::PredicateAtom::ObjectSafe(..)
-        | ty::PredicateAtom::ClosureKind(..)
-        | ty::PredicateAtom::Subtype(..)
-        | ty::PredicateAtom::ConstEvaluatable(..)
-        | ty::PredicateAtom::ConstEquate(..)
-        | ty::PredicateAtom::TypeWellFormedFromEnv(..) => true,
+    match p.kind().skip_binder() {
+        ty::PredicateKind::RegionOutlives(..) | ty::PredicateKind::TypeOutlives(..) => false,
+        ty::PredicateKind::Trait(..)
+        | ty::PredicateKind::Projection(..)
+        | ty::PredicateKind::WellFormed(..)
+        | ty::PredicateKind::ObjectSafe(..)
+        | ty::PredicateKind::ClosureKind(..)
+        | ty::PredicateKind::Subtype(..)
+        | ty::PredicateKind::ConstEvaluatable(..)
+        | ty::PredicateKind::ConstEquate(..)
+        | ty::PredicateKind::TypeWellFormedFromEnv(..) => true,
     }
 }
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index 0addde5..6304f69 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -140,7 +140,7 @@
             self.relate(self_ty, Variance::Invariant, impl_self_ty)?;
 
             self.prove_predicate(
-                ty::PredicateAtom::WellFormed(impl_self_ty.into()).to_predicate(self.tcx()),
+                ty::PredicateKind::WellFormed(impl_self_ty.into()).to_predicate(self.tcx()),
             );
         }
 
@@ -155,7 +155,7 @@
         // them?  This would only be relevant if some input
         // type were ill-formed but did not appear in `ty`,
         // which...could happen with normalization...
-        self.prove_predicate(ty::PredicateAtom::WellFormed(ty.into()).to_predicate(self.tcx()));
+        self.prove_predicate(ty::PredicateKind::WellFormed(ty.into()).to_predicate(self.tcx()));
         Ok(())
     }
 }
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index aa1de6d..bd1d9cc 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -5,7 +5,7 @@
 use rustc_middle::hir::map as hir_map;
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{
-    self, Binder, Predicate, PredicateAtom, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness,
+    self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness,
 };
 use rustc_session::CrateDisambiguator;
 use rustc_span::symbol::Symbol;
@@ -129,8 +129,8 @@
     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) {
+        hir::ItemKind::Impl(ref impl_) => {
+            if let Some(impl_item_ref) = impl_.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);
@@ -160,8 +160,8 @@
 fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     let item = tcx.hir().expect_item(hir_id);
-    if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
-        defaultness
+    if let hir::ItemKind::Impl(impl_) = &item.kind {
+        impl_.defaultness
     } else {
         bug!("`impl_defaultness` called on {:?}", item);
     }
@@ -201,8 +201,9 @@
                 .map(|trait_item_ref| trait_item_ref.id)
                 .map(|id| tcx.hir().local_def_id(id.hir_id).to_def_id()),
         ),
-        hir::ItemKind::Impl { ref items, .. } => tcx.arena.alloc_from_iter(
-            items
+        hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter(
+            impl_
+                .items
                 .iter()
                 .map(|impl_item_ref| impl_item_ref.id)
                 .map(|id| tcx.hir().local_def_id(id.hir_id).to_def_id()),
@@ -221,6 +222,10 @@
     tcx.hir().span_if_local(def_id).unwrap()
 }
 
+fn def_ident_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
+    tcx.hir().get_if_local(def_id).and_then(|node| node.ident()).map(|ident| ident.span)
+}
+
 /// 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`.
@@ -323,8 +328,8 @@
         },
 
         Node::Item(item) => match item.kind {
-            ItemKind::Impl { of_trait: Some(_), .. } => NodeKind::TraitImpl,
-            ItemKind::Impl { of_trait: None, .. } => NodeKind::InherentImpl,
+            ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => NodeKind::TraitImpl,
+            ItemKind::Impl(hir::Impl { of_trait: None, .. }) => NodeKind::InherentImpl,
             ItemKind::Fn(..) => NodeKind::Fn,
             _ => NodeKind::Other,
         },
@@ -373,8 +378,8 @@
     let input_clauses = inputs.into_iter().filter_map(|arg| {
         match arg.unpack() {
             GenericArgKind::Type(ty) => {
-                let binder = Binder::dummy(PredicateAtom::TypeWellFormedFromEnv(ty));
-                Some(tcx.mk_predicate(PredicateKind::ForAll(binder)))
+                let binder = Binder::dummy(PredicateKind::TypeWellFormedFromEnv(ty));
+                Some(tcx.mk_predicate(binder))
             }
 
             // FIXME(eddyb) no WF conditions from lifetimes?
@@ -491,6 +496,7 @@
         associated_items,
         adt_sized_constraint,
         def_span,
+        def_ident_span,
         param_env,
         param_env_reveal_all_normalized,
         trait_of_item,
diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs
index b04acd9..545c301 100644
--- a/compiler/rustc_typeck/src/astconv/errors.rs
+++ b/compiler/rustc_typeck/src/astconv/errors.rs
@@ -96,7 +96,7 @@
         let trait_def = self.tcx().trait_def(trait_def_id);
 
         if !self.tcx().features().unboxed_closures
-            && trait_segment.generic_args().parenthesized != trait_def.paren_sugar
+            && trait_segment.args().parenthesized != trait_def.paren_sugar
         {
             let sess = &self.tcx().sess.parse_sess;
             // For now, require that parenthetical notation be used only with `Fn()` etc.
@@ -126,7 +126,7 @@
                             })
                             .unwrap_or_else(|| "()".to_string()),
                         trait_segment
-                            .generic_args()
+                            .args()
                             .bindings
                             .iter()
                             .find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs
index 0feac03..0797c95 100644
--- a/compiler/rustc_typeck/src/astconv/generics.rs
+++ b/compiler/rustc_typeck/src/astconv/generics.rs
@@ -1,81 +1,92 @@
+use super::IsMethodCall;
 use crate::astconv::{
     AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
     GenericArgCountResult, GenericArgPosition,
 };
 use crate::errors::AssocTypeBindingNotAllowed;
+use crate::structured_errors::{StructuredDiagnostic, WrongNumberOfGenericArgs};
 use rustc_ast::ast::ParamKindOrd;
-use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorReported};
+use rustc_errors::{struct_span_err, Applicability, ErrorReported};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
 use rustc_middle::ty::{
     self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, Ty, TyCtxt,
 };
-use rustc_session::{lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, Session};
+use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS;
 use rustc_span::{symbol::kw, MultiSpan, Span};
-
 use smallvec::SmallVec;
 
 impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     /// Report an error that a generic argument did not match the generic parameter that was
     /// expected.
     fn generic_arg_mismatch_err(
-        sess: &Session,
+        tcx: TyCtxt<'_>,
         arg: &GenericArg<'_>,
-        kind: &'static str,
+        param: &GenericParamDef,
         possible_ordering_error: bool,
         help: Option<&str>,
     ) {
+        let sess = tcx.sess;
         let mut err = struct_span_err!(
             sess,
             arg.span(),
             E0747,
             "{} provided when a {} was expected",
             arg.descr(),
-            kind,
+            param.kind.descr(),
         );
 
-        let unordered = sess.features_untracked().const_generics;
-        let kind_ord = match kind {
-            "lifetime" => ParamKindOrd::Lifetime,
-            "type" => ParamKindOrd::Type,
-            "constant" => ParamKindOrd::Const { unordered },
-            // It's more concise to match on the string representation, though it means
-            // the match is non-exhaustive.
-            _ => bug!("invalid generic parameter kind {}", kind),
-        };
-
-        if let ParamKindOrd::Const { .. } = kind_ord {
+        if let GenericParamDefKind::Const { .. } = param.kind {
             if let GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. }) = arg {
                 err.help("const arguments cannot yet be inferred with `_`");
             }
         }
 
-        let arg_ord = match arg {
-            GenericArg::Lifetime(_) => ParamKindOrd::Lifetime,
-            GenericArg::Type(_) => ParamKindOrd::Type,
-            GenericArg::Const(_) => ParamKindOrd::Const { unordered },
-        };
-
-        if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Path { .. }, .. }))
-            && matches!(kind_ord, ParamKindOrd::Const { .. })
-        {
-            let suggestions = vec![
-                (arg.span().shrink_to_lo(), String::from("{ ")),
-                (arg.span().shrink_to_hi(), String::from(" }")),
-            ];
-            err.multipart_suggestion(
-                "if this generic argument was intended as a const parameter, \
+        // Specific suggestion set for diagnostics
+        match (arg, &param.kind) {
+            (
+                GenericArg::Type(hir::Ty { kind: hir::TyKind::Path { .. }, .. }),
+                GenericParamDefKind::Const { .. },
+            ) => {
+                let suggestions = vec![
+                    (arg.span().shrink_to_lo(), String::from("{ ")),
+                    (arg.span().shrink_to_hi(), String::from(" }")),
+                ];
+                err.multipart_suggestion(
+                    "if this generic argument was intended as a const parameter, \
                 try surrounding it with braces:",
-                suggestions,
-                Applicability::MaybeIncorrect,
-            );
+                    suggestions,
+                    Applicability::MaybeIncorrect,
+                );
+            }
+            (
+                GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
+                GenericParamDefKind::Const { .. },
+            ) if tcx.type_of(param.def_id) == tcx.types.usize => {
+                let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id));
+                if let Ok(snippet) = snippet {
+                    err.span_suggestion(
+                        arg.span(),
+                        "array type provided where a `usize` was expected, try",
+                        format!("{{ {} }}", snippet),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+            }
+            _ => {}
         }
 
+        let kind_ord = param.kind.to_ord(tcx);
+        let arg_ord = arg.to_ord(&tcx.features());
+
         // This note is only true when generic parameters are strictly ordered by their kind.
         if possible_ordering_error && kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal {
-            let (first, last) =
-                if kind_ord < arg_ord { (kind, arg.descr()) } else { (arg.descr(), kind) };
+            let (first, last) = if kind_ord < arg_ord {
+                (param.kind.descr(), arg.descr())
+            } else {
+                (arg.descr(), param.kind.descr())
+            };
             err.note(&format!("{} arguments must be provided before {} arguments", first, last));
             if let Some(help) = help {
                 err.help(help);
@@ -203,7 +214,7 @@
                                 // We expected a lifetime argument, but got a type or const
                                 // argument. That means we're inferring the lifetimes.
                                 substs.push(ctx.inferred_kind(None, param, infer_args));
-                                force_infer_lt = Some(arg);
+                                force_infer_lt = Some((arg, param));
                                 params.next();
                             }
                             (GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => {
@@ -213,7 +224,7 @@
                                 // ignore it.
                                 args.next();
                             }
-                            (_, kind, _) => {
+                            (_, _, _) => {
                                 // We expected one kind of parameter, but the user provided
                                 // another. This is an error. However, if we already know that
                                 // the arguments don't match up with the parameters, we won't issue
@@ -256,9 +267,9 @@
                                     param_types_present.dedup();
 
                                     Self::generic_arg_mismatch_err(
-                                        tcx.sess,
+                                        tcx,
                                         arg,
-                                        kind.descr(),
+                                        param,
                                         !args_iter.clone().is_sorted_by_key(|arg| match arg {
                                             GenericArg::Lifetime(_) => ParamKindOrd::Lifetime,
                                             GenericArg::Type(_) => ParamKindOrd::Type,
@@ -315,9 +326,9 @@
                         {
                             let kind = arg.descr();
                             assert_eq!(kind, "lifetime");
-                            let provided =
+                            let (provided_arg, param) =
                                 force_infer_lt.expect("lifetimes ought to have been inferred");
-                            Self::generic_arg_mismatch_err(tcx.sess, provided, kind, false, None);
+                            Self::generic_arg_mismatch_err(tcx, provided_arg, param, false, None);
                         }
 
                         break;
@@ -343,20 +354,25 @@
     pub fn check_generic_arg_count_for_call(
         tcx: TyCtxt<'_>,
         span: Span,
-        def: &ty::Generics,
+        def_id: DefId,
+        generics: &ty::Generics,
         seg: &hir::PathSegment<'_>,
-        is_method_call: bool,
+        is_method_call: IsMethodCall,
     ) -> GenericArgCountResult {
         let empty_args = hir::GenericArgs::none();
-        let suppress_mismatch = Self::check_impl_trait(tcx, seg, &def);
+        let suppress_mismatch = Self::check_impl_trait(tcx, seg, &generics);
+
+        let gen_args = seg.args.unwrap_or(&empty_args);
+        let gen_pos = if is_method_call == IsMethodCall::Yes {
+            GenericArgPosition::MethodCall
+        } else {
+            GenericArgPosition::Value
+        };
+        let has_self = generics.parent.is_none() && generics.has_self;
+        let infer_args = seg.infer_args || suppress_mismatch;
+
         Self::check_generic_arg_count(
-            tcx,
-            span,
-            def,
-            if let Some(ref args) = seg.args { args } else { &empty_args },
-            if is_method_call { GenericArgPosition::MethodCall } else { GenericArgPosition::Value },
-            def.parent.is_none() && def.has_self, // `has_self`
-            seg.infer_args || suppress_mismatch,  // `infer_args`
+            tcx, span, def_id, seg, generics, gen_args, gen_pos, has_self, infer_args,
         )
     }
 
@@ -365,156 +381,109 @@
     pub(crate) fn check_generic_arg_count(
         tcx: TyCtxt<'_>,
         span: Span,
-        def: &ty::Generics,
-        args: &hir::GenericArgs<'_>,
-        position: GenericArgPosition,
+        def_id: DefId,
+        seg: &hir::PathSegment<'_>,
+        gen_params: &ty::Generics,
+        gen_args: &hir::GenericArgs<'_>,
+        gen_pos: GenericArgPosition,
         has_self: bool,
         infer_args: bool,
     ) -> GenericArgCountResult {
-        // At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
-        // that lifetimes will proceed types. So it suffices to check the number of each generic
-        // arguments in order to validate them with respect to the generic parameters.
-        let param_counts = def.own_counts();
+        let default_counts = gen_params.own_defaults();
+        let param_counts = gen_params.own_counts();
         let named_type_param_count = param_counts.types - has_self as usize;
-        let arg_counts = args.own_counts();
-        let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
+        let arg_counts = gen_args.own_counts();
+        let infer_lifetimes = gen_pos != GenericArgPosition::Type && arg_counts.lifetimes == 0;
 
-        let mut defaults: ty::GenericParamCount = Default::default();
-        for param in &def.params {
-            match param.kind {
-                GenericParamDefKind::Lifetime => {}
-                GenericParamDefKind::Type { has_default, .. } => {
-                    defaults.types += has_default as usize
-                }
-                GenericParamDefKind::Const => {
-                    // FIXME(const_generics:defaults)
-                }
-            };
-        }
-
-        if position != GenericArgPosition::Type && !args.bindings.is_empty() {
-            AstConv::prohibit_assoc_ty_binding(tcx, args.bindings[0].span);
+        if gen_pos != GenericArgPosition::Type && !gen_args.bindings.is_empty() {
+            Self::prohibit_assoc_ty_binding(tcx, gen_args.bindings[0].span);
         }
 
         let explicit_late_bound =
-            Self::prohibit_explicit_late_bound_lifetimes(tcx, def, args, position);
+            Self::prohibit_explicit_late_bound_lifetimes(tcx, gen_params, gen_args, gen_pos);
 
-        let check_kind_count = |kind,
-                                required,
-                                permitted,
-                                provided,
-                                offset,
-                                unexpected_spans: &mut Vec<Span>,
-                                silent| {
-            debug!(
-                "check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}",
-                kind, required, permitted, provided, offset
-            );
-            // We enforce the following: `required` <= `provided` <= `permitted`.
-            // For kinds without defaults (e.g.., lifetimes), `required == permitted`.
-            // For other kinds (i.e., types), `permitted` may be greater than `required`.
-            if required <= provided && provided <= permitted {
-                return true;
-            }
+        let mut invalid_args = vec![];
 
-            if silent {
-                return false;
-            }
-
-            // Unfortunately lifetime and type parameter mismatches are typically styled
-            // differently in diagnostics, which means we have a few cases to consider here.
-            let (bound, quantifier) = if required != permitted {
-                if provided < required {
-                    (required, "at least ")
-                } else {
-                    // provided > permitted
-                    (permitted, "at most ")
+        let mut check_generics =
+            |kind, expected_min, expected_max, provided, params_offset, args_offset, silent| {
+                if (expected_min..=expected_max).contains(&provided) {
+                    return true;
                 }
-            } else {
-                (required, "")
+
+                if silent {
+                    return false;
+                }
+
+                if provided > expected_max {
+                    invalid_args.extend(
+                        gen_args.args[args_offset + expected_max..args_offset + provided]
+                            .iter()
+                            .map(|arg| arg.span()),
+                    );
+                };
+
+                WrongNumberOfGenericArgs {
+                    tcx,
+                    kind,
+                    expected_min,
+                    expected_max,
+                    provided,
+                    params_offset,
+                    args_offset,
+                    path_segment: seg,
+                    gen_params,
+                    gen_args,
+                    def_id,
+                    span,
+                }
+                .diagnostic()
+                .emit();
+
+                false
             };
 
-            let (spans, labels) = if provided > permitted {
-                // In the case when the user has provided too many arguments,
-                // we want to point to the unexpected arguments.
-                let (spans, labels): (Vec<Span>, Vec<String>) = args.args
-                    [offset + permitted..offset + provided]
-                    .iter()
-                    .map(|arg| (arg.span(), format!("unexpected {} argument", arg.short_descr())))
-                    .unzip();
-                unexpected_spans.extend(spans.clone());
-                (spans, labels)
-            } else {
-                (
-                    vec![span],
-                    vec![format!(
-                        "expected {}{} {} argument{}",
-                        quantifier,
-                        bound,
-                        kind,
-                        pluralize!(bound),
-                    )],
-                )
-            };
-
-            let mut err = tcx.sess.struct_span_err_with_code(
-                spans.clone(),
-                &format!(
-                    "wrong number of {} arguments: expected {}{}, found {}",
-                    kind, quantifier, bound, provided,
-                ),
-                DiagnosticId::Error("E0107".into()),
-            );
-            for (span, label) in spans.into_iter().zip(labels) {
-                err.span_label(span, label.as_str());
-            }
-            err.emit();
-            false
-        };
-
-        let mut unexpected_spans = vec![];
-
-        let lifetime_count_correct = check_kind_count(
+        let lifetimes_correct = check_generics(
             "lifetime",
             if infer_lifetimes { 0 } else { param_counts.lifetimes },
             param_counts.lifetimes,
             arg_counts.lifetimes,
+            has_self as usize,
             0,
-            &mut unexpected_spans,
             explicit_late_bound == ExplicitLateBound::Yes,
         );
 
-        let kind_str = if param_counts.consts + arg_counts.consts == 0 {
-            "type"
-        } else if named_type_param_count + arg_counts.types == 0 {
-            "const"
-        } else {
-            "generic"
-        };
+        let args_correct = {
+            let kind = if param_counts.consts + arg_counts.consts == 0 {
+                "type"
+            } else if named_type_param_count + arg_counts.types == 0 {
+                "const"
+            } else {
+                "generic"
+            };
 
-        let arg_count_correct = check_kind_count(
-            kind_str,
-            if infer_args {
+            let expected_min = if infer_args {
                 0
             } else {
-                param_counts.consts + named_type_param_count - defaults.types
-            },
-            param_counts.consts + named_type_param_count,
-            arg_counts.consts + arg_counts.types,
-            arg_counts.lifetimes,
-            &mut unexpected_spans,
-            false,
-        );
+                param_counts.consts + named_type_param_count - default_counts.types
+            };
+
+            check_generics(
+                kind,
+                expected_min,
+                param_counts.consts + named_type_param_count,
+                arg_counts.consts + arg_counts.types,
+                param_counts.lifetimes + has_self as usize,
+                arg_counts.lifetimes,
+                false,
+            )
+        };
 
         GenericArgCountResult {
             explicit_late_bound,
-            correct: if lifetime_count_correct && arg_count_correct {
+            correct: if lifetimes_correct && args_correct {
                 Ok(())
             } else {
-                Err(GenericArgCountMismatch {
-                    reported: Some(ErrorReported),
-                    invalid_args: unexpected_spans,
-                })
+                Err(GenericArgCountMismatch { reported: Some(ErrorReported), invalid_args })
             },
         }
     }
@@ -539,7 +508,7 @@
 
         if explicit && impl_trait {
             let spans = seg
-                .generic_args()
+                .args()
                 .args
                 .iter()
                 .filter_map(|arg| match arg {
@@ -584,12 +553,15 @@
         let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
 
         if infer_lifetimes {
-            ExplicitLateBound::No
-        } else if let Some(span_late) = def.has_late_bound_regions {
+            return ExplicitLateBound::No;
+        }
+
+        if let Some(span_late) = def.has_late_bound_regions {
             let msg = "cannot specify lifetime arguments explicitly \
                        if late bound lifetime parameters are present";
             let note = "the late bound lifetime parameter is introduced here";
             let span = args.args[0].span();
+
             if position == GenericArgPosition::Value
                 && arg_counts.lifetimes != param_counts.lifetimes
             {
@@ -606,6 +578,7 @@
                     |lint| lint.build(msg).emit(),
                 );
             }
+
             ExplicitLateBound::Yes
         } else {
             ExplicitLateBound::No
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 38d33e5..059f9b4 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -138,6 +138,12 @@
     No,
 }
 
+#[derive(Copy, Clone, PartialEq)]
+pub enum IsMethodCall {
+    Yes,
+    No,
+}
+
 /// Denotes the "position" of a generic argument, indicating if it is a generic type,
 /// generic function or generic method call.
 #[derive(Copy, Clone, PartialEq)]
@@ -252,7 +258,8 @@
             span,
             def_id,
             &[],
-            item_segment.generic_args(),
+            item_segment,
+            item_segment.args(),
             item_segment.infer_args,
             None,
         );
@@ -300,6 +307,7 @@
         span: Span,
         def_id: DefId,
         parent_substs: &[subst::GenericArg<'tcx>],
+        seg: &hir::PathSegment<'_>,
         generic_args: &'a hir::GenericArgs<'_>,
         infer_args: bool,
         self_ty: Option<Ty<'tcx>>,
@@ -314,10 +322,10 @@
         );
 
         let tcx = self.tcx();
-        let generic_params = tcx.generics_of(def_id);
+        let generics = tcx.generics_of(def_id);
 
-        if generic_params.has_self {
-            if generic_params.parent.is_some() {
+        if generics.has_self {
+            if generics.parent.is_some() {
                 // The parent is a trait so it should have at least one subst
                 // for the `Self` type.
                 assert!(!parent_substs.is_empty())
@@ -332,7 +340,9 @@
         let arg_count = Self::check_generic_arg_count(
             tcx,
             span,
-            &generic_params,
+            def_id,
+            seg,
+            &generics,
             &generic_args,
             GenericArgPosition::Type,
             self_ty.is_some(),
@@ -343,7 +353,7 @@
         // Traits always have `Self` as a generic parameter, which means they will not return early
         // here and so associated type bindings will be handled regardless of whether there are any
         // non-`Self` generic parameters.
-        if generic_params.params.len() == 0 {
+        if generics.params.len() == 0 {
             return (tcx.intern_substs(&[]), vec![], arg_count);
         }
 
@@ -486,7 +496,7 @@
                     }
                     GenericParamDefKind::Const => {
                         let ty = tcx.at(self.span).type_of(param.def_id);
-                        // FIXME(const_generics:defaults)
+                        // FIXME(const_generics_defaults)
                         if infer_args {
                             // No const parameters were provided, we can infer all.
                             self.astconv.ct_infer(ty, Some(param), self.span).into()
@@ -553,7 +563,7 @@
 
         debug!(
             "create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}",
-            generic_params, self_ty, substs
+            generics, self_ty, substs
         );
 
         (substs, assoc_bindings, arg_count)
@@ -576,7 +586,8 @@
                 span,
                 item_def_id,
                 parent_substs,
-                item_segment.generic_args(),
+                item_segment,
+                item_segment.args(),
                 item_segment.infer_args,
                 None,
             )
@@ -701,8 +712,15 @@
     ) {
         let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span));
 
-        let (substs, assoc_bindings, _) =
-            self.create_substs_for_ast_path(span, trait_def_id, &[], args, false, Some(self_ty));
+        let (substs, assoc_bindings, _) = self.create_substs_for_ast_path(
+            span,
+            trait_def_id,
+            &[],
+            &hir::PathSegment::invalid(),
+            args,
+            false,
+            Some(self_ty),
+        );
         let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
         bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst));
 
@@ -750,7 +768,8 @@
             span,
             trait_def_id,
             &[],
-            trait_segment.generic_args(),
+            trait_segment,
+            trait_segment.args(),
             trait_segment.infer_args,
             Some(self_ty),
         )
@@ -770,7 +789,7 @@
         // Try to find an unbound in bounds.
         let mut unbound = None;
         for ab in ast_bounds {
-            if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
+            if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
                 if unbound.is_none() {
                     unbound = Some(&ptr.trait_ref);
                 } else {
@@ -1076,7 +1095,7 @@
                 dummy_self,
                 &mut bounds,
             ) {
-                potential_assoc_types.extend(cur_potential_assoc_types.into_iter());
+                potential_assoc_types.extend(cur_potential_assoc_types);
             }
         }
 
@@ -1158,9 +1177,9 @@
                     obligation.predicate
                 );
 
-                let bound_predicate = obligation.predicate.bound_atom();
+                let bound_predicate = obligation.predicate.kind();
                 match bound_predicate.skip_binder() {
-                    ty::PredicateAtom::Trait(pred, _) => {
+                    ty::PredicateKind::Trait(pred, _) => {
                         let pred = bound_predicate.rebind(pred);
                         associated_types.entry(span).or_default().extend(
                             tcx.associated_items(pred.def_id())
@@ -1169,7 +1188,7 @@
                                 .map(|item| item.def_id),
                         );
                     }
-                    ty::PredicateAtom::Projection(pred) => {
+                    ty::PredicateKind::Projection(pred) => {
                         let pred = bound_predicate.rebind(pred);
                         // A `Self` within the original bound will be substituted with a
                         // `trait_object_dummy_self`, so check for that.
@@ -1256,17 +1275,15 @@
             })
         });
 
-        let regular_trait_predicates = existential_trait_refs.map(|trait_ref| {
-            trait_ref.map_bound(|trait_ref| ty::ExistentialPredicate::Trait(trait_ref))
-        });
+        let regular_trait_predicates = existential_trait_refs
+            .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait));
         let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| {
             ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()))
         });
         let mut v = regular_trait_predicates
             .chain(auto_trait_predicates)
             .chain(
-                existential_projections
-                    .map(|x| x.map_bound(|x| ty::ExistentialPredicate::Projection(x))),
+                existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)),
             )
             .collect::<SmallVec<[_; 8]>>();
         v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
@@ -1753,7 +1770,7 @@
         let mut has_err = false;
         for segment in segments {
             let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false);
-            for arg in segment.generic_args().args {
+            for arg in segment.args().args {
                 let (span, kind) = match arg {
                     hir::GenericArg::Lifetime(lt) => {
                         if err_for_lt {
@@ -1795,7 +1812,7 @@
             }
 
             // Only emit the first error to avoid overloading the user with error messages.
-            if let [binding, ..] = segment.generic_args().bindings {
+            if let [binding, ..] = segment.args().bindings {
                 has_err = true;
                 Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
             }
@@ -2013,11 +2030,11 @@
                         "generic `Self` types are currently not permitted in anonymous constants",
                     );
                     if let Some(hir::Node::Item(&hir::Item {
-                        kind: hir::ItemKind::Impl { self_ty, .. },
+                        kind: hir::ItemKind::Impl(ref impl_),
                         ..
                     })) = tcx.hir().get_if_local(def_id)
                     {
-                        err.span_note(self_ty.span, "not a concrete type");
+                        err.span_note(impl_.self_ty.span, "not a concrete type");
                     }
                     err.emit();
                     tcx.ty_error()
@@ -2132,6 +2149,7 @@
                     span,
                     def_id,
                     &[],
+                    &hir::PathSegment::invalid(),
                     &GenericArgs::none(),
                     true,
                     None,
diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs
index 6467e04..30e0e3e 100644
--- a/compiler/rustc_typeck/src/check/_match.rs
+++ b/compiler/rustc_typeck/src/check/_match.rs
@@ -1,9 +1,9 @@
-use crate::check::coercion::CoerceMany;
+use crate::check::coercion::{AsCoercionSite, CoerceMany};
 use crate::check::{Diverges, Expectation, FnCtxt, Needs};
 use rustc_hir::{self as hir, ExprKind};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::traits::Obligation;
-use rustc_middle::ty::{self, ToPredicate, Ty};
+use rustc_middle::ty::{self, ToPredicate, Ty, TyS};
 use rustc_span::Span;
 use rustc_trait_selection::opaque_types::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@@ -12,6 +12,41 @@
     StatementAsExpression,
 };
 
+macro_rules! create_maybe_get_coercion_reason {
+    ($fn_name:ident, $node:expr) => {
+        pub(crate) fn $fn_name(&self, hir_id: hir::HirId, sp: Span) -> Option<(Span, String)> {
+            let node = $node(self.tcx.hir(), hir_id);
+            if let hir::Node::Block(block) = node {
+                // check that the body's parent is an fn
+                let parent = self.tcx.hir().get(
+                    self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(block.hir_id)),
+                );
+                if let (
+                    Some(expr),
+                    hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }),
+                ) = (&block.expr, parent)
+                {
+                    // check that the `if` expr without `else` is the fn body's expr
+                    if expr.span == sp {
+                        return self.get_fn_decl(hir_id).and_then(|(fn_decl, _)| {
+                            let span = fn_decl.output.span();
+                            let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?;
+                            Some((
+                                span,
+                                format!("expected `{}` because of this return type", snippet),
+                            ))
+                        });
+                    }
+                }
+            }
+            if let hir::Node::Local(hir::Local { ty: Some(_), pat, .. }) = node {
+                return Some((pat.span, "expected because of this assignment".to_string()));
+            }
+            None
+        }
+    };
+}
+
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn check_match(
         &self,
@@ -25,7 +60,6 @@
 
         use hir::MatchSource::*;
         let (source_if, if_no_else, force_scrutinee_bool) = match match_src {
-            IfDesugar { contains_else_clause } => (true, !contains_else_clause, true),
             IfLetDesugar { contains_else_clause, .. } => (true, !contains_else_clause, false),
             WhileDesugar => (false, false, true),
             _ => (false, false, false),
@@ -115,8 +149,12 @@
             let arm_ty = if source_if
                 && if_no_else
                 && i != 0
-                && self.if_fallback_coercion(expr.span, &arms[0].body, &mut coercion)
-            {
+                && self.if_fallback_coercion(
+                    expr.span,
+                    &arms[0].body,
+                    &mut coercion,
+                    |hir_id, span| self.maybe_get_coercion_reason(hir_id, span),
+                ) {
                 tcx.ty_error()
             } else {
                 // Only call this if this is not an `if` expr with an expected type and no `else`
@@ -125,58 +163,8 @@
             };
             all_arms_diverge &= self.diverges.get();
 
-            // When we have a `match` as a tail expression in a `fn` with a returned `impl Trait`
-            // we check if the different arms would work with boxed trait objects instead and
-            // provide a structured suggestion in that case.
-            let opt_suggest_box_span = match (
-                orig_expected,
-                self.ret_coercion_impl_trait.map(|ty| (self.body_id.owner, ty)),
-            ) {
-                (Expectation::ExpectHasType(expected), Some((id, ty)))
-                    if self.in_tail_expr && self.can_coerce(arm_ty, expected) =>
-                {
-                    let impl_trait_ret_ty = self.infcx.instantiate_opaque_types(
-                        id,
-                        self.body_id,
-                        self.param_env,
-                        ty,
-                        arm.body.span,
-                    );
-                    let mut suggest_box = !impl_trait_ret_ty.obligations.is_empty();
-                    for o in impl_trait_ret_ty.obligations {
-                        match o.predicate.skip_binders_unchecked() {
-                            ty::PredicateAtom::Trait(t, constness) => {
-                                let pred = ty::PredicateAtom::Trait(
-                                    ty::TraitPredicate {
-                                        trait_ref: ty::TraitRef {
-                                            def_id: t.def_id(),
-                                            substs: self.infcx.tcx.mk_substs_trait(arm_ty, &[]),
-                                        },
-                                    },
-                                    constness,
-                                );
-                                let obl = Obligation::new(
-                                    o.cause.clone(),
-                                    self.param_env,
-                                    pred.to_predicate(self.infcx.tcx),
-                                );
-                                suggest_box &= self.infcx.predicate_must_hold_modulo_regions(&obl);
-                                if !suggest_box {
-                                    // We've encountered some obligation that didn't hold, so the
-                                    // return expression can't just be boxed. We don't need to
-                                    // evaluate the rest of the obligations.
-                                    break;
-                                }
-                            }
-                            _ => {}
-                        }
-                    }
-                    // If all the obligations hold (or there are no obligations) the tail expression
-                    // we can suggest to return a boxed trait object instead of an opaque type.
-                    if suggest_box { self.ret_type_span } else { None }
-                }
-                _ => None,
-            };
+            let opt_suggest_box_span =
+                self.opt_suggest_box_span(arm.body.span, arm_ty, orig_expected);
 
             if source_if {
                 let then_expr = &arms[0].body;
@@ -279,7 +267,7 @@
     ) {
         use hir::MatchSource::*;
         let msg = match source {
-            IfDesugar { .. } | IfLetDesugar { .. } => "block in `if` expression",
+            IfLetDesugar { .. } => "block in `if` expression",
             WhileDesugar { .. } | WhileLetDesugar { .. } => "block in `while` expression",
             _ => "arm",
         };
@@ -291,15 +279,20 @@
     /// Handle the fallback arm of a desugared if(-let) like a missing else.
     ///
     /// Returns `true` if there was an error forcing the coercion to the `()` type.
-    fn if_fallback_coercion(
+    pub(crate) fn if_fallback_coercion<F, T>(
         &self,
         span: Span,
         then_expr: &'tcx hir::Expr<'tcx>,
-        coercion: &mut CoerceMany<'tcx, '_, rustc_hir::Arm<'tcx>>,
-    ) -> bool {
+        coercion: &mut CoerceMany<'tcx, '_, T>,
+        ret_reason: F,
+    ) -> bool
+    where
+        F: Fn(hir::HirId, Span) -> Option<(Span, String)>,
+        T: AsCoercionSite,
+    {
         // If this `if` expr is the parent's function return expr,
         // the cause of the type coercion is the return type, point at it. (#25228)
-        let ret_reason = self.maybe_get_coercion_reason(then_expr.hir_id, span);
+        let ret_reason = ret_reason(then_expr.hir_id, span);
         let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse);
         let mut error = false;
         coercion.coerce_forced_unit(
@@ -322,38 +315,25 @@
         error
     }
 
-    fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, span: Span) -> Option<(Span, String)> {
-        use hir::Node::{Block, Item, Local};
-
-        let hir = self.tcx.hir();
-        let arm_id = hir.get_parent_node(hir_id);
-        let match_id = hir.get_parent_node(arm_id);
-        let containing_id = hir.get_parent_node(match_id);
-
-        let node = hir.get(containing_id);
-        if let Block(block) = node {
-            // check that the body's parent is an fn
-            let parent = hir.get(hir.get_parent_node(hir.get_parent_node(block.hir_id)));
-            if let (Some(expr), Item(hir::Item { kind: hir::ItemKind::Fn(..), .. })) =
-                (&block.expr, parent)
-            {
-                // check that the `if` expr without `else` is the fn body's expr
-                if expr.span == span {
-                    return self.get_fn_decl(hir_id).and_then(|(fn_decl, _)| {
-                        let span = fn_decl.output.span();
-                        let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?;
-                        Some((span, format!("expected `{}` because of this return type", snippet)))
-                    });
-                }
-            }
+    create_maybe_get_coercion_reason!(
+        maybe_get_coercion_reason,
+        |hir: rustc_middle::hir::map::Map<'a>, id| {
+            let arm_id = hir.get_parent_node(id);
+            let match_id = hir.get_parent_node(arm_id);
+            let containing_id = hir.get_parent_node(match_id);
+            hir.get(containing_id)
         }
-        if let Local(hir::Local { ty: Some(_), pat, .. }) = node {
-            return Some((pat.span, "expected because of this assignment".to_string()));
-        }
-        None
-    }
+    );
 
-    fn if_cause(
+    create_maybe_get_coercion_reason!(
+        maybe_get_coercion_reason_if,
+        |hir: rustc_middle::hir::map::Map<'a>, id| {
+            let rslt = hir.get_parent_node(hir.get_parent_node(id));
+            hir.get(rslt)
+        }
+    );
+
+    pub(crate) fn if_cause(
         &self,
         span: Span,
         then_expr: &'tcx hir::Expr<'tcx>,
@@ -546,6 +526,58 @@
             (block.span, None)
         }
     }
+
+    // When we have a `match` as a tail expression in a `fn` with a returned `impl Trait`
+    // we check if the different arms would work with boxed trait objects instead and
+    // provide a structured suggestion in that case.
+    pub(crate) fn opt_suggest_box_span(
+        &self,
+        span: Span,
+        outer_ty: &'tcx TyS<'tcx>,
+        orig_expected: Expectation<'tcx>,
+    ) -> Option<Span> {
+        match (orig_expected, self.ret_coercion_impl_trait.map(|ty| (self.body_id.owner, ty))) {
+            (Expectation::ExpectHasType(expected), Some((id, ty)))
+                if self.in_tail_expr && self.can_coerce(outer_ty, expected) =>
+            {
+                let impl_trait_ret_ty =
+                    self.infcx.instantiate_opaque_types(id, self.body_id, self.param_env, ty, span);
+                let mut suggest_box = !impl_trait_ret_ty.obligations.is_empty();
+                for o in impl_trait_ret_ty.obligations {
+                    match o.predicate.kind().skip_binder() {
+                        ty::PredicateKind::Trait(t, constness) => {
+                            let pred = ty::PredicateKind::Trait(
+                                ty::TraitPredicate {
+                                    trait_ref: ty::TraitRef {
+                                        def_id: t.def_id(),
+                                        substs: self.infcx.tcx.mk_substs_trait(outer_ty, &[]),
+                                    },
+                                },
+                                constness,
+                            );
+                            let obl = Obligation::new(
+                                o.cause.clone(),
+                                self.param_env,
+                                pred.to_predicate(self.infcx.tcx),
+                            );
+                            suggest_box &= self.infcx.predicate_must_hold_modulo_regions(&obl);
+                            if !suggest_box {
+                                // We've encountered some obligation that didn't hold, so the
+                                // return expression can't just be boxed. We don't need to
+                                // evaluate the rest of the obligations.
+                                break;
+                            }
+                        }
+                        _ => {}
+                    }
+                }
+                // If all the obligations hold (or there are no obligations) the tail expression
+                // we can suggest to return a boxed trait object instead of an opaque type.
+                if suggest_box { self.ret_type_span } else { None }
+            }
+            _ => None,
+        }
+    }
 }
 
 fn arms_contain_ref_bindings(arms: &'tcx [hir::Arm<'tcx>]) -> Option<hir::Mutability> {
diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs
index 22e2873..116b079 100644
--- a/compiler/rustc_typeck/src/check/callee.rs
+++ b/compiler/rustc_typeck/src/check/callee.rs
@@ -290,16 +290,16 @@
             ty::FnPtr(sig) => (sig, None),
             ref t => {
                 let mut unit_variant = None;
-                if let &ty::Adt(adt_def, ..) = t {
+                if let ty::Adt(adt_def, ..) = t {
                     if adt_def.is_enum() {
-                        if let hir::ExprKind::Call(ref expr, _) = call_expr.kind {
+                        if let hir::ExprKind::Call(expr, _) = call_expr.kind {
                             unit_variant =
                                 self.tcx.sess.source_map().span_to_snippet(expr.span).ok();
                         }
                     }
                 }
 
-                if let hir::ExprKind::Call(ref callee, _) = call_expr.kind {
+                if let hir::ExprKind::Call(callee, _) = call_expr.kind {
                     let mut err = type_error_struct!(
                         self.tcx.sess,
                         callee.span,
diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs
index 36240a9..39dac0a 100644
--- a/compiler/rustc_typeck/src/check/cast.rs
+++ b/compiler/rustc_typeck/src/check/cast.rs
@@ -418,13 +418,14 @@
                 err.emit();
             }
             CastError::SizedUnsizedCast => {
-                use crate::structured_errors::{SizedUnsizedCastError, StructuredDiagnostic};
-                SizedUnsizedCastError::new(
-                    &fcx.tcx.sess,
-                    self.span,
-                    self.expr_ty,
-                    fcx.ty_to_string(self.cast_ty),
-                )
+                use crate::structured_errors::{SizedUnsizedCast, StructuredDiagnostic};
+
+                SizedUnsizedCast {
+                    sess: &fcx.tcx.sess,
+                    span: self.span,
+                    expr_ty: self.expr_ty,
+                    cast_ty: fcx.ty_to_string(self.cast_ty),
+                }
                 .diagnostic()
                 .emit();
             }
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 9c60e89..8e339eb 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -103,13 +103,17 @@
                 Node::ImplItem(hir::ImplItem {
                     kind: hir::ImplItemKind::Fn(header, ..), ..
                 }) => Some(header),
+                Node::TraitItem(hir::TraitItem {
+                    kind: hir::TraitItemKind::Fn(header, ..),
+                    ..
+                }) => Some(header),
                 // Closures are RustCall, but they tuple their arguments, so shouldn't be checked
                 Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => None,
                 node => bug!("Item being checked wasn't a function/closure: {:?}", node),
             };
 
             if let Some(header) = item {
-                tcx.sess.span_err(header.span, "A function with the \"rust-call\" ABI must take a single non-self argument that is a tuple")
+                tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple")
             }
         };
 
@@ -688,11 +692,17 @@
             check_enum(tcx, it.span, &enum_definition.variants, it.hir_id);
         }
         hir::ItemKind::Fn(..) => {} // entirely within check_item_body
-        hir::ItemKind::Impl { ref items, .. } => {
+        hir::ItemKind::Impl(ref impl_) => {
             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, items);
+                check_impl_items_against_trait(
+                    tcx,
+                    it.span,
+                    impl_def_id,
+                    impl_trait_ref,
+                    &impl_.items,
+                );
                 let trait_def_id = impl_trait_ref.def_id;
                 check_on_unimplemented(tcx, trait_def_id, it);
             }
@@ -1249,8 +1259,8 @@
         let layout = tcx.layout_of(param_env.and(ty));
         // We are currently checking the type this field came from, so it must be local
         let span = tcx.hir().span_if_local(field.did).unwrap();
-        let zst = layout.map(|layout| layout.is_zst()).unwrap_or(false);
-        let align1 = layout.map(|layout| layout.align.abi.bytes() == 1).unwrap_or(false);
+        let zst = layout.map_or(false, |layout| layout.is_zst());
+        let align1 = layout.map_or(false, |layout| layout.align.abi.bytes() == 1);
         (span, zst, align1)
     });
 
diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs
index 7470c1a..f34aaec 100644
--- a/compiler/rustc_typeck/src/check/closure.rs
+++ b/compiler/rustc_typeck/src/check/closure.rs
@@ -192,9 +192,9 @@
                     obligation.predicate
                 );
 
-                let bound_predicate = obligation.predicate.bound_atom();
-                if let ty::PredicateAtom::Projection(proj_predicate) =
-                    obligation.predicate.skip_binders()
+                let bound_predicate = obligation.predicate.kind();
+                if let ty::PredicateKind::Projection(proj_predicate) =
+                    obligation.predicate.kind().skip_binder()
                 {
                     // Given a Projection predicate, we can potentially infer
                     // the complete signature.
@@ -622,8 +622,8 @@
         // where R is the return type we are expecting. This type `T`
         // will be our output.
         let output_ty = self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| {
-            let bound_predicate = obligation.predicate.bound_atom();
-            if let ty::PredicateAtom::Projection(proj_predicate) = bound_predicate.skip_binder() {
+            let bound_predicate = obligation.predicate.kind();
+            if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() {
                 self.deduce_future_output_from_projection(
                     obligation.cause.span,
                     bound_predicate.rebind(proj_predicate),
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index 0f5f0ab..34ad8ec 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -583,9 +583,9 @@
         while !queue.is_empty() {
             let obligation = queue.remove(0);
             debug!("coerce_unsized resolve step: {:?}", obligation);
-            let bound_predicate = obligation.predicate.bound_atom();
+            let bound_predicate = obligation.predicate.kind();
             let trait_pred = match bound_predicate.skip_binder() {
-                ty::PredicateAtom::Trait(trait_pred, _)
+                ty::PredicateKind::Trait(trait_pred, _)
                     if traits.contains(&trait_pred.def_id()) =>
                 {
                     if unsize_did == trait_pred.def_id() {
@@ -926,11 +926,11 @@
                     false
                 }
             };
-            if is_capturing_closure(&prev_ty.kind()) || is_capturing_closure(&new_ty.kind()) {
+            if is_capturing_closure(prev_ty.kind()) || is_capturing_closure(new_ty.kind()) {
                 (None, None)
             } else {
-                match (&prev_ty.kind(), &new_ty.kind()) {
-                    (&ty::FnDef(..), &ty::FnDef(..)) => {
+                match (prev_ty.kind(), new_ty.kind()) {
+                    (ty::FnDef(..), ty::FnDef(..)) => {
                         // Don't reify if the function types have a LUB, i.e., they
                         // are the same function and their parameters have a LUB.
                         match self
@@ -943,21 +943,21 @@
                             }
                         }
                     }
-                    (&ty::Closure(_, substs), &ty::FnDef(..)) => {
+                    (ty::Closure(_, substs), ty::FnDef(..)) => {
                         let b_sig = new_ty.fn_sig(self.tcx);
                         let a_sig = self
                             .tcx
                             .signature_unclosure(substs.as_closure().sig(), b_sig.unsafety());
                         (Some(a_sig), Some(b_sig))
                     }
-                    (&ty::FnDef(..), &ty::Closure(_, substs)) => {
+                    (ty::FnDef(..), ty::Closure(_, substs)) => {
                         let a_sig = prev_ty.fn_sig(self.tcx);
                         let b_sig = self
                             .tcx
                             .signature_unclosure(substs.as_closure().sig(), a_sig.unsafety());
                         (Some(a_sig), Some(b_sig))
                     }
-                    (&ty::Closure(_, substs_a), &ty::Closure(_, substs_b)) => (
+                    (ty::Closure(_, substs_a), ty::Closure(_, substs_b)) => (
                         Some(self.tcx.signature_unclosure(
                             substs_a.as_closure().sig(),
                             hir::Unsafety::Normal,
@@ -1443,14 +1443,14 @@
                 &mut err, expr, expected, found, cause.span, blk_id,
             );
             let parent = fcx.tcx.hir().get(parent_id);
-            if let (Some(match_expr), true, false) = (
-                fcx.tcx.hir().get_match_if_cause(expr.hir_id),
+            if let (Some(cond_expr), true, false) = (
+                fcx.tcx.hir().get_if_cause(expr.hir_id),
                 expected.is_unit(),
                 pointing_at_return_type,
             ) {
-                if match_expr.span.desugaring_kind().is_none() {
-                    err.span_label(match_expr.span, "expected this to be `()`");
-                    fcx.suggest_semicolon_at_end(match_expr.span, &mut err);
+                if cond_expr.span.desugaring_kind().is_none() {
+                    err.span_label(cond_expr.span, "expected this to be `()`");
+                    fcx.suggest_semicolon_at_end(cond_expr.span, &mut err);
                 }
             }
             fcx.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index bb324d0..d37d6bc 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -296,7 +296,7 @@
                     {
                         diag.span_suggestion(
                             impl_err_span,
-                            "consider change the type to match the mutability in trait",
+                            "consider changing the mutability to match the trait",
                             trait_err_str,
                             Applicability::MachineApplicable,
                         );
@@ -364,13 +364,12 @@
     if trait_params != impl_params {
         let item_kind = assoc_item_kind_str(impl_m);
         let def_span = tcx.sess.source_map().guess_head_span(span);
-        let span = tcx.hir().get_generics(impl_m.def_id).map(|g| g.span).unwrap_or(def_span);
-        let generics_span = if let Some(sp) = tcx.hir().span_if_local(trait_m.def_id) {
+        let span = tcx.hir().get_generics(impl_m.def_id).map_or(def_span, |g| g.span);
+        let generics_span = tcx.hir().span_if_local(trait_m.def_id).map(|sp| {
             let def_sp = tcx.sess.source_map().guess_head_span(sp);
-            Some(tcx.hir().get_generics(trait_m.def_id).map(|g| g.span).unwrap_or(def_sp))
-        } else {
-            None
-        };
+            tcx.hir().get_generics(trait_m.def_id).map_or(def_sp, |g| g.span)
+        });
+
         tcx.sess.emit_err(LifetimesOrBoundsMismatchOnTrait {
             span,
             item_kind,
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 2728e03..c22f001 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -32,6 +32,7 @@
         if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) {
             return;
         }
+        self.suggest_no_capture_closure(err, expected, expr_ty);
         self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
         self.suggest_missing_parentheses(err, expr);
         self.note_need_for_fn_pointer(err, expected, expr_ty);
diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs
index be19919..4c3c4fd 100644
--- a/compiler/rustc_typeck/src/check/dropck.rs
+++ b/compiler/rustc_typeck/src/check/dropck.rs
@@ -226,13 +226,13 @@
         // could be extended easily also to the other `Predicate`.
         let predicate_matches_closure = |p: Predicate<'tcx>| {
             let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env);
-            let predicate = predicate.bound_atom();
-            let p = p.bound_atom();
+            let predicate = predicate.kind();
+            let p = p.kind();
             match (predicate.skip_binder(), p.skip_binder()) {
-                (ty::PredicateAtom::Trait(a, _), ty::PredicateAtom::Trait(b, _)) => {
+                (ty::PredicateKind::Trait(a, _), ty::PredicateKind::Trait(b, _)) => {
                     relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
                 }
-                (ty::PredicateAtom::Projection(a), ty::PredicateAtom::Projection(b)) => {
+                (ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => {
                     relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
                 }
                 _ => predicate == p,
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 93eb2cf..8aa6c6d 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -10,6 +10,7 @@
 use crate::check::report_unexpected_variant_res;
 use crate::check::BreakableCtxt;
 use crate::check::Diverges;
+use crate::check::DynamicCoerceMany;
 use crate::check::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
 use crate::check::FnCtxt;
 use crate::check::Needs;
@@ -38,6 +39,7 @@
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::TypeFoldable;
 use rustc_middle::ty::{AdtKind, Visibility};
+use rustc_span::edition::LATEST_STABLE_EDITION;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::Span;
@@ -187,7 +189,7 @@
 
         // Warn for non-block expressions with diverging children.
         match expr.kind {
-            ExprKind::Block(..) | ExprKind::Loop(..) | ExprKind::Match(..) => {}
+            ExprKind::Block(..) | ExprKind::If(..) | ExprKind::Loop(..) | ExprKind::Match(..) => {}
             // If `expr` is a result of desugaring the try block and is an ok-wrapped
             // diverging expression (e.g. it arose from desugaring of `try { return }`),
             // we skip issuing a warning because it is autogenerated code.
@@ -284,6 +286,13 @@
                 self.check_expr_eq_type(&e, ty);
                 ty
             }
+            ExprKind::If(ref cond, ref then_expr, ref opt_else_expr) => self.check_then_else(
+                &cond,
+                then_expr,
+                opt_else_expr.as_ref().map(|e| &**e),
+                expr.span,
+                expected,
+            ),
             ExprKind::DropTemps(ref e) => self.check_expr_with_expectation(e, expected),
             ExprKind::Array(ref args) => self.check_expr_array(args, expected, expr),
             ExprKind::ConstBlock(ref anon_const) => self.to_const(anon_const).ty,
@@ -738,8 +747,67 @@
         err.emit();
     }
 
+    // A generic function for checking the 'then' and 'else' clauses in an 'if'
+    // or 'if-else' expression.
+    fn check_then_else(
+        &self,
+        cond_expr: &'tcx hir::Expr<'tcx>,
+        then_expr: &'tcx hir::Expr<'tcx>,
+        opt_else_expr: Option<&'tcx hir::Expr<'tcx>>,
+        sp: Span,
+        orig_expected: Expectation<'tcx>,
+    ) -> Ty<'tcx> {
+        let cond_ty = self.check_expr_has_type_or_error(cond_expr, self.tcx.types.bool, |_| {});
+
+        self.warn_if_unreachable(cond_expr.hir_id, then_expr.span, "block in `if` expression");
+
+        let cond_diverges = self.diverges.get();
+        self.diverges.set(Diverges::Maybe);
+
+        let expected = orig_expected.adjust_for_branches(self);
+        let then_ty = self.check_expr_with_expectation(then_expr, expected);
+        let then_diverges = self.diverges.get();
+        self.diverges.set(Diverges::Maybe);
+
+        // We've already taken the expected type's preferences
+        // into account when typing the `then` branch. To figure
+        // out the initial shot at a LUB, we thus only consider
+        // `expected` if it represents a *hard* constraint
+        // (`only_has_type`); otherwise, we just go with a
+        // fresh type variable.
+        let coerce_to_ty = expected.coercion_target_type(self, sp);
+        let mut coerce: DynamicCoerceMany<'_> = CoerceMany::new(coerce_to_ty);
+
+        coerce.coerce(self, &self.misc(sp), then_expr, then_ty);
+
+        if let Some(else_expr) = opt_else_expr {
+            let else_ty = self.check_expr_with_expectation(else_expr, expected);
+            let else_diverges = self.diverges.get();
+
+            let opt_suggest_box_span =
+                self.opt_suggest_box_span(else_expr.span, else_ty, orig_expected);
+            let if_cause =
+                self.if_cause(sp, then_expr, else_expr, then_ty, else_ty, opt_suggest_box_span);
+
+            coerce.coerce(self, &if_cause, else_expr, else_ty);
+
+            // We won't diverge unless both branches do (or the condition does).
+            self.diverges.set(cond_diverges | then_diverges & else_diverges);
+        } else {
+            self.if_fallback_coercion(sp, then_expr, &mut coerce, |hir_id, span| {
+                self.maybe_get_coercion_reason_if(hir_id, span)
+            });
+
+            // If the condition is false we can't diverge.
+            self.diverges.set(cond_diverges);
+        }
+
+        let result_ty = coerce.complete(self);
+        if cond_ty.references_error() { self.tcx.ty_error() } else { result_ty }
+    }
+
     /// Type check assignment expression `expr` of form `lhs = rhs`.
-    /// The expected type is `()` and is passsed to the function for the purposes of diagnostics.
+    /// The expected type is `()` and is passed to the function for the purposes of diagnostics.
     fn check_expr_assign(
         &self,
         expr: &'tcx hir::Expr<'tcx>,
@@ -764,17 +832,7 @@
             };
             if !lhs.is_syntactic_place_expr() {
                 // Do not suggest `if let x = y` as `==` is way more likely to be the intention.
-                if let hir::Node::Expr(hir::Expr {
-                    kind:
-                        ExprKind::Match(
-                            _,
-                            _,
-                            hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar,
-                        ),
-                    ..
-                }) = self.tcx.hir().get(
-                    self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(expr.hir_id)),
-                ) {
+                let mut span_err = || {
                     // Likely `if let` intended.
                     err.span_suggestion_verbose(
                         expr.span.shrink_to_lo(),
@@ -782,6 +840,18 @@
                         "let ".to_string(),
                         applicability,
                     );
+                };
+                if let hir::Node::Expr(hir::Expr {
+                    kind: ExprKind::Match(_, _, hir::MatchSource::WhileDesugar),
+                    ..
+                }) = self.tcx.hir().get(
+                    self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(expr.hir_id)),
+                ) {
+                    span_err();
+                } else if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) =
+                    self.tcx.hir().get(self.tcx.hir().get_parent_node(expr.hir_id))
+                {
+                    span_err();
                 }
             }
             if eq {
@@ -1124,7 +1194,7 @@
             fields,
             base_expr.is_none(),
         );
-        if let &Some(ref base_expr) = base_expr {
+        if let Some(base_expr) = base_expr {
             // If check_expr_struct_fields hit an error, do not attempt to populate
             // the fields with the base_expr. This could cause us to hit errors later
             // when certain fields are assumed to exist that in fact do not.
@@ -1181,8 +1251,8 @@
         // re-link the regions that EIfEO can erase.
         self.demand_eqtype(span, adt_ty_hint, adt_ty);
 
-        let (substs, adt_kind, kind_name) = match &adt_ty.kind() {
-            &ty::Adt(adt, substs) => (substs, adt.adt_kind(), adt.variant_descr()),
+        let (substs, adt_kind, kind_name) = match adt_ty.kind() {
+            ty::Adt(adt, substs) => (substs, adt.adt_kind(), adt.variant_descr()),
             _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields"),
         };
 
@@ -1380,19 +1450,42 @@
             ty,
         );
         match variant.ctor_kind {
-            CtorKind::Fn => {
-                err.span_label(variant.ident.span, format!("`{adt}` defined here", adt = ty));
-                err.span_label(field.ident.span, "field does not exist");
-                err.span_label(
-                    ty_span,
-                    format!(
-                        "`{adt}` is a tuple {kind_name}, \
-                         use the appropriate syntax: `{adt}(/* fields */)`",
-                        adt = ty,
-                        kind_name = kind_name
-                    ),
-                );
-            }
+            CtorKind::Fn => match ty.kind() {
+                ty::Adt(adt, ..) if adt.is_enum() => {
+                    err.span_label(
+                        variant.ident.span,
+                        format!(
+                            "`{adt}::{variant}` defined here",
+                            adt = ty,
+                            variant = variant.ident,
+                        ),
+                    );
+                    err.span_label(field.ident.span, "field does not exist");
+                    err.span_label(
+                        ty_span,
+                        format!(
+                            "`{adt}::{variant}` is a tuple {kind_name}, \
+                             use the appropriate syntax: `{adt}::{variant}(/* fields */)`",
+                            adt = ty,
+                            variant = variant.ident,
+                            kind_name = kind_name
+                        ),
+                    );
+                }
+                _ => {
+                    err.span_label(variant.ident.span, format!("`{adt}` defined here", adt = ty));
+                    err.span_label(field.ident.span, "field does not exist");
+                    err.span_label(
+                        ty_span,
+                        format!(
+                            "`{adt}` is a tuple {kind_name}, \
+                                 use the appropriate syntax: `{adt}(/* fields */)`",
+                            adt = ty,
+                            kind_name = kind_name
+                        ),
+                    );
+                }
+            },
             _ => {
                 // prevent all specified fields from being suggested
                 let skip_fields = skip_fields.iter().map(|ref x| x.ident.name);
@@ -1637,8 +1730,8 @@
         if field.name == kw::Await {
             // We know by construction that `<expr>.await` is either on Rust 2015
             // or results in `ExprKind::Await`. Suggest switching the edition to 2018.
-            err.note("to `.await` a `Future`, switch to Rust 2018");
-            err.help("set `edition = \"2018\"` in `Cargo.toml`");
+            err.note("to `.await` a `Future`, switch to Rust 2018 or later");
+            err.help(&format!("set `edition = \"{}\"` in `Cargo.toml`", LATEST_STABLE_EDITION));
             err.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
         }
 
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index 2a8b77d..5a372c0 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -1,6 +1,6 @@
 use crate::astconv::{
     AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
-    GenericArgCountResult, PathSeg,
+    GenericArgCountResult, IsMethodCall, PathSeg,
 };
 use crate::check::callee::{self, DeferredCallResolution};
 use crate::check::method::{self, MethodCallee, SelfSource};
@@ -542,7 +542,7 @@
         self.register_predicate(traits::Obligation::new(
             cause,
             self.param_env,
-            ty::PredicateAtom::WellFormed(arg).to_predicate(self.tcx),
+            ty::PredicateKind::WellFormed(arg).to_predicate(self.tcx),
         ));
     }
 
@@ -764,21 +764,21 @@
             .pending_obligations()
             .into_iter()
             .filter_map(move |obligation| {
-                let bound_predicate = obligation.predicate.bound_atom();
+                let bound_predicate = obligation.predicate.kind();
                 match bound_predicate.skip_binder() {
-                    ty::PredicateAtom::Projection(data) => {
+                    ty::PredicateKind::Projection(data) => {
                         Some((bound_predicate.rebind(data).to_poly_trait_ref(self.tcx), obligation))
                     }
-                    ty::PredicateAtom::Trait(data, _) => {
+                    ty::PredicateKind::Trait(data, _) => {
                         Some((bound_predicate.rebind(data).to_poly_trait_ref(), obligation))
                     }
-                    ty::PredicateAtom::Subtype(..) => None,
-                    ty::PredicateAtom::RegionOutlives(..) => None,
-                    ty::PredicateAtom::TypeOutlives(..) => None,
-                    ty::PredicateAtom::WellFormed(..) => None,
-                    ty::PredicateAtom::ObjectSafe(..) => None,
-                    ty::PredicateAtom::ConstEvaluatable(..) => None,
-                    ty::PredicateAtom::ConstEquate(..) => None,
+                    ty::PredicateKind::Subtype(..) => None,
+                    ty::PredicateKind::RegionOutlives(..) => None,
+                    ty::PredicateKind::TypeOutlives(..) => None,
+                    ty::PredicateKind::WellFormed(..) => None,
+                    ty::PredicateKind::ObjectSafe(..) => None,
+                    ty::PredicateKind::ConstEvaluatable(..) => None,
+                    ty::PredicateKind::ConstEquate(..) => None,
                     // N.B., this predicate is created by breaking down a
                     // `ClosureType: FnFoo()` predicate, where
                     // `ClosureType` represents some `Closure`. It can't
@@ -787,8 +787,8 @@
                     // this closure yet; this is exactly why the other
                     // code is looking for a self type of a unresolved
                     // inference variable.
-                    ty::PredicateAtom::ClosureKind(..) => None,
-                    ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
+                    ty::PredicateKind::ClosureKind(..) => None,
+                    ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
                 }
             })
             .filter(move |(tr, _)| self.self_type_matches_expected_vid(*tr, ty_var_root))
@@ -904,8 +904,7 @@
         {
             // Return directly on cache hit. This is useful to avoid doubly reporting
             // errors with default match binding modes. See #44614.
-            let def =
-                cached_result.map(|(kind, def_id)| Res::Def(kind, def_id)).unwrap_or(Res::Err);
+            let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id));
             return (def, Some(ty), slice::from_ref(&**item_segment));
         }
         let item_name = item_segment.ident;
@@ -932,7 +931,7 @@
         // Write back the new resolution.
         self.write_resolution(hir_id, result);
         (
-            result.map(|(kind, def_id)| Res::Def(kind, def_id)).unwrap_or(Res::Err),
+            result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
             Some(ty),
             slice::from_ref(&**item_segment),
         )
@@ -1219,18 +1218,25 @@
         // a problem.
 
         let mut infer_args_for_err = FxHashSet::default();
+
         for &PathSeg(def_id, index) in &path_segs {
             let seg = &segments[index];
             let generics = tcx.generics_of(def_id);
+
             // Argument-position `impl Trait` is treated as a normal generic
             // parameter internally, but we don't allow users to specify the
             // parameter's value explicitly, so we have to do some error-
             // checking here.
             if let GenericArgCountResult {
-                correct: Err(GenericArgCountMismatch { reported: Some(ErrorReported), .. }),
+                correct: Err(GenericArgCountMismatch { reported: Some(_), .. }),
                 ..
             } = AstConv::check_generic_arg_count_for_call(
-                tcx, span, &generics, &seg, false, // `is_method_call`
+                tcx,
+                span,
+                def_id,
+                &generics,
+                seg,
+                IsMethodCall::No,
             ) {
                 infer_args_for_err.insert(index);
                 self.set_tainted_by_errors(); // See issue #53251.
@@ -1376,7 +1382,7 @@
                         }
                     }
                     GenericParamDefKind::Const => {
-                        // FIXME(const_generics:defaults)
+                        // FIXME(const_generics_defaults)
                         // No const parameters were provided, we have to infer them.
                         self.fcx.var_for_def(self.span, param)
                     }
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 3e60924..6df9e3a 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -22,6 +22,7 @@
 use rustc_span::{self, MultiSpan, Span};
 use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression};
 
+use crate::structured_errors::StructuredDiagnostic;
 use std::mem::replace;
 use std::slice;
 
@@ -173,18 +174,19 @@
             }
 
             if let Some(def_id) = def_id {
-                if let Some(node) = tcx.hir().get_if_local(def_id) {
-                    let mut spans: MultiSpan = node
-                        .ident()
-                        .map(|ident| ident.span)
-                        .unwrap_or_else(|| tcx.hir().span(node.hir_id().unwrap()))
-                        .into();
+                if let Some(def_span) = tcx.def_ident_span(def_id) {
+                    let mut spans: MultiSpan = def_span.into();
 
-                    if let Some(id) = node.body_id() {
-                        let body = tcx.hir().body(id);
-                        for param in body.params {
-                            spans.push_span_label(param.span, String::new());
-                        }
+                    let params = tcx
+                        .hir()
+                        .get_if_local(def_id)
+                        .and_then(|node| node.body_id())
+                        .into_iter()
+                        .map(|id| tcx.hir().body(id).params)
+                        .flatten();
+
+                    for param in params {
+                        spans.push_span_label(param.span, String::new());
                     }
 
                     let def_kind = tcx.def_kind(def_id);
@@ -358,9 +360,10 @@
         // We also need to make sure we at least write the ty of the other
         // arguments which we skipped above.
         if c_variadic {
-            fn variadic_error<'tcx>(s: &Session, span: Span, t: Ty<'tcx>, cast_ty: &str) {
-                use crate::structured_errors::{StructuredDiagnostic, VariadicError};
-                VariadicError::new(s, span, t, cast_ty).diagnostic().emit();
+            fn variadic_error<'tcx>(sess: &Session, span: Span, ty: Ty<'tcx>, cast_ty: &str) {
+                use crate::structured_errors::MissingCastForVariadicArg;
+
+                MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit()
             }
 
             for arg in args.iter().skip(expected_arg_count) {
@@ -803,33 +806,39 @@
     /// //                               ^^^^ point at this instead of the whole `if` expression
     /// ```
     fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span {
-        if let hir::ExprKind::Match(_, arms, _) = &expr.kind {
-            let arm_spans: Vec<Span> = arms
-                .iter()
-                .filter_map(|arm| {
-                    self.in_progress_typeck_results
-                        .and_then(|typeck_results| {
-                            typeck_results.borrow().node_type_opt(arm.body.hir_id)
-                        })
-                        .and_then(|arm_ty| {
-                            if arm_ty.is_never() {
-                                None
-                            } else {
-                                Some(match &arm.body.kind {
-                                    // Point at the tail expression when possible.
-                                    hir::ExprKind::Block(block, _) => {
-                                        block.expr.as_ref().map(|e| e.span).unwrap_or(block.span)
-                                    }
-                                    _ => arm.body.span,
-                                })
+        let check_in_progress = |elem: &hir::Expr<'_>| {
+            self.in_progress_typeck_results
+                .and_then(|typeck_results| typeck_results.borrow().node_type_opt(elem.hir_id))
+                .and_then(|ty| {
+                    if ty.is_never() {
+                        None
+                    } else {
+                        Some(match elem.kind {
+                            // Point at the tail expression when possible.
+                            hir::ExprKind::Block(block, _) => {
+                                block.expr.map_or(block.span, |e| e.span)
                             }
+                            _ => elem.span,
                         })
+                    }
                 })
-                .collect();
-            if arm_spans.len() == 1 {
-                return arm_spans[0];
+        };
+
+        if let hir::ExprKind::If(_, _, Some(el)) = expr.kind {
+            if let Some(rslt) = check_in_progress(el) {
+                return rslt;
             }
         }
+
+        if let hir::ExprKind::Match(_, arms, _) = expr.kind {
+            let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
+            if let Some(span) = iter.next() {
+                if iter.next().is_none() {
+                    return span;
+                }
+            }
+        }
+
         expr.span
     }
 
@@ -879,7 +888,7 @@
                 // Write back the new resolution.
                 self.write_resolution(hir_id, result);
 
-                (result.map(|(kind, def_id)| Res::Def(kind, def_id)).unwrap_or(Res::Err), ty)
+                (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
             }
             QPath::LangItem(lang_item, span) => {
                 self.resolve_lang_item_path(lang_item, span, hir_id)
@@ -914,8 +923,8 @@
                 continue;
             }
 
-            if let ty::PredicateAtom::Trait(predicate, _) =
-                error.obligation.predicate.skip_binders()
+            if let ty::PredicateKind::Trait(predicate, _) =
+                error.obligation.predicate.kind().skip_binder()
             {
                 // Collect the argument position for all arguments that could have caused this
                 // `FulfillmentError`.
@@ -965,8 +974,8 @@
             if let hir::ExprKind::Path(qpath) = &path.kind {
                 if let hir::QPath::Resolved(_, path) = &qpath {
                     for error in errors {
-                        if let ty::PredicateAtom::Trait(predicate, _) =
-                            error.obligation.predicate.skip_binders()
+                        if let ty::PredicateKind::Trait(predicate, _) =
+                            error.obligation.predicate.kind().skip_binder()
                         {
                             // If any of the type arguments in this path segment caused the
                             // `FullfillmentError`, point at its span (#61860).
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
index f635e0b..6d09043 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
@@ -194,8 +194,8 @@
             parent: None,
             predicates: tcx.arena.alloc_from_iter(
                 self.param_env.caller_bounds().iter().filter_map(|predicate| {
-                    match predicate.skip_binders() {
-                        ty::PredicateAtom::Trait(data, _) if data.self_ty().is_param(index) => {
+                    match predicate.kind().skip_binder() {
+                        ty::PredicateKind::Trait(data, _) if data.self_ty().is_param(index) => {
                             // HACK(eddyb) should get the original `Span`.
                             let span = tcx.def_span(def_id);
                             Some((predicate, span))
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index 17dbf98..a0465ca 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -2,7 +2,7 @@
 use crate::astconv::AstConv;
 
 use rustc_ast::util::parser::ExprPrecedence;
-use rustc_span::{self, Span};
+use rustc_span::{self, MultiSpan, Span};
 
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
@@ -287,6 +287,38 @@
         }
     }
 
+    /// When encountering a closure that captures variables, where a FnPtr is expected,
+    /// suggest a non-capturing closure
+    pub(in super::super) fn suggest_no_capture_closure(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        expected: Ty<'tcx>,
+        found: Ty<'tcx>,
+    ) {
+        if let (ty::FnPtr(_), ty::Closure(def_id, _)) = (expected.kind(), found.kind()) {
+            if let Some(upvars) = self.tcx.upvars_mentioned(*def_id) {
+                // Report upto four upvars being captured to reduce the amount error messages
+                // reported back to the user.
+                let spans_and_labels = upvars
+                    .iter()
+                    .take(4)
+                    .map(|(var_hir_id, upvar)| {
+                        let var_name = self.tcx.hir().name(*var_hir_id).to_string();
+                        let msg = format!("`{}` captured here", var_name);
+                        (upvar.span, msg)
+                    })
+                    .collect::<Vec<_>>();
+
+                let mut multi_span: MultiSpan =
+                    spans_and_labels.iter().map(|(sp, _)| *sp).collect::<Vec<_>>().into();
+                for (sp, label) in spans_and_labels {
+                    multi_span.push_span_label(sp, label);
+                }
+                err.span_note(multi_span, "closures can only be coerced to `fn` types if they do not capture any variables");
+            }
+        }
+    }
+
     /// When encountering an `impl Future` where `BoxFuture` is expected, suggest `Box::pin`.
     pub(in super::super) fn suggest_calling_boxed_future_when_appropriate(
         &self,
@@ -358,6 +390,7 @@
                 ExprKind::Call(..)
                 | ExprKind::MethodCall(..)
                 | ExprKind::Loop(..)
+                | ExprKind::If(..)
                 | ExprKind::Match(..)
                 | ExprKind::Block(..) => {
                     err.span_suggestion(
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs
index 673dec6..e99db7a 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -63,8 +63,6 @@
         | sym::min_align_of
         | sym::needs_drop
         | sym::caller_location
-        | sym::size_of_val
-        | sym::min_align_of_val
         | sym::add_with_overflow
         | sym::sub_with_overflow
         | sym::mul_with_overflow
@@ -159,7 +157,6 @@
             }
             sym::forget => (1, vec![param(0)], tcx.mk_unit()),
             sym::transmute => (2, vec![param(0)], param(1)),
-            sym::move_val_init => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
             sym::prefetch_read_data
             | sym::prefetch_write_data
             | sym::prefetch_read_instruction
diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs
index 76ab730..97c9620 100644
--- a/compiler/rustc_typeck/src/check/method/confirm.rs
+++ b/compiler/rustc_typeck/src/check/method/confirm.rs
@@ -1,6 +1,6 @@
 use super::{probe, MethodCallee};
 
-use crate::astconv::{AstConv, CreateSubstsForGenericArgsCtxt};
+use crate::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall};
 use crate::check::{callee, FnCtxt};
 use crate::hir::def_id::DefId;
 use crate::hir::GenericArg;
@@ -299,8 +299,14 @@
         // If they were not explicitly supplied, just construct fresh
         // variables.
         let generics = self.tcx.generics_of(pick.item.def_id);
+
         let arg_count_correct = AstConv::check_generic_arg_count_for_call(
-            self.tcx, self.span, &generics, &seg, true, // `is_method_call`
+            self.tcx,
+            self.span,
+            pick.item.def_id,
+            &generics,
+            seg,
+            IsMethodCall::Yes,
         );
 
         // Create subst for early-bound lifetime parameters, combining
@@ -473,8 +479,8 @@
 
         traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied())
             // We don't care about regions here.
-            .filter_map(|obligation| match obligation.predicate.skip_binders() {
-                ty::PredicateAtom::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
+            .filter_map(|obligation| match obligation.predicate.kind().skip_binder() {
+                ty::PredicateKind::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
                     let span = predicates
                         .predicates
                         .iter()
diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs
index 4ea1888..9a3d1e4 100644
--- a/compiler/rustc_typeck/src/check/method/mod.rs
+++ b/compiler/rustc_typeck/src/check/method/mod.rs
@@ -405,7 +405,7 @@
         obligations.push(traits::Obligation::new(
             cause,
             self.param_env,
-            ty::PredicateAtom::WellFormed(method_ty.into()).to_predicate(tcx),
+            ty::PredicateKind::WellFormed(method_ty.into()).to_predicate(tcx),
         ));
 
         let callee = MethodCallee { def_id, substs: trait_ref.substs, sig: fn_sig };
diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs
index ccf1303..8335239 100644
--- a/compiler/rustc_typeck/src/check/method/probe.rs
+++ b/compiler/rustc_typeck/src/check/method/probe.rs
@@ -797,9 +797,9 @@
         debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty);
 
         let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
-            let bound_predicate = predicate.bound_atom();
+            let bound_predicate = predicate.kind();
             match bound_predicate.skip_binder() {
-                ty::PredicateAtom::Trait(trait_predicate, _) => {
+                ty::PredicateKind::Trait(trait_predicate, _) => {
                     match *trait_predicate.trait_ref.self_ty().kind() {
                         ty::Param(p) if p == param_ty => {
                             Some(bound_predicate.rebind(trait_predicate.trait_ref))
@@ -807,16 +807,16 @@
                         _ => None,
                     }
                 }
-                ty::PredicateAtom::Subtype(..)
-                | ty::PredicateAtom::Projection(..)
-                | ty::PredicateAtom::RegionOutlives(..)
-                | ty::PredicateAtom::WellFormed(..)
-                | ty::PredicateAtom::ObjectSafe(..)
-                | ty::PredicateAtom::ClosureKind(..)
-                | ty::PredicateAtom::TypeOutlives(..)
-                | ty::PredicateAtom::ConstEvaluatable(..)
-                | ty::PredicateAtom::ConstEquate(..)
-                | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
+                ty::PredicateKind::Subtype(..)
+                | ty::PredicateKind::Projection(..)
+                | ty::PredicateKind::RegionOutlives(..)
+                | ty::PredicateKind::WellFormed(..)
+                | ty::PredicateKind::ObjectSafe(..)
+                | ty::PredicateKind::ClosureKind(..)
+                | ty::PredicateKind::TypeOutlives(..)
+                | ty::PredicateKind::ConstEvaluatable(..)
+                | ty::PredicateKind::ConstEquate(..)
+                | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
             }
         });
 
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 3bf4198..c553fda 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -333,7 +333,7 @@
                             }
                             ExprKind::Path(ref qpath) => {
                                 // local binding
-                                if let &QPath::Resolved(_, ref path) = &qpath {
+                                if let QPath::Resolved(_, path) = qpath {
                                     if let hir::def::Res::Local(hir_id) = path.res {
                                         let span = tcx.hir().span(hir_id);
                                         let snippet = tcx.sess.source_map().span_to_snippet(span);
@@ -582,8 +582,8 @@
                     let mut collect_type_param_suggestions =
                         |self_ty: Ty<'tcx>, parent_pred: &ty::Predicate<'tcx>, obligation: &str| {
                             // We don't care about regions here, so it's fine to skip the binder here.
-                            if let (ty::Param(_), ty::PredicateAtom::Trait(p, _)) =
-                                (self_ty.kind(), parent_pred.skip_binders())
+                            if let (ty::Param(_), ty::PredicateKind::Trait(p, _)) =
+                                (self_ty.kind(), parent_pred.kind().skip_binder())
                             {
                                 if let ty::Adt(def, _) = p.trait_ref.self_ty().kind() {
                                     let node = def.did.as_local().map(|def_id| {
@@ -637,9 +637,9 @@
                         }
                     };
                     let mut format_pred = |pred: ty::Predicate<'tcx>| {
-                        let bound_predicate = pred.bound_atom();
+                        let bound_predicate = pred.kind();
                         match bound_predicate.skip_binder() {
-                            ty::PredicateAtom::Projection(pred) => {
+                            ty::PredicateKind::Projection(pred) => {
                                 let pred = bound_predicate.rebind(pred);
                                 // `<Foo as Iterator>::Item = String`.
                                 let trait_ref =
@@ -658,7 +658,7 @@
                                 bound_span_label(trait_ref.self_ty(), &obligation, &quiet);
                                 Some((obligation, trait_ref.self_ty()))
                             }
-                            ty::PredicateAtom::Trait(poly_trait_ref, _) => {
+                            ty::PredicateKind::Trait(poly_trait_ref, _) => {
                                 let p = poly_trait_ref.trait_ref;
                                 let self_ty = p.self_ty();
                                 let path = p.print_only_trait_path();
@@ -992,11 +992,11 @@
                 // implementing a trait would be legal but is rejected
                 // here).
                 unsatisfied_predicates.iter().all(|(p, _)| {
-                    match p.skip_binders() {
+                    match p.kind().skip_binder() {
                         // Hide traits if they are present in predicates as they can be fixed without
                         // having to implement them.
-                        ty::PredicateAtom::Trait(t, _) => t.def_id() == info.def_id,
-                        ty::PredicateAtom::Projection(p) => {
+                        ty::PredicateKind::Trait(t, _) => t.def_id() == info.def_id,
+                        ty::PredicateKind::Projection(p) => {
                             p.projection_ty.item_def_id == info.def_id
                         }
                         _ => false,
@@ -1193,7 +1193,7 @@
                         .any(|imp_did| {
                             let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
                             let imp_simp = simplify_type(self.tcx, imp.self_ty(), true);
-                            imp_simp.map(|s| s == simp_rcvr_ty).unwrap_or(false)
+                            imp_simp.map_or(false, |s| s == simp_rcvr_ty)
                         })
                     {
                         explicitly_negative.push(candidate);
@@ -1270,11 +1270,7 @@
             match ty.kind() {
                 ty::Adt(def, _) => def.did.is_local(),
                 ty::Foreign(did) => did.is_local(),
-
-                ty::Dynamic(ref tr, ..) => {
-                    tr.principal().map(|d| d.def_id().is_local()).unwrap_or(false)
-                }
-
+                ty::Dynamic(ref tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
                 ty::Param(_) => true,
 
                 // Everything else (primitive types, etc.) is effectively
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 8177b36..52276ed 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -864,9 +864,9 @@
     let mut projections = vec![];
     for (predicate, _) in predicates.predicates {
         debug!("predicate {:?}", predicate);
-        let bound_predicate = predicate.bound_atom();
+        let bound_predicate = predicate.kind();
         match bound_predicate.skip_binder() {
-            ty::PredicateAtom::Trait(trait_predicate, _) => {
+            ty::PredicateKind::Trait(trait_predicate, _) => {
                 let entry = types.entry(trait_predicate.self_ty()).or_default();
                 let def_id = trait_predicate.def_id();
                 if Some(def_id) != tcx.lang_items().sized_trait() {
@@ -875,7 +875,7 @@
                     entry.push(trait_predicate.def_id());
                 }
             }
-            ty::PredicateAtom::Projection(projection_pred) => {
+            ty::PredicateKind::Projection(projection_pred) => {
                 projections.push(bound_predicate.rebind(projection_pred));
             }
             _ => {}
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 5fc573a..ecc6e85 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -15,6 +15,7 @@
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::{Span, Spanned};
 use rustc_span::symbol::Ident;
+use rustc_span::{BytePos, DUMMY_SP};
 use rustc_trait_selection::traits::{ObligationCause, Pattern};
 
 use std::cmp;
@@ -1001,7 +1002,7 @@
         // More generally, the expected type wants a tuple variant with one field of an
         // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern
         // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`.
-        let missing_parenthesis = match (&expected.kind(), fields, had_err) {
+        let missing_parentheses = match (&expected.kind(), fields, had_err) {
             // #67037: only do this if we could successfully type-check the expected type against
             // the tuple struct pattern. Otherwise the substs could get out of range on e.g.,
             // `let P() = U;` where `P != U` with `struct P<T>(T);`.
@@ -1014,13 +1015,13 @@
             }
             _ => false,
         };
-        if missing_parenthesis {
+        if missing_parentheses {
             let (left, right) = match subpats {
                 // This is the zero case; we aim to get the "hi" part of the `QPath`'s
                 // span as the "lo" and then the "hi" part of the pattern's span as the "hi".
                 // This looks like:
                 //
-                // help: missing parenthesis
+                // help: missing parentheses
                 //   |
                 // L |     let A(()) = A(());
                 //   |          ^  ^
@@ -1029,17 +1030,63 @@
                 // last sub-pattern. In the case of `A(x)` the first and last may coincide.
                 // This looks like:
                 //
-                // help: missing parenthesis
+                // help: missing parentheses
                 //   |
                 // L |     let A((x, y)) = A((1, 2));
                 //   |           ^    ^
                 [first, ..] => (first.span.shrink_to_lo(), subpats.last().unwrap().span),
             };
             err.multipart_suggestion(
-                "missing parenthesis",
+                "missing parentheses",
                 vec![(left, "(".to_string()), (right.shrink_to_hi(), ")".to_string())],
                 Applicability::MachineApplicable,
             );
+        } else if fields.len() > subpats.len() {
+            let after_fields_span = if pat_span == DUMMY_SP {
+                pat_span
+            } else {
+                pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi()
+            };
+            let all_fields_span = match subpats {
+                [] => after_fields_span,
+                [field] => field.span,
+                [first, .., last] => first.span.to(last.span),
+            };
+
+            // Check if all the fields in the pattern are wildcards.
+            let all_wildcards = subpats.iter().all(|pat| matches!(pat.kind, PatKind::Wild));
+
+            let mut wildcard_sugg = vec!["_"; fields.len() - subpats.len()].join(", ");
+            if !subpats.is_empty() {
+                wildcard_sugg = String::from(", ") + &wildcard_sugg;
+            }
+
+            err.span_suggestion_verbose(
+                after_fields_span,
+                "use `_` to explicitly ignore each field",
+                wildcard_sugg,
+                Applicability::MaybeIncorrect,
+            );
+
+            // Only suggest `..` if more than one field is missing
+            // or the pattern consists of all wildcards.
+            if fields.len() - subpats.len() > 1 || all_wildcards {
+                if subpats.is_empty() || all_wildcards {
+                    err.span_suggestion_verbose(
+                        all_fields_span,
+                        "use `..` to ignore all fields",
+                        String::from(".."),
+                        Applicability::MaybeIncorrect,
+                    );
+                } else {
+                    err.span_suggestion_verbose(
+                        after_fields_span,
+                        "use `..` to ignore the rest of the fields",
+                        String::from(", .."),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+            }
         }
 
         err.emit();
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs
index e8cbefd..feda35d 100644
--- a/compiler/rustc_typeck/src/check/upvar.rs
+++ b/compiler/rustc_typeck/src/check/upvar.rs
@@ -176,7 +176,17 @@
             self.demand_eqtype(span, inferred_kind.to_ty(self.tcx), closure_kind_ty);
 
             // If we have an origin, store it.
-            if let Some(origin) = delegate.current_origin {
+            if let Some(origin) = delegate.current_origin.clone() {
+                let origin = if self.tcx.features().capture_disjoint_fields {
+                    origin
+                } else {
+                    // FIXME(project-rfc-2229#26): Once rust-lang#80092 is merged, we should restrict the
+                    // precision of origin as well. Otherwise, this will cause issues when project-rfc-2229#26
+                    // is fixed as we might see Index projections in the origin, which we can't print because
+                    // we don't store enough information.
+                    (origin.0, Place { projections: vec![], ..origin.1 })
+                };
+
                 self.typeck_results
                     .borrow_mut()
                     .closure_kind_origins_mut()
@@ -563,7 +573,7 @@
 
     // If we modified `current_closure_kind`, this field contains a `Some()` with the
     // variable access that caused us to do so.
-    current_origin: Option<(Span, Symbol)>,
+    current_origin: Option<(Span, Place<'tcx>)>,
 
     /// For each Place that is captured by the closure, we track the minimal kind of
     /// access we need (ref, ref mut, move, etc) and the expression that resulted in such access.
@@ -628,7 +638,7 @@
             upvar_id.closure_expr_id,
             ty::ClosureKind::FnOnce,
             usage_span,
-            var_name(tcx, upvar_id.var_path.hir_id),
+            place_with_id.place.clone(),
         );
 
         let capture_info = ty::CaptureInfo {
@@ -720,7 +730,7 @@
                 upvar_id.closure_expr_id,
                 ty::ClosureKind::FnMut,
                 tcx.hir().span(diag_expr_id),
-                var_name(tcx, upvar_id.var_path.hir_id),
+                place_with_id.place.clone(),
             );
         }
     }
@@ -765,11 +775,11 @@
         closure_id: LocalDefId,
         new_kind: ty::ClosureKind,
         upvar_span: Span,
-        var_name: Symbol,
+        place: Place<'tcx>,
     ) {
         debug!(
-            "adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, var_name={})",
-            closure_id, new_kind, upvar_span, var_name
+            "adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, place={:?})",
+            closure_id, new_kind, upvar_span, place
         );
 
         // Is this the closure whose kind is currently being inferred?
@@ -797,7 +807,7 @@
             | (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
                 // new kind is stronger than the old kind
                 self.current_closure_kind = new_kind;
-                self.current_origin = Some((upvar_span, var_name));
+                self.current_origin = Some((upvar_span, place));
             }
         }
     }
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index cd871a4..c90db47 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -51,7 +51,7 @@
             let fcx = FnCtxt::new(&inh, param_env, id);
             if !inh.tcx.features().trivial_bounds {
                 // As predicates are cached rather than obligations, this
-                // needsto be called first so that they are checked with an
+                // needs to be called first so that they are checked with an
                 // empty `param_env`.
                 check_false_global_bounds(&fcx, span, id);
             }
@@ -103,35 +103,28 @@
         //
         // won't be allowed unless there's an *explicit* implementation of `Send`
         // for `T`
-        hir::ItemKind::Impl {
-            defaultness,
-            defaultness_span,
-            polarity,
-            ref of_trait,
-            ref self_ty,
-            ..
-        } => {
+        hir::ItemKind::Impl(ref impl_) => {
             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));
-            if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) {
-                let sp = of_trait.as_ref().map(|t| t.path.span).unwrap_or(item.span);
+            if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
+                let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
                 let mut err =
                     tcx.sess.struct_span_err(sp, "impls of auto traits cannot be default");
-                err.span_labels(defaultness_span, "default because of this");
+                err.span_labels(impl_.defaultness_span, "default because of this");
                 err.span_label(sp, "auto trait");
                 err.emit();
             }
             // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
-            match (tcx.impl_polarity(def_id), polarity) {
+            match (tcx.impl_polarity(def_id), impl_.polarity) {
                 (ty::ImplPolarity::Positive, _) => {
-                    check_impl(tcx, item, self_ty, of_trait);
+                    check_impl(tcx, item, impl_.self_ty, &impl_.of_trait);
                 }
                 (ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => {
                     // FIXME(#27579): what amount of WF checking do we need for neg impls?
-                    if let hir::Defaultness::Default { .. } = defaultness {
+                    if let hir::Defaultness::Default { .. } = impl_.defaultness {
                         let mut spans = vec![span];
-                        spans.extend(defaultness_span);
+                        spans.extend(impl_.defaultness_span);
                         struct_span_err!(
                             tcx.sess,
                             spans,
@@ -286,9 +279,9 @@
         // We currently only check wf of const params here.
         hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => (),
 
-        // Const parameters are well formed if their
-        // type is structural match.
-        hir::GenericParamKind::Const { ty: hir_ty } => {
+        // Const parameters are well formed if their type is structural match.
+        // FIXME(const_generics_defaults): we also need to check that the `default` is wf.
+        hir::GenericParamKind::Const { ty: hir_ty, default: _ } => {
             let ty = tcx.type_of(tcx.hir().local_def_id(param.hir_id));
 
             let err_ty_str;
@@ -330,7 +323,7 @@
                             ),
                         )
                         .note("the only supported types are integers, `bool` and `char`")
-                        .help("more complex types are supported with `#[feature(const_generics)]`")
+                        .help("more complex types are supported with `#![feature(const_generics)]`")
                         .emit()
                 }
             };
@@ -539,7 +532,7 @@
                 fcx.register_predicate(traits::Obligation::new(
                     cause,
                     fcx.param_env,
-                    ty::PredicateAtom::ConstEvaluatable(
+                    ty::PredicateKind::ConstEvaluatable(
                         ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
                         discr_substs,
                     )
@@ -785,7 +778,7 @@
             }
 
             GenericParamDefKind::Const => {
-                // FIXME(const_generics:defaults)
+                // FIXME(const_generics_defaults)
                 fcx.tcx.mk_param_from_def(param)
             }
         }
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index 7c9cfe6..6edce62 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -384,9 +384,11 @@
         assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
         let common_hir_owner = fcx_typeck_results.hir_owner;
 
-        for (&id, &origin) in fcx_typeck_results.closure_kind_origins().iter() {
-            let hir_id = hir::HirId { owner: common_hir_owner, local_id: id };
-            self.typeck_results.closure_kind_origins_mut().insert(hir_id, origin);
+        for (id, origin) in fcx_typeck_results.closure_kind_origins().iter() {
+            let hir_id = hir::HirId { owner: common_hir_owner, local_id: *id };
+            let place_span = origin.0;
+            let place = self.resolve(origin.1.clone(), &place_span);
+            self.typeck_results.closure_kind_origins_mut().insert(hir_id, (place_span, place));
         }
     }
 
diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs
index 89270fb..6726b9b 100644
--- a/compiler/rustc_typeck/src/coherence/builtin.rs
+++ b/compiler/rustc_typeck/src/coherence/builtin.rs
@@ -55,7 +55,7 @@
 
     let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
     let sp = match tcx.hir().expect_item(impl_hir_id).kind {
-        ItemKind::Impl { self_ty, .. } => self_ty.span,
+        ItemKind::Impl(ref impl_) => impl_.self_ty.span,
         _ => bug!("expected Drop impl item"),
     };
 
@@ -80,7 +80,7 @@
         Ok(()) => {}
         Err(CopyImplementationError::InfrigingFields(fields)) => {
             let item = tcx.hir().expect_item(impl_hir_id);
-            let span = if let ItemKind::Impl { of_trait: Some(ref tr), .. } = item.kind {
+            let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref tr), .. }) = item.kind {
                 tr.path.span
             } else {
                 span
@@ -100,7 +100,7 @@
         Err(CopyImplementationError::NotAnAdt) => {
             let item = tcx.hir().expect_item(impl_hir_id);
             let span =
-                if let ItemKind::Impl { self_ty, .. } = item.kind { self_ty.span } else { span };
+                if let ItemKind::Impl(ref impl_) = item.kind { impl_.self_ty.span } else { span };
 
             tcx.sess.emit_err(CopyImplOnNonAdt { span });
         }
@@ -453,7 +453,9 @@
                     return err_info;
                 } else if diff_fields.len() > 1 {
                     let item = tcx.hir().expect_item(impl_hir_id);
-                    let span = if let ItemKind::Impl { of_trait: Some(ref t), .. } = item.kind {
+                    let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref t), .. }) =
+                        item.kind
+                    {
                         t.path.span
                     } else {
                         tcx.hir().span(impl_hir_id)
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
index 0c15784..6b6c669 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
@@ -45,7 +45,9 @@
 impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
         let (ty, assoc_items) = match item.kind {
-            hir::ItemKind::Impl { of_trait: None, ref self_ty, items, .. } => (self_ty, items),
+            hir::ItemKind::Impl(hir::Impl { of_trait: None, ref self_ty, items, .. }) => {
+                (self_ty, items)
+            }
             _ => return,
         };
 
diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs
index 253dcf0..9333aac 100644
--- a/compiler/rustc_typeck/src/coherence/orphan.rs
+++ b/compiler/rustc_typeck/src/coherence/orphan.rs
@@ -26,7 +26,10 @@
     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, of_trait: Some(ref tr), self_ty, .. } = &item.kind {
+        if let hir::ItemKind::Impl(hir::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)
diff --git a/compiler/rustc_typeck/src/coherence/unsafety.rs b/compiler/rustc_typeck/src/coherence/unsafety.rs
index 2d9128e..3a290b7 100644
--- a/compiler/rustc_typeck/src/coherence/unsafety.rs
+++ b/compiler/rustc_typeck/src/coherence/unsafety.rs
@@ -86,8 +86,13 @@
 
 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 {
-            self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
+        if let hir::ItemKind::Impl(ref impl_) = item.kind {
+            self.check_unsafety_coherence(
+                item,
+                Some(&impl_.generics),
+                impl_.unsafety,
+                impl_.polarity,
+            );
         }
     }
 
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 3e40f5b..d589989 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -189,7 +189,7 @@
         | hir::ItemKind::Enum(_, generics)
         | hir::ItemKind::TraitAlias(generics, _)
         | hir::ItemKind::Trait(_, _, generics, ..)
-        | hir::ItemKind::Impl { generics, .. }
+        | hir::ItemKind::Impl(hir::Impl { generics, .. })
         | hir::ItemKind::Struct(_, generics) => (generics, true),
         hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. })
         | hir::ItemKind::TyAlias(_, generics) => (generics, false),
@@ -228,7 +228,7 @@
                 hir::GenericParamKind::Const { .. } => {
                     let def_id = self.tcx.hir().local_def_id(param.hir_id);
                     self.tcx.ensure().type_of(def_id);
-                    // FIXME(const_generics:defaults)
+                    // FIXME(const_generics_defaults)
                 }
             }
         }
@@ -531,7 +531,7 @@
         Node::Item(item) => {
             match item.kind {
                 ItemKind::Fn(.., ref generics, _)
-                | ItemKind::Impl { ref generics, .. }
+                | ItemKind::Impl(hir::Impl { ref generics, .. })
                 | ItemKind::TyAlias(_, ref generics)
                 | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. })
                 | ItemKind::Enum(_, ref generics)
@@ -562,8 +562,8 @@
     let extra_predicates = extend.into_iter().chain(
         icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true))
             .into_iter()
-            .filter(|(predicate, _)| match predicate.skip_binders() {
-                ty::PredicateAtom::Trait(data, _) => data.self_ty().is_param(index),
+            .filter(|(predicate, _)| match predicate.kind().skip_binder() {
+                ty::PredicateKind::Trait(data, _) => data.self_ty().is_param(index),
                 _ => false,
             }),
     );
@@ -1027,7 +1027,7 @@
     // which will, in turn, reach indirect supertraits.
     for &(pred, span) in superbounds {
         debug!("superbound: {:?}", pred);
-        if let ty::PredicateAtom::Trait(bound, _) = pred.skip_binders() {
+        if let ty::PredicateKind::Trait(bound, _) = pred.kind().skip_binder() {
             tcx.at(span).super_predicates_of(bound.def_id());
         }
     }
@@ -1310,7 +1310,8 @@
 
         Node::Item(item) => {
             match item.kind {
-                ItemKind::Fn(.., ref generics, _) | ItemKind::Impl { ref generics, .. } => generics,
+                ItemKind::Fn(.., ref generics, _)
+                | ItemKind::Impl(hir::Impl { ref generics, .. }) => generics,
 
                 ItemKind::TyAlias(_, ref generics)
                 | ItemKind::Enum(_, ref generics)
@@ -1497,13 +1498,11 @@
         Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
         OpaqueDef(_, 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)
+            is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.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))
+                || segments.iter().any(|segment| are_suggestable_generic_args(segment.args().args))
         }
         _ => false,
     }
@@ -1638,7 +1637,7 @@
 
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     match tcx.hir().expect_item(hir_id).kind {
-        hir::ItemKind::Impl { ref of_trait, .. } => of_trait.as_ref().map(|ast_trait_ref| {
+        hir::ItemKind::Impl(ref impl_) => impl_.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)
         }),
@@ -1651,29 +1650,39 @@
     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 { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => {
+        hir::ItemKind::Impl(hir::Impl {
+            polarity: hir::ImplPolarity::Negative(span),
+            of_trait,
+            ..
+        }) => {
             if is_rustc_reservation {
-                let span = span.to(of_trait.as_ref().map(|t| t.path.span).unwrap_or(*span));
+                let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span));
                 tcx.sess.span_err(span, "reservation impls can't be negative");
             }
             ty::ImplPolarity::Negative
         }
-        hir::ItemKind::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => {
+        hir::ItemKind::Impl(hir::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 {
-            polarity: hir::ImplPolarity::Positive, of_trait: Some(_), ..
-        } => {
+        hir::ItemKind::Impl(hir::Impl {
+            polarity: hir::ImplPolarity::Positive,
+            of_trait: Some(_),
+            ..
+        }) => {
             if is_rustc_reservation {
                 ty::ImplPolarity::Reservation
             } else {
                 ty::ImplPolarity::Positive
             }
         }
-        ref item => bug!("impl_polarity: {:?} not an impl", item),
+        item => bug!("impl_polarity: {:?} not an impl", item),
     }
 }
 
@@ -1777,11 +1786,11 @@
 
         Node::Item(item) => {
             match item.kind {
-                ItemKind::Impl { defaultness, ref generics, .. } => {
-                    if defaultness.is_default() {
+                ItemKind::Impl(ref impl_) => {
+                    if impl_.defaultness.is_default() {
                         is_default_impl_trait = tcx.impl_trait_ref(def_id);
                     }
-                    generics
+                    &impl_.generics
                 }
                 ItemKind::Fn(.., ref generics, _)
                 | ItemKind::TyAlias(_, ref generics)
@@ -1920,7 +1929,7 @@
     let where_clause = &ast_generics.where_clause;
     for predicate in where_clause.predicates {
         match predicate {
-            &hir::WherePredicate::BoundPredicate(ref bound_pred) => {
+            hir::WherePredicate::BoundPredicate(bound_pred) => {
                 let ty = icx.to_ty(&bound_pred.bounded_ty);
 
                 // Keep the type around in a dummy predicate, in case of no bounds.
@@ -1937,19 +1946,16 @@
                     } else {
                         let span = bound_pred.bounded_ty.span;
                         let re_root_empty = tcx.lifetimes.re_root_empty;
-                        let predicate = ty::Binder::bind(ty::PredicateAtom::TypeOutlives(
+                        let predicate = ty::Binder::bind(ty::PredicateKind::TypeOutlives(
                             ty::OutlivesPredicate(ty, re_root_empty),
                         ));
-                        predicates.insert((
-                            predicate.potentially_quantified(tcx, ty::PredicateKind::ForAll),
-                            span,
-                        ));
+                        predicates.insert((predicate.to_predicate(tcx), span));
                     }
                 }
 
                 for bound in bound_pred.bounds.iter() {
                     match bound {
-                        &hir::GenericBound::Trait(ref poly_trait_ref, modifier) => {
+                        hir::GenericBound::Trait(poly_trait_ref, modifier) => {
                             let constness = match modifier {
                                 hir::TraitBoundModifier::MaybeConst => hir::Constness::NotConst,
                                 hir::TraitBoundModifier::None => constness,
@@ -1959,7 +1965,7 @@
                             let mut bounds = Bounds::default();
                             let _ = AstConv::instantiate_poly_trait_ref(
                                 &icx,
-                                poly_trait_ref,
+                                &poly_trait_ref,
                                 constness,
                                 ty,
                                 &mut bounds,
@@ -1981,13 +1987,13 @@
                             predicates.extend(bounds.predicates(tcx, ty));
                         }
 
-                        &hir::GenericBound::Outlives(ref lifetime) => {
+                        hir::GenericBound::Outlives(lifetime) => {
                             let region = AstConv::ast_region_to_region(&icx, lifetime, None);
                             predicates.insert((
-                                ty::Binder::bind(ty::PredicateAtom::TypeOutlives(
+                                ty::Binder::bind(ty::PredicateKind::TypeOutlives(
                                     ty::OutlivesPredicate(ty, region),
                                 ))
-                                .potentially_quantified(tcx, ty::PredicateKind::ForAll),
+                                .to_predicate(tcx),
                                 lifetime.span,
                             ));
                         }
@@ -1995,7 +2001,7 @@
                 }
             }
 
-            &hir::WherePredicate::RegionPredicate(ref region_pred) => {
+            hir::WherePredicate::RegionPredicate(region_pred) => {
                 let r1 = AstConv::ast_region_to_region(&icx, &region_pred.lifetime, None);
                 predicates.extend(region_pred.bounds.iter().map(|bound| {
                     let (r2, span) = match bound {
@@ -2004,14 +2010,14 @@
                         }
                         _ => bug!(),
                     };
-                    let pred = ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r1, r2))
+                    let pred = ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
                         .to_predicate(icx.tcx);
 
                     (pred, span)
                 }))
             }
 
-            &hir::WherePredicate::EqPredicate(..) => {
+            hir::WherePredicate::EqPredicate(..) => {
                 // FIXME(#20041)
             }
         }
@@ -2069,7 +2075,7 @@
             if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val {
                 let span = self.tcx.hir().span(c.hir_id);
                 self.preds.insert((
-                    ty::PredicateAtom::ConstEvaluatable(def, substs).to_predicate(self.tcx),
+                    ty::PredicateKind::ConstEvaluatable(def, substs).to_predicate(self.tcx),
                     span,
                 ));
             }
@@ -2088,7 +2094,7 @@
                 fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
                     if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val {
                         self.preds.insert((
-                            ty::PredicateAtom::ConstEvaluatable(def, substs).to_predicate(self.tcx),
+                            ty::PredicateKind::ConstEvaluatable(def, substs).to_predicate(self.tcx),
                             self.span,
                         ));
                     }
@@ -2113,14 +2119,14 @@
 
     let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
     if let hir::Node::Item(item) = node {
-        if let hir::ItemKind::Impl { ref of_trait, ref self_ty, .. } = item.kind {
-            if let Some(of_trait) = of_trait {
+        if let hir::ItemKind::Impl(ref impl_) = item.kind {
+            if let Some(of_trait) = &impl_.of_trait {
                 debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id);
                 collector.visit_trait_ref(of_trait);
             }
 
             debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id);
-            collector.visit_ty(self_ty);
+            collector.visit_ty(impl_.self_ty);
         }
     }
 
@@ -2174,12 +2180,12 @@
             .predicates
             .iter()
             .copied()
-            .filter(|(pred, _)| match pred.skip_binders() {
-                ty::PredicateAtom::Trait(tr, _) => !is_assoc_item_ty(tr.self_ty()),
-                ty::PredicateAtom::Projection(proj) => {
+            .filter(|(pred, _)| match pred.kind().skip_binder() {
+                ty::PredicateKind::Trait(tr, _) => !is_assoc_item_ty(tr.self_ty()),
+                ty::PredicateKind::Projection(proj) => {
                     !is_assoc_item_ty(proj.projection_ty.self_ty())
                 }
-                ty::PredicateAtom::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
+                ty::PredicateKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
                 _ => true,
             })
             .collect();
@@ -2208,7 +2214,8 @@
     let (ty_def_id, item_def_id) = key;
     let mut projection_ty = None;
     for (predicate, _) in tcx.predicates_of(ty_def_id).predicates {
-        if let ty::PredicateAtom::Projection(projection_predicate) = predicate.skip_binders() {
+        if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder()
+        {
             if item_def_id == projection_predicate.projection_ty.item_def_id {
                 projection_ty = Some(projection_predicate.projection_ty);
                 break;
@@ -2255,7 +2262,7 @@
         }
         hir::GenericBound::Outlives(ref lifetime) => {
             let region = astconv.ast_region_to_region(lifetime, None);
-            let pred = ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(param_ty, region))
+            let pred = ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region))
                 .to_predicate(astconv.tcx());
             vec![(pred, lifetime.span)]
         }
@@ -2952,7 +2959,7 @@
     if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
         let parent_id = tcx.hir().get_parent_item(hir_id);
         let parent_item = tcx.hir().expect_item(parent_id);
-        if let hir::ItemKind::Impl { of_trait: Some(_), .. } = parent_item.kind {
+        if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
             tcx.sess
                 .struct_span_err(
                     attr_span,
diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs
index e596dd1..537a583 100644
--- a/compiler/rustc_typeck/src/collect/item_bounds.rs
+++ b/compiler/rustc_typeck/src/collect/item_bounds.rs
@@ -36,13 +36,14 @@
     let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id();
     let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
 
-    let bounds_from_parent =
-        trait_predicates.predicates.iter().copied().filter(|(pred, _)| match pred.skip_binders() {
-            ty::PredicateAtom::Trait(tr, _) => tr.self_ty() == item_ty,
-            ty::PredicateAtom::Projection(proj) => proj.projection_ty.self_ty() == item_ty,
-            ty::PredicateAtom::TypeOutlives(outlives) => outlives.0 == item_ty,
+    let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| {
+        match pred.kind().skip_binder() {
+            ty::PredicateKind::Trait(tr, _) => tr.self_ty() == item_ty,
+            ty::PredicateKind::Projection(proj) => proj.projection_ty.self_ty() == item_ty,
+            ty::PredicateKind::TypeOutlives(outlives) => outlives.0 == item_ty,
             _ => false,
-        });
+        }
+    });
 
     let all_bounds = tcx
         .arena
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index 88ba578..e4eabca 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -6,7 +6,7 @@
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit;
 use rustc_hir::intravisit::Visitor;
-use rustc_hir::Node;
+use rustc_hir::{HirId, Node};
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::util::IntTypeExt;
@@ -22,7 +22,6 @@
 /// This should be called using the query `tcx.opt_const_param_of`.
 pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
     use hir::*;
-
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
 
     if let Node::AnonConst(_) = tcx.hir().get(hir_id) {
@@ -62,9 +61,9 @@
             }
 
             Node::Ty(&Ty { kind: TyKind::Path(_), .. })
-            | Node::Expr(&Expr { kind: ExprKind::Struct(..), .. })
-            | Node::Expr(&Expr { kind: ExprKind::Path(_), .. })
-            | Node::TraitRef(..) => {
+            | Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. })
+            | Node::TraitRef(..)
+            | Node::Pat(_) => {
                 let path = match parent_node {
                     Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
                     | Node::TraitRef(&TraitRef { path, .. }) => &*path,
@@ -79,6 +78,20 @@
                         let _tables = tcx.typeck(body_owner);
                         &*path
                     }
+                    Node::Pat(pat) => {
+                        if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
+                            path
+                        } else {
+                            tcx.sess.delay_span_bug(
+                                tcx.def_span(def_id),
+                                &format!(
+                                    "unable to find const parent for {} in pat {:?}",
+                                    hir_id, pat
+                                ),
+                            );
+                            return None;
+                        }
+                    }
                     _ => {
                         tcx.sess.delay_span_bug(
                             tcx.def_span(def_id),
@@ -91,7 +104,6 @@
                 // We've encountered an `AnonConst` in some path, so we need to
                 // figure out which generic parameter it corresponds to and return
                 // the relevant type.
-
                 let (arg_index, segment) = path
                     .segments
                     .iter()
@@ -144,6 +156,34 @@
     }
 }
 
+fn get_path_containing_arg_in_pat<'hir>(
+    pat: &'hir hir::Pat<'hir>,
+    arg_id: HirId,
+) -> Option<&'hir hir::Path<'hir>> {
+    use hir::*;
+
+    let is_arg_in_path = |p: &hir::Path<'_>| {
+        p.segments
+            .iter()
+            .filter_map(|seg| seg.args)
+            .flat_map(|args| args.args)
+            .any(|arg| arg.id() == arg_id)
+    };
+    let mut arg_path = None;
+    pat.walk(|pat| match pat.kind {
+        PatKind::Struct(QPath::Resolved(_, path), _, _)
+        | PatKind::TupleStruct(QPath::Resolved(_, path), _, _)
+        | PatKind::Path(QPath::Resolved(_, path))
+            if is_arg_in_path(path) =>
+        {
+            arg_path = Some(path);
+            false
+        }
+        _ => true,
+    });
+    arg_path
+}
+
 pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
     let def_id = def_id.expect_local();
     use rustc_hir::*;
@@ -203,9 +243,8 @@
                         icx.to_ty(ty)
                     }
                 }
-                ItemKind::TyAlias(ref self_ty, _) | ItemKind::Impl { ref self_ty, .. } => {
-                    icx.to_ty(self_ty)
-                }
+                ItemKind::TyAlias(ref self_ty, _)
+                | ItemKind::Impl(hir::Impl { ref self_ty, .. }) => icx.to_ty(self_ty),
                 ItemKind::Fn(..) => {
                     let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
                     tcx.mk_fn_def(def_id.to_def_id(), substs)
diff --git a/compiler/rustc_typeck/src/constrained_generic_params.rs b/compiler/rustc_typeck/src/constrained_generic_params.rs
index e389fd4..95670b9 100644
--- a/compiler/rustc_typeck/src/constrained_generic_params.rs
+++ b/compiler/rustc_typeck/src/constrained_generic_params.rs
@@ -183,7 +183,8 @@
         for j in i..predicates.len() {
             // Note that we don't have to care about binders here,
             // as the impl trait ref never contains any late-bound regions.
-            if let ty::PredicateAtom::Projection(projection) = predicates[j].0.skip_binders() {
+            if let ty::PredicateKind::Projection(projection) = predicates[j].0.kind().skip_binder()
+            {
                 // Special case: watch out for some kind of sneaky attempt
                 // to project out an associated type defined by this very
                 // trait.
diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs
index 3ce244e..01519e4 100644
--- a/compiler/rustc_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_typeck/src/expr_use_visitor.rs
@@ -219,6 +219,14 @@
                 self.consume_exprs(exprs);
             }
 
+            hir::ExprKind::If(ref cond_expr, ref then_expr, ref opt_else_expr) => {
+                self.consume_expr(&cond_expr);
+                self.consume_expr(&then_expr);
+                if let Some(ref else_expr) = *opt_else_expr {
+                    self.consume_expr(&else_expr);
+                }
+            }
+
             hir::ExprKind::Match(ref discr, arms, _) => {
                 let discr_place = return_if_err!(self.mc.cat_expr(&discr));
                 self.borrow_expr(&discr, ty::ImmBorrow);
diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs
index 14daa97..0bdcbaa 100644
--- a/compiler/rustc_typeck/src/impl_wf_check.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check.rs
@@ -80,10 +80,10 @@
 
 impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        if let hir::ItemKind::Impl { ref items, .. } = item.kind {
+        if let hir::ItemKind::Impl(ref impl_) = 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, items);
-            enforce_impl_items_are_distinct(self.tcx, items);
+            enforce_impl_params_are_constrained(self.tcx, impl_def_id, impl_.items);
+            enforce_impl_items_are_distinct(self.tcx, impl_.items);
             if self.min_specialization {
                 check_min_specialization(self.tcx, impl_def_id.to_def_id(), item.span);
             }
diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
index 5db9ff9..505d9a5 100644
--- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
@@ -198,7 +198,7 @@
     // the functions in `cgp` add the constrained parameters to a list of
     // unconstrained parameters.
     for (predicate, _) in impl_generic_predicates.predicates.iter() {
-        if let ty::PredicateAtom::Projection(proj) = predicate.skip_binders() {
+        if let ty::PredicateKind::Projection(proj) = predicate.kind().skip_binder() {
             let projection_ty = proj.projection_ty;
             let projected_ty = proj.ty;
 
@@ -360,13 +360,13 @@
 
 fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>, span: Span) {
     debug!("can_specialize_on(predicate = {:?})", predicate);
-    match predicate.skip_binders() {
+    match predicate.kind().skip_binder() {
         // Global predicates are either always true or always false, so we
         // are fine to specialize on.
         _ if predicate.is_global() => (),
         // We allow specializing on explicitly marked traits with no associated
         // items.
-        ty::PredicateAtom::Trait(pred, hir::Constness::NotConst) => {
+        ty::PredicateKind::Trait(pred, hir::Constness::NotConst) => {
             if !matches!(
                 trait_predicate_kind(tcx, predicate),
                 Some(TraitSpecializationKind::Marker)
@@ -393,20 +393,20 @@
     tcx: TyCtxt<'tcx>,
     predicate: ty::Predicate<'tcx>,
 ) -> Option<TraitSpecializationKind> {
-    match predicate.skip_binders() {
-        ty::PredicateAtom::Trait(pred, hir::Constness::NotConst) => {
+    match predicate.kind().skip_binder() {
+        ty::PredicateKind::Trait(pred, hir::Constness::NotConst) => {
             Some(tcx.trait_def(pred.def_id()).specialization_kind)
         }
-        ty::PredicateAtom::Trait(_, hir::Constness::Const)
-        | ty::PredicateAtom::RegionOutlives(_)
-        | ty::PredicateAtom::TypeOutlives(_)
-        | ty::PredicateAtom::Projection(_)
-        | ty::PredicateAtom::WellFormed(_)
-        | ty::PredicateAtom::Subtype(_)
-        | ty::PredicateAtom::ObjectSafe(_)
-        | ty::PredicateAtom::ClosureKind(..)
-        | ty::PredicateAtom::ConstEvaluatable(..)
-        | ty::PredicateAtom::ConstEquate(..)
-        | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
+        ty::PredicateKind::Trait(_, hir::Constness::Const)
+        | ty::PredicateKind::RegionOutlives(_)
+        | ty::PredicateKind::TypeOutlives(_)
+        | ty::PredicateKind::Projection(_)
+        | ty::PredicateKind::WellFormed(_)
+        | ty::PredicateKind::Subtype(_)
+        | ty::PredicateKind::ObjectSafe(_)
+        | ty::PredicateKind::ClosureKind(..)
+        | ty::PredicateKind::ConstEvaluatable(..)
+        | ty::PredicateKind::ConstEquate(..)
+        | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
     }
 }
diff --git a/compiler/rustc_typeck/src/mem_categorization.rs b/compiler/rustc_typeck/src/mem_categorization.rs
index a601123..fef52a3 100644
--- a/compiler/rustc_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_typeck/src/mem_categorization.rs
@@ -364,6 +364,7 @@
             | hir::ExprKind::Cast(..)
             | hir::ExprKind::DropTemps(..)
             | hir::ExprKind::Array(..)
+            | hir::ExprKind::If(..)
             | hir::ExprKind::Tup(..)
             | hir::ExprKind::Binary(..)
             | hir::ExprKind::Block(..)
@@ -653,9 +654,7 @@
         // Then we see that to get the same result, we must start with
         // `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)`
         // and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`.
-        for _ in
-            0..self.typeck_results.pat_adjustments().get(pat.hir_id).map(|v| v.len()).unwrap_or(0)
-        {
+        for _ in 0..self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(0, |v| v.len()) {
             debug!("cat_pattern: applying adjustment to place_with_id={:?}", place_with_id);
             place_with_id = self.cat_deref(pat, place_with_id)?;
         }
diff --git a/compiler/rustc_typeck/src/outlives/explicit.rs b/compiler/rustc_typeck/src/outlives/explicit.rs
index ae336cc..6e5be87 100644
--- a/compiler/rustc_typeck/src/outlives/explicit.rs
+++ b/compiler/rustc_typeck/src/outlives/explicit.rs
@@ -29,8 +29,8 @@
 
             // process predicates and convert to `RequiredPredicates` entry, see below
             for &(predicate, span) in predicates.predicates {
-                match predicate.skip_binders() {
-                    ty::PredicateAtom::TypeOutlives(OutlivesPredicate(ref ty, ref reg)) => {
+                match predicate.kind().skip_binder() {
+                    ty::PredicateKind::TypeOutlives(OutlivesPredicate(ref ty, ref reg)) => {
                         insert_outlives_predicate(
                             tcx,
                             (*ty).into(),
@@ -40,7 +40,7 @@
                         )
                     }
 
-                    ty::PredicateAtom::RegionOutlives(OutlivesPredicate(ref reg1, ref reg2)) => {
+                    ty::PredicateKind::RegionOutlives(OutlivesPredicate(ref reg1, ref reg2)) => {
                         insert_outlives_predicate(
                             tcx,
                             (*reg1).into(),
@@ -50,15 +50,15 @@
                         )
                     }
 
-                    ty::PredicateAtom::Trait(..)
-                    | ty::PredicateAtom::Projection(..)
-                    | ty::PredicateAtom::WellFormed(..)
-                    | ty::PredicateAtom::ObjectSafe(..)
-                    | ty::PredicateAtom::ClosureKind(..)
-                    | ty::PredicateAtom::Subtype(..)
-                    | ty::PredicateAtom::ConstEvaluatable(..)
-                    | ty::PredicateAtom::ConstEquate(..)
-                    | ty::PredicateAtom::TypeWellFormedFromEnv(..) => (),
+                    ty::PredicateKind::Trait(..)
+                    | ty::PredicateKind::Projection(..)
+                    | ty::PredicateKind::WellFormed(..)
+                    | ty::PredicateKind::ObjectSafe(..)
+                    | ty::PredicateKind::ClosureKind(..)
+                    | ty::PredicateKind::Subtype(..)
+                    | ty::PredicateKind::ConstEvaluatable(..)
+                    | ty::PredicateKind::ConstEquate(..)
+                    | ty::PredicateKind::TypeWellFormedFromEnv(..) => (),
                 }
             }
 
diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs
index 3d0635e..02008e1 100644
--- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs
@@ -99,7 +99,7 @@
         // we walk the crates again and re-calculate predicates for all
         // items.
         let item_predicates_len: usize =
-            self.global_inferred_outlives.get(&item_did.to_def_id()).map(|p| p.len()).unwrap_or(0);
+            self.global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.len());
         if item_required_predicates.len() > item_predicates_len {
             *self.predicates_added = true;
             self.global_inferred_outlives.insert(item_did.to_def_id(), item_required_predicates);
diff --git a/compiler/rustc_typeck/src/outlives/mod.rs b/compiler/rustc_typeck/src/outlives/mod.rs
index b1f7933..e94b845 100644
--- a/compiler/rustc_typeck/src/outlives/mod.rs
+++ b/compiler/rustc_typeck/src/outlives/mod.rs
@@ -30,13 +30,9 @@
                 if tcx.has_attr(item_def_id, sym::rustc_outlives) {
                     let mut pred: Vec<String> = predicates
                         .iter()
-                        .map(|(out_pred, _)| match out_pred.kind() {
-                            ty::PredicateKind::Atom(ty::PredicateAtom::RegionOutlives(p)) => {
-                                p.to_string()
-                            }
-                            ty::PredicateKind::Atom(ty::PredicateAtom::TypeOutlives(p)) => {
-                                p.to_string()
-                            }
+                        .map(|(out_pred, _)| match out_pred.kind().skip_binder() {
+                            ty::PredicateKind::RegionOutlives(p) => p.to_string(),
+                            ty::PredicateKind::TypeOutlives(p) => p.to_string(),
                             err => bug!("unexpected predicate {:?}", err),
                         })
                         .collect();
@@ -89,12 +85,12 @@
                 |(ty::OutlivesPredicate(kind1, region2), &span)| {
                     match kind1.unpack() {
                         GenericArgKind::Type(ty1) => Some((
-                            ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty1, region2))
+                            ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty1, region2))
                                 .to_predicate(tcx),
                             span,
                         )),
                         GenericArgKind::Lifetime(region1) => Some((
-                            ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(
+                            ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(
                                 region1, region2,
                             ))
                             .to_predicate(tcx),
diff --git a/compiler/rustc_typeck/src/structured_errors.rs b/compiler/rustc_typeck/src/structured_errors.rs
index 83125a3..04d0430 100644
--- a/compiler/rustc_typeck/src/structured_errors.rs
+++ b/compiler/rustc_typeck/src/structured_errors.rs
@@ -1,149 +1,36 @@
-use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
-use rustc_middle::ty::{Ty, TypeFoldable};
+mod missing_cast_for_variadic_arg;
+mod sized_unsized_cast;
+mod wrong_number_of_generic_args;
+
+pub use self::{
+    missing_cast_for_variadic_arg::*, sized_unsized_cast::*, wrong_number_of_generic_args::*,
+};
+
+use rustc_errors::{DiagnosticBuilder, DiagnosticId};
 use rustc_session::Session;
-use rustc_span::Span;
 
 pub trait StructuredDiagnostic<'tcx> {
     fn session(&self) -> &Session;
 
     fn code(&self) -> DiagnosticId;
 
-    fn common(&self) -> DiagnosticBuilder<'tcx>;
-
     fn diagnostic(&self) -> DiagnosticBuilder<'tcx> {
-        let err = self.common();
-        if self.session().teach(&self.code()) { self.extended(err) } else { self.regular(err) }
-    }
+        let err = self.diagnostic_common();
 
-    fn regular(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
-        err
-    }
-
-    fn extended(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
-        err
-    }
-}
-
-pub struct VariadicError<'tcx> {
-    sess: &'tcx Session,
-    span: Span,
-    t: Ty<'tcx>,
-    cast_ty: &'tcx str,
-}
-
-impl<'tcx> VariadicError<'tcx> {
-    pub fn new(
-        sess: &'tcx Session,
-        span: Span,
-        t: Ty<'tcx>,
-        cast_ty: &'tcx str,
-    ) -> VariadicError<'tcx> {
-        VariadicError { sess, span, t, cast_ty }
-    }
-}
-
-impl<'tcx> StructuredDiagnostic<'tcx> for VariadicError<'tcx> {
-    fn session(&self) -> &Session {
-        self.sess
-    }
-
-    fn code(&self) -> DiagnosticId {
-        rustc_errors::error_code!(E0617)
-    }
-
-    fn common(&self) -> DiagnosticBuilder<'tcx> {
-        let mut err = if self.t.references_error() {
-            self.sess.diagnostic().struct_dummy()
+        if self.session().teach(&self.code()) {
+            self.diagnostic_extended(err)
         } else {
-            self.sess.struct_span_fatal_with_code(
-                self.span,
-                &format!("can't pass `{}` to variadic function", self.t),
-                self.code(),
-            )
-        };
-        if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) {
-            err.span_suggestion(
-                self.span,
-                &format!("cast the value to `{}`", self.cast_ty),
-                format!("{} as {}", snippet, self.cast_ty),
-                Applicability::MachineApplicable,
-            );
-        } else {
-            err.help(&format!("cast the value to `{}`", self.cast_ty));
-        }
-        err
-    }
-
-    fn extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
-        err.note(&format!(
-            "certain types, like `{}`, must be cast before passing them to a \
-                           variadic function, because of arcane ABI rules dictated by the C \
-                           standard",
-            self.t
-        ));
-        err
-    }
-}
-
-pub struct SizedUnsizedCastError<'tcx> {
-    sess: &'tcx Session,
-    span: Span,
-    expr_ty: Ty<'tcx>,
-    cast_ty: String,
-}
-
-impl<'tcx> SizedUnsizedCastError<'tcx> {
-    pub fn new(
-        sess: &'tcx Session,
-        span: Span,
-        expr_ty: Ty<'tcx>,
-        cast_ty: String,
-    ) -> SizedUnsizedCastError<'tcx> {
-        SizedUnsizedCastError { sess, span, expr_ty, cast_ty }
-    }
-}
-
-impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCastError<'tcx> {
-    fn session(&self) -> &Session {
-        self.sess
-    }
-
-    fn code(&self) -> DiagnosticId {
-        rustc_errors::error_code!(E0607)
-    }
-
-    fn common(&self) -> DiagnosticBuilder<'tcx> {
-        if self.expr_ty.references_error() {
-            self.sess.diagnostic().struct_dummy()
-        } else {
-            self.sess.struct_span_fatal_with_code(
-                self.span,
-                &format!(
-                    "cannot cast thin pointer `{}` to fat pointer `{}`",
-                    self.expr_ty, self.cast_ty
-                ),
-                self.code(),
-            )
+            self.diagnostic_regular(err)
         }
     }
 
-    fn extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
-        err.help(
-            "Thin pointers are \"simple\" pointers: they are purely a reference to a
-memory address.
+    fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx>;
 
-Fat pointers are pointers referencing \"Dynamically Sized Types\" (also
-called DST). DST don't have a statically known size, therefore they can
-only exist behind some kind of pointers that contain additional
-information. Slices and trait objects are DSTs. In the case of slices,
-the additional information the fat pointer holds is their size.
+    fn diagnostic_regular(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
+        err
+    }
 
-To fix this error, don't try to cast directly between thin and fat
-pointers.
-
-For more information about casts, take a look at The Book:
-https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions",
-        );
+    fn diagnostic_extended(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
         err
     }
 }
diff --git a/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs
new file mode 100644
index 0000000..674b0e4
--- /dev/null
+++ b/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs
@@ -0,0 +1,58 @@
+use crate::structured_errors::StructuredDiagnostic;
+use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
+use rustc_middle::ty::{Ty, TypeFoldable};
+use rustc_session::Session;
+use rustc_span::Span;
+
+pub struct MissingCastForVariadicArg<'tcx> {
+    pub sess: &'tcx Session,
+    pub span: Span,
+    pub ty: Ty<'tcx>,
+    pub cast_ty: &'tcx str,
+}
+
+impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx> {
+    fn session(&self) -> &Session {
+        self.sess
+    }
+
+    fn code(&self) -> DiagnosticId {
+        rustc_errors::error_code!(E0617)
+    }
+
+    fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
+        let mut err = if self.ty.references_error() {
+            self.sess.diagnostic().struct_dummy()
+        } else {
+            self.sess.struct_span_fatal_with_code(
+                self.span,
+                &format!("can't pass `{}` to variadic function", self.ty),
+                self.code(),
+            )
+        };
+
+        if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) {
+            err.span_suggestion(
+                self.span,
+                &format!("cast the value to `{}`", self.cast_ty),
+                format!("{} as {}", snippet, self.cast_ty),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            err.help(&format!("cast the value to `{}`", self.cast_ty));
+        }
+
+        err
+    }
+
+    fn diagnostic_extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
+        err.note(&format!(
+            "certain types, like `{}`, must be casted before passing them to a \
+                variadic function, because of arcane ABI rules dictated by the C \
+                standard",
+            self.ty
+        ));
+
+        err
+    }
+}
diff --git a/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs
new file mode 100644
index 0000000..d0477a3
--- /dev/null
+++ b/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs
@@ -0,0 +1,57 @@
+use crate::structured_errors::StructuredDiagnostic;
+use rustc_errors::{DiagnosticBuilder, DiagnosticId};
+use rustc_middle::ty::{Ty, TypeFoldable};
+use rustc_session::Session;
+use rustc_span::Span;
+
+pub struct SizedUnsizedCast<'tcx> {
+    pub sess: &'tcx Session,
+    pub span: Span,
+    pub expr_ty: Ty<'tcx>,
+    pub cast_ty: String,
+}
+
+impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
+    fn session(&self) -> &Session {
+        self.sess
+    }
+
+    fn code(&self) -> DiagnosticId {
+        rustc_errors::error_code!(E0607)
+    }
+
+    fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
+        if self.expr_ty.references_error() {
+            self.sess.diagnostic().struct_dummy()
+        } else {
+            self.sess.struct_span_fatal_with_code(
+                self.span,
+                &format!(
+                    "cannot cast thin pointer `{}` to fat pointer `{}`",
+                    self.expr_ty, self.cast_ty
+                ),
+                self.code(),
+            )
+        }
+    }
+
+    fn diagnostic_extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
+        err.help(
+            "Thin pointers are \"simple\" pointers: they are purely a reference to a
+memory address.
+
+Fat pointers are pointers referencing \"Dynamically Sized Types\" (also
+called DST). DST don't have a statically known size, therefore they can
+only exist behind some kind of pointers that contain additional
+information. Slices and trait objects are DSTs. In the case of slices,
+the additional information the fat pointer holds is their size.
+
+To fix this error, don't try to cast directly between thin and fat
+pointers.
+
+For more information about casts, take a look at The Book:
+https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions",
+        );
+        err
+    }
+}
diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
new file mode 100644
index 0000000..e35c155
--- /dev/null
+++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
@@ -0,0 +1,393 @@
+use crate::structured_errors::StructuredDiagnostic;
+use hir::def::DefKind;
+use rustc_errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
+use rustc_hir as hir;
+use rustc_middle::ty::{self as ty, TyCtxt};
+use rustc_session::Session;
+use rustc_span::Span;
+use rustc_span::{def_id::DefId, MultiSpan};
+
+/// Handles the `wrong number of type / lifetime / ... arguments` family of error messages.
+pub struct WrongNumberOfGenericArgs<'a, 'tcx> {
+    crate tcx: TyCtxt<'tcx>,
+
+    /// "type", "lifetime" etc., put verbatim into the message
+    crate kind: &'static str,
+
+    /// Minimum number of expected generic arguments (e.g. `2` for `HashMap`)
+    crate expected_min: usize,
+
+    /// Maximum number of expected generic arguments (e.g. `3` for `HashMap`)
+    crate expected_max: usize,
+
+    /// Number of generic arguments provided by the user
+    crate provided: usize,
+
+    /// Offset into `gen_params` - depends on the `kind`; might be different than `args_offset` when
+    /// user passed e.g. more arguments than was actually expected
+    crate params_offset: usize,
+
+    /// Offset into `gen_args` - depends on the `kind`
+    crate args_offset: usize,
+
+    /// Offending path segment
+    crate path_segment: &'a hir::PathSegment<'a>,
+
+    /// Generic parameters as expected by type or trait
+    crate gen_params: &'a ty::Generics,
+
+    /// Generic arguments as provided by user
+    crate gen_args: &'a hir::GenericArgs<'a>,
+
+    /// DefId of the generic type
+    crate def_id: DefId,
+
+    /// Offending place where the generic type has been misused
+    crate span: Span,
+}
+
+impl<'tcx> WrongNumberOfGenericArgs<'_, 'tcx> {
+    fn quantifier_and_bound(&self) -> (&'static str, usize) {
+        if self.expected_min == self.expected_max {
+            ("", self.expected_min)
+        } else if self.provided < self.expected_min {
+            ("at least ", self.expected_min)
+        } else {
+            ("at most ", self.expected_max)
+        }
+    }
+
+    fn start_diagnostics(&self) -> DiagnosticBuilder<'tcx> {
+        let span = self.path_segment.ident.span;
+
+        let msg = {
+            let def_path = self.tcx.def_path_str(self.def_id);
+            let def_kind = self.tcx.def_kind(self.def_id).descr(self.def_id);
+            let (quantifier, bound) = self.quantifier_and_bound();
+
+            if self.gen_args.span().is_some() {
+                format!(
+                    "this {} takes {}{} {} argument{} but {}{} {} argument{} {} supplied",
+                    def_kind,
+                    quantifier,
+                    bound,
+                    self.kind,
+                    pluralize!(bound),
+                    if self.provided > 0 && self.provided < self.expected_min {
+                        "only "
+                    } else {
+                        ""
+                    },
+                    self.provided,
+                    self.kind,
+                    pluralize!(self.provided),
+                    if self.provided == 1 { "was" } else { "were" },
+                )
+            } else {
+                format!("missing generics for {} `{}`", def_kind, def_path)
+            }
+        };
+
+        self.tcx.sess.struct_span_err_with_code(span, &msg, self.code())
+    }
+
+    /// Builds the `expected 1 type argument / supplied 2 type arguments` message.
+    fn notify(&self, err: &mut DiagnosticBuilder<'_>) {
+        let (quantifier, bound) = self.quantifier_and_bound();
+
+        err.span_label(
+            self.path_segment.ident.span,
+            format!(
+                "expected {}{} {} argument{}",
+                quantifier,
+                bound,
+                self.kind,
+                pluralize!(bound),
+            ),
+        );
+
+        // When user's provided too many arguments, we don't highlight each of them, because it
+        // would overlap with the suggestion to remove them:
+        //
+        // ```
+        // type Foo = Bar<usize, usize>;
+        //                -----  ----- supplied 2 type arguments
+        //                     ^^^^^^^ remove this type argument
+        // ```
+        if self.provided > self.expected_max {
+            return;
+        }
+
+        let args = self.gen_args.args.iter().skip(self.args_offset).take(self.provided).enumerate();
+
+        for (i, arg) in args {
+            err.span_label(
+                arg.span(),
+                if i + 1 == self.provided {
+                    format!(
+                        "supplied {} {} argument{}",
+                        self.provided,
+                        self.kind,
+                        pluralize!(self.provided)
+                    )
+                } else {
+                    String::new()
+                },
+            );
+        }
+    }
+
+    fn suggest(&self, err: &mut DiagnosticBuilder<'_>) {
+        if self.provided == 0 {
+            if self.gen_args.span().is_some() {
+                self.suggest_adding_args(err);
+            } else {
+                self.suggest_creating_generics(err);
+            }
+        } else if self.provided < self.expected_min {
+            self.suggest_adding_args(err);
+        } else {
+            self.suggest_removing_args_or_generics(err);
+        }
+    }
+
+    /// Suggests to create generics (`<...>`) when current invocation site contains no generics at
+    /// all:
+    ///
+    /// ```text
+    /// type Map = HashMap;
+    /// ```
+    fn suggest_creating_generics(&self, err: &mut DiagnosticBuilder<'_>) {
+        let params = self
+            .gen_params
+            .params
+            .iter()
+            .skip(self.params_offset)
+            .take(self.expected_min)
+            .map(|param| param.name.to_string())
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        let def_kind = self.tcx.def_kind(self.def_id);
+
+        let sugg = if matches!(def_kind, DefKind::Fn | DefKind::AssocFn) {
+            format!("::<{}>", params)
+        } else {
+            format!("<{}>", params)
+        };
+
+        let msg = format!(
+            "use angle brackets to add missing {} argument{}",
+            self.kind,
+            pluralize!(self.expected_min),
+        );
+
+        err.span_suggestion_verbose(
+            self.path_segment.ident.span.shrink_to_hi(),
+            &msg,
+            sugg,
+            Applicability::HasPlaceholders,
+        );
+    }
+
+    /// Suggests to add missing argument(s) when current invocation site already contains some
+    /// generics:
+    ///
+    /// ```text
+    /// type Map = HashMap<String>;
+    /// ```
+    fn suggest_adding_args(&self, err: &mut DiagnosticBuilder<'_>) {
+        assert!(!self.gen_args.is_empty());
+
+        if self.gen_args.parenthesized {
+            return;
+        }
+
+        let missing_arg_count = self.expected_min - self.provided;
+
+        let (span, sugg_prefix) = if self.args_offset + self.provided == 0 {
+            let span = self.gen_args.args[0].span().shrink_to_lo();
+            (span, "")
+        } else {
+            let span =
+                self.gen_args.args[self.args_offset + self.provided - 1].span().shrink_to_hi();
+            (span, ", ")
+        };
+
+        let msg = format!("add missing {} argument{}", self.kind, pluralize!(missing_arg_count));
+
+        let sugg = self
+            .gen_params
+            .params
+            .iter()
+            .skip(self.params_offset + self.provided)
+            .take(missing_arg_count)
+            .map(|param| param.name.to_string())
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        let sugg = format!("{}{}", sugg_prefix, sugg);
+
+        err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders);
+    }
+
+    /// Suggests to remove redundant argument(s):
+    ///
+    /// ```text
+    /// type Map = HashMap<String, String, String, String>;
+    /// ```
+    fn suggest_removing_args_or_generics(&self, err: &mut DiagnosticBuilder<'_>) {
+        assert!(self.provided > 0);
+
+        let redundant_args_count = self.provided - self.expected_max;
+        let remove_entire_generics = redundant_args_count >= self.gen_args.args.len();
+
+        let (span, msg) = if remove_entire_generics {
+            let sm = self.tcx.sess.source_map();
+
+            let span = self
+                .path_segment
+                .args
+                .unwrap()
+                .span_ext(sm)
+                .unwrap()
+                .with_lo(self.path_segment.ident.span.hi());
+
+            let msg = format!(
+                "remove these {}generics",
+                if self.gen_args.parenthesized { "parenthetical " } else { "" },
+            );
+
+            (span, msg)
+        } else {
+            // When it comes to removing particular argument(s) from the generics, there are two
+            // edge cases we have to consider:
+            //
+            // When the first redundant argument is at the beginning or in the middle of the
+            // generics, like so:
+            //
+            // ```
+            // type Map = HashMap<String, String, String, String>;
+            //                    ^^^^^^^^^^^^^^^^
+            //                    | span must start with the argument
+            // ```
+            //
+            // When the last redundant argument is at the ending of the generics, like so:
+            //
+            // ```
+            // type Map = HashMap<String, String, String, String>;
+            //                                  ^^^^^^^^^^^^^^^^
+            //                                  | span must start with the comma
+            // ```
+
+            // Index of the first redundant argument
+            let from_idx = self.args_offset + self.expected_max;
+
+            // Index of the last redundant argument
+            let to_idx = self.args_offset + self.provided - 1;
+
+            assert!(from_idx <= to_idx);
+
+            let (from, comma_eaten) = {
+                let first_argument_starts_generics = from_idx == 0;
+                let last_argument_ends_generics = to_idx + 1 == self.gen_args.args.len();
+
+                if !first_argument_starts_generics && last_argument_ends_generics {
+                    (self.gen_args.args[from_idx - 1].span().hi(), true)
+                } else {
+                    (self.gen_args.args[from_idx].span().lo(), false)
+                }
+            };
+
+            let to = {
+                let hi = self.gen_args.args[to_idx].span().hi();
+
+                if comma_eaten {
+                    hi
+                } else {
+                    self.gen_args.args.get(to_idx + 1).map(|arg| arg.span().lo()).unwrap_or(hi)
+                }
+            };
+
+            let span = Span::new(from, to, self.span.ctxt());
+
+            let msg = format!(
+                "remove {} {} argument{}",
+                if redundant_args_count == 1 { "this" } else { "these" },
+                self.kind,
+                pluralize!(redundant_args_count),
+            );
+
+            (span, msg)
+        };
+
+        err.span_suggestion(span, &msg, String::new(), Applicability::MaybeIncorrect);
+    }
+
+    /// Builds the `type defined here` message.
+    fn show_definition(&self, err: &mut DiagnosticBuilder<'_>) {
+        let mut spans: MultiSpan = if let Some(def_span) = self.tcx.def_ident_span(self.def_id) {
+            def_span.into()
+        } else {
+            return;
+        };
+
+        let msg = {
+            let def_kind = self.tcx.def_kind(self.def_id).descr(self.def_id);
+            let (quantifier, bound) = self.quantifier_and_bound();
+
+            let params = if bound == 0 {
+                String::new()
+            } else {
+                let params = self
+                    .gen_params
+                    .params
+                    .iter()
+                    .skip(self.params_offset)
+                    .take(bound)
+                    .map(|param| {
+                        let span = self.tcx.def_span(param.def_id);
+                        spans.push_span_label(span, String::new());
+                        param
+                    })
+                    .map(|param| format!("`{}`", param.name))
+                    .collect::<Vec<_>>()
+                    .join(", ");
+
+                format!(": {}", params)
+            };
+
+            format!(
+                "{} defined here, with {}{} {} parameter{}{}",
+                def_kind,
+                quantifier,
+                bound,
+                self.kind,
+                pluralize!(bound),
+                params,
+            )
+        };
+
+        err.span_note(spans, &msg);
+    }
+}
+
+impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> {
+    fn session(&self) -> &Session {
+        self.tcx.sess
+    }
+
+    fn code(&self) -> DiagnosticId {
+        rustc_errors::error_code!(E0107)
+    }
+
+    fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
+        let mut err = self.start_diagnostics();
+
+        self.notify(&mut err);
+        self.suggest(&mut err);
+        self.show_definition(&mut err);
+
+        err
+    }
+}
diff --git a/config.toml.example b/config.toml.example
index b1fb890..55b20ad 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -35,9 +35,11 @@
 # Unless you're developing for a target where Rust CI doesn't build a compiler
 # toolchain or changing LLVM locally, you probably want to set this to true.
 #
-# It's currently false by default due to being newly added; please file bugs if
-# enabling this did not work for you on x86_64-unknown-linux-gnu.
-# Other target triples are currently not supported; see #77084.
+# This is false by default so that distributions don't unexpectedly download
+# LLVM from the internet.
+#
+# All tier 1 targets are currently supported; set this to `"if-supported"` if
+# you are not sure whether you're on a tier 1 target.
 #
 # We also currently only support this when building LLVM for the build triple.
 #
@@ -669,3 +671,7 @@
 
 # Whether to allow failures when building tools
 #missing-tools = false
+
+# List of compression formats to use when generating dist tarballs. The list of
+# formats is provided to rust-installer, which must support all of them.
+#compression-formats = ["gz", "xz"]
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index eff197d..d95b5b7 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -8,7 +8,7 @@
 
 [dependencies]
 core = { path = "../core" }
-compiler_builtins = { version = "0.1.10", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "0.1.39", features = ['rustc-dep-of-std'] }
 
 [dev-dependencies]
 rand = "0.7"
@@ -31,5 +31,5 @@
 [features]
 compiler-builtins-mem = ['compiler_builtins/mem']
 compiler-builtins-c = ["compiler_builtins/c"]
-compiler-builtins-asm = ["compiler_builtins/asm"]
+compiler-builtins-no-asm = ["compiler_builtins/no-asm"]
 compiler-builtins-mangled-names = ["compiler_builtins/mangled-names"]
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 4fbcc45..cb9daae 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -397,3 +397,26 @@
         unsafe { oom_impl(layout) }
     }
 }
+
+/// Specialize clones into pre-allocated, uninitialized memory.
+/// Used by `Box::clone` and `Rc`/`Arc::make_mut`.
+pub(crate) trait WriteCloneIntoRaw: Sized {
+    unsafe fn write_clone_into_raw(&self, target: *mut Self);
+}
+
+impl<T: Clone> WriteCloneIntoRaw for T {
+    #[inline]
+    default unsafe fn write_clone_into_raw(&self, target: *mut Self) {
+        // Having allocated *first* may allow the optimizer to create
+        // the cloned value in-place, skipping the local and move.
+        unsafe { target.write(self.clone()) };
+    }
+}
+
+impl<T: Copy> WriteCloneIntoRaw for T {
+    #[inline]
+    unsafe fn write_clone_into_raw(&self, target: *mut Self) {
+        // We can always copy in-place, without ever involving a local value.
+        unsafe { target.copy_from_nonoverlapping(self, 1) };
+    }
+}
diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs
index f801c1a..adf996f 100644
--- a/library/alloc/src/borrow.rs
+++ b/library/alloc/src/borrow.rs
@@ -103,6 +103,11 @@
 /// is desired, `to_mut` will obtain a mutable reference to an owned
 /// value, cloning if necessary.
 ///
+/// If you need reference-counting pointers, note that
+/// [`Rc::make_mut`][crate::rc::Rc::make_mut] and
+/// [`Arc::make_mut`][crate::sync::Arc::make_mut] can provide clone-on-write
+/// functionality as well.
+///
 /// # Examples
 ///
 /// ```
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index a6360f2..0aa52b3 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -126,9 +126,7 @@
 //!
 //! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198
 //! [dereferencing]: core::ops::Deref
-//! [`Box<T>`]: Box
 //! [`Box::<T>::from_raw(value)`]: Box::from_raw
-//! [`Box::<T>::into_raw`]: Box::into_raw
 //! [`Global`]: crate::alloc::Global
 //! [`Layout`]: crate::alloc::Layout
 //! [`Layout::for_value(&*value)`]: crate::alloc::Layout::for_value
@@ -153,7 +151,7 @@
 use core::ptr::{self, Unique};
 use core::task::{Context, Poll};
 
-use crate::alloc::{handle_alloc_error, Allocator, Global, Layout};
+use crate::alloc::{handle_alloc_error, AllocError, Allocator, Global, Layout, WriteCloneIntoRaw};
 use crate::borrow::Cow;
 use crate::raw_vec::RawVec;
 use crate::str::from_boxed_utf8_unchecked;
@@ -241,6 +239,78 @@
     pub fn pin(x: T) -> Pin<Box<T>> {
         (box x).into()
     }
+
+    /// Allocates memory on the heap then places `x` into it,
+    /// returning an error if the allocation fails
+    ///
+    /// This doesn't actually allocate if `T` is zero-sized.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api)]
+    ///
+    /// let five = Box::try_new(5)?;
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    #[inline]
+    pub fn try_new(x: T) -> Result<Self, AllocError> {
+        Self::try_new_in(x, Global)
+    }
+
+    /// Constructs a new box with uninitialized contents on the heap,
+    /// returning an error if the allocation fails
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api, new_uninit)]
+    ///
+    /// let mut five = Box::<u32>::try_new_uninit()?;
+    ///
+    /// let five = unsafe {
+    ///     // Deferred initialization:
+    ///     five.as_mut_ptr().write(5);
+    ///
+    ///     five.assume_init()
+    /// };
+    ///
+    /// assert_eq!(*five, 5);
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    // #[unstable(feature = "new_uninit", issue = "63291")]
+    #[inline]
+    pub fn try_new_uninit() -> Result<Box<mem::MaybeUninit<T>>, AllocError> {
+        Box::try_new_uninit_in(Global)
+    }
+
+    /// Constructs a new `Box` with uninitialized contents, with the memory
+    /// being filled with `0` bytes on the heap
+    ///
+    /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
+    /// of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api, new_uninit)]
+    ///
+    /// let zero = Box::<u32>::try_new_zeroed()?;
+    /// let zero = unsafe { zero.assume_init() };
+    ///
+    /// assert_eq!(*zero, 0);
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    ///
+    /// [zeroed]: mem::MaybeUninit::zeroed
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    // #[unstable(feature = "new_uninit", issue = "63291")]
+    #[inline]
+    pub fn try_new_zeroed() -> Result<Box<mem::MaybeUninit<T>>, AllocError> {
+        Box::try_new_zeroed_in(Global)
+    }
 }
 
 impl<T, A: Allocator> Box<T, A> {
@@ -267,6 +337,31 @@
         }
     }
 
+    /// Allocates memory in the given allocator then places `x` into it,
+    /// returning an error if the allocation fails
+    ///
+    /// This doesn't actually allocate if `T` is zero-sized.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api)]
+    ///
+    /// use std::alloc::System;
+    ///
+    /// let five = Box::try_new_in(5, System)?;
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    #[inline]
+    pub fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError> {
+        let mut boxed = Self::try_new_uninit_in(alloc)?;
+        unsafe {
+            boxed.as_mut_ptr().write(x);
+            Ok(boxed.assume_init())
+        }
+    }
+
     /// Constructs a new box with uninitialized contents in the provided allocator.
     ///
     /// # Examples
@@ -291,8 +386,37 @@
     // #[unstable(feature = "new_uninit", issue = "63291")]
     pub fn new_uninit_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> {
         let layout = Layout::new::<mem::MaybeUninit<T>>();
-        let ptr = alloc.allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout)).cast();
-        unsafe { Box::from_raw_in(ptr.as_ptr(), alloc) }
+        Box::try_new_uninit_in(alloc).unwrap_or_else(|_| handle_alloc_error(layout))
+    }
+
+    /// Constructs a new box with uninitialized contents in the provided allocator,
+    /// returning an error if the allocation fails
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api, new_uninit)]
+    ///
+    /// use std::alloc::System;
+    ///
+    /// let mut five = Box::<u32, _>::try_new_uninit_in(System)?;
+    ///
+    /// let five = unsafe {
+    ///     // Deferred initialization:
+    ///     five.as_mut_ptr().write(5);
+    ///
+    ///     five.assume_init()
+    /// };
+    ///
+    /// assert_eq!(*five, 5);
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    // #[unstable(feature = "new_uninit", issue = "63291")]
+    pub fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> {
+        let layout = Layout::new::<mem::MaybeUninit<T>>();
+        let ptr = alloc.allocate(layout)?.cast();
+        unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) }
     }
 
     /// Constructs a new `Box` with uninitialized contents, with the memory
@@ -319,9 +443,37 @@
     // #[unstable(feature = "new_uninit", issue = "63291")]
     pub fn new_zeroed_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> {
         let layout = Layout::new::<mem::MaybeUninit<T>>();
-        let ptr =
-            alloc.allocate_zeroed(layout).unwrap_or_else(|_| handle_alloc_error(layout)).cast();
-        unsafe { Box::from_raw_in(ptr.as_ptr(), alloc) }
+        Box::try_new_zeroed_in(alloc).unwrap_or_else(|_| handle_alloc_error(layout))
+    }
+
+    /// Constructs a new `Box` with uninitialized contents, with the memory
+    /// being filled with `0` bytes in the provided allocator,
+    /// returning an error if the allocation fails,
+    ///
+    /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
+    /// of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api, new_uninit)]
+    ///
+    /// use std::alloc::System;
+    ///
+    /// let zero = Box::<u32, _>::try_new_zeroed_in(System)?;
+    /// let zero = unsafe { zero.assume_init() };
+    ///
+    /// assert_eq!(*zero, 0);
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    ///
+    /// [zeroed]: mem::MaybeUninit::zeroed
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    // #[unstable(feature = "new_uninit", issue = "63291")]
+    pub fn try_new_zeroed_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> {
+        let layout = Layout::new::<mem::MaybeUninit<T>>();
+        let ptr = alloc.allocate_zeroed(layout)?.cast();
+        unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) }
     }
 
     /// Constructs a new `Pin<Box<T, A>>`. If `T` does not implement `Unpin`, then
@@ -862,10 +1014,14 @@
     /// // But they are unique objects
     /// assert_ne!(&*x as *const i32, &*y as *const i32);
     /// ```
-    #[rustfmt::skip]
     #[inline]
     fn clone(&self) -> Self {
-        Self::new_in((**self).clone(), self.1.clone())
+        // Pre-allocate memory to allow writing the cloned value directly.
+        let mut boxed = Self::new_uninit_in(self.1.clone());
+        unsafe {
+            (**self).write_clone_into_raw(boxed.as_mut_ptr());
+            boxed.assume_init()
+        }
     }
 
     /// Copies `source`'s contents into `self` without creating a new allocation.
diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs
index 76051d9..3c515af 100644
--- a/library/alloc/src/collections/binary_heap.rs
+++ b/library/alloc/src/collections/binary_heap.rs
@@ -161,7 +161,10 @@
 /// It is a logic error for an item to be modified in such a way that the
 /// item's ordering relative to any other item, as determined by the `Ord`
 /// trait, changes while it is in the heap. This is normally only possible
-/// through `Cell`, `RefCell`, global state, I/O, or unsafe code.
+/// through `Cell`, `RefCell`, global state, I/O, or unsafe code. The
+/// behavior resulting from such a logic error is not specified, but will
+/// not result in undefined behavior. This could include panics, incorrect
+/// results, aborts, memory leaks, and non-termination.
 ///
 /// # Examples
 ///
@@ -630,10 +633,16 @@
         // and about 2 * (len1 + len2) comparisons in the worst case
         // while `extend` takes O(len2 * log(len1)) operations
         // and about 1 * len2 * log_2(len1) comparisons in the worst case,
-        // assuming len1 >= len2.
+        // assuming len1 >= len2. For larger heaps, the crossover point
+        // no longer follows this reasoning and was determined empirically.
         #[inline]
         fn better_to_rebuild(len1: usize, len2: usize) -> bool {
-            2 * (len1 + len2) < len2 * log2_fast(len1)
+            let tot_len = len1 + len2;
+            if tot_len <= 2048 {
+                2 * tot_len < len2 * log2_fast(len1)
+            } else {
+                2 * tot_len < len2 * 11
+            }
         }
 
         if better_to_rebuild(self.len(), other.len()) {
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 944e0e6..5e63a30 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -51,6 +51,9 @@
 /// It is a logic error for a key to be modified in such a way that the key's ordering relative to
 /// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is
 /// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
+/// The behavior resulting from such a logic error is not specified, but will not result in
+/// undefined behavior. This could include panics, incorrect results, aborts, memory leaks, and
+/// non-termination.
 ///
 /// [`Cell`]: core::cell::Cell
 /// [`RefCell`]: core::cell::RefCell
diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs
index b3641a7..097e3e6 100644
--- a/library/alloc/src/collections/btree/node.rs
+++ b/library/alloc/src/collections/btree/node.rs
@@ -142,8 +142,17 @@
 }
 
 impl<K, V> NodeRef<marker::Owned, K, V, marker::Internal> {
+    fn new_internal(child: Root<K, V>) -> Self {
+        let mut new_node = Box::new(unsafe { InternalNode::new() });
+        new_node.edges[0].write(child.node);
+        NodeRef::from_new_internal(new_node, child.height + 1)
+    }
+
     fn from_new_internal(internal: Box<InternalNode<K, V>>, height: usize) -> Self {
-        NodeRef { height, node: NonNull::from(Box::leak(internal)).cast(), _marker: PhantomData }
+        let node = NonNull::from(Box::leak(internal)).cast();
+        let mut this = NodeRef { height, node, _marker: PhantomData };
+        this.borrow_mut().correct_all_childrens_parent_links();
+        this
     }
 }
 
@@ -167,11 +176,7 @@
     /// make that new node the root node, and return it. This increases the height by 1
     /// and is the opposite of `pop_internal_level`.
     pub fn push_internal_level(&mut self) -> NodeRef<marker::Mut<'_>, K, V, marker::Internal> {
-        let mut new_node = Box::new(unsafe { InternalNode::new() });
-        new_node.edges[0].write(self.node);
-        let mut new_root = NodeRef::from_new_internal(new_node, self.height + 1);
-        new_root.borrow_mut().first_edge().correct_parent_link();
-        *self = new_root.forget_type();
+        super::mem::take_mut(self, |old_root| NodeRef::new_internal(old_root).forget_type());
 
         // `self.borrow_mut()`, except that we just forgot we're internal now:
         NodeRef { height: self.height, node: self.node, _marker: PhantomData }
@@ -179,7 +184,7 @@
 
     /// Removes the internal root node, using its first child as the new root node.
     /// As it is intended only to be called when the root node has only one child,
-    /// no cleanup is done on any of the other children.
+    /// no cleanup is done on any of the keys, values and other children.
     /// This decreases the height by 1 and is the opposite of `push_internal_level`.
     ///
     /// Requires exclusive access to the `Root` object but not to the root node;
@@ -220,7 +225,7 @@
 ///    - When this is `Owned`, the `NodeRef` acts roughly like `Box<Node>`,
 ///      but does not have a destructor, and must be cleaned up manually.
 ///   Since any `NodeRef` allows navigating through the tree, `BorrowType`
-///   effectively applies to the entire tree, not just the node itself.
+///   effectively applies to the entire tree, not just to the node itself.
 /// - `K` and `V`: These are the types of keys and values stored in the nodes.
 /// - `Type`: This can be `Leaf`, `Internal`, or `LeafOrInternal`. When this is
 ///   `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the
@@ -420,7 +425,7 @@
 
 impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
     /// Similar to `ascend`, gets a reference to a node's parent node, but also
-    /// deallocate the current node in the process. This is unsafe because the
+    /// deallocates the current node in the process. This is unsafe because the
     /// current node will still be accessible despite being deallocated.
     pub unsafe fn deallocate_and_ascend(
         self,
@@ -656,7 +661,10 @@
     /// Removes a key-value pair from the end of the node and returns the pair.
     /// Also removes the edge that was to the right of that pair and, if the node
     /// is internal, returns the orphaned subtree that this edge owned.
-    fn pop(&mut self) -> (K, V, Option<Root<K, V>>) {
+    ///
+    /// # Safety
+    /// The node must not be empty.
+    unsafe fn pop(&mut self) -> (K, V, Option<Root<K, V>>) {
         debug_assert!(self.len() > 0);
 
         let idx = self.len() - 1;
@@ -712,13 +720,6 @@
             (key, val, edge)
         }
     }
-
-    fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) {
-        let leaf = self.as_leaf_mut();
-        let keys = MaybeUninit::slice_as_mut_ptr(&mut leaf.keys);
-        let vals = MaybeUninit::slice_as_mut_ptr(&mut leaf.vals);
-        (keys, vals)
-    }
 }
 
 impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
@@ -1124,21 +1125,20 @@
     /// by taking care of leaf data.
     fn split_leaf_data(&mut self, new_node: &mut LeafNode<K, V>) -> (K, V) {
         debug_assert!(self.idx < self.node.len());
-        let new_len = self.node.len() - self.idx - 1;
+        let old_len = self.node.len();
+        let new_len = old_len - self.idx - 1;
         new_node.len = new_len as u16;
         unsafe {
             let k = self.node.key_area_mut(self.idx).assume_init_read();
             let v = self.node.val_area_mut(self.idx).assume_init_read();
 
-            ptr::copy_nonoverlapping(
-                self.node.key_area_mut(self.idx + 1..).as_ptr(),
-                new_node.keys.as_mut_ptr(),
-                new_len,
+            move_to_slice(
+                self.node.key_area_mut(self.idx + 1..old_len),
+                &mut new_node.keys[..new_len],
             );
-            ptr::copy_nonoverlapping(
-                self.node.val_area_mut(self.idx + 1..).as_ptr(),
-                new_node.vals.as_mut_ptr(),
-                new_len,
+            move_to_slice(
+                self.node.val_area_mut(self.idx + 1..old_len),
+                &mut new_node.vals[..new_len],
             );
 
             *self.node.len_mut() = self.idx as u16;
@@ -1190,20 +1190,18 @@
     /// - All the edges and key-value pairs to the right of this handle are put into
     ///   a newly allocated node.
     pub fn split(mut self) -> SplitResult<'a, K, V, marker::Internal> {
+        let old_len = self.node.len();
         unsafe {
             let mut new_node = Box::new(InternalNode::new());
             let kv = self.split_leaf_data(&mut new_node.data);
             let new_len = usize::from(new_node.data.len);
-            ptr::copy_nonoverlapping(
-                self.node.edge_area_mut(self.idx + 1..).as_ptr(),
-                new_node.edges.as_mut_ptr(),
-                new_len + 1,
+            move_to_slice(
+                self.node.edge_area_mut(self.idx + 1..old_len + 1),
+                &mut new_node.edges[..new_len + 1],
             );
 
             let height = self.node.height;
-            let mut right = NodeRef::from_new_internal(new_node, height);
-
-            right.borrow_mut().correct_childrens_parent_links(0..=new_len);
+            let right = NodeRef::from_new_internal(new_node, height);
 
             SplitResult { left: self.node, kv, right }
         }
@@ -1284,25 +1282,25 @@
         self.right_child
     }
 
-    /// Returns `true` if it is valid to call `.merge()` in the balancing context,
-    /// i.e., whether there is enough room in a node to hold the combination of
-    /// both adjacent child nodes, along with the key-value pair in the parent.
+    /// Returns whether merging is possible, i.e., whether there is enough room
+    /// in a node to combine the central KV with both adjacent child nodes.
     pub fn can_merge(&self) -> bool {
         self.left_child.len() + 1 + self.right_child.len() <= CAPACITY
     }
 }
 
 impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> {
-    /// Merges the parent's key-value pair and both adjacent child nodes into
-    /// the left node and returns an edge handle in that expanded left node.
-    /// If `track_edge_idx` is given some value, the returned edge corresponds
-    /// to where the edge in that child node ended up,
-    ///
-    /// Panics unless we `.can_merge()`.
-    pub fn merge(
+    /// Performs a merge and lets a closure decide what to return.
+    fn do_merge<
+        F: FnOnce(
+            NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
+            NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>,
+        ) -> R,
+        R,
+    >(
         self,
-        track_edge_idx: Option<LeftOrRight<usize>>,
-    ) -> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::Edge> {
+        result: F,
+    ) -> R {
         let Handle { node: mut parent_node, idx: parent_idx, _marker } = self.parent;
         let old_parent_len = parent_node.len();
         let mut left_node = self.left_child;
@@ -1312,29 +1310,22 @@
         let new_left_len = old_left_len + 1 + right_len;
 
         assert!(new_left_len <= CAPACITY);
-        assert!(match track_edge_idx {
-            None => true,
-            Some(LeftOrRight::Left(idx)) => idx <= old_left_len,
-            Some(LeftOrRight::Right(idx)) => idx <= right_len,
-        });
 
         unsafe {
             *left_node.len_mut() = new_left_len as u16;
 
             let parent_key = slice_remove(parent_node.key_area_mut(..old_parent_len), parent_idx);
             left_node.key_area_mut(old_left_len).write(parent_key);
-            ptr::copy_nonoverlapping(
-                right_node.key_area_mut(..).as_ptr(),
-                left_node.key_area_mut(old_left_len + 1..).as_mut_ptr(),
-                right_len,
+            move_to_slice(
+                right_node.key_area_mut(..right_len),
+                left_node.key_area_mut(old_left_len + 1..new_left_len),
             );
 
             let parent_val = slice_remove(parent_node.val_area_mut(..old_parent_len), parent_idx);
             left_node.val_area_mut(old_left_len).write(parent_val);
-            ptr::copy_nonoverlapping(
-                right_node.val_area_mut(..).as_ptr(),
-                left_node.val_area_mut(old_left_len + 1..).as_mut_ptr(),
-                right_len,
+            move_to_slice(
+                right_node.val_area_mut(..right_len),
+                left_node.val_area_mut(old_left_len + 1..new_left_len),
             );
 
             slice_remove(&mut parent_node.edge_area_mut(..old_parent_len + 1), parent_idx + 1);
@@ -1346,10 +1337,9 @@
                 // of the node of this edge, thus above zero, so they are internal.
                 let mut left_node = left_node.reborrow_mut().cast_to_internal_unchecked();
                 let mut right_node = right_node.cast_to_internal_unchecked();
-                ptr::copy_nonoverlapping(
-                    right_node.edge_area_mut(..).as_ptr(),
-                    left_node.edge_area_mut(old_left_len + 1..).as_mut_ptr(),
-                    right_len + 1,
+                move_to_slice(
+                    right_node.edge_area_mut(..right_len + 1),
+                    left_node.edge_area_mut(old_left_len + 1..new_left_len + 1),
                 );
 
                 left_node.correct_childrens_parent_links(old_left_len + 1..new_left_len + 1);
@@ -1358,14 +1348,47 @@
             } else {
                 Global.deallocate(right_node.node.cast(), Layout::new::<LeafNode<K, V>>());
             }
-
-            let new_idx = match track_edge_idx {
-                None => 0,
-                Some(LeftOrRight::Left(idx)) => idx,
-                Some(LeftOrRight::Right(idx)) => old_left_len + 1 + idx,
-            };
-            Handle::new_edge(left_node, new_idx)
         }
+        result(parent_node, left_node)
+    }
+
+    /// Merges the parent's key-value pair and both adjacent child nodes into
+    /// the left child node and returns the shrunk parent node.
+    ///
+    /// Panics unless we `.can_merge()`.
+    pub fn merge_tracking_parent(self) -> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
+        self.do_merge(|parent, _child| parent)
+    }
+
+    /// Merges the parent's key-value pair and both adjacent child nodes into
+    /// the left child node and returns that child node.
+    ///
+    /// Panics unless we `.can_merge()`.
+    pub fn merge_tracking_child(self) -> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
+        self.do_merge(|_parent, child| child)
+    }
+
+    /// Merges the parent's key-value pair and both adjacent child nodes into
+    /// the left child node and returns the edge handle in that child node
+    /// where the tracked child edge ended up,
+    ///
+    /// Panics unless we `.can_merge()`.
+    pub fn merge_tracking_child_edge(
+        self,
+        track_edge_idx: LeftOrRight<usize>,
+    ) -> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::Edge> {
+        let old_left_len = self.left_child.len();
+        let right_len = self.right_child.len();
+        assert!(match track_edge_idx {
+            LeftOrRight::Left(idx) => idx <= old_left_len,
+            LeftOrRight::Right(idx) => idx <= right_len,
+        });
+        let child = self.merge_tracking_child();
+        let new_idx = match track_edge_idx {
+            LeftOrRight::Left(idx) => idx,
+            LeftOrRight::Right(idx) => old_left_len + 1 + idx,
+        };
+        unsafe { Handle::new_edge(child, new_idx) }
     }
 
     /// Removes a key-value pair from the left child and places it in the key-value storage
@@ -1432,36 +1455,42 @@
 
             // Move leaf data.
             {
-                let left_kv = left_node.reborrow_mut().into_kv_pointers_mut();
-                let right_kv = right_node.reborrow_mut().into_kv_pointers_mut();
-                let parent_kv = {
-                    let kv = self.parent.kv_mut();
-                    (kv.0 as *mut K, kv.1 as *mut V)
-                };
-
                 // Make room for stolen elements in the right child.
-                ptr::copy(right_kv.0, right_kv.0.add(count), old_right_len);
-                ptr::copy(right_kv.1, right_kv.1.add(count), old_right_len);
+                slice_shr(right_node.key_area_mut(..new_right_len), count);
+                slice_shr(right_node.val_area_mut(..new_right_len), count);
 
                 // Move elements from the left child to the right one.
-                move_kv(left_kv, new_left_len + 1, right_kv, 0, count - 1);
-
-                // Move parent's key-value pair to the right child.
-                move_kv(parent_kv, 0, right_kv, count - 1, 1);
+                move_to_slice(
+                    left_node.key_area_mut(new_left_len + 1..old_left_len),
+                    right_node.key_area_mut(..count - 1),
+                );
+                move_to_slice(
+                    left_node.val_area_mut(new_left_len + 1..old_left_len),
+                    right_node.val_area_mut(..count - 1),
+                );
 
                 // Move the left-most stolen pair to the parent.
-                move_kv(left_kv, new_left_len, parent_kv, 0, 1);
+                let k = left_node.key_area_mut(new_left_len).assume_init_read();
+                let v = left_node.val_area_mut(new_left_len).assume_init_read();
+                let (k, v) = self.parent.replace_kv(k, v);
+
+                // Move parent's key-value pair to the right child.
+                right_node.key_area_mut(count - 1).write(k);
+                right_node.val_area_mut(count - 1).write(v);
             }
 
             match (left_node.reborrow_mut().force(), right_node.reborrow_mut().force()) {
-                (ForceResult::Internal(left), ForceResult::Internal(mut right)) => {
+                (ForceResult::Internal(mut left), ForceResult::Internal(mut right)) => {
                     // Make room for stolen edges.
-                    let right_edges = right.edge_area_mut(..).as_mut_ptr();
-                    ptr::copy(right_edges, right_edges.add(count), old_right_len + 1);
-                    right.correct_childrens_parent_links(count..new_right_len + 1);
+                    slice_shr(right.edge_area_mut(..new_right_len + 1), count);
 
                     // Steal edges.
-                    move_edges(left, new_left_len + 1, right, 0, count);
+                    move_to_slice(
+                        left.edge_area_mut(new_left_len + 1..old_left_len + 1),
+                        right.edge_area_mut(..count),
+                    );
+
+                    right.correct_childrens_parent_links(0..new_right_len + 1);
                 }
                 (ForceResult::Leaf(_), ForceResult::Leaf(_)) => {}
                 _ => unreachable!(),
@@ -1489,36 +1518,43 @@
 
             // Move leaf data.
             {
-                let left_kv = left_node.reborrow_mut().into_kv_pointers_mut();
-                let right_kv = right_node.reborrow_mut().into_kv_pointers_mut();
-                let parent_kv = {
-                    let kv = self.parent.kv_mut();
-                    (kv.0 as *mut K, kv.1 as *mut V)
-                };
+                // Move the right-most stolen pair to the parent.
+                let k = right_node.key_area_mut(count - 1).assume_init_read();
+                let v = right_node.val_area_mut(count - 1).assume_init_read();
+                let (k, v) = self.parent.replace_kv(k, v);
 
                 // Move parent's key-value pair to the left child.
-                move_kv(parent_kv, 0, left_kv, old_left_len, 1);
+                left_node.key_area_mut(old_left_len).write(k);
+                left_node.val_area_mut(old_left_len).write(v);
 
                 // Move elements from the right child to the left one.
-                move_kv(right_kv, 0, left_kv, old_left_len + 1, count - 1);
-
-                // Move the right-most stolen pair to the parent.
-                move_kv(right_kv, count - 1, parent_kv, 0, 1);
+                move_to_slice(
+                    right_node.key_area_mut(..count - 1),
+                    left_node.key_area_mut(old_left_len + 1..new_left_len),
+                );
+                move_to_slice(
+                    right_node.val_area_mut(..count - 1),
+                    left_node.val_area_mut(old_left_len + 1..new_left_len),
+                );
 
                 // Fill gap where stolen elements used to be.
-                ptr::copy(right_kv.0.add(count), right_kv.0, new_right_len);
-                ptr::copy(right_kv.1.add(count), right_kv.1, new_right_len);
+                slice_shl(right_node.key_area_mut(..old_right_len), count);
+                slice_shl(right_node.val_area_mut(..old_right_len), count);
             }
 
             match (left_node.reborrow_mut().force(), right_node.reborrow_mut().force()) {
-                (ForceResult::Internal(left), ForceResult::Internal(mut right)) => {
+                (ForceResult::Internal(mut left), ForceResult::Internal(mut right)) => {
                     // Steal edges.
-                    move_edges(right.reborrow_mut(), 0, left, old_left_len + 1, count);
+                    move_to_slice(
+                        right.edge_area_mut(..count),
+                        left.edge_area_mut(old_left_len + 1..new_left_len + 1),
+                    );
 
                     // Fill gap where stolen edges used to be.
-                    let right_edges = right.edge_area_mut(..).as_mut_ptr();
-                    ptr::copy(right_edges.add(count), right_edges, new_right_len + 1);
-                    right.correct_childrens_parent_links(0..=new_right_len);
+                    slice_shl(right.edge_area_mut(..old_right_len + 1), count);
+
+                    left.correct_childrens_parent_links(old_left_len + 1..new_left_len + 1);
+                    right.correct_childrens_parent_links(0..new_right_len + 1);
                 }
                 (ForceResult::Leaf(_), ForceResult::Leaf(_)) => {}
                 _ => unreachable!(),
@@ -1527,35 +1563,6 @@
     }
 }
 
-unsafe fn move_kv<K, V>(
-    source: (*mut K, *mut V),
-    source_offset: usize,
-    dest: (*mut K, *mut V),
-    dest_offset: usize,
-    count: usize,
-) {
-    unsafe {
-        ptr::copy_nonoverlapping(source.0.add(source_offset), dest.0.add(dest_offset), count);
-        ptr::copy_nonoverlapping(source.1.add(source_offset), dest.1.add(dest_offset), count);
-    }
-}
-
-// Source and destination must have the same height.
-unsafe fn move_edges<'a, K: 'a, V: 'a>(
-    mut source: NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
-    source_offset: usize,
-    mut dest: NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
-    dest_offset: usize,
-    count: usize,
-) {
-    unsafe {
-        let source_ptr = source.edge_area_mut(..).as_ptr();
-        let dest_ptr = dest.edge_area_mut(dest_offset..).as_mut_ptr();
-        ptr::copy_nonoverlapping(source_ptr.add(source_offset), dest_ptr, count);
-        dest.correct_childrens_parent_links(dest_offset..dest_offset + count);
-    }
-}
-
 impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Leaf> {
     /// Removes any static information asserting that this node is a `Leaf` node.
     pub fn forget_type(self) -> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
@@ -1633,25 +1640,33 @@
         unsafe {
             let new_left_len = self.idx;
             let mut left_node = self.reborrow_mut().into_node();
+            let old_left_len = left_node.len();
 
-            let new_right_len = left_node.len() - new_left_len;
+            let new_right_len = old_left_len - new_left_len;
             let mut right_node = right.reborrow_mut();
 
             assert!(right_node.len() == 0);
             assert!(left_node.height == right_node.height);
 
             if new_right_len > 0 {
-                let left_kv = left_node.reborrow_mut().into_kv_pointers_mut();
-                let right_kv = right_node.reborrow_mut().into_kv_pointers_mut();
-
-                move_kv(left_kv, new_left_len, right_kv, 0, new_right_len);
-
                 *left_node.len_mut() = new_left_len as u16;
                 *right_node.len_mut() = new_right_len as u16;
 
+                move_to_slice(
+                    left_node.key_area_mut(new_left_len..old_left_len),
+                    right_node.key_area_mut(..new_right_len),
+                );
+                move_to_slice(
+                    left_node.val_area_mut(new_left_len..old_left_len),
+                    right_node.val_area_mut(..new_right_len),
+                );
                 match (left_node.force(), right_node.force()) {
-                    (ForceResult::Internal(left), ForceResult::Internal(right)) => {
-                        move_edges(left, new_left_len + 1, right, 1, new_right_len);
+                    (ForceResult::Internal(mut left), ForceResult::Internal(mut right)) => {
+                        move_to_slice(
+                            left.edge_area_mut(new_left_len + 1..old_left_len + 1),
+                            right.edge_area_mut(1..new_right_len + 1),
+                        );
+                        right.correct_childrens_parent_links(1..new_right_len + 1);
                     }
                     (ForceResult::Leaf(_), ForceResult::Leaf(_)) => {}
                     _ => unreachable!(),
@@ -1741,5 +1756,37 @@
     }
 }
 
+/// Shifts the elements in a slice `distance` positions to the left.
+///
+/// # Safety
+/// The slice has at least `distance` elements.
+unsafe fn slice_shl<T>(slice: &mut [MaybeUninit<T>], distance: usize) {
+    unsafe {
+        let slice_ptr = slice.as_mut_ptr();
+        ptr::copy(slice_ptr.add(distance), slice_ptr, slice.len() - distance);
+    }
+}
+
+/// Shifts the elements in a slice `distance` positions to the right.
+///
+/// # Safety
+/// The slice has at least `distance` elements.
+unsafe fn slice_shr<T>(slice: &mut [MaybeUninit<T>], distance: usize) {
+    unsafe {
+        let slice_ptr = slice.as_mut_ptr();
+        ptr::copy(slice_ptr, slice_ptr.add(distance), slice.len() - distance);
+    }
+}
+
+/// Moves all values from a slice of initialized elements to a slice
+/// of uninitialized elements, leaving behind `src` as all uninitialized.
+/// Works like `dst.copy_from_slice(src)` but does not require `T` to be `Copy`.
+fn move_to_slice<T>(src: &mut [MaybeUninit<T>], dst: &mut [MaybeUninit<T>]) {
+    assert!(src.len() == dst.len());
+    unsafe {
+        ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len());
+    }
+}
+
 #[cfg(test)]
 mod tests;
diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs
index 7fe8ff7..48ce9f2 100644
--- a/library/alloc/src/collections/btree/node/tests.rs
+++ b/library/alloc/src/collections/btree/node/tests.rs
@@ -79,10 +79,8 @@
 #[test]
 fn test_partial_cmp_eq() {
     let mut root1 = NodeRef::new_leaf();
-    let mut leaf1 = root1.borrow_mut();
-    leaf1.push(1, ());
-    let mut root1 = root1.forget_type();
-    root1.push_internal_level();
+    root1.borrow_mut().push(1, ());
+    let mut root1 = NodeRef::new_internal(root1.forget_type()).forget_type();
     let root2 = Root::new();
     root1.reborrow().assert_back_pointers();
     root2.reborrow().assert_back_pointers();
diff --git a/library/alloc/src/collections/btree/remove.rs b/library/alloc/src/collections/btree/remove.rs
index 7aeb39c..04683e0 100644
--- a/library/alloc/src/collections/btree/remove.rs
+++ b/library/alloc/src/collections/btree/remove.rs
@@ -33,7 +33,7 @@
                 Ok(Left(left_parent_kv)) => {
                     debug_assert!(left_parent_kv.right_child_len() == MIN_LEN - 1);
                     if left_parent_kv.can_merge() {
-                        left_parent_kv.merge(Some(Right(idx)))
+                        left_parent_kv.merge_tracking_child_edge(Right(idx))
                     } else {
                         debug_assert!(left_parent_kv.left_child_len() > MIN_LEN);
                         left_parent_kv.steal_left(idx)
@@ -42,7 +42,7 @@
                 Ok(Right(right_parent_kv)) => {
                     debug_assert!(right_parent_kv.left_child_len() == MIN_LEN - 1);
                     if right_parent_kv.can_merge() {
-                        right_parent_kv.merge(Some(Left(idx)))
+                        right_parent_kv.merge_tracking_child_edge(Left(idx))
                     } else {
                         debug_assert!(right_parent_kv.right_child_len() > MIN_LEN);
                         right_parent_kv.steal_right(idx)
@@ -124,9 +124,8 @@
             Ok(Left(left_parent_kv)) => {
                 debug_assert_eq!(left_parent_kv.right_child_len(), MIN_LEN - 1);
                 if left_parent_kv.can_merge() {
-                    let pos = left_parent_kv.merge(None);
-                    let parent_edge = unsafe { unwrap_unchecked(pos.into_node().ascend().ok()) };
-                    Some(parent_edge.into_node())
+                    let parent = left_parent_kv.merge_tracking_parent();
+                    Some(parent)
                 } else {
                     debug_assert!(left_parent_kv.left_child_len() > MIN_LEN);
                     left_parent_kv.steal_left(0);
@@ -136,9 +135,8 @@
             Ok(Right(right_parent_kv)) => {
                 debug_assert_eq!(right_parent_kv.left_child_len(), MIN_LEN - 1);
                 if right_parent_kv.can_merge() {
-                    let pos = right_parent_kv.merge(None);
-                    let parent_edge = unsafe { unwrap_unchecked(pos.into_node().ascend().ok()) };
-                    Some(parent_edge.into_node())
+                    let parent = right_parent_kv.merge_tracking_parent();
+                    Some(parent)
                 } else {
                     debug_assert!(right_parent_kv.right_child_len() > MIN_LEN);
                     right_parent_kv.steal_right(0);
diff --git a/library/alloc/src/collections/btree/search.rs b/library/alloc/src/collections/btree/search.rs
index ed7f95f..efe94ef 100644
--- a/library/alloc/src/collections/btree/search.rs
+++ b/library/alloc/src/collections/btree/search.rs
@@ -12,8 +12,7 @@
 
 /// Looks up a given key in a (sub)tree headed by the given node, recursively.
 /// Returns a `Found` with the handle of the matching KV, if any. Otherwise,
-/// returns a `GoDown` with the handle of the possible leaf edge where the key
-/// belongs.
+/// returns a `GoDown` with the handle of the leaf edge where the key belongs.
 ///
 /// The result is meaningful only if the tree is ordered by key, like the tree
 /// in a `BTreeMap` is.
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index c72e305..c2a96dd 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -22,6 +22,9 @@
 /// It is a logic error for an item to be modified in such a way that the item's ordering relative
 /// to any other item, as determined by the [`Ord`] trait, changes while it is in the set. This is
 /// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
+/// The behavior resulting from such a logic error is not specified, but will not result in
+/// undefined behavior. This could include panics, incorrect results, aborts, memory leaks, and
+/// non-termination.
 ///
 /// [`Ord`]: core::cmp::Ord
 /// [`Cell`]: core::cell::Cell
diff --git a/library/alloc/src/collections/btree/split.rs b/library/alloc/src/collections/btree/split.rs
index 4561c8e..375c617 100644
--- a/library/alloc/src/collections/btree/split.rs
+++ b/library/alloc/src/collections/btree/split.rs
@@ -66,7 +66,7 @@
                 let mut last_kv = node.last_kv().consider_for_balancing();
 
                 if last_kv.can_merge() {
-                    cur_node = last_kv.merge(None).into_node();
+                    cur_node = last_kv.merge_tracking_child();
                 } else {
                     let right_len = last_kv.right_child_len();
                     // `MIN_LEN + 1` to avoid readjust if merge happens on the next level.
@@ -93,7 +93,7 @@
                 let mut first_kv = node.first_kv().consider_for_balancing();
 
                 if first_kv.can_merge() {
-                    cur_node = first_kv.merge(None).into_node();
+                    cur_node = first_kv.merge_tracking_child();
                 } else {
                     let left_len = first_kv.left_child_len();
                     // `MIN_LEN + 1` to avoid readjust if merge happens on the next level.
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index f8fad6d..5b61e89 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -1292,7 +1292,7 @@
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn front(&self) -> Option<&T> {
-        if !self.is_empty() { Some(&self[0]) } else { None }
+        self.get(0)
     }
 
     /// Provides a mutable reference to the front element, or `None` if the
@@ -1316,7 +1316,7 @@
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn front_mut(&mut self) -> Option<&mut T> {
-        if !self.is_empty() { Some(&mut self[0]) } else { None }
+        self.get_mut(0)
     }
 
     /// Provides a reference to the back element, or `None` if the `VecDeque` is
@@ -1336,7 +1336,7 @@
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn back(&self) -> Option<&T> {
-        if !self.is_empty() { Some(&self[self.len() - 1]) } else { None }
+        self.get(self.len().wrapping_sub(1))
     }
 
     /// Provides a mutable reference to the back element, or `None` if the
@@ -1360,8 +1360,7 @@
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn back_mut(&mut self) -> Option<&mut T> {
-        let len = self.len();
-        if !self.is_empty() { Some(&mut self[len - 1]) } else { None }
+        self.get_mut(self.len().wrapping_sub(1))
     }
 
     /// Removes the first element and returns it, or `None` if the `VecDeque` is
diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs
index 21f52af..27dc59a 100644
--- a/library/alloc/src/collections/vec_deque/tests.rs
+++ b/library/alloc/src/collections/vec_deque/tests.rs
@@ -225,6 +225,21 @@
 }
 
 #[test]
+fn make_contiguous_head_to_end_2() {
+    // Another test case for #79808, taken from #80293.
+
+    let mut dq = VecDeque::from_iter(0..6);
+    dq.pop_front();
+    dq.pop_front();
+    dq.push_back(6);
+    dq.push_back(7);
+    dq.push_back(8);
+    dq.make_contiguous();
+    let collected: Vec<_> = dq.iter().copied().collect();
+    assert_eq!(dq.as_slices(), (&collected[..], &[] as &[_]));
+}
+
+#[test]
 fn test_remove() {
     // This test checks that every single combination of tail position, length, and
     // removal position is tested. Capacity 15 should be large enough to cover every case.
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 54b402f..14a10aa 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -70,7 +70,6 @@
 #![warn(missing_docs)]
 #![warn(missing_debug_implementations)]
 #![allow(explicit_outlives_requirements)]
-#![allow(incomplete_features)]
 #![deny(unsafe_op_in_unsafe_fn)]
 #![feature(rustc_allow_const_fn_unstable)]
 #![cfg_attr(not(test), feature(generator_trait))]
@@ -90,7 +89,6 @@
 #![feature(coerce_unsized)]
 #![feature(const_btree_new)]
 #![feature(const_fn)]
-#![feature(const_generics)]
 #![feature(const_in_array_repeat_expressions)]
 #![feature(cow_is_borrowed)]
 #![feature(const_cow_is_borrowed)]
@@ -120,7 +118,9 @@
 #![feature(raw_ref_op)]
 #![feature(rustc_attrs)]
 #![feature(receiver_trait)]
+#![cfg_attr(bootstrap, feature(min_const_generics))]
 #![feature(min_specialization)]
+#![feature(set_ptr_value)]
 #![feature(slice_ptr_get)]
 #![feature(slice_ptr_len)]
 #![feature(staged_api)]
@@ -139,6 +139,8 @@
 #![feature(try_trait)]
 #![feature(type_alias_impl_trait)]
 #![feature(associated_type_bounds)]
+#![feature(slice_group_by)]
+#![feature(decl_macro)]
 // Allow testing this library
 
 #[cfg(test)]
@@ -192,4 +194,11 @@
 #[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
 pub mod __export {
     pub use core::format_args;
+
+    /// Force AST node to an expression to improve diagnostics in pattern position.
+    #[rustc_macro_transparency = "semitransparent"]
+    #[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
+    pub macro force_expr($e:expr) {
+        $e
+    }
 }
diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs
index 7d4eff6..3a46763 100644
--- a/library/alloc/src/macros.rs
+++ b/library/alloc/src/macros.rs
@@ -37,16 +37,16 @@
 #[cfg(not(test))]
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow_internal_unstable(box_syntax)]
+#[allow_internal_unstable(box_syntax, liballoc_internals)]
 macro_rules! vec {
     () => (
-        $crate::vec::Vec::new()
+        $crate::__export::force_expr!($crate::vec::Vec::new())
     );
     ($elem:expr; $n:expr) => (
-        $crate::vec::from_elem($elem, $n)
+        $crate::__export::force_expr!($crate::vec::from_elem($elem, $n))
     );
     ($($x:expr),+ $(,)?) => (
-        <[_]>::into_vec(box [$($x),+])
+        $crate::__export::force_expr!(<[_]>::into_vec(box [$($x),+]))
     );
 }
 
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 57df28a..ee03f15 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -238,6 +238,7 @@
 //! [downgrade]: Rc::downgrade
 //! [upgrade]: Weak::upgrade
 //! [mutability]: core::cell#introducing-mutability-inside-of-something-immutable
+//! [fully qualified syntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -262,7 +263,9 @@
 use core::ptr::{self, NonNull};
 use core::slice::from_raw_parts_mut;
 
-use crate::alloc::{box_free, handle_alloc_error, AllocError, Allocator, Global, Layout};
+use crate::alloc::{
+    box_free, handle_alloc_error, AllocError, Allocator, Global, Layout, WriteCloneIntoRaw,
+};
 use crate::borrow::{Cow, ToOwned};
 use crate::string::String;
 use crate::vec::Vec;
@@ -350,6 +353,26 @@
     /// to upgrade the weak reference before this function returns will result
     /// in a `None` value. However, the weak reference may be cloned freely and
     /// stored for use at a later time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(arc_new_cyclic)]
+    /// #![allow(dead_code)]
+    /// use std::rc::{Rc, Weak};
+    ///
+    /// struct Gadget {
+    ///     self_weak: Weak<Self>,
+    ///     // ... more fields
+    /// }
+    /// impl Gadget {
+    ///     pub fn new() -> Rc<Self> {
+    ///         Rc::new_cyclic(|self_weak| {
+    ///             Gadget { self_weak: self_weak.clone(), /* ... */ }
+    ///         })
+    ///     }
+    /// }
+    /// ```
     #[unstable(feature = "arc_new_cyclic", issue = "75861")]
     pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Rc<T> {
         // Construct the inner in the "uninitialized" state with a single
@@ -453,6 +476,95 @@
         }
     }
 
+    /// Constructs a new `Rc<T>`, returning an error if the allocation fails
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api)]
+    /// use std::rc::Rc;
+    ///
+    /// let five = Rc::try_new(5);
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    pub fn try_new(value: T) -> Result<Rc<T>, AllocError> {
+        // There is an implicit weak pointer owned by all the strong
+        // pointers, which ensures that the weak destructor never frees
+        // the allocation while the strong destructor is running, even
+        // if the weak pointer is stored inside the strong one.
+        Ok(Self::from_inner(
+            Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?)
+                .into(),
+        ))
+    }
+
+    /// Constructs a new `Rc` with uninitialized contents, returning an error if the allocation fails
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api, new_uninit)]
+    /// #![feature(get_mut_unchecked)]
+    ///
+    /// use std::rc::Rc;
+    ///
+    /// let mut five = Rc::<u32>::try_new_uninit()?;
+    ///
+    /// let five = unsafe {
+    ///     // Deferred initialization:
+    ///     Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
+    ///
+    ///     five.assume_init()
+    /// };
+    ///
+    /// assert_eq!(*five, 5);
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    // #[unstable(feature = "new_uninit", issue = "63291")]
+    pub fn try_new_uninit() -> Result<Rc<mem::MaybeUninit<T>>, AllocError> {
+        unsafe {
+            Ok(Rc::from_ptr(Rc::try_allocate_for_layout(
+                Layout::new::<T>(),
+                |layout| Global.allocate(layout),
+                |mem| mem as *mut RcBox<mem::MaybeUninit<T>>,
+            )?))
+        }
+    }
+
+    /// Constructs a new `Rc` with uninitialized contents, with the memory
+    /// being filled with `0` bytes, returning an error if the allocation fails
+    ///
+    /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and
+    /// incorrect usage of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api, new_uninit)]
+    ///
+    /// use std::rc::Rc;
+    ///
+    /// let zero = Rc::<u32>::try_new_zeroed()?;
+    /// let zero = unsafe { zero.assume_init() };
+    ///
+    /// assert_eq!(*zero, 0);
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    ///
+    /// [zeroed]: mem::MaybeUninit::zeroed
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    //#[unstable(feature = "new_uninit", issue = "63291")]
+    pub fn try_new_zeroed() -> Result<Rc<mem::MaybeUninit<T>>, AllocError> {
+        unsafe {
+            Ok(Rc::from_ptr(Rc::try_allocate_for_layout(
+                Layout::new::<T>(),
+                |layout| Global.allocate_zeroed(layout),
+                |mem| mem as *mut RcBox<mem::MaybeUninit<T>>,
+            )?))
+        }
+    }
     /// Constructs a new `Pin<Rc<T>>`. If `T` does not implement `Unpin`, then
     /// `value` will be pinned in memory and unable to be moved.
     #[stable(feature = "pin", since = "1.33.0")]
@@ -737,8 +849,8 @@
         let offset = unsafe { data_offset(ptr) };
 
         // Reverse the offset to find the original RcBox.
-        let fake_ptr = ptr as *mut RcBox<T>;
-        let rc_ptr = unsafe { set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)) };
+        let rc_ptr =
+            unsafe { (ptr as *mut RcBox<T>).set_ptr_value((ptr as *mut u8).offset(-offset)) };
 
         unsafe { Self::from_ptr(rc_ptr) }
     }
@@ -758,7 +870,7 @@
     pub fn downgrade(this: &Self) -> Weak<T> {
         this.inner().inc_weak();
         // Make sure we do not create a dangling Weak
-        debug_assert!(!is_dangling(this.ptr));
+        debug_assert!(!is_dangling(this.ptr.as_ptr()));
         Weak { ptr: this.ptr }
     }
 
@@ -947,18 +1059,26 @@
     #[stable(feature = "rc_unique", since = "1.4.0")]
     pub fn make_mut(this: &mut Self) -> &mut T {
         if Rc::strong_count(this) != 1 {
-            // Gotta clone the data, there are other Rcs
-            *this = Rc::new((**this).clone())
+            // Gotta clone the data, there are other Rcs.
+            // Pre-allocate memory to allow writing the cloned value directly.
+            let mut rc = Self::new_uninit();
+            unsafe {
+                let data = Rc::get_mut_unchecked(&mut rc);
+                (**this).write_clone_into_raw(data.as_mut_ptr());
+                *this = rc.assume_init();
+            }
         } else if Rc::weak_count(this) != 0 {
             // Can just steal the data, all that's left is Weaks
+            let mut rc = Self::new_uninit();
             unsafe {
-                let mut swap = Rc::new(ptr::read(&this.ptr.as_ref().value));
-                mem::swap(this, &mut swap);
-                swap.inner().dec_strong();
+                let data = Rc::get_mut_unchecked(&mut rc);
+                data.as_mut_ptr().copy_from_nonoverlapping(&**this, 1);
+
+                this.inner().dec_strong();
                 // Remove implicit strong-weak ref (no need to craft a fake
                 // Weak here -- we know other Weaks can clean up for us)
-                swap.inner().dec_weak();
-                forget(swap);
+                this.inner().dec_weak();
+                ptr::write(this, rc.assume_init());
             }
         }
         // This unsafety is ok because we're guaranteed that the pointer
@@ -1018,9 +1138,32 @@
         // `&*(ptr as *const RcBox<T>)`, but this created a misaligned
         // reference (see #54908).
         let layout = Layout::new::<RcBox<()>>().extend(value_layout).unwrap().0.pad_to_align();
+        unsafe {
+            Rc::try_allocate_for_layout(value_layout, allocate, mem_to_rcbox)
+                .unwrap_or_else(|_| handle_alloc_error(layout))
+        }
+    }
+
+    /// Allocates an `RcBox<T>` with sufficient space for
+    /// a possibly-unsized inner value where the value has the layout provided,
+    /// returning an error if allocation fails.
+    ///
+    /// The function `mem_to_rcbox` is called with the data pointer
+    /// and must return back a (potentially fat)-pointer for the `RcBox<T>`.
+    #[inline]
+    unsafe fn try_allocate_for_layout(
+        value_layout: Layout,
+        allocate: impl FnOnce(Layout) -> Result<NonNull<[u8]>, AllocError>,
+        mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox<T>,
+    ) -> Result<*mut RcBox<T>, AllocError> {
+        // Calculate layout using the given value layout.
+        // Previously, layout was calculated on the expression
+        // `&*(ptr as *const RcBox<T>)`, but this created a misaligned
+        // reference (see #54908).
+        let layout = Layout::new::<RcBox<()>>().extend(value_layout).unwrap().0.pad_to_align();
 
         // Allocate for the layout.
-        let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout));
+        let ptr = allocate(layout)?;
 
         // Initialize the RcBox
         let inner = mem_to_rcbox(ptr.as_non_null_ptr().as_ptr());
@@ -1031,7 +1174,7 @@
             ptr::write(&mut (*inner).weak, Cell::new(1));
         }
 
-        inner
+        Ok(inner)
     }
 
     /// Allocates an `RcBox<T>` with sufficient space for an unsized inner value
@@ -1041,7 +1184,7 @@
             Self::allocate_for_layout(
                 Layout::for_value(&*ptr),
                 |layout| Global.allocate(layout),
-                |mem| set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>,
+                |mem| (ptr as *mut RcBox<T>).set_ptr_value(mem),
             )
         }
     }
@@ -1080,20 +1223,7 @@
             )
         }
     }
-}
 
-/// Sets the data pointer of a `?Sized` raw pointer.
-///
-/// For a slice/trait object, this sets the `data` field and leaves the rest
-/// unchanged. For a sized raw pointer, this simply sets the pointer.
-unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T {
-    unsafe {
-        ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8);
-    }
-    ptr
-}
-
-impl<T> Rc<[T]> {
     /// Copy elements from slice into newly allocated Rc<\[T\]>
     ///
     /// Unsafe because the caller must either take ownership or bind `T: Copy`
@@ -1737,8 +1867,8 @@
     }
 }
 
-pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool {
-    let address = ptr.as_ptr() as *mut () as usize;
+pub(crate) fn is_dangling<T: ?Sized>(ptr: *mut T) -> bool {
+    let address = ptr as *mut () as usize;
     address == usize::MAX
 }
 
@@ -1749,7 +1879,7 @@
     strong: &'a Cell<usize>,
 }
 
-impl<T> Weak<T> {
+impl<T: ?Sized> Weak<T> {
     /// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
     ///
     /// The pointer is valid only if there are some strong references. The pointer may be dangling,
@@ -1779,15 +1909,15 @@
     pub fn as_ptr(&self) -> *const T {
         let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr);
 
-        // SAFETY: we must offset the pointer manually, and said pointer may be
-        // a dangling weak (usize::MAX) if T is sized. data_offset is safe to call,
-        // because we know that a pointer to unsized T was derived from a real
-        // unsized T, as dangling weaks are only created for sized T. wrapping_offset
-        // is used so that we can use the same code path for the non-dangling
-        // unsized case and the potentially dangling sized case.
-        unsafe {
-            let offset = data_offset(ptr as *mut T);
-            set_data_ptr(ptr as *mut T, (ptr as *mut u8).wrapping_offset(offset))
+        if is_dangling(ptr) {
+            // If the pointer is dangling, we return the sentinel directly. This cannot be
+            // a valid payload address, as the payload is at least as aligned as RcBox (usize).
+            ptr as *const T
+        } else {
+            // SAFETY: if is_dangling returns false, then the pointer is dereferencable.
+            // The payload may be dropped at this point, and we have to maintain provenance,
+            // so use raw pointer manipulation.
+            unsafe { &raw const (*ptr).value }
         }
     }
 
@@ -1869,22 +1999,24 @@
     /// [`new`]: Weak::new
     #[stable(feature = "weak_into_raw", since = "1.45.0")]
     pub unsafe fn from_raw(ptr: *const T) -> Self {
-        // SAFETY: data_offset is safe to call, because this pointer originates from a Weak.
         // See Weak::as_ptr for context on how the input pointer is derived.
-        let offset = unsafe { data_offset(ptr) };
 
-        // Reverse the offset to find the original RcBox.
-        // SAFETY: we use wrapping_offset here because the pointer may be dangling (but only if T: Sized).
-        let ptr = unsafe {
-            set_data_ptr(ptr as *mut RcBox<T>, (ptr as *mut u8).wrapping_offset(-offset))
+        let ptr = if is_dangling(ptr as *mut T) {
+            // This is a dangling Weak.
+            ptr as *mut RcBox<T>
+        } else {
+            // Otherwise, we're guaranteed the pointer came from a nondangling Weak.
+            // SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T.
+            let offset = unsafe { data_offset(ptr) };
+            // Thus, we reverse the offset to get the whole RcBox.
+            // SAFETY: the pointer originated from a Weak, so this offset is safe.
+            unsafe { (ptr as *mut RcBox<T>).set_ptr_value((ptr as *mut u8).offset(-offset)) }
         };
 
         // SAFETY: we now have recovered the original Weak pointer, so can create the Weak.
         Weak { ptr: unsafe { NonNull::new_unchecked(ptr) } }
     }
-}
 
-impl<T: ?Sized> Weak<T> {
     /// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying
     /// dropping of the inner value if successful.
     ///
@@ -1947,7 +2079,7 @@
     /// (i.e., when this `Weak` was created by `Weak::new`).
     #[inline]
     fn inner(&self) -> Option<WeakInner<'_>> {
-        if is_dangling(self.ptr) {
+        if is_dangling(self.ptr.as_ptr()) {
             None
         } else {
             // We are careful to *not* create a reference covering the "data" field, as
@@ -2202,21 +2334,19 @@
 #[stable(feature = "pin", since = "1.33.0")]
 impl<T: ?Sized> Unpin for Rc<T> {}
 
-/// Get the offset within an `RcBox` for
-/// a payload of type described by a pointer.
+/// Get the offset within an `RcBox` for the payload behind a pointer.
 ///
 /// # Safety
 ///
-/// This has the same safety requirements as `align_of_val_raw`. In effect:
-///
-/// - This function is safe for any argument if `T` is sized, and
-/// - if `T` is unsized, the pointer must have appropriate pointer metadata
-///   acquired from the real instance that you are getting this offset for.
+/// The pointer must point to (and have valid metadata for) a previously
+/// valid instance of T, but the T is allowed to be dropped.
 unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
-    // Align the unsized value to the end of the `RcBox`.
-    // Because it is ?Sized, it will always be the last field in memory.
-    // Note: This is a detail of the current implementation of the compiler,
-    // and is not a guaranteed language detail. Do not rely on it outside of std.
+    // Align the unsized value to the end of the RcBox.
+    // Because RcBox is repr(C), it will always be the last field in memory.
+    // SAFETY: since the only unsized types possible are slices, trait objects,
+    // and extern types, the input safety requirement is currently enough to
+    // satisfy the requirements of align_of_val_raw; this is an implementation
+    // detail of the language that may not be relied upon outside of std.
     unsafe { data_offset_align(align_of_val_raw(ptr)) }
 }
 
diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs
index 2d183a8..843a9b0 100644
--- a/library/alloc/src/rc/tests.rs
+++ b/library/alloc/src/rc/tests.rs
@@ -209,6 +209,30 @@
 }
 
 #[test]
+fn test_into_from_weak_raw_unsized() {
+    use std::fmt::Display;
+    use std::string::ToString;
+
+    let arc: Rc<str> = Rc::from("foo");
+    let weak: Weak<str> = Rc::downgrade(&arc);
+
+    let ptr = Weak::into_raw(weak.clone());
+    let weak2 = unsafe { Weak::from_raw(ptr) };
+
+    assert_eq!(unsafe { &*ptr }, "foo");
+    assert!(weak.ptr_eq(&weak2));
+
+    let arc: Rc<dyn Display> = Rc::new(123);
+    let weak: Weak<dyn Display> = Rc::downgrade(&arc);
+
+    let ptr = Weak::into_raw(weak.clone());
+    let weak2 = unsafe { Weak::from_raw(ptr) };
+
+    assert_eq!(unsafe { &*ptr }.to_string(), "123");
+    assert!(weak.ptr_eq(&weak2));
+}
+
+#[test]
 fn get_mut() {
     let mut x = Rc::new(3);
     *Rc::get_mut(&mut x).unwrap() = 4;
@@ -295,6 +319,23 @@
 }
 
 #[test]
+fn test_maybe_thin_unsized() {
+    // If/when custom thin DSTs exist, this test should be updated to use one
+    use std::ffi::{CStr, CString};
+
+    let x: Rc<CStr> = Rc::from(CString::new("swordfish").unwrap().into_boxed_c_str());
+    assert_eq!(format!("{:?}", x), "\"swordfish\"");
+    let y: Weak<CStr> = Rc::downgrade(&x);
+    drop(x);
+
+    // At this point, the weak points to a dropped DST
+    assert!(y.upgrade().is_none());
+    // But we still need to be able to get the alloc layout to drop.
+    // CStr has no drop glue, but custom DSTs might, and need to work.
+    drop(y);
+}
+
+#[test]
 fn test_from_owned() {
     let foo = 123;
     let foo_rc = Rc::from(foo);
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index 064700f..cb015b9 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -110,6 +110,8 @@
 pub use core::slice::{ChunksExact, ChunksExactMut};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::slice::{ChunksMut, Split, SplitMut};
+#[unstable(feature = "slice_group_by", issue = "80552")]
+pub use core::slice::{GroupBy, GroupByMut};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::slice::{Iter, IterMut};
 #[stable(feature = "rchunks", since = "1.31.0")]
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 578eca7..70e0c7d 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -451,8 +451,6 @@
 
     /// Converts a [`Box<str>`] into a [`String`] without copying or allocating.
     ///
-    /// [`Box<str>`]: Box
-    ///
     /// # Examples
     ///
     /// Basic usage:
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 85c0a9f..c0d684f 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -22,7 +22,9 @@
 use core::sync::atomic;
 use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};
 
-use crate::alloc::{box_free, handle_alloc_error, AllocError, Allocator, Global, Layout};
+use crate::alloc::{
+    box_free, handle_alloc_error, AllocError, Allocator, Global, Layout, WriteCloneIntoRaw,
+};
 use crate::borrow::{Cow, ToOwned};
 use crate::boxed::Box;
 use crate::rc::is_dangling;
@@ -478,6 +480,97 @@
         unsafe { Pin::new_unchecked(Arc::new(data)) }
     }
 
+    /// Constructs a new `Arc<T>`, returning an error if allocation fails.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api)]
+    /// use std::sync::Arc;
+    ///
+    /// let five = Arc::try_new(5)?;
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    #[inline]
+    pub fn try_new(data: T) -> Result<Arc<T>, AllocError> {
+        // Start the weak pointer count as 1 which is the weak pointer that's
+        // held by all the strong pointers (kinda), see std/rc.rs for more info
+        let x: Box<_> = Box::try_new(ArcInner {
+            strong: atomic::AtomicUsize::new(1),
+            weak: atomic::AtomicUsize::new(1),
+            data,
+        })?;
+        Ok(Self::from_inner(Box::leak(x).into()))
+    }
+
+    /// Constructs a new `Arc` with uninitialized contents, returning an error
+    /// if allocation fails.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(new_uninit, allocator_api)]
+    /// #![feature(get_mut_unchecked)]
+    ///
+    /// use std::sync::Arc;
+    ///
+    /// let mut five = Arc::<u32>::try_new_uninit()?;
+    ///
+    /// let five = unsafe {
+    ///     // Deferred initialization:
+    ///     Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
+    ///
+    ///     five.assume_init()
+    /// };
+    ///
+    /// assert_eq!(*five, 5);
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    // #[unstable(feature = "new_uninit", issue = "63291")]
+    pub fn try_new_uninit() -> Result<Arc<mem::MaybeUninit<T>>, AllocError> {
+        unsafe {
+            Ok(Arc::from_ptr(Arc::try_allocate_for_layout(
+                Layout::new::<T>(),
+                |layout| Global.allocate(layout),
+                |mem| mem as *mut ArcInner<mem::MaybeUninit<T>>,
+            )?))
+        }
+    }
+
+    /// Constructs a new `Arc` with uninitialized contents, with the memory
+    /// being filled with `0` bytes, returning an error if allocation fails.
+    ///
+    /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
+    /// of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(new_uninit, allocator_api)]
+    ///
+    /// use std::sync::Arc;
+    ///
+    /// let zero = Arc::<u32>::try_new_zeroed()?;
+    /// let zero = unsafe { zero.assume_init() };
+    ///
+    /// assert_eq!(*zero, 0);
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    ///
+    /// [zeroed]: mem::MaybeUninit::zeroed
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    // #[unstable(feature = "new_uninit", issue = "63291")]
+    pub fn try_new_zeroed() -> Result<Arc<mem::MaybeUninit<T>>, AllocError> {
+        unsafe {
+            Ok(Arc::from_ptr(Arc::try_allocate_for_layout(
+                Layout::new::<T>(),
+                |layout| Global.allocate_zeroed(layout),
+                |mem| mem as *mut ArcInner<mem::MaybeUninit<T>>,
+            )?))
+        }
+    }
     /// Returns the inner value, if the `Arc` has exactly one strong reference.
     ///
     /// Otherwise, an [`Err`] is returned with the same `Arc` that was
@@ -753,8 +846,7 @@
             let offset = data_offset(ptr);
 
             // Reverse the offset to find the original ArcInner.
-            let fake_ptr = ptr as *mut ArcInner<T>;
-            let arc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
+            let arc_ptr = (ptr as *mut ArcInner<T>).set_ptr_value((ptr as *mut u8).offset(-offset));
 
             Self::from_ptr(arc_ptr)
         }
@@ -795,7 +887,7 @@
             match this.inner().weak.compare_exchange_weak(cur, cur + 1, Acquire, Relaxed) {
                 Ok(_) => {
                     // Make sure we do not create a dangling Weak
-                    debug_assert!(!is_dangling(this.ptr));
+                    debug_assert!(!is_dangling(this.ptr.as_ptr()));
                     return Weak { ptr: this.ptr };
                 }
                 Err(old) => cur = old,
@@ -994,8 +1086,30 @@
         // `&*(ptr as *const ArcInner<T>)`, but this created a misaligned
         // reference (see #54908).
         let layout = Layout::new::<ArcInner<()>>().extend(value_layout).unwrap().0.pad_to_align();
+        unsafe {
+            Arc::try_allocate_for_layout(value_layout, allocate, mem_to_arcinner)
+                .unwrap_or_else(|_| handle_alloc_error(layout))
+        }
+    }
 
-        let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout));
+    /// Allocates an `ArcInner<T>` with sufficient space for
+    /// a possibly-unsized inner value where the value has the layout provided,
+    /// returning an error if allocation fails.
+    ///
+    /// The function `mem_to_arcinner` is called with the data pointer
+    /// and must return back a (potentially fat)-pointer for the `ArcInner<T>`.
+    unsafe fn try_allocate_for_layout(
+        value_layout: Layout,
+        allocate: impl FnOnce(Layout) -> Result<NonNull<[u8]>, AllocError>,
+        mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>,
+    ) -> Result<*mut ArcInner<T>, AllocError> {
+        // Calculate layout using the given value layout.
+        // Previously, layout was calculated on the expression
+        // `&*(ptr as *const ArcInner<T>)`, but this created a misaligned
+        // reference (see #54908).
+        let layout = Layout::new::<ArcInner<()>>().extend(value_layout).unwrap().0.pad_to_align();
+
+        let ptr = allocate(layout)?;
 
         // Initialize the ArcInner
         let inner = mem_to_arcinner(ptr.as_non_null_ptr().as_ptr());
@@ -1006,7 +1120,7 @@
             ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1));
         }
 
-        inner
+        Ok(inner)
     }
 
     /// Allocates an `ArcInner<T>` with sufficient space for an unsized inner value.
@@ -1016,7 +1130,7 @@
             Self::allocate_for_layout(
                 Layout::for_value(&*ptr),
                 |layout| Global.allocate(layout),
-                |mem| set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>,
+                |mem| (ptr as *mut ArcInner<T>).set_ptr_value(mem) as *mut ArcInner<T>,
             )
         }
     }
@@ -1055,20 +1169,7 @@
             )
         }
     }
-}
 
-/// Sets the data pointer of a `?Sized` raw pointer.
-///
-/// For a slice/trait object, this sets the `data` field and leaves the rest
-/// unchanged. For a sized raw pointer, this simply sets the pointer.
-unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T {
-    unsafe {
-        ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8);
-    }
-    ptr
-}
-
-impl<T> Arc<[T]> {
     /// Copy elements from slice into newly allocated Arc<\[T\]>
     ///
     /// Unsafe because the caller must either take ownership or bind `T: Copy`.
@@ -1256,8 +1357,14 @@
         // weak count, there's no chance the ArcInner itself could be
         // deallocated.
         if this.inner().strong.compare_exchange(1, 0, Acquire, Relaxed).is_err() {
-            // Another strong pointer exists; clone
-            *this = Arc::new((**this).clone());
+            // Another strong pointer exists, so we must clone.
+            // Pre-allocate memory to allow writing the cloned value directly.
+            let mut arc = Self::new_uninit();
+            unsafe {
+                let data = Arc::get_mut_unchecked(&mut arc);
+                (**this).write_clone_into_raw(data.as_mut_ptr());
+                *this = arc.assume_init();
+            }
         } else if this.inner().weak.load(Relaxed) != 1 {
             // Relaxed suffices in the above because this is fundamentally an
             // optimization: we are always racing with weak pointers being
@@ -1273,17 +1380,14 @@
 
             // Materialize our own implicit weak pointer, so that it can clean
             // up the ArcInner as needed.
-            let weak = Weak { ptr: this.ptr };
+            let _weak = Weak { ptr: this.ptr };
 
-            // mark the data itself as already deallocated
+            // Can just steal the data, all that's left is Weaks
+            let mut arc = Self::new_uninit();
             unsafe {
-                // there is no data race in the implicit write caused by `read`
-                // here (due to zeroing) because data is no longer accessed by
-                // other threads (due to there being no more strong refs at this
-                // point).
-                let mut swap = Arc::new(ptr::read(&weak.ptr.as_ref().data));
-                mem::swap(this, &mut swap);
-                mem::forget(swap);
+                let data = Arc::get_mut_unchecked(&mut arc);
+                data.as_mut_ptr().copy_from_nonoverlapping(&**this, 1);
+                ptr::write(this, arc.assume_init());
             }
         } else {
             // We were the sole reference of either kind; bump back up the
@@ -1535,7 +1639,7 @@
     strong: &'a atomic::AtomicUsize,
 }
 
-impl<T> Weak<T> {
+impl<T: ?Sized> Weak<T> {
     /// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
     ///
     /// The pointer is valid only if there are some strong references. The pointer may be dangling,
@@ -1565,15 +1669,15 @@
     pub fn as_ptr(&self) -> *const T {
         let ptr: *mut ArcInner<T> = NonNull::as_ptr(self.ptr);
 
-        // SAFETY: we must offset the pointer manually, and said pointer may be
-        // a dangling weak (usize::MAX) if T is sized. data_offset is safe to call,
-        // because we know that a pointer to unsized T was derived from a real
-        // unsized T, as dangling weaks are only created for sized T. wrapping_offset
-        // is used so that we can use the same code path for the non-dangling
-        // unsized case and the potentially dangling sized case.
-        unsafe {
-            let offset = data_offset(ptr as *mut T);
-            set_data_ptr(ptr as *mut T, (ptr as *mut u8).wrapping_offset(offset))
+        if is_dangling(ptr) {
+            // If the pointer is dangling, we return the sentinel directly. This cannot be
+            // a valid payload address, as the payload is at least as aligned as ArcInner (usize).
+            ptr as *const T
+        } else {
+            // SAFETY: if is_dangling returns false, then the pointer is dereferencable.
+            // The payload may be dropped at this point, and we have to maintain provenance,
+            // so use raw pointer manipulation.
+            unsafe { &raw mut (*ptr).data }
         }
     }
 
@@ -1655,18 +1759,22 @@
     /// [`forget`]: std::mem::forget
     #[stable(feature = "weak_into_raw", since = "1.45.0")]
     pub unsafe fn from_raw(ptr: *const T) -> Self {
-        // SAFETY: data_offset is safe to call, because this pointer originates from a Weak.
         // See Weak::as_ptr for context on how the input pointer is derived.
-        let offset = unsafe { data_offset(ptr) };
 
-        // Reverse the offset to find the original ArcInner.
-        // SAFETY: we use wrapping_offset here because the pointer may be dangling (but only if T: Sized)
-        let ptr = unsafe {
-            set_data_ptr(ptr as *mut ArcInner<T>, (ptr as *mut u8).wrapping_offset(-offset))
+        let ptr = if is_dangling(ptr as *mut T) {
+            // This is a dangling Weak.
+            ptr as *mut ArcInner<T>
+        } else {
+            // Otherwise, we're guaranteed the pointer came from a nondangling Weak.
+            // SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T.
+            let offset = unsafe { data_offset(ptr) };
+            // Thus, we reverse the offset to get the whole RcBox.
+            // SAFETY: the pointer originated from a Weak, so this offset is safe.
+            unsafe { (ptr as *mut ArcInner<T>).set_ptr_value((ptr as *mut u8).offset(-offset)) }
         };
 
         // SAFETY: we now have recovered the original Weak pointer, so can create the Weak.
-        unsafe { Weak { ptr: NonNull::new_unchecked(ptr) } }
+        Weak { ptr: unsafe { NonNull::new_unchecked(ptr) } }
     }
 }
 
@@ -1771,7 +1879,7 @@
     /// (i.e., when this `Weak` was created by `Weak::new`).
     #[inline]
     fn inner(&self) -> Option<WeakInner<'_>> {
-        if is_dangling(self.ptr) {
+        if is_dangling(self.ptr.as_ptr()) {
             None
         } else {
             // We are careful to *not* create a reference covering the "data" field, as
@@ -2351,21 +2459,19 @@
 #[stable(feature = "pin", since = "1.33.0")]
 impl<T: ?Sized> Unpin for Arc<T> {}
 
-/// Get the offset within an `ArcInner` for
-/// a payload of type described by a pointer.
+/// Get the offset within an `ArcInner` for the payload behind a pointer.
 ///
 /// # Safety
 ///
-/// This has the same safety requirements as `align_of_val_raw`. In effect:
-///
-/// - This function is safe for any argument if `T` is sized, and
-/// - if `T` is unsized, the pointer must have appropriate pointer metadata
-///   acquired from the real instance that you are getting this offset for.
+/// The pointer must point to (and have valid metadata for) a previously
+/// valid instance of T, but the T is allowed to be dropped.
 unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
-    // Align the unsized value to the end of the `ArcInner`.
-    // Because it is `?Sized`, it will always be the last field in memory.
-    // Note: This is a detail of the current implementation of the compiler,
-    // and is not a guaranteed language detail. Do not rely on it outside of std.
+    // Align the unsized value to the end of the ArcInner.
+    // Because RcBox is repr(C), it will always be the last field in memory.
+    // SAFETY: since the only unsized types possible are slices, trait objects,
+    // and extern types, the input safety requirement is currently enough to
+    // satisfy the requirements of align_of_val_raw; this is an implementation
+    // detail of the language that may not be relied upon outside of std.
     unsafe { data_offset_align(align_of_val_raw(ptr)) }
 }
 
diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs
index e8e1e66..4ccb32f 100644
--- a/library/alloc/src/sync/tests.rs
+++ b/library/alloc/src/sync/tests.rs
@@ -159,6 +159,30 @@
 }
 
 #[test]
+fn test_into_from_weak_raw_unsized() {
+    use std::fmt::Display;
+    use std::string::ToString;
+
+    let arc: Arc<str> = Arc::from("foo");
+    let weak: Weak<str> = Arc::downgrade(&arc);
+
+    let ptr = Weak::into_raw(weak.clone());
+    let weak2 = unsafe { Weak::from_raw(ptr) };
+
+    assert_eq!(unsafe { &*ptr }, "foo");
+    assert!(weak.ptr_eq(&weak2));
+
+    let arc: Arc<dyn Display> = Arc::new(123);
+    let weak: Weak<dyn Display> = Arc::downgrade(&arc);
+
+    let ptr = Weak::into_raw(weak.clone());
+    let weak2 = unsafe { Weak::from_raw(ptr) };
+
+    assert_eq!(unsafe { &*ptr }.to_string(), "123");
+    assert!(weak.ptr_eq(&weak2));
+}
+
+#[test]
 fn test_cowarc_clone_make_mut() {
     let mut cow0 = Arc::new(75);
     let mut cow1 = cow0.clone();
@@ -330,6 +354,23 @@
 }
 
 #[test]
+fn test_maybe_thin_unsized() {
+    // If/when custom thin DSTs exist, this test should be updated to use one
+    use std::ffi::{CStr, CString};
+
+    let x: Arc<CStr> = Arc::from(CString::new("swordfish").unwrap().into_boxed_c_str());
+    assert_eq!(format!("{:?}", x), "\"swordfish\"");
+    let y: Weak<CStr> = Arc::downgrade(&x);
+    drop(x);
+
+    // At this point, the weak points to a dropped DST
+    assert!(y.upgrade().is_none());
+    // But we still need to be able to get the alloc layout to drop.
+    // CStr has no drop glue, but custom DSTs might, and need to work.
+    drop(y);
+}
+
+#[test]
 fn test_from_owned() {
     let foo = 123;
     let foo_arc = Arc::from(foo);
@@ -370,7 +411,7 @@
         let n = Arc::weak_count(&a2);
         assert!(n < 2, "bad weak count: {}", n);
         #[cfg(miri)] // Miri's scheduler does not guarantee liveness, and thus needs this hint.
-        atomic::spin_loop_hint();
+        std::hint::spin_loop();
     }
     t.join().unwrap();
 }
diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs
index fcab3fd..6969049 100644
--- a/library/alloc/src/task.rs
+++ b/library/alloc/src/task.rs
@@ -33,7 +33,8 @@
     }
 }
 
-#[allow(rustc::ineffective_unstable_trait_impl)]
+#[cfg_attr(bootstrap, allow(rustc::ineffective_unstable_trait_impl))]
+#[cfg_attr(not(bootstrap), allow(ineffective_unstable_trait_impl))]
 #[unstable(feature = "wake_trait", issue = "69912")]
 impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for Waker {
     fn from(waker: Arc<W>) -> Waker {
@@ -43,7 +44,8 @@
     }
 }
 
-#[allow(rustc::ineffective_unstable_trait_impl)]
+#[cfg_attr(bootstrap, allow(rustc::ineffective_unstable_trait_impl))]
+#[cfg_attr(not(bootstrap), allow(ineffective_unstable_trait_impl))]
 #[unstable(feature = "wake_trait", issue = "69912")]
 impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for RawWaker {
     fn from(waker: Arc<W>) -> RawWaker {
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 2a83eb3..ccc4f03 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -990,6 +990,9 @@
         //   such that no value will be dropped twice in case `drop_in_place`
         //   were to panic once (if it panics twice, the program aborts).
         unsafe {
+            // Note: It's intentional that this is `>` and not `>=`.
+            //       Changing it to `>=` has negative performance
+            //       implications in some cases. See #78884 for more.
             if len > self.len {
                 return;
             }
@@ -1950,27 +1953,6 @@
     }
 }
 
-impl<T, A: Allocator> Vec<T, A> {
-    /// Removes the first instance of `item` from the vector if the item exists.
-    ///
-    /// This method will be removed soon.
-    #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")]
-    #[rustc_deprecated(
-        reason = "Removing the first item equal to a needle is already easily possible \
-            with iterators and the current Vec methods. Furthermore, having a method for \
-            one particular case of removal (linear search, only the first item, no swap remove) \
-            but not for others is inconsistent. This method will be removed soon.",
-        since = "1.46.0"
-    )]
-    pub fn remove_item<V>(&mut self, item: &V) -> Option<T>
-    where
-        T: PartialEq<V>,
-    {
-        let pos = self.iter().position(|x| *x == *item)?;
-        Some(self.remove(pos))
-    }
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Internal methods and functions
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index b56437b..0b7eeab 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -14,12 +14,12 @@
 #![feature(binary_heap_into_iter_sorted)]
 #![feature(binary_heap_drain_sorted)]
 #![feature(slice_ptr_get)]
-#![feature(split_inclusive)]
 #![feature(binary_heap_retain)]
 #![feature(inplace_iteration)]
 #![feature(iter_map_while)]
 #![feature(int_bits_const)]
 #![feature(vecdeque_binary_search)]
+#![feature(slice_group_by)]
 
 use std::collections::hash_map::DefaultHasher;
 use std::hash::{Hash, Hasher};
diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs
index a4f0fb4..777c10b 100644
--- a/library/alloc/tests/slice.rs
+++ b/library/alloc/tests/slice.rs
@@ -1898,3 +1898,61 @@
     m!(&mut v, [..] => ());
     m!(&mut v, [x, .., y] => c!((x, y), (&mut N, &mut N), (&mut N(0), &mut N(4))));
 }
+
+#[test]
+fn test_group_by() {
+    let slice = &[1, 1, 1, 3, 3, 2, 2, 2, 1, 0];
+
+    let mut iter = slice.group_by(|a, b| a == b);
+    assert_eq!(iter.next(), Some(&[1, 1, 1][..]));
+    assert_eq!(iter.next(), Some(&[3, 3][..]));
+    assert_eq!(iter.next(), Some(&[2, 2, 2][..]));
+    assert_eq!(iter.next(), Some(&[1][..]));
+    assert_eq!(iter.next(), Some(&[0][..]));
+    assert_eq!(iter.next(), None);
+
+    let mut iter = slice.group_by(|a, b| a == b);
+    assert_eq!(iter.next_back(), Some(&[0][..]));
+    assert_eq!(iter.next_back(), Some(&[1][..]));
+    assert_eq!(iter.next_back(), Some(&[2, 2, 2][..]));
+    assert_eq!(iter.next_back(), Some(&[3, 3][..]));
+    assert_eq!(iter.next_back(), Some(&[1, 1, 1][..]));
+    assert_eq!(iter.next_back(), None);
+
+    let mut iter = slice.group_by(|a, b| a == b);
+    assert_eq!(iter.next(), Some(&[1, 1, 1][..]));
+    assert_eq!(iter.next_back(), Some(&[0][..]));
+    assert_eq!(iter.next(), Some(&[3, 3][..]));
+    assert_eq!(iter.next_back(), Some(&[1][..]));
+    assert_eq!(iter.next(), Some(&[2, 2, 2][..]));
+    assert_eq!(iter.next_back(), None);
+}
+
+#[test]
+fn test_group_by_mut() {
+    let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2, 1, 0];
+
+    let mut iter = slice.group_by_mut(|a, b| a == b);
+    assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
+    assert_eq!(iter.next(), Some(&mut [3, 3][..]));
+    assert_eq!(iter.next(), Some(&mut [2, 2, 2][..]));
+    assert_eq!(iter.next(), Some(&mut [1][..]));
+    assert_eq!(iter.next(), Some(&mut [0][..]));
+    assert_eq!(iter.next(), None);
+
+    let mut iter = slice.group_by_mut(|a, b| a == b);
+    assert_eq!(iter.next_back(), Some(&mut [0][..]));
+    assert_eq!(iter.next_back(), Some(&mut [1][..]));
+    assert_eq!(iter.next_back(), Some(&mut [2, 2, 2][..]));
+    assert_eq!(iter.next_back(), Some(&mut [3, 3][..]));
+    assert_eq!(iter.next_back(), Some(&mut [1, 1, 1][..]));
+    assert_eq!(iter.next_back(), None);
+
+    let mut iter = slice.group_by_mut(|a, b| a == b);
+    assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
+    assert_eq!(iter.next_back(), Some(&mut [0][..]));
+    assert_eq!(iter.next(), Some(&mut [3, 3][..]));
+    assert_eq!(iter.next_back(), Some(&mut [1][..]));
+    assert_eq!(iter.next(), Some(&mut [2, 2, 2][..]));
+    assert_eq!(iter.next_back(), None);
+}
diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs
index 57c6624..c572c66 100644
--- a/library/core/src/alloc/layout.rs
+++ b/library/core/src/alloc/layout.rs
@@ -4,6 +4,12 @@
 use crate::num::NonZeroUsize;
 use crate::ptr::NonNull;
 
+// While this function is used in one place and its implementation
+// could be inlined, the previous attempts to do so made rustc
+// slower:
+//
+// * https://github.com/rust-lang/rust/pull/72189
+// * https://github.com/rust-lang/rust/pull/79827
 const fn size_align<T>() -> (usize, usize) {
     (mem::size_of::<T>(), mem::align_of::<T>())
 }
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index d1951fb..eef8f20 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -14,6 +14,29 @@
 //!
 //! [`Box`]: ../../std/boxed/struct.Box.html
 //!
+//! # Smart pointers and `dyn Any`
+//!
+//! One piece of behavior to keep in mind when using `Any` as a trait object,
+//! especially with types like `Box<dyn Any>` or `Arc<dyn Any>`, is that simply
+//! calling `.type_id()` on the value will produce the `TypeId` of the
+//! *container*, not the underlying trait object. This can be avoided by
+//! converting the smart pointer into a `&dyn Any` instead, which will return
+//! the object's `TypeId`. For example:
+//!
+//! ```
+//! use std::any::{Any, TypeId};
+//!
+//! let boxed: Box<dyn Any> = Box::new(3_i32);
+//!
+//! // You're more likely to want this:
+//! let actual_id = (&*boxed).type_id();
+//! // ... than this:
+//! let boxed_id = boxed.type_id();
+//!
+//! assert_eq!(actual_id, TypeId::of::<i32>());
+//! assert_eq!(boxed_id, TypeId::of::<Box<dyn Any>>());
+//! ```
+//!
 //! # Examples
 //!
 //! Consider a situation where we want to log out a value passed to a function.
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 71548be..85b1a47 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -12,6 +12,7 @@
 use crate::fmt;
 use crate::hash::{self, Hash};
 use crate::marker::Unsize;
+use crate::mem::MaybeUninit;
 use crate::ops::{Index, IndexMut};
 use crate::slice::{Iter, IterMut};
 
@@ -429,7 +430,6 @@
     where
         F: FnMut(T) -> U,
     {
-        use crate::mem::MaybeUninit;
         struct Guard<T, const N: usize> {
             dst: *mut T,
             initialized: usize,
@@ -481,8 +481,6 @@
     /// ```
     #[unstable(feature = "array_zip", issue = "80094")]
     pub fn zip<U>(self, rhs: [U; N]) -> [(T, U); N] {
-        use crate::mem::MaybeUninit;
-
         let mut dst = MaybeUninit::uninit_array::<N>();
         for (i, (lhs, rhs)) in IntoIter::new(self).zip(IntoIter::new(rhs)).enumerate() {
             dst[i].write((lhs, rhs));
@@ -506,4 +504,75 @@
     pub fn as_mut_slice(&mut self) -> &mut [T] {
         self
     }
+
+    /// Borrows each element and returns an array of references with the same
+    /// size as `self`.
+    ///
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(array_methods)]
+    ///
+    /// let floats = [3.1, 2.7, -1.0];
+    /// let float_refs: [&f64; 3] = floats.each_ref();
+    /// assert_eq!(float_refs, [&3.1, &2.7, &-1.0]);
+    /// ```
+    ///
+    /// This method is particularly useful if combined with other methods, like
+    /// [`map`](#method.map). This way, you can can avoid moving the original
+    /// array if its elements are not `Copy`.
+    ///
+    /// ```
+    /// #![feature(array_methods, array_map)]
+    ///
+    /// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()];
+    /// let is_ascii = strings.each_ref().map(|s| s.is_ascii());
+    /// assert_eq!(is_ascii, [true, false, true]);
+    ///
+    /// // We can still access the original array: it has not been moved.
+    /// assert_eq!(strings.len(), 3);
+    /// ```
+    #[unstable(feature = "array_methods", issue = "76118")]
+    pub fn each_ref(&self) -> [&T; N] {
+        // Unlike in `map`, we don't need a guard here, as dropping a reference
+        // is a noop.
+        let mut out = MaybeUninit::uninit_array::<N>();
+        for (src, dst) in self.iter().zip(&mut out) {
+            dst.write(src);
+        }
+
+        // SAFETY: All elements of `dst` are properly initialized and
+        // `MaybeUninit<T>` has the same layout as `T`, so this cast is valid.
+        unsafe { (&mut out as *mut _ as *mut [&T; N]).read() }
+    }
+
+    /// Borrows each element mutably and returns an array of mutable references
+    /// with the same size as `self`.
+    ///
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(array_methods)]
+    ///
+    /// let mut floats = [3.1, 2.7, -1.0];
+    /// let float_refs: [&mut f64; 3] = floats.each_mut();
+    /// *float_refs[0] = 0.0;
+    /// assert_eq!(float_refs, [&mut 0.0, &mut 2.7, &mut -1.0]);
+    /// assert_eq!(floats, [0.0, 2.7, -1.0]);
+    /// ```
+    #[unstable(feature = "array_methods", issue = "76118")]
+    pub fn each_mut(&mut self) -> [&mut T; N] {
+        // Unlike in `map`, we don't need a guard here, as dropping a reference
+        // is a noop.
+        let mut out = MaybeUninit::uninit_array::<N>();
+        for (src, dst) in self.iter_mut().zip(&mut out) {
+            dst.write(src);
+        }
+
+        // SAFETY: All elements of `dst` are properly initialized and
+        // `MaybeUninit<T>` has the same layout as `T`, so this cast is valid.
+        unsafe { (&mut out as *mut _ as *mut [&mut T; N]).read() }
+    }
 }
diff --git a/library/core/src/borrow.rs b/library/core/src/borrow.rs
index 6f5a6aa..c9040cd 100644
--- a/library/core/src/borrow.rs
+++ b/library/core/src/borrow.rs
@@ -40,7 +40,6 @@
 /// provide a reference to related type `T`, it is often better to use
 /// [`AsRef<T>`] as more types can safely implement it.
 ///
-/// [`BorrowMut<T>`]: BorrowMut
 /// [`Box<T>`]: ../../std/boxed/struct.Box.html
 /// [`Mutex<T>`]: ../../std/sync/struct.Mutex.html
 /// [`Rc<T>`]: ../../std/rc/struct.Rc.html
@@ -183,8 +182,6 @@
 /// As a companion to [`Borrow<T>`] this trait allows a type to borrow as
 /// an underlying type by providing a mutable reference. See [`Borrow<T>`]
 /// for more information on borrowing as another type.
-///
-/// [`Borrow<T>`]: Borrow
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
     /// Mutably borrows from an owned value.
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index c5ab7a3..fa0fbaa 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1261,6 +1261,40 @@
         Ref { value: f(orig.value), borrow: orig.borrow }
     }
 
+    /// Makes a new `Ref` for an optional component of the borrowed data. The
+    /// original guard is returned as an `Err(..)` if the closure returns
+    /// `None`.
+    ///
+    /// The `RefCell` is already immutably borrowed, so this cannot fail.
+    ///
+    /// This is an associated function that needs to be used as
+    /// `Ref::filter_map(...)`. A method would interfere with methods of the same
+    /// name on the contents of a `RefCell` used through `Deref`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cell_filter_map)]
+    ///
+    /// use std::cell::{RefCell, Ref};
+    ///
+    /// let c = RefCell::new(vec![1, 2, 3]);
+    /// let b1: Ref<Vec<u32>> = c.borrow();
+    /// let b2: Result<Ref<u32>, _> = Ref::filter_map(b1, |v| v.get(1));
+    /// assert_eq!(*b2.unwrap(), 2);
+    /// ```
+    #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "81061")]
+    #[inline]
+    pub fn filter_map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Result<Ref<'b, U>, Self>
+    where
+        F: FnOnce(&T) -> Option<&U>,
+    {
+        match f(orig.value) {
+            Some(value) => Ok(Ref { value, borrow: orig.borrow }),
+            None => Err(orig),
+        }
+    }
+
     /// Splits a `Ref` into multiple `Ref`s for different components of the
     /// borrowed data.
     ///
@@ -1372,6 +1406,58 @@
         RefMut { value: f(value), borrow }
     }
 
+    /// Makes a new `RefMut` for an optional component of the borrowed data. The
+    /// original guard is returned as an `Err(..)` if the closure returns
+    /// `None`.
+    ///
+    /// The `RefCell` is already mutably borrowed, so this cannot fail.
+    ///
+    /// This is an associated function that needs to be used as
+    /// `RefMut::filter_map(...)`. A method would interfere with methods of the
+    /// same name on the contents of a `RefCell` used through `Deref`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cell_filter_map)]
+    ///
+    /// use std::cell::{RefCell, RefMut};
+    ///
+    /// let c = RefCell::new(vec![1, 2, 3]);
+    ///
+    /// {
+    ///     let b1: RefMut<Vec<u32>> = c.borrow_mut();
+    ///     let mut b2: Result<RefMut<u32>, _> = RefMut::filter_map(b1, |v| v.get_mut(1));
+    ///
+    ///     if let Ok(mut b2) = b2 {
+    ///         *b2 += 2;
+    ///     }
+    /// }
+    ///
+    /// assert_eq!(*c.borrow(), vec![1, 4, 3]);
+    /// ```
+    #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "81061")]
+    #[inline]
+    pub fn filter_map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> Result<RefMut<'b, U>, Self>
+    where
+        F: FnOnce(&mut T) -> Option<&mut U>,
+    {
+        // FIXME(nll-rfc#40): fix borrow-check
+        let RefMut { value, borrow } = orig;
+        let value = value as *mut T;
+        // SAFETY: function holds onto an exclusive reference for the duration
+        // of its call through `orig`, and the pointer is only de-referenced
+        // inside of the function call never allowing the exclusive reference to
+        // escape.
+        match f(unsafe { &mut *value }) {
+            Some(value) => Ok(RefMut { value, borrow }),
+            None => {
+                // SAFETY: same as above.
+                Err(RefMut { value: unsafe { &mut *value }, borrow })
+            }
+        }
+    }
+
     /// Splits a `RefMut` into multiple `RefMut`s for different components of the
     /// borrowed data.
     ///
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index de05a8c..7a0ec32 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -113,6 +113,48 @@
     }
 }
 
+#[stable(feature = "more_char_conversions", since = "1.51.0")]
+impl From<char> for u64 {
+    /// Converts a [`char`] into a [`u64`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::mem;
+    ///
+    /// let c = '👤';
+    /// let u = u64::from(c);
+    /// assert!(8 == mem::size_of_val(&u))
+    /// ```
+    #[inline]
+    fn from(c: char) -> Self {
+        // The char is casted to the value of the code point, then zero-extended to 64 bit.
+        // See [https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics]
+        c as u64
+    }
+}
+
+#[stable(feature = "more_char_conversions", since = "1.51.0")]
+impl From<char> for u128 {
+    /// Converts a [`char`] into a [`u128`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::mem;
+    ///
+    /// let c = '⚙';
+    /// let u = u128::from(c);
+    /// assert!(16 == mem::size_of_val(&u))
+    /// ```
+    #[inline]
+    fn from(c: char) -> Self {
+        // The char is casted to the value of the code point, then zero-extended to 128 bit.
+        // See [https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics]
+        c as u128
+    }
+}
+
 /// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF.
 ///
 /// Unicode is designed such that this effectively decodes bytes
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 0c459a8..38c6bfb 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -29,7 +29,7 @@
 ///
 /// This trait allows for partial equality, for types that do not have a full
 /// equivalence relation. For example, in floating point numbers `NaN != NaN`,
-/// so floating point types implement `PartialEq` but not [`Eq`].
+/// so floating point types implement `PartialEq` but not [`trait@Eq`].
 ///
 /// Formally, the equality must be (for all `a`, `b` and `c`):
 ///
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 3f7110b..041f40f 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -135,8 +135,6 @@
 /// Since both [`String`] and [`&str`] implement `AsRef<str>` we can accept both as input argument.
 ///
 /// [`&str`]: primitive@str
-/// [`Option<T>`]: Option
-/// [`Result<T, E>`]: Result
 /// [`Borrow`]: crate::borrow::Borrow
 /// [`Eq`]: crate::cmp::Eq
 /// [`Ord`]: crate::cmp::Ord
@@ -169,9 +167,6 @@
 /// **Note: This trait must not fail**. If the conversion can fail, use a
 /// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
 ///
-/// [`Option<T>`]: Option
-/// [`Result<T, E>`]: Result
-///
 /// # Generic Implementations
 ///
 /// - `AsMut` auto-dereferences if the inner type is a mutable reference
@@ -270,8 +265,6 @@
 /// is_hello(s);
 /// ```
 ///
-/// [`Option<T>`]: Option
-/// [`Result<T, E>`]: Result
 /// [`String`]: ../../std/string/struct.String.html
 /// [`Vec`]: ../../std/vec/struct.Vec.html
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -359,8 +352,6 @@
 /// }
 /// ```
 ///
-/// [`Option<T>`]: Option
-/// [`Result<T, E>`]: Result
 /// [`String`]: ../../std/string/struct.String.html
 /// [`from`]: From::from
 /// [book]: ../../book/ch09-00-error-handling.html
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 0c65c1c..73cf5d1 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -456,7 +456,9 @@
 ///
 /// When used with the alternate format specifier `#?`, the output is pretty-printed.
 ///
-/// For more information on formatters, see [the module-level documentation][self].
+/// For more information on formatters, see [the module-level documentation][module].
+///
+/// [module]: ../../std/fmt/index.html
 ///
 /// This trait can be used with `#[derive]` if all fields implement `Debug`. When
 /// `derive`d for structs, it will use the name of the `struct`, then `{`, then a
@@ -602,7 +604,9 @@
 /// `Display` is similar to [`Debug`], but `Display` is for user-facing
 /// output, and so cannot be derived.
 ///
-/// For more information on formatters, see [the module-level documentation][self].
+/// For more information on formatters, see [the module-level documentation][module].
+///
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -674,7 +678,9 @@
 ///
 /// The alternate flag, `#`, adds a `0o` in front of the output.
 ///
-/// For more information on formatters, see [the module-level documentation][self].
+/// For more information on formatters, see [the module-level documentation][module].
+///
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -726,7 +732,9 @@
 ///
 /// The alternate flag, `#`, adds a `0b` in front of the output.
 ///
-/// For more information on formatters, see [the module-level documentation][self].
+/// For more information on formatters, see [the module-level documentation][module].
+///
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -782,7 +790,9 @@
 ///
 /// The alternate flag, `#`, adds a `0x` in front of the output.
 ///
-/// For more information on formatters, see [the module-level documentation][self].
+/// For more information on formatters, see [the module-level documentation][module].
+///
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -835,7 +845,9 @@
 ///
 /// The alternate flag, `#`, adds a `0x` in front of the output.
 ///
-/// For more information on formatters, see [the module-level documentation][self].
+/// For more information on formatters, see [the module-level documentation][module].
+///
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -883,7 +895,9 @@
 /// The `Pointer` trait should format its output as a memory location. This is commonly presented
 /// as hexadecimal.
 ///
-/// For more information on formatters, see [the module-level documentation][self].
+/// For more information on formatters, see [the module-level documentation][module].
+///
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -932,7 +946,9 @@
 ///
 /// The `LowerExp` trait should format its output in scientific notation with a lower-case `e`.
 ///
-/// For more information on formatters, see [the module-level documentation][self].
+/// For more information on formatters, see [the module-level documentation][module].
+///
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -981,7 +997,9 @@
 ///
 /// The `UpperExp` trait should format its output in scientific notation with an upper-case `E`.
 ///
-/// For more information on formatters, see [the module-level documentation][self].
+/// For more information on formatters, see [the module-level documentation][module].
+///
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -1555,7 +1573,7 @@
     ///     }
     /// }
     ///
-    /// // We set alignment to the left with ">".
+    /// // We set alignment to the right with ">".
     /// assert_eq!(&format!("{:G>3}", Foo), "GGG");
     /// assert_eq!(&format!("{:t>6}", Foo), "tttttt");
     /// ```
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 979a5f8..3137295 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -91,7 +91,7 @@
 /// };
 ///
 /// // Back on our current thread, we wait for the value to be set
-/// while live.load(Ordering::Acquire) {
+/// while !live.load(Ordering::Acquire) {
 ///     // The spin loop is a hint to the CPU that we're waiting, but probably
 ///     // not for very long
 ///     hint::spin_loop();
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 938dc21..fa5f0d5 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -712,8 +712,8 @@
     /// [`std::process::abort`](../../std/process/fn.abort.html).
     pub fn abort() -> !;
 
-    /// Tells LLVM that this point in the code is not reachable, enabling
-    /// further optimizations.
+    /// Informs the optimizer that this point in the code is not reachable,
+    /// enabling further optimizations.
     ///
     /// N.B., this is very different from the `unreachable!()` macro: Unlike the
     /// macro, which panics when it is executed, it is *undefined behavior* to
@@ -768,13 +768,6 @@
     #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
     pub fn size_of<T>() -> usize;
 
-    /// Moves a value to an uninitialized memory location.
-    ///
-    /// Drop glue is not run on the destination.
-    ///
-    /// The stabilized version of this intrinsic is [`core::ptr::write`](crate::ptr::write).
-    pub fn move_val_init<T>(dst: *mut T, src: T);
-
     /// The minimum alignment of a type.
     ///
     /// The stabilized version of this intrinsic is [`core::mem::align_of`](crate::mem::align_of).
@@ -1133,7 +1126,7 @@
     /// This intrinsic does not have a stable counterpart.
     pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize);
     /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with
-    /// a size of `count` * `size_of::<T>()` and an alignment of
+    /// a size of `count * size_of::<T>()` and an alignment of
     /// `min_align_of::<T>()`
     ///
     /// The volatile parameter is set to `true`, so it will not be optimized out
@@ -1142,7 +1135,7 @@
     /// This intrinsic does not have a stable counterpart.
     pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize);
     /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a
-    /// size of `count` * `size_of::<T>()` and an alignment of
+    /// size of `count * size_of::<T>()` and an alignment of
     /// `min_align_of::<T>()`.
     ///
     /// The volatile parameter is set to `true`, so it will not be optimized out
@@ -1588,7 +1581,7 @@
     pub fn exact_div<T: Copy>(x: T, y: T) -> T;
 
     /// Performs an unchecked division, resulting in undefined behavior
-    /// where y = 0 or x = `T::MIN` and y = -1
+    /// where `y == 0` or `x == T::MIN && y == -1`
     ///
     /// Safe wrappers for this intrinsic are available on the integer
     /// primitives via the `checked_div` method. For example,
@@ -1596,7 +1589,7 @@
     #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_div<T: Copy>(x: T, y: T) -> T;
     /// Returns the remainder of an unchecked division, resulting in
-    /// undefined behavior where y = 0 or x = `T::MIN` and y = -1
+    /// undefined behavior when `y == 0` or `x == T::MIN && y == -1`
     ///
     /// Safe wrappers for this intrinsic are available on the integer
     /// primitives via the `checked_rem` method. For example,
@@ -1605,7 +1598,7 @@
     pub fn unchecked_rem<T: Copy>(x: T, y: T) -> T;
 
     /// Performs an unchecked left shift, resulting in undefined behavior when
-    /// y < 0 or y >= N, where N is the width of T in bits.
+    /// `y < 0` or `y >= N`, where N is the width of T in bits.
     ///
     /// Safe wrappers for this intrinsic are available on the integer
     /// primitives via the `checked_shl` method. For example,
@@ -1613,7 +1606,7 @@
     #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
     pub fn unchecked_shl<T: Copy>(x: T, y: T) -> T;
     /// Performs an unchecked right shift, resulting in undefined behavior when
-    /// y < 0 or y >= N, where N is the width of T in bits.
+    /// `y < 0` or `y >= N`, where N is the width of T in bits.
     ///
     /// Safe wrappers for this intrinsic are available on the integer
     /// primitives via the `checked_shr` method. For example,
@@ -1680,14 +1673,14 @@
     #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
     pub fn wrapping_mul<T: Copy>(a: T, b: T) -> T;
 
-    /// Computes `a + b`, while saturating at numeric bounds.
+    /// Computes `a + b`, saturating at numeric bounds.
     ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_add` method. For example,
     /// [`u32::saturating_add`]
     #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
     pub fn saturating_add<T: Copy>(a: T, b: T) -> T;
-    /// Computes `a - b`, while saturating at numeric bounds.
+    /// Computes `a - b`, saturating at numeric bounds.
     ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_sub` method. For example,
@@ -1696,14 +1689,14 @@
     pub fn saturating_sub<T: Copy>(a: T, b: T) -> T;
 
     /// Returns the value of the discriminant for the variant in 'v',
-    /// cast to a `u64`; if `T` has no discriminant, returns 0.
+    /// cast to a `u64`; if `T` has no discriminant, returns `0`.
     ///
     /// The stabilized version of this intrinsic is [`core::mem::discriminant`](crate::mem::discriminant).
     #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
     pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
 
     /// Returns the number of variants of the type `T` cast to a `usize`;
-    /// if `T` has no variants, returns 0. Uninhabited variants will be counted.
+    /// if `T` has no variants, returns `0`. Uninhabited variants will be counted.
     ///
     /// The to-be-stabilized version of this intrinsic is [`mem::variant_count`].
     #[rustc_const_unstable(feature = "variant_count", issue = "73662")]
@@ -1845,7 +1838,7 @@
 /// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append
 #[doc(alias = "memcpy")]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "none")]
+#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
 #[inline]
 pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
     extern "rust-intrinsic" {
@@ -1929,11 +1922,10 @@
 /// ```
 #[doc(alias = "memmove")]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "none")]
+#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
 #[inline]
 pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
     extern "rust-intrinsic" {
-        #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "none")]
         fn copy<T>(src: *const T, dst: *mut T, count: usize);
     }
 
diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs
index 3623267..1d01e9b 100644
--- a/library/core/src/iter/adapters/intersperse.rs
+++ b/library/core/src/iter/adapters/intersperse.rs
@@ -1,6 +1,9 @@
 use super::Peekable;
 
 /// An iterator adapter that places a separator between all elements.
+///
+/// This `struct` is created by [`Iterator::intersperse`]. See its documentation
+/// for more information.
 #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
 #[derive(Debug, Clone)]
 pub struct Intersperse<I: Iterator>
@@ -40,37 +43,146 @@
         }
     }
 
-    fn fold<B, F>(mut self, init: B, mut f: F) -> B
+    fn fold<B, F>(self, init: B, f: F) -> B
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> B,
     {
-        let mut accum = init;
-
-        // Use `peek()` first to avoid calling `next()` on an empty iterator.
-        if !self.needs_sep || self.iter.peek().is_some() {
-            if let Some(x) = self.iter.next() {
-                accum = f(accum, x);
-            }
-        }
-
-        let element = &self.separator;
-
-        self.iter.fold(accum, |mut accum, x| {
-            accum = f(accum, element.clone());
-            accum = f(accum, x);
-            accum
-        })
+        let separator = self.separator;
+        intersperse_fold(self.iter, init, f, move || separator.clone(), self.needs_sep)
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
-        let (lo, hi) = self.iter.size_hint();
-        let next_is_elem = !self.needs_sep;
-        let lo = lo.saturating_sub(next_is_elem as usize).saturating_add(lo);
-        let hi = match hi {
-            Some(hi) => hi.saturating_sub(next_is_elem as usize).checked_add(hi),
-            None => None,
-        };
-        (lo, hi)
+        intersperse_size_hint(&self.iter, self.needs_sep)
     }
 }
+
+/// An iterator adapter that places a separator between all elements.
+///
+/// This `struct` is created by [`Iterator::intersperse_with`]. See its
+/// documentation for more information.
+#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+pub struct IntersperseWith<I, G>
+where
+    I: Iterator,
+{
+    separator: G,
+    iter: Peekable<I>,
+    needs_sep: bool,
+}
+
+#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+impl<I, G> crate::fmt::Debug for IntersperseWith<I, G>
+where
+    I: Iterator + crate::fmt::Debug,
+    I::Item: crate::fmt::Debug,
+    G: crate::fmt::Debug,
+{
+    fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
+        f.debug_struct("IntersperseWith")
+            .field("separator", &self.separator)
+            .field("iter", &self.iter)
+            .field("needs_sep", &self.needs_sep)
+            .finish()
+    }
+}
+
+#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+impl<I, G> crate::clone::Clone for IntersperseWith<I, G>
+where
+    I: Iterator + crate::clone::Clone,
+    I::Item: crate::clone::Clone,
+    G: Clone,
+{
+    fn clone(&self) -> Self {
+        IntersperseWith {
+            separator: self.separator.clone(),
+            iter: self.iter.clone(),
+            needs_sep: self.needs_sep.clone(),
+        }
+    }
+}
+
+impl<I, G> IntersperseWith<I, G>
+where
+    I: Iterator,
+    G: FnMut() -> I::Item,
+{
+    pub(in crate::iter) fn new(iter: I, separator: G) -> Self {
+        Self { iter: iter.peekable(), separator, needs_sep: false }
+    }
+}
+
+#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+impl<I, G> Iterator for IntersperseWith<I, G>
+where
+    I: Iterator,
+    G: FnMut() -> I::Item,
+{
+    type Item = I::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<I::Item> {
+        if self.needs_sep && self.iter.peek().is_some() {
+            self.needs_sep = false;
+            Some((self.separator)())
+        } else {
+            self.needs_sep = true;
+            self.iter.next()
+        }
+    }
+
+    fn fold<B, F>(self, init: B, f: F) -> B
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> B,
+    {
+        intersperse_fold(self.iter, init, f, self.separator, self.needs_sep)
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        intersperse_size_hint(&self.iter, self.needs_sep)
+    }
+}
+
+fn intersperse_size_hint<I>(iter: &I, needs_sep: bool) -> (usize, Option<usize>)
+where
+    I: Iterator,
+{
+    let (lo, hi) = iter.size_hint();
+    let next_is_elem = !needs_sep;
+    let lo = lo.saturating_sub(next_is_elem as usize).saturating_add(lo);
+    let hi = match hi {
+        Some(hi) => hi.saturating_sub(next_is_elem as usize).checked_add(hi),
+        None => None,
+    };
+    (lo, hi)
+}
+
+fn intersperse_fold<I, B, F, G>(
+    mut iter: Peekable<I>,
+    init: B,
+    mut f: F,
+    mut separator: G,
+    needs_sep: bool,
+) -> B
+where
+    I: Iterator,
+    F: FnMut(B, I::Item) -> B,
+    G: FnMut() -> I::Item,
+{
+    let mut accum = init;
+
+    // Use `peek()` first to avoid calling `next()` on an empty iterator.
+    if !needs_sep || iter.peek().is_some() {
+        if let Some(x) = iter.next() {
+            accum = f(accum, x);
+        }
+    }
+
+    iter.fold(accum, |mut accum, x| {
+        accum = f(accum, separator());
+        accum = f(accum, x);
+        accum
+    })
+}
diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs
index 7dfbf32..41a7b13 100644
--- a/library/core/src/iter/adapters/mod.rs
+++ b/library/core/src/iter/adapters/mod.rs
@@ -43,7 +43,7 @@
 pub use self::copied::Copied;
 
 #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
-pub use self::intersperse::Intersperse;
+pub use self::intersperse::{Intersperse, IntersperseWith};
 
 #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
 pub use self::map_while::MapWhile;
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index 8cd4c77..98b8dca 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -286,6 +286,7 @@
 
     #[inline]
     unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item {
+        let idx = self.index + idx;
         // SAFETY: the caller must uphold the contract for
         // `Iterator::__iterator_get_unchecked`.
         unsafe { (self.a.__iterator_get_unchecked(idx), self.b.__iterator_get_unchecked(idx)) }
@@ -397,7 +398,7 @@
 ///    only be called at most `self.size() - idx - 1` times.
 /// 4. After `get_unchecked` is called, then only the following methods will be
 ///    called on `self`:
-///     * `std::clone::Clone::clone`
+///     * `std::clone::Clone::clone()`
 ///     * `std::iter::Iterator::size_hint()`
 ///     * `std::iter::Iterator::next_back()`
 ///     * `std::iter::Iterator::__iterator_get_unchecked()`
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index 569de71..c57ba2b 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -395,8 +395,6 @@
 pub use self::adapters::Copied;
 #[stable(feature = "iterator_flatten", since = "1.29.0")]
 pub use self::adapters::Flatten;
-#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
-pub use self::adapters::Intersperse;
 #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
 pub use self::adapters::MapWhile;
 #[unstable(feature = "inplace_iteration", issue = "none")]
@@ -410,6 +408,8 @@
     Chain, Cycle, Enumerate, Filter, FilterMap, FlatMap, Fuse, Inspect, Map, Peekable, Rev, Scan,
     Skip, SkipWhile, Take, TakeWhile, Zip,
 };
+#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+pub use self::adapters::{Intersperse, IntersperseWith};
 
 pub(crate) use self::adapters::process_results;
 
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index cd8ab11..4321b21 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -111,7 +111,7 @@
         Step::forward(start, count)
     }
 
-    /// Returns the value that would be obtained by taking the *successor*
+    /// Returns the value that would be obtained by taking the *predecessor*
     /// of `self` `count` times.
     ///
     /// If this would overflow the range of values supported by `Self`, returns `None`.
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 6331757..83d339d 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -8,7 +8,7 @@
 use super::super::TrustedRandomAccess;
 use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
 use super::super::{FlatMap, Flatten};
-use super::super::{FromIterator, Intersperse, Product, Sum, Zip};
+use super::super::{FromIterator, Intersperse, IntersperseWith, Product, Sum, Zip};
 use super::super::{
     Inspect, Map, MapWhile, Peekable, Rev, Scan, Skip, SkipWhile, StepBy, Take, TakeWhile,
 };
@@ -571,6 +571,9 @@
 
     /// Places a copy of `separator` between all elements.
     ///
+    /// In case the separator does not implement [`Clone`] or needs to be
+    /// computed every time, use [`intersperse_with`].
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -578,9 +581,12 @@
     /// ```
     /// #![feature(iter_intersperse)]
     ///
-    /// let hello = ["Hello", "World"].iter().copied().intersperse(" ").collect::<String>();
-    /// assert_eq!(hello, "Hello World");
+    /// let hello = ["Hello", "World", "!"].iter().copied().intersperse(" ").collect::<String>();
+    /// assert_eq!(hello, "Hello World !");
     /// ```
+    ///
+    /// [`Clone`]: crate::clone::Clone
+    /// [`intersperse_with`]: Iterator::intersperse_with
     #[inline]
     #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
     fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
@@ -591,6 +597,33 @@
         Intersperse::new(self, separator)
     }
 
+    /// Places an element generated by `separator` between all elements.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(iter_intersperse)]
+    ///
+    /// let src = ["Hello", "to", "all", "people", "!!"].iter().copied();
+    ///
+    /// let mut happy_emojis = [" ❤️ ", " 😀 "].iter().copied();
+    /// let separator = || happy_emojis.next().unwrap_or(" 🦀 ");
+    ///
+    /// let result = src.intersperse_with(separator).collect::<String>();
+    /// assert_eq!(result, "Hello ❤️ to 😀 all 🦀 people 🦀 !!");
+    /// ```
+    #[inline]
+    #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+    fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
+    where
+        Self: Sized,
+        G: FnMut() -> Self::Item,
+    {
+        IntersperseWith::new(self, separator)
+    }
+
     /// Takes a closure and creates an iterator which calls that closure on each
     /// element.
     ///
@@ -805,8 +838,6 @@
     /// assert_eq!(iter.next(), Some(5));
     /// assert_eq!(iter.next(), None);
     /// ```
-    ///
-    /// [`Option<T>`]: Option
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index eb47479..df8d9ff 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -62,7 +62,6 @@
 #![warn(missing_docs)]
 #![warn(missing_debug_implementations)]
 #![allow(explicit_outlives_requirements)]
-#![allow(incomplete_features)]
 #![feature(rustc_allow_const_fn_unstable)]
 #![feature(allow_internal_unstable)]
 #![feature(arbitrary_self_types)]
@@ -89,7 +88,6 @@
 #![feature(const_impl_trait)]
 #![feature(const_fn_floating_point_arithmetic)]
 #![feature(const_fn_fn_ptr_basics)]
-#![feature(const_generics)]
 #![feature(const_option)]
 #![feature(const_precise_live_drops)]
 #![feature(const_ptr_offset)]
@@ -113,6 +111,7 @@
 #![feature(doc_spotlight)]
 #![feature(duration_consts_2)]
 #![feature(duration_saturating_ops)]
+#![feature(extended_key_value_attributes)]
 #![feature(extern_types)]
 #![feature(fundamental)]
 #![feature(intrinsics)]
@@ -130,6 +129,7 @@
 #![feature(repr_simd, platform_intrinsics)]
 #![feature(rustc_attrs)]
 #![feature(simd_ffi)]
+#![cfg_attr(bootstrap, feature(min_const_generics))]
 #![feature(min_specialization)]
 #![feature(staged_api)]
 #![feature(std_internals)]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 1634aff..90964ba 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -401,7 +401,7 @@
 /// For more information, see [`write!`]. For information on the format string syntax, see
 /// [`std::fmt`].
 ///
-/// [`std::fmt`]: crate::fmt
+/// [`std::fmt`]: ../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -730,7 +730,7 @@
     /// [`Display`]: crate::fmt::Display
     /// [`Debug`]: crate::fmt::Debug
     /// [`fmt::Arguments`]: crate::fmt::Arguments
-    /// [`std::fmt`]: crate::fmt
+    /// [`std::fmt`]: ../std/fmt/index.html
     /// [`format!`]: ../std/macro.format.html
     /// [`println!`]: ../std/macro.println.html
     ///
@@ -1194,7 +1194,7 @@
     /// be provided with or without arguments for formatting. See [`std::fmt`]
     /// for syntax for this form.
     ///
-    /// [`std::fmt`]: crate::fmt
+    /// [`std::fmt`]: ../std/fmt/index.html
     ///
     /// # Examples
     ///
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index b2a4d89..fda0553 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -804,6 +804,46 @@
         }
     }
 
+    /// Extracts the values from an array of `MaybeUninit` containers.
+    ///
+    /// # Safety
+    ///
+    /// It is up to the caller to guarantee that all elements of the array are
+    /// in an initialized state.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(maybe_uninit_uninit_array)]
+    /// #![feature(maybe_uninit_array_assume_init)]
+    /// use std::mem::MaybeUninit;
+    ///
+    /// let mut array: [MaybeUninit<i32>; 3] = MaybeUninit::uninit_array();
+    /// array[0] = MaybeUninit::new(0);
+    /// array[1] = MaybeUninit::new(1);
+    /// array[2] = MaybeUninit::new(2);
+    ///
+    /// // SAFETY: Now safe as we initialised all elements
+    /// let array = unsafe {
+    ///     MaybeUninit::array_assume_init(array)
+    /// };
+    ///
+    /// assert_eq!(array, [0, 1, 2]);
+    /// ```
+    #[unstable(feature = "maybe_uninit_array_assume_init", issue = "80908")]
+    #[inline(always)]
+    pub unsafe fn array_assume_init<const N: usize>(array: [Self; N]) -> [T; N] {
+        // SAFETY:
+        // * The caller guarantees that all elements of the array are initialized
+        // * `MaybeUninit<T>` and T are guaranteed to have the same layout
+        // * MaybeUnint does not drop, so there are no double-frees
+        // And thus the conversion is safe
+        unsafe {
+            intrinsics::assert_inhabited::<T>();
+            (&array as *const _ as *const [T; N]).read()
+        }
+    }
+
     /// Assuming all the elements are initialized, get a slice to them.
     ///
     /// # Safety
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 22e44a3..64cf528 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -4,6 +4,7 @@
 //! types, initializing and manipulating memory.
 
 #![stable(feature = "rust1", since = "1.0.0")]
+#![cfg_attr(bootstrap, allow(unused_unsafe))]
 
 use crate::clone;
 use crate::cmp;
@@ -333,7 +334,8 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
 pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
-    intrinsics::size_of_val(val)
+    // SAFETY: `val` is a reference, so it's a valid raw pointer
+    unsafe { intrinsics::size_of_val(val) }
 }
 
 /// Returns the size of the pointed-to value in bytes.
@@ -381,7 +383,8 @@
 #[unstable(feature = "layout_for_ptr", issue = "69835")]
 #[rustc_const_unstable(feature = "const_size_of_val_raw", issue = "46571")]
 pub const unsafe fn size_of_val_raw<T: ?Sized>(val: *const T) -> usize {
-    intrinsics::size_of_val(val)
+    // SAFETY: the caller must provide a valid raw pointer
+    unsafe { intrinsics::size_of_val(val) }
 }
 
 /// Returns the [ABI]-required minimum alignment of a type.
@@ -425,7 +428,8 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(reason = "use `align_of_val` instead", since = "1.2.0")]
 pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
-    intrinsics::min_align_of_val(val)
+    // SAFETY: val is a reference, so it's a valid raw pointer
+    unsafe { intrinsics::min_align_of_val(val) }
 }
 
 /// Returns the [ABI]-required minimum alignment of a type.
@@ -469,7 +473,8 @@
 #[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
 #[allow(deprecated)]
 pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
-    intrinsics::min_align_of_val(val)
+    // SAFETY: val is a reference, so it's a valid raw pointer
+    unsafe { intrinsics::min_align_of_val(val) }
 }
 
 /// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
@@ -513,7 +518,8 @@
 #[unstable(feature = "layout_for_ptr", issue = "69835")]
 #[rustc_const_unstable(feature = "const_align_of_val_raw", issue = "46571")]
 pub const unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize {
-    intrinsics::min_align_of_val(val)
+    // SAFETY: the caller must provide a valid raw pointer
+    unsafe { intrinsics::min_align_of_val(val) }
 }
 
 /// Returns `true` if dropping values of type `T` matters.
@@ -650,7 +656,6 @@
 /// (Notice that the rules around uninitialized integers are not finalized yet, but
 /// until they are, it is advisable to avoid them.)
 ///
-/// [`MaybeUninit<T>`]: MaybeUninit
 /// [uninit]: MaybeUninit::uninit
 /// [assume_init]: MaybeUninit::assume_init
 /// [inv]: MaybeUninit#initialization-invariant
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 2cde5d9..162ed7d 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -1,2240 +1,2008 @@
 macro_rules! int_impl {
-    ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr, $Min:expr, $Max:expr, $Feature:expr,
-     $EndFeature:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
+    ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr, $Min:expr, $Max:expr,
+     $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
      $reversed:expr, $le_bytes:expr, $be_bytes:expr,
      $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => {
-        doc_comment! {
-            concat!("The smallest value that can be represented by this integer type.
+        /// The smallest value that can be represented by this integer type.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN, ", stringify!($Min), ");")]
+        /// ```
+        #[stable(feature = "assoc_int_consts", since = "1.43.0")]
+        pub const MIN: Self = !0 ^ ((!0 as $UnsignedT) >> 1) as Self;
 
-# Examples
+        /// The largest value that can be represented by this integer type.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($Max), ");")]
+        /// ```
+        #[stable(feature = "assoc_int_consts", since = "1.43.0")]
+        pub const MAX: Self = !Self::MIN;
 
-Basic usage:
+        /// The size of this integer type in bits.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_bits_const)]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
+        /// ```
+        #[unstable(feature = "int_bits_const", issue = "76904")]
+        pub const BITS: u32 = $BITS;
 
-```
-", $Feature, "assert_eq!(", stringify!($SelfT), "::MIN, ", stringify!($Min), ");",
-$EndFeature, "
-```"),
-            #[stable(feature = "assoc_int_consts", since = "1.43.0")]
-            pub const MIN: Self = !0 ^ ((!0 as $UnsignedT) >> 1) as Self;
+        /// Converts a string slice in a given base to an integer.
+        ///
+        /// The string is expected to be an optional `+` or `-` sign followed by digits.
+        /// Leading and trailing whitespace represent an error. Digits are a subset of these characters,
+        /// depending on `radix`:
+        ///
+        ///  * `0-9`
+        ///  * `a-z`
+        ///  * `A-Z`
+        ///
+        /// # Panics
+        ///
+        /// This function panics if `radix` is not in the range from 2 to 36.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_str_radix(\"A\", 16), Ok(10));")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
+            from_str_radix(src, radix)
         }
 
-        doc_comment! {
-            concat!("The largest value that can be represented by this integer type.
+        /// Returns the number of ones in the binary representation of `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = 0b100_0000", stringify!($SelfT), ";")]
+        ///
+        /// assert_eq!(n.count_ones(), 1);
+        /// ```
+        ///
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[doc(alias = "popcount")]
+        #[doc(alias = "popcnt")]
+        #[inline]
+        pub const fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() }
 
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($Max), ");",
-$EndFeature, "
-```"),
-            #[stable(feature = "assoc_int_consts", since = "1.43.0")]
-            pub const MAX: Self = !Self::MIN;
+        /// Returns the number of zeros in the binary representation of `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.count_zeros(), 1);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[inline]
+        pub const fn count_zeros(self) -> u32 {
+            (!self).count_ones()
         }
 
-        doc_comment! {
-            concat!("The size of this integer type in bits.
-
-# Examples
-
-```
-", $Feature, "#![feature(int_bits_const)]
-assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");",
-$EndFeature, "
-```"),
-            #[unstable(feature = "int_bits_const", issue = "76904")]
-            pub const BITS: u32 = $BITS;
+        /// Returns the number of leading zeros in the binary representation of `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = -1", stringify!($SelfT), ";")]
+        ///
+        /// assert_eq!(n.leading_zeros(), 0);
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[inline]
+        pub const fn leading_zeros(self) -> u32 {
+            (self as $UnsignedT).leading_zeros()
         }
 
-        doc_comment! {
-            concat!("Converts a string slice in a given base to an integer.
+        /// Returns the number of trailing zeros in the binary representation of `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = -4", stringify!($SelfT), ";")]
+        ///
+        /// assert_eq!(n.trailing_zeros(), 2);
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[inline]
+        pub const fn trailing_zeros(self) -> u32 {
+            (self as $UnsignedT).trailing_zeros()
+        }
 
-The string is expected to be an optional `+` or `-` sign followed by digits.
-Leading and trailing whitespace represent an error. Digits are a subset of these characters,
-depending on `radix`:
+        /// Returns the number of leading ones in the binary representation of `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = -1", stringify!($SelfT), ";")]
+        ///
+        #[doc = concat!("assert_eq!(n.leading_ones(), ", stringify!($BITS), ");")]
+        /// ```
+        #[stable(feature = "leading_trailing_ones", since = "1.46.0")]
+        #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")]
+        #[inline]
+        pub const fn leading_ones(self) -> u32 {
+            (self as $UnsignedT).leading_ones()
+        }
 
- * `0-9`
- * `a-z`
- * `A-Z`
+        /// Returns the number of trailing ones in the binary representation of `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = 3", stringify!($SelfT), ";")]
+        ///
+        /// assert_eq!(n.trailing_ones(), 2);
+        /// ```
+        #[stable(feature = "leading_trailing_ones", since = "1.46.0")]
+        #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")]
+        #[inline]
+        pub const fn trailing_ones(self) -> u32 {
+            (self as $UnsignedT).trailing_ones()
+        }
 
-# Panics
+        /// Shifts the bits to the left by a specified amount, `n`,
+        /// wrapping the truncated bits to the end of the resulting integer.
+        ///
+        /// Please note this isn't the same operation as the `<<` shifting operator!
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = ", $rot_op, stringify!($SelfT), ";")]
+        #[doc = concat!("let m = ", $rot_result, ";")]
+        ///
+        #[doc = concat!("assert_eq!(n.rotate_left(", $rot, "), m);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn rotate_left(self, n: u32) -> Self {
+            (self as $UnsignedT).rotate_left(n) as Self
+        }
 
-This function panics if `radix` is not in the range from 2 to 36.
+        /// Shifts the bits to the right by a specified amount, `n`,
+        /// wrapping the truncated bits to the beginning of the resulting
+        /// integer.
+        ///
+        /// Please note this isn't the same operation as the `>>` shifting operator!
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = ", $rot_result, stringify!($SelfT), ";")]
+        #[doc = concat!("let m = ", $rot_op, ";")]
+        ///
+        #[doc = concat!("assert_eq!(n.rotate_right(", $rot, "), m);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn rotate_right(self, n: u32) -> Self {
+            (self as $UnsignedT).rotate_right(n) as Self
+        }
 
-# Examples
+        /// Reverses the byte order of the integer.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = ", $swap_op, stringify!($SelfT), ";")]
+        ///
+        /// let m = n.swap_bytes();
+        ///
+        #[doc = concat!("assert_eq!(m, ", $swapped, ");")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[inline]
+        pub const fn swap_bytes(self) -> Self {
+            (self as $UnsignedT).swap_bytes() as Self
+        }
 
-Basic usage:
+        /// Reverses the order of bits in the integer. The least significant bit becomes the most significant bit,
+        ///                 second least-significant bit becomes second most-significant bit, etc.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = ", $swap_op, stringify!($SelfT), ";")]
+        /// let m = n.reverse_bits();
+        ///
+        #[doc = concat!("assert_eq!(m, ", $reversed, ");")]
+        #[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")]
+        /// ```
+        #[stable(feature = "reverse_bits", since = "1.37.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[inline]
+        #[must_use]
+        pub const fn reverse_bits(self) -> Self {
+            (self as $UnsignedT).reverse_bits() as Self
+        }
 
-```
-", $Feature, "assert_eq!(", stringify!($SelfT), "::from_str_radix(\"A\", 16), Ok(10));",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
-                from_str_radix(src, radix)
+        /// Converts an integer from big endian to the target's endianness.
+        ///
+        /// On big endian this is a no-op. On little endian the bytes are swapped.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")]
+        ///
+        /// if cfg!(target_endian = "big") {
+        #[doc = concat!("    assert_eq!(", stringify!($SelfT), "::from_be(n), n)")]
+        /// } else {
+        #[doc = concat!("    assert_eq!(", stringify!($SelfT), "::from_be(n), n.swap_bytes())")]
+        /// }
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")]
+        #[inline]
+        pub const fn from_be(x: Self) -> Self {
+            #[cfg(target_endian = "big")]
+            {
+                x
+            }
+            #[cfg(not(target_endian = "big"))]
+            {
+                x.swap_bytes()
             }
         }
 
-        doc_comment! {
-            concat!("Returns the number of ones in the binary representation of `self`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = 0b100_0000", stringify!($SelfT), ";
-
-assert_eq!(n.count_ones(), 1);",
-$EndFeature, "
-```
-"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[doc(alias = "popcount")]
-            #[doc(alias = "popcnt")]
-            #[inline]
-            pub const fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() }
-        }
-
-        doc_comment! {
-            concat!("Returns the number of zeros in the binary representation of `self`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX.count_zeros(), 1);", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[inline]
-            pub const fn count_zeros(self) -> u32 {
-                (!self).count_ones()
+        /// Converts an integer from little endian to the target's endianness.
+        ///
+        /// On little endian this is a no-op. On big endian the bytes are swapped.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")]
+        ///
+        /// if cfg!(target_endian = "little") {
+        #[doc = concat!("    assert_eq!(", stringify!($SelfT), "::from_le(n), n)")]
+        /// } else {
+        #[doc = concat!("    assert_eq!(", stringify!($SelfT), "::from_le(n), n.swap_bytes())")]
+        /// }
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")]
+        #[inline]
+        pub const fn from_le(x: Self) -> Self {
+            #[cfg(target_endian = "little")]
+            {
+                x
+            }
+            #[cfg(not(target_endian = "little"))]
+            {
+                x.swap_bytes()
             }
         }
 
-        doc_comment! {
-            concat!("Returns the number of leading zeros in the binary representation of `self`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = -1", stringify!($SelfT), ";
-
-assert_eq!(n.leading_zeros(), 0);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[inline]
-            pub const fn leading_zeros(self) -> u32 {
-                (self as $UnsignedT).leading_zeros()
+        /// Converts `self` to big endian from the target's endianness.
+        ///
+        /// On big endian this is a no-op. On little endian the bytes are swapped.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")]
+        ///
+        /// if cfg!(target_endian = "big") {
+        ///     assert_eq!(n.to_be(), n)
+        /// } else {
+        ///     assert_eq!(n.to_be(), n.swap_bytes())
+        /// }
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")]
+        #[inline]
+        pub const fn to_be(self) -> Self { // or not to be?
+            #[cfg(target_endian = "big")]
+            {
+                self
+            }
+            #[cfg(not(target_endian = "big"))]
+            {
+                self.swap_bytes()
             }
         }
 
-        doc_comment! {
-            concat!("Returns the number of trailing zeros in the binary representation of `self`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = -4", stringify!($SelfT), ";
-
-assert_eq!(n.trailing_zeros(), 2);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[inline]
-            pub const fn trailing_zeros(self) -> u32 {
-                (self as $UnsignedT).trailing_zeros()
+        /// Converts `self` to little endian from the target's endianness.
+        ///
+        /// On little endian this is a no-op. On big endian the bytes are swapped.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")]
+        ///
+        /// if cfg!(target_endian = "little") {
+        ///     assert_eq!(n.to_le(), n)
+        /// } else {
+        ///     assert_eq!(n.to_le(), n.swap_bytes())
+        /// }
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")]
+        #[inline]
+        pub const fn to_le(self) -> Self {
+            #[cfg(target_endian = "little")]
+            {
+                self
+            }
+            #[cfg(not(target_endian = "little"))]
+            {
+                self.swap_bytes()
             }
         }
 
-        doc_comment! {
-            concat!("Returns the number of leading ones in the binary representation of `self`.
+        /// Checked integer addition. Computes `self + rhs`, returning `None`
+        /// if overflow occurred.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(1), Some(", stringify!($SelfT), "::MAX - 1));")]
+        #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_add(self, rhs: Self) -> Option<Self> {
+            let (a, b) = self.overflowing_add(rhs);
+            if unlikely!(b) {None} else {Some(a)}
+        }
 
-# Examples
+        /// Unchecked integer addition. Computes `self + rhs`, assuming overflow
+        /// cannot occur. This results in undefined behavior when
+        #[doc = concat!("`self + rhs > ", stringify!($SelfT), "::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`.")]
+        #[unstable(
+            feature = "unchecked_math",
+            reason = "niche optimization path",
+            issue = "none",
+        )]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub unsafe fn unchecked_add(self, rhs: Self) -> Self {
+            // SAFETY: the caller must uphold the safety contract for
+            // `unchecked_add`.
+            unsafe { intrinsics::unchecked_add(self, rhs) }
+        }
 
-Basic usage:
+        /// Checked integer subtraction. Computes `self - rhs`, returning `None` if
+        /// overflow occurred.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub(1), Some(", stringify!($SelfT), "::MIN + 1));")]
+        #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub(3), None);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
+            let (a, b) = self.overflowing_sub(rhs);
+            if unlikely!(b) {None} else {Some(a)}
+        }
 
-```
-", $Feature, "let n = -1", stringify!($SelfT), ";
+        /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
+        /// cannot occur. This results in undefined behavior when
+        #[doc = concat!("`self - rhs > ", stringify!($SelfT), "::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`.")]
+        #[unstable(
+            feature = "unchecked_math",
+            reason = "niche optimization path",
+            issue = "none",
+        )]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub unsafe fn unchecked_sub(self, rhs: Self) -> Self {
+            // SAFETY: the caller must uphold the safety contract for
+            // `unchecked_sub`.
+            unsafe { intrinsics::unchecked_sub(self, rhs) }
+        }
 
-assert_eq!(n.leading_ones(), ", stringify!($BITS), ");",
-$EndFeature, "
-```"),
-            #[stable(feature = "leading_trailing_ones", since = "1.46.0")]
-            #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")]
-            #[inline]
-            pub const fn leading_ones(self) -> u32 {
-                (self as $UnsignedT).leading_ones()
+        /// Checked integer multiplication. Computes `self * rhs`, returning `None` if
+        /// overflow occurred.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(1), Some(", stringify!($SelfT), "::MAX));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
+            let (a, b) = self.overflowing_mul(rhs);
+            if unlikely!(b) {None} else {Some(a)}
+        }
+
+        /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
+        /// cannot occur. This results in undefined behavior when
+        #[doc = concat!("`self * rhs > ", stringify!($SelfT), "::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`.")]
+        #[unstable(
+            feature = "unchecked_math",
+            reason = "niche optimization path",
+            issue = "none",
+        )]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub unsafe fn unchecked_mul(self, rhs: Self) -> Self {
+            // SAFETY: the caller must uphold the safety contract for
+            // `unchecked_mul`.
+            unsafe { intrinsics::unchecked_mul(self, rhs) }
+        }
+
+        /// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`
+        /// or the division results in overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).checked_div(-1), Some(", stringify!($Max), "));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_div(-1), None);")]
+        #[doc = concat!("assert_eq!((1", stringify!($SelfT), ").checked_div(0), None);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_div(self, rhs: Self) -> Option<Self> {
+            if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
+                None
+            } else {
+                // SAFETY: div by zero and by INT_MIN have been checked above
+                Some(unsafe { intrinsics::unchecked_div(self, rhs) })
             }
         }
 
-        doc_comment! {
-            concat!("Returns the number of trailing ones in the binary representation of `self`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = 3", stringify!($SelfT), ";
-
-assert_eq!(n.trailing_ones(), 2);",
-$EndFeature, "
-```"),
-            #[stable(feature = "leading_trailing_ones", since = "1.46.0")]
-            #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")]
-            #[inline]
-            pub const fn trailing_ones(self) -> u32 {
-                (self as $UnsignedT).trailing_ones()
+        /// Checked Euclidean division. Computes `self.div_euclid(rhs)`,
+        /// returning `None` if `rhs == 0` or the division results in overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).checked_div_euclid(-1), Some(", stringify!($Max), "));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_div_euclid(-1), None);")]
+        #[doc = concat!("assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None);")]
+        /// ```
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
+            if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
+                None
+            } else {
+                Some(self.div_euclid(rhs))
             }
         }
 
-        doc_comment! {
-            concat!("Shifts the bits to the left by a specified amount, `n`,
-wrapping the truncated bits to the end of the resulting integer.
-
-Please note this isn't the same operation as the `<<` shifting operator!
-
-# Examples
-
-Basic usage:
-
-```
-let n = ", $rot_op, stringify!($SelfT), ";
-let m = ", $rot_result, ";
-
-assert_eq!(n.rotate_left(", $rot, "), m);
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn rotate_left(self, n: u32) -> Self {
-                (self as $UnsignedT).rotate_left(n) as Self
+        /// Checked integer remainder. Computes `self % rhs`, returning `None` if
+        /// `rhs == 0` or the division results in overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        ///
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(2), Some(1));")]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
+            if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
+                None
+            } else {
+                // SAFETY: div by zero and by INT_MIN have been checked above
+                Some(unsafe { intrinsics::unchecked_rem(self, rhs) })
             }
         }
 
-        doc_comment! {
-            concat!("Shifts the bits to the right by a specified amount, `n`,
-wrapping the truncated bits to the beginning of the resulting
-integer.
-
-Please note this isn't the same operation as the `>>` shifting operator!
-
-# Examples
-
-Basic usage:
-
-```
-let n = ", $rot_result, stringify!($SelfT), ";
-let m = ", $rot_op, ";
-
-assert_eq!(n.rotate_right(", $rot, "), m);
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn rotate_right(self, n: u32) -> Self {
-                (self as $UnsignedT).rotate_right(n) as Self
+        /// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None`
+        /// if `rhs == 0` or the division results in overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));")]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None);")]
+        /// ```
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
+            if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
+                None
+            } else {
+                Some(self.rem_euclid(rhs))
             }
         }
 
-        doc_comment! {
-            concat!("Reverses the byte order of the integer.
+        /// Checked negation. Computes `-self`, returning `None` if `self == MIN`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        ///
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_neg(), Some(-5));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_neg(), None);")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
+        #[inline]
+        pub const fn checked_neg(self) -> Option<Self> {
+            let (a, b) = self.overflowing_neg();
+            if unlikely!(b) {None} else {Some(a)}
+        }
 
-# Examples
+        /// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger
+        /// than or equal to the number of bits in `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".checked_shl(4), Some(0x10));")]
+        #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".checked_shl(129), None);")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
+            let (a, b) = self.overflowing_shl(rhs);
+            if unlikely!(b) {None} else {Some(a)}
+        }
 
-Basic usage:
+        /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
+        /// larger than or equal to the number of bits in `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shr(4), Some(0x1));")]
+        #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shr(128), None);")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
+            let (a, b) = self.overflowing_shr(rhs);
+            if unlikely!(b) {None} else {Some(a)}
+        }
 
-```
-let n = ", $swap_op, stringify!($SelfT), ";
-
-let m = n.swap_bytes();
-
-assert_eq!(m, ", $swapped, ");
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[inline]
-            pub const fn swap_bytes(self) -> Self {
-                (self as $UnsignedT).swap_bytes() as Self
+        /// Checked absolute value. Computes `self.abs()`, returning `None` if
+        /// `self == MIN`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        ///
+        #[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").checked_abs(), Some(5));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_abs(), None);")]
+        /// ```
+        #[stable(feature = "no_panic_abs", since = "1.13.0")]
+        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
+        #[inline]
+        pub const fn checked_abs(self) -> Option<Self> {
+            if self.is_negative() {
+                self.checked_neg()
+            } else {
+                Some(self)
             }
         }
 
-        doc_comment! {
-            concat!("Reverses the order of bits in the integer. The least significant bit becomes the most significant bit,
-                second least-significant bit becomes second most-significant bit, etc.
+        /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if
+        /// overflow occurred.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(8", stringify!($SelfT), ".checked_pow(2), Some(64));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);")]
+        /// ```
 
-# Examples
-
-Basic usage:
-
-```
-let n = ", $swap_op, stringify!($SelfT), ";
-let m = n.reverse_bits();
-
-assert_eq!(m, ", $reversed, ");
-assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());
-```"),
-            #[stable(feature = "reverse_bits", since = "1.37.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[inline]
-            #[must_use]
-            pub const fn reverse_bits(self) -> Self {
-                (self as $UnsignedT).reverse_bits() as Self
+        #[stable(feature = "no_panic_pow", since = "1.34.0")]
+        #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
+            if exp == 0 {
+                return Some(1);
             }
-        }
+            let mut base = self;
+            let mut acc: Self = 1;
 
-        doc_comment! {
-            concat!("Converts an integer from big endian to the target's endianness.
-
-On big endian this is a no-op. On little endian the bytes are swapped.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = 0x1A", stringify!($SelfT), ";
-
-if cfg!(target_endian = \"big\") {
-    assert_eq!(", stringify!($SelfT), "::from_be(n), n)
-} else {
-    assert_eq!(", stringify!($SelfT), "::from_be(n), n.swap_bytes())
-}",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")]
-            #[inline]
-            pub const fn from_be(x: Self) -> Self {
-                #[cfg(target_endian = "big")]
-                {
-                    x
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    acc = try_opt!(acc.checked_mul(base));
                 }
-                #[cfg(not(target_endian = "big"))]
-                {
-                    x.swap_bytes()
-                }
+                exp /= 2;
+                base = try_opt!(base.checked_mul(base));
+            }
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
+            Some(try_opt!(acc.checked_mul(base)))
+        }
+
+        /// Saturating integer addition. Computes `self + rhs`, saturating at the numeric
+        /// bounds instead of overflowing.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_add(100), ", stringify!($SelfT), "::MAX);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_add(-1), ", stringify!($SelfT), "::MIN);")]
+        /// ```
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn saturating_add(self, rhs: Self) -> Self {
+            intrinsics::saturating_add(self, rhs)
+        }
+
+        /// Saturating integer subtraction. Computes `self - rhs`, saturating at the
+        /// numeric bounds instead of overflowing.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_sub(127), -27);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub(100), ", stringify!($SelfT), "::MIN);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_sub(-1), ", stringify!($SelfT), "::MAX);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn saturating_sub(self, rhs: Self) -> Self {
+            intrinsics::saturating_sub(self, rhs)
+        }
+
+        /// Saturating integer negation. Computes `-self`, returning `MAX` if `self == MIN`
+        /// instead of overflowing.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_neg(), -100);")]
+        #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").saturating_neg(), 100);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_neg(), ", stringify!($SelfT), "::MAX);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_neg(), ", stringify!($SelfT), "::MIN + 1);")]
+        /// ```
+
+        #[stable(feature = "saturating_neg", since = "1.45.0")]
+        #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
+        #[inline]
+        pub const fn saturating_neg(self) -> Self {
+            intrinsics::saturating_sub(0, self)
+        }
+
+        /// Saturating absolute value. Computes `self.abs()`, returning `MAX` if `self ==
+        /// MIN` instead of overflowing.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_abs(), 100);")]
+        #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").saturating_abs(), 100);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_abs(), ", stringify!($SelfT), "::MAX);")]
+        #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).saturating_abs(), ", stringify!($SelfT), "::MAX);")]
+        /// ```
+
+        #[stable(feature = "saturating_neg", since = "1.45.0")]
+        #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
+        #[inline]
+        pub const fn saturating_abs(self) -> Self {
+            if self.is_negative() {
+                self.saturating_neg()
+            } else {
+                self
             }
         }
 
-        doc_comment! {
-            concat!("Converts an integer from little endian to the target's endianness.
-
-On little endian this is a no-op. On big endian the bytes are swapped.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = 0x1A", stringify!($SelfT), ";
-
-if cfg!(target_endian = \"little\") {
-    assert_eq!(", stringify!($SelfT), "::from_le(n), n)
-} else {
-    assert_eq!(", stringify!($SelfT), "::from_le(n), n.swap_bytes())
-}",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")]
-            #[inline]
-            pub const fn from_le(x: Self) -> Self {
-                #[cfg(target_endian = "little")]
-                {
-                    x
-                }
-                #[cfg(not(target_endian = "little"))]
-                {
-                    x.swap_bytes()
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Converts `self` to big endian from the target's endianness.
-
-On big endian this is a no-op. On little endian the bytes are swapped.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = 0x1A", stringify!($SelfT), ";
-
-if cfg!(target_endian = \"big\") {
-    assert_eq!(n.to_be(), n)
-} else {
-    assert_eq!(n.to_be(), n.swap_bytes())
-}",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")]
-            #[inline]
-            pub const fn to_be(self) -> Self { // or not to be?
-                #[cfg(target_endian = "big")]
-                {
-                    self
-                }
-                #[cfg(not(target_endian = "big"))]
-                {
-                    self.swap_bytes()
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Converts `self` to little endian from the target's endianness.
-
-On little endian this is a no-op. On big endian the bytes are swapped.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = 0x1A", stringify!($SelfT), ";
-
-if cfg!(target_endian = \"little\") {
-    assert_eq!(n.to_le(), n)
-} else {
-    assert_eq!(n.to_le(), n.swap_bytes())
-}",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")]
-            #[inline]
-            pub const fn to_le(self) -> Self {
-                #[cfg(target_endian = "little")]
-                {
-                    self
-                }
-                #[cfg(not(target_endian = "little"))]
-                {
-                    self.swap_bytes()
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked integer addition. Computes `self + rhs`, returning `None`
-if overflow occurred.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!((", stringify!($SelfT),
-"::MAX - 2).checked_add(1), Some(", stringify!($SelfT), "::MAX - 1));
-assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_add(self, rhs: Self) -> Option<Self> {
-                let (a, b) = self.overflowing_add(rhs);
-                if unlikely!(b) {None} else {Some(a)}
-            }
-        }
-
-        doc_comment! {
-            concat!("Unchecked integer addition. Computes `self + rhs`, assuming overflow
-cannot occur. This results in undefined behavior when `self + rhs > ", stringify!($SelfT),
-"::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`."),
-            #[unstable(
-                feature = "unchecked_math",
-                reason = "niche optimization path",
-                issue = "none",
-            )]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub unsafe fn unchecked_add(self, rhs: Self) -> Self {
-                // SAFETY: the caller must uphold the safety contract for
-                // `unchecked_add`.
-                unsafe { intrinsics::unchecked_add(self, rhs) }
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked integer subtraction. Computes `self - rhs`, returning `None` if
-overflow occurred.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!((", stringify!($SelfT),
-"::MIN + 2).checked_sub(1), Some(", stringify!($SelfT), "::MIN + 1));
-assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub(3), None);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
-                let (a, b) = self.overflowing_sub(rhs);
-                if unlikely!(b) {None} else {Some(a)}
-            }
-        }
-
-        doc_comment! {
-            concat!("Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
-cannot occur. This results in undefined behavior when `self - rhs > ", stringify!($SelfT),
-"::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`."),
-            #[unstable(
-                feature = "unchecked_math",
-                reason = "niche optimization path",
-                issue = "none",
-            )]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub unsafe fn unchecked_sub(self, rhs: Self) -> Self {
-                // SAFETY: the caller must uphold the safety contract for
-                // `unchecked_sub`.
-                unsafe { intrinsics::unchecked_sub(self, rhs) }
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked integer multiplication. Computes `self * rhs`, returning `None` if
-overflow occurred.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(", stringify!($SelfT),
-"::MAX.checked_mul(1), Some(", stringify!($SelfT), "::MAX));
-assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
-                let (a, b) = self.overflowing_mul(rhs);
-                if unlikely!(b) {None} else {Some(a)}
-            }
-        }
-
-        doc_comment! {
-            concat!("Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
-cannot occur. This results in undefined behavior when `self * rhs > ", stringify!($SelfT),
-"::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`."),
-            #[unstable(
-                feature = "unchecked_math",
-                reason = "niche optimization path",
-                issue = "none",
-            )]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub unsafe fn unchecked_mul(self, rhs: Self) -> Self {
-                // SAFETY: the caller must uphold the safety contract for
-                // `unchecked_mul`.
-                unsafe { intrinsics::unchecked_mul(self, rhs) }
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`
-or the division results in overflow.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!((", stringify!($SelfT),
-"::MIN + 1).checked_div(-1), Some(", stringify!($Max), "));
-assert_eq!(", stringify!($SelfT), "::MIN.checked_div(-1), None);
-assert_eq!((1", stringify!($SelfT), ").checked_div(0), None);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_div(self, rhs: Self) -> Option<Self> {
-                if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
-                    None
+        /// Saturating integer multiplication. Computes `self * rhs`, saturating at the
+        /// numeric bounds instead of overflowing.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        ///
+        #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".saturating_mul(12), 120);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_mul(10), ", stringify!($SelfT), "::MAX);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_mul(10), ", stringify!($SelfT), "::MIN);")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn saturating_mul(self, rhs: Self) -> Self {
+            match self.checked_mul(rhs) {
+                Some(x) => x,
+                None => if (self < 0) == (rhs < 0) {
+                    Self::MAX
                 } else {
-                    // SAFETY: div by zero and by INT_MIN have been checked above
-                    Some(unsafe { intrinsics::unchecked_div(self, rhs) })
+                    Self::MIN
                 }
             }
         }
 
-        doc_comment! {
-            concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`,
-returning `None` if `rhs == 0` or the division results in overflow.
+        /// Saturating integer exponentiation. Computes `self.pow(exp)`,
+        /// saturating at the numeric bounds instead of overflowing.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        ///
+        #[doc = concat!("assert_eq!((-4", stringify!($SelfT), ").saturating_pow(3), -64);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(2), ", stringify!($SelfT), "::MAX);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT), "::MIN);")]
+        /// ```
+        #[stable(feature = "no_panic_pow", since = "1.34.0")]
+        #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn saturating_pow(self, exp: u32) -> Self {
+            match self.checked_pow(exp) {
+                Some(x) => x,
+                None if self < 0 && exp % 2 == 1 => Self::MIN,
+                None => Self::MAX,
+            }
+        }
 
-# Examples
+        /// Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the
+        /// boundary of the type.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_add(27), 127);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add(2), ", stringify!($SelfT), "::MIN + 1);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_add(self, rhs: Self) -> Self {
+            intrinsics::wrapping_add(self, rhs)
+        }
 
-Basic usage:
+        /// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the
+        /// boundary of the type.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".wrapping_sub(127), -127);")]
+        #[doc = concat!("assert_eq!((-2", stringify!($SelfT), ").wrapping_sub(", stringify!($SelfT), "::MAX), ", stringify!($SelfT), "::MAX);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_sub(self, rhs: Self) -> Self {
+            intrinsics::wrapping_sub(self, rhs)
+        }
 
-```
-assert_eq!((", stringify!($SelfT),
-"::MIN + 1).checked_div_euclid(-1), Some(", stringify!($Max), "));
-assert_eq!(", stringify!($SelfT), "::MIN.checked_div_euclid(-1), None);
-assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None);
-```"),
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
-                if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
-                    None
-                } else {
-                    Some(self.div_euclid(rhs))
+        /// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at
+        /// the boundary of the type.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".wrapping_mul(12), 120);")]
+        /// assert_eq!(11i8.wrapping_mul(12), -124);
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_mul(self, rhs: Self) -> Self {
+            intrinsics::wrapping_mul(self, rhs)
+        }
+
+        /// Wrapping (modular) division. Computes `self / rhs`, wrapping around at the
+        /// boundary of the type.
+        ///
+        /// The only case where such wrapping can occur is when one divides `MIN / -1` on a signed type (where
+        /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value
+        /// that is too large to represent in the type. In such a case, this function returns `MIN` itself.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_div(10), 10);")]
+        /// assert_eq!((-128i8).wrapping_div(-1), -128);
+        /// ```
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_div(self, rhs: Self) -> Self {
+            self.overflowing_div(rhs).0
+        }
+
+        /// Wrapping Euclidean division. Computes `self.div_euclid(rhs)`,
+        /// wrapping around at the boundary of the type.
+        ///
+        /// Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is the negative minimal value
+        /// for the type). This is equivalent to `-MIN`, a positive value that is too large to represent in the
+        /// type. In this case, this method returns `MIN` itself.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);")]
+        /// assert_eq!((-128i8).wrapping_div_euclid(-1), -128);
+        /// ```
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_div_euclid(self, rhs: Self) -> Self {
+            self.overflowing_div_euclid(rhs).0
+        }
+
+        /// Wrapping (modular) remainder. Computes `self % rhs`, wrapping around at the
+        /// boundary of the type.
+        ///
+        /// Such wrap-around never actually occurs mathematically; implementation artifacts make `x % y`
+        /// invalid for `MIN / -1` on a signed type (where `MIN` is the negative minimal value). In such a case,
+        /// this function returns `0`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_rem(10), 0);")]
+        /// assert_eq!((-128i8).wrapping_rem(-1), 0);
+        /// ```
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_rem(self, rhs: Self) -> Self {
+            self.overflowing_rem(rhs).0
+        }
+
+        /// Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around
+        /// at the boundary of the type.
+        ///
+        /// Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is the negative minimal value
+        /// for the type). In this case, this method returns 0.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);")]
+        /// assert_eq!((-128i8).wrapping_rem_euclid(-1), 0);
+        /// ```
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self {
+            self.overflowing_rem_euclid(rhs).0
+        }
+
+        /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary
+        /// of the type.
+        ///
+        /// The only case where such wrapping can occur is when one negates `MIN` on a signed type (where `MIN`
+        /// is the negative minimal value for the type); this is a positive value that is too large to represent
+        /// in the type. In such a case, this function returns `MIN` itself.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_neg(), -100);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.wrapping_neg(), ", stringify!($SelfT), "::MIN);")]
+        /// ```
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[inline]
+        pub const fn wrapping_neg(self) -> Self {
+            self.overflowing_neg().0
+        }
+
+        /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` removes
+        /// any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type.
+        ///
+        /// Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is restricted to
+        /// the range of the type, rather than the bits shifted out of the LHS being returned to the other end.
+        /// The primitive integer types all implement a [`rotate_left`](#method.rotate_left) function,
+        /// which may be what you want instead.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").wrapping_shl(7), -128);")]
+        #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").wrapping_shl(128), -1);")]
+        /// ```
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_shl(self, rhs: u32) -> Self {
+            // SAFETY: the masking by the bitsize of the type ensures that we do not shift
+            // out of bounds
+            unsafe {
+                intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
+            }
+        }
+
+        /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`, where `mask`
+        /// removes any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type.
+        ///
+        /// Note that this is *not* the same as a rotate-right; the RHS of a wrapping shift-right is restricted
+        /// to the range of the type, rather than the bits shifted out of the LHS being returned to the other
+        /// end. The primitive integer types all implement a [`rotate_right`](#method.rotate_right) function,
+        /// which may be what you want instead.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!((-128", stringify!($SelfT), ").wrapping_shr(7), -1);")]
+        /// assert_eq!((-128i16).wrapping_shr(64), -128);
+        /// ```
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_shr(self, rhs: u32) -> Self {
+            // SAFETY: the masking by the bitsize of the type ensures that we do not shift
+            // out of bounds
+            unsafe {
+                intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
+            }
+        }
+
+        /// Wrapping (modular) absolute value. Computes `self.abs()`, wrapping around at
+        /// the boundary of the type.
+        ///
+        /// The only case where such wrapping can occur is when one takes the absolute value of the negative
+        /// minimal value for the type; this is a positive value that is too large to represent in the type. In
+        /// such a case, this function returns `MIN` itself.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_abs(), 100);")]
+        #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").wrapping_abs(), 100);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.wrapping_abs(), ", stringify!($SelfT), "::MIN);")]
+        /// assert_eq!((-128i8).wrapping_abs() as u8, 128);
+        /// ```
+        #[stable(feature = "no_panic_abs", since = "1.13.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[allow(unused_attributes)]
+        #[inline]
+        pub const fn wrapping_abs(self) -> Self {
+             if self.is_negative() {
+                 self.wrapping_neg()
+             } else {
+                 self
+             }
+        }
+
+        /// Computes the absolute value of `self` without any wrapping
+        /// or panicking.
+        ///
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(unsigned_abs)]
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".unsigned_abs(), 100", stringify!($UnsignedT), ");")]
+        #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").unsigned_abs(), 100", stringify!($UnsignedT), ");")]
+        /// assert_eq!((-128i8).unsigned_abs(), 128u8);
+        /// ```
+        #[unstable(feature = "unsigned_abs", issue = "74913")]
+        #[inline]
+        pub const fn unsigned_abs(self) -> $UnsignedT {
+             self.wrapping_abs() as $UnsignedT
+        }
+
+        /// Wrapping (modular) exponentiation. Computes `self.pow(exp)`,
+        /// wrapping around at the boundary of the type.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".wrapping_pow(4), 81);")]
+        /// assert_eq!(3i8.wrapping_pow(5), -13);
+        /// assert_eq!(3i8.wrapping_pow(6), -39);
+        /// ```
+        #[stable(feature = "no_panic_pow", since = "1.34.0")]
+        #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_pow(self, mut exp: u32) -> Self {
+            if exp == 0 {
+                return 1;
+            }
+            let mut base = self;
+            let mut acc: Self = 1;
+
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    acc = acc.wrapping_mul(base);
                 }
+                exp /= 2;
+                base = base.wrapping_mul(base);
+            }
+
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
+            acc.wrapping_mul(base)
+        }
+
+        /// Calculates `self` + `rhs`
+        ///
+        /// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would
+        /// occur. If an overflow would have occurred then the wrapped value is returned.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        ///
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($SelfT), "::MIN, true));")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+            let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT);
+            (a as Self, b)
+        }
+
+        /// Calculates `self` - `rhs`
+        ///
+        /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow
+        /// would occur. If an overflow would have occurred then the wrapped value is returned.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        ///
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
+            let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT);
+            (a as Self, b)
+        }
+
+        /// Calculates the multiplication of `self` and `rhs`.
+        ///
+        /// Returns a tuple of the multiplication along with a boolean indicating whether an arithmetic overflow
+        /// would occur. If an overflow would have occurred then the wrapped value is returned.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_mul(2), (10, false));")]
+        /// assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true));
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
+            let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT);
+            (a as Self, b)
+        }
+
+        /// Calculates the divisor when `self` is divided by `rhs`.
+        ///
+        /// Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would
+        /// occur. If an overflow would occur then self is returned.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        ///
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div(-1), (", stringify!($SelfT), "::MIN, true));")]
+        /// ```
+        #[inline]
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
+            if unlikely!(self == Self::MIN && rhs == -1) {
+                (self, true)
+            } else {
+                (self / rhs, false)
             }
         }
 
-        doc_comment! {
-            concat!("Checked integer remainder. Computes `self % rhs`, returning `None` if
-`rhs == 0` or the division results in overflow.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "
-assert_eq!(5", stringify!($SelfT), ".checked_rem(2), Some(1));
-assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);
-assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);",
-$EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
-                if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
-                    None
-                } else {
-                    // SAFETY: div by zero and by INT_MIN have been checked above
-                    Some(unsafe { intrinsics::unchecked_rem(self, rhs) })
-                }
+        /// Calculates the quotient of Euclidean division `self.div_euclid(rhs)`.
+        ///
+        /// Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would
+        /// occur. If an overflow would occur then `self` is returned.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringify!($SelfT), "::MIN, true));")]
+        /// ```
+        #[inline]
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
+            if unlikely!(self == Self::MIN && rhs == -1) {
+                (self, true)
+            } else {
+                (self.div_euclid(rhs), false)
             }
         }
 
-        doc_comment! {
-            concat!("Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None`
-if `rhs == 0` or the division results in overflow.
-
-# Examples
-
-Basic usage:
-
-```
-assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));
-assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);
-assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None);
-```"),
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
-                if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
-                    None
-                } else {
-                    Some(self.rem_euclid(rhs))
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked negation. Computes `-self`, returning `None` if `self == MIN`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "
-assert_eq!(5", stringify!($SelfT), ".checked_neg(), Some(-5));
-assert_eq!(", stringify!($SelfT), "::MIN.checked_neg(), None);",
-$EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
-            #[inline]
-            pub const fn checked_neg(self) -> Option<Self> {
-                let (a, b) = self.overflowing_neg();
-                if unlikely!(b) {None} else {Some(a)}
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger
-than or equal to the number of bits in `self`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(0x1", stringify!($SelfT), ".checked_shl(4), Some(0x10));
-assert_eq!(0x1", stringify!($SelfT), ".checked_shl(129), None);",
-$EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
-                let (a, b) = self.overflowing_shl(rhs);
-                if unlikely!(b) {None} else {Some(a)}
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
-larger than or equal to the number of bits in `self`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(0x10", stringify!($SelfT), ".checked_shr(4), Some(0x1));
-assert_eq!(0x10", stringify!($SelfT), ".checked_shr(128), None);",
-$EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
-                let (a, b) = self.overflowing_shr(rhs);
-                if unlikely!(b) {None} else {Some(a)}
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked absolute value. Computes `self.abs()`, returning `None` if
-`self == MIN`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "
-assert_eq!((-5", stringify!($SelfT), ").checked_abs(), Some(5));
-assert_eq!(", stringify!($SelfT), "::MIN.checked_abs(), None);",
-$EndFeature, "
-```"),
-            #[stable(feature = "no_panic_abs", since = "1.13.0")]
-            #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
-            #[inline]
-            pub const fn checked_abs(self) -> Option<Self> {
-                if self.is_negative() {
-                    self.checked_neg()
-                } else {
-                    Some(self)
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked exponentiation. Computes `self.pow(exp)`, returning `None` if
-overflow occurred.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(8", stringify!($SelfT), ".checked_pow(2), Some(64));
-assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);",
-$EndFeature, "
-```"),
-
-            #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
-                if exp == 0 {
-                    return Some(1);
-                }
-                let mut base = self;
-                let mut acc: Self = 1;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        acc = try_opt!(acc.checked_mul(base));
-                    }
-                    exp /= 2;
-                    base = try_opt!(base.checked_mul(base));
-                }
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
-                Some(try_opt!(acc.checked_mul(base)))
-            }
-        }
-
-        doc_comment! {
-            concat!("Saturating integer addition. Computes `self + rhs`, saturating at the numeric
-bounds instead of overflowing.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);
-assert_eq!(", stringify!($SelfT), "::MAX.saturating_add(100), ", stringify!($SelfT),
-"::MAX);
-assert_eq!(", stringify!($SelfT), "::MIN.saturating_add(-1), ", stringify!($SelfT),
-"::MIN);",
-$EndFeature, "
-```"),
-
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn saturating_add(self, rhs: Self) -> Self {
-                intrinsics::saturating_add(self, rhs)
-            }
-        }
-
-        doc_comment! {
-            concat!("Saturating integer subtraction. Computes `self - rhs`, saturating at the
-numeric bounds instead of overflowing.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_sub(127), -27);
-assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub(100), ", stringify!($SelfT),
-"::MIN);
-assert_eq!(", stringify!($SelfT), "::MAX.saturating_sub(-1), ", stringify!($SelfT),
-"::MAX);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn saturating_sub(self, rhs: Self) -> Self {
-                intrinsics::saturating_sub(self, rhs)
-            }
-        }
-
-        doc_comment! {
-            concat!("Saturating integer negation. Computes `-self`, returning `MAX` if `self == MIN`
-instead of overflowing.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_neg(), -100);
-assert_eq!((-100", stringify!($SelfT), ").saturating_neg(), 100);
-assert_eq!(", stringify!($SelfT), "::MIN.saturating_neg(), ", stringify!($SelfT),
-"::MAX);
-assert_eq!(", stringify!($SelfT), "::MAX.saturating_neg(), ", stringify!($SelfT),
-"::MIN + 1);",
-$EndFeature, "
-```"),
-
-            #[stable(feature = "saturating_neg", since = "1.45.0")]
-            #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
-            #[inline]
-            pub const fn saturating_neg(self) -> Self {
-                intrinsics::saturating_sub(0, self)
-            }
-        }
-
-        doc_comment! {
-            concat!("Saturating absolute value. Computes `self.abs()`, returning `MAX` if `self ==
-MIN` instead of overflowing.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_abs(), 100);
-assert_eq!((-100", stringify!($SelfT), ").saturating_abs(), 100);
-assert_eq!(", stringify!($SelfT), "::MIN.saturating_abs(), ", stringify!($SelfT),
-"::MAX);
-assert_eq!((", stringify!($SelfT), "::MIN + 1).saturating_abs(), ", stringify!($SelfT),
-"::MAX);",
-$EndFeature, "
-```"),
-
-            #[stable(feature = "saturating_neg", since = "1.45.0")]
-            #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
-            #[inline]
-            pub const fn saturating_abs(self) -> Self {
-                if self.is_negative() {
-                    self.saturating_neg()
-                } else {
-                    self
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Saturating integer multiplication. Computes `self * rhs`, saturating at the
-numeric bounds instead of overflowing.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "
-assert_eq!(10", stringify!($SelfT), ".saturating_mul(12), 120);
-assert_eq!(", stringify!($SelfT), "::MAX.saturating_mul(10), ", stringify!($SelfT), "::MAX);
-assert_eq!(", stringify!($SelfT), "::MIN.saturating_mul(10), ", stringify!($SelfT), "::MIN);",
-$EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn saturating_mul(self, rhs: Self) -> Self {
-                match self.checked_mul(rhs) {
-                    Some(x) => x,
-                    None => if (self < 0) == (rhs < 0) {
-                        Self::MAX
-                    } else {
-                        Self::MIN
-                    }
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Saturating integer exponentiation. Computes `self.pow(exp)`,
-saturating at the numeric bounds instead of overflowing.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "
-assert_eq!((-4", stringify!($SelfT), ").saturating_pow(3), -64);
-assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(2), ", stringify!($SelfT), "::MAX);
-assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT), "::MIN);",
-$EndFeature, "
-```"),
-            #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn saturating_pow(self, exp: u32) -> Self {
-                match self.checked_pow(exp) {
-                    Some(x) => x,
-                    None if self < 0 && exp % 2 == 1 => Self::MIN,
-                    None => Self::MAX,
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the
-boundary of the type.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_add(27), 127);
-assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add(2), ", stringify!($SelfT),
-"::MIN + 1);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_add(self, rhs: Self) -> Self {
-                intrinsics::wrapping_add(self, rhs)
-            }
-        }
-
-        doc_comment! {
-            concat!("Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the
-boundary of the type.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(0", stringify!($SelfT), ".wrapping_sub(127), -127);
-assert_eq!((-2", stringify!($SelfT), ").wrapping_sub(", stringify!($SelfT), "::MAX), ",
-stringify!($SelfT), "::MAX);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_sub(self, rhs: Self) -> Self {
-                intrinsics::wrapping_sub(self, rhs)
-            }
-        }
-
-        doc_comment! {
-            concat!("Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at
-the boundary of the type.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(10", stringify!($SelfT), ".wrapping_mul(12), 120);
-assert_eq!(11i8.wrapping_mul(12), -124);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_mul(self, rhs: Self) -> Self {
-                intrinsics::wrapping_mul(self, rhs)
-            }
-        }
-
-        doc_comment! {
-            concat!("Wrapping (modular) division. Computes `self / rhs`, wrapping around at the
-boundary of the type.
-
-The only case where such wrapping can occur is when one divides `MIN / -1` on a signed type (where
-`MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value
-that is too large to represent in the type. In such a case, this function returns `MIN` itself.
-
-# Panics
-
-This function will panic if `rhs` is 0.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_div(10), 10);
-assert_eq!((-128i8).wrapping_div(-1), -128);",
-$EndFeature, "
-```"),
-            #[stable(feature = "num_wrapping", since = "1.2.0")]
-            #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_div(self, rhs: Self) -> Self {
-                self.overflowing_div(rhs).0
-            }
-        }
-
-        doc_comment! {
-            concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`,
-wrapping around at the boundary of the type.
-
-Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is the negative minimal value
-for the type). This is equivalent to `-MIN`, a positive value that is too large to represent in the
-type. In this case, this method returns `MIN` itself.
-
-# Panics
-
-This function will panic if `rhs` is 0.
-
-# Examples
-
-Basic usage:
-
-```
-assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);
-assert_eq!((-128i8).wrapping_div_euclid(-1), -128);
-```"),
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_div_euclid(self, rhs: Self) -> Self {
-                self.overflowing_div_euclid(rhs).0
-            }
-        }
-
-        doc_comment! {
-            concat!("Wrapping (modular) remainder. Computes `self % rhs`, wrapping around at the
-boundary of the type.
-
-Such wrap-around never actually occurs mathematically; implementation artifacts make `x % y`
-invalid for `MIN / -1` on a signed type (where `MIN` is the negative minimal value). In such a case,
-this function returns `0`.
-
-# Panics
-
-This function will panic if `rhs` is 0.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_rem(10), 0);
-assert_eq!((-128i8).wrapping_rem(-1), 0);",
-$EndFeature, "
-```"),
-            #[stable(feature = "num_wrapping", since = "1.2.0")]
-            #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_rem(self, rhs: Self) -> Self {
-                self.overflowing_rem(rhs).0
-            }
-        }
-
-        doc_comment! {
-            concat!("Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around
-at the boundary of the type.
-
-Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is the negative minimal value
-for the type). In this case, this method returns 0.
-
-# Panics
-
-This function will panic if `rhs` is 0.
-
-# Examples
-
-Basic usage:
-
-```
-assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);
-assert_eq!((-128i8).wrapping_rem_euclid(-1), 0);
-```"),
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self {
-                self.overflowing_rem_euclid(rhs).0
-            }
-        }
-
-        doc_comment! {
-            concat!("Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary
-of the type.
-
-The only case where such wrapping can occur is when one negates `MIN` on a signed type (where `MIN`
-is the negative minimal value for the type); this is a positive value that is too large to represent
-in the type. In such a case, this function returns `MIN` itself.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_neg(), -100);
-assert_eq!(", stringify!($SelfT), "::MIN.wrapping_neg(), ", stringify!($SelfT),
-"::MIN);",
-$EndFeature, "
-```"),
-            #[stable(feature = "num_wrapping", since = "1.2.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[inline]
-            pub const fn wrapping_neg(self) -> Self {
-                self.overflowing_neg().0
-            }
-        }
-
-        doc_comment! {
-            concat!("Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` removes
-any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type.
-
-Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is restricted to
-the range of the type, rather than the bits shifted out of the LHS being returned to the other end.
-The primitive integer types all implement a [`rotate_left`](#method.rotate_left) function,
-which may be what you want instead.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!((-1", stringify!($SelfT), ").wrapping_shl(7), -128);
-assert_eq!((-1", stringify!($SelfT), ").wrapping_shl(128), -1);",
-$EndFeature, "
-```"),
-            #[stable(feature = "num_wrapping", since = "1.2.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_shl(self, rhs: u32) -> Self {
-                // SAFETY: the masking by the bitsize of the type ensures that we do not shift
-                // out of bounds
-                unsafe {
-                    intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Panic-free bitwise shift-right; yields `self >> mask(rhs)`, where `mask`
-removes any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type.
-
-Note that this is *not* the same as a rotate-right; the RHS of a wrapping shift-right is restricted
-to the range of the type, rather than the bits shifted out of the LHS being returned to the other
-end. The primitive integer types all implement a [`rotate_right`](#method.rotate_right) function,
-which may be what you want instead.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!((-128", stringify!($SelfT), ").wrapping_shr(7), -1);
-assert_eq!((-128i16).wrapping_shr(64), -128);",
-$EndFeature, "
-```"),
-            #[stable(feature = "num_wrapping", since = "1.2.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_shr(self, rhs: u32) -> Self {
-                // SAFETY: the masking by the bitsize of the type ensures that we do not shift
-                // out of bounds
-                unsafe {
-                    intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Wrapping (modular) absolute value. Computes `self.abs()`, wrapping around at
-the boundary of the type.
-
-The only case where such wrapping can occur is when one takes the absolute value of the negative
-minimal value for the type; this is a positive value that is too large to represent in the type. In
-such a case, this function returns `MIN` itself.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_abs(), 100);
-assert_eq!((-100", stringify!($SelfT), ").wrapping_abs(), 100);
-assert_eq!(", stringify!($SelfT), "::MIN.wrapping_abs(), ", stringify!($SelfT),
-"::MIN);
-assert_eq!((-128i8).wrapping_abs() as u8, 128);",
-$EndFeature, "
-```"),
-            #[stable(feature = "no_panic_abs", since = "1.13.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[allow(unused_attributes)]
-            #[inline]
-            pub const fn wrapping_abs(self) -> Self {
-                 if self.is_negative() {
-                     self.wrapping_neg()
-                 } else {
-                     self
-                 }
-            }
-        }
-
-        doc_comment! {
-            concat!("Computes the absolute value of `self` without any wrapping
-or panicking.
-
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "#![feature(unsigned_abs)]
-assert_eq!(100", stringify!($SelfT), ".unsigned_abs(), 100", stringify!($UnsignedT), ");
-assert_eq!((-100", stringify!($SelfT), ").unsigned_abs(), 100", stringify!($UnsignedT), ");
-assert_eq!((-128i8).unsigned_abs(), 128u8);",
-$EndFeature, "
-```"),
-            #[unstable(feature = "unsigned_abs", issue = "74913")]
-            #[inline]
-            pub const fn unsigned_abs(self) -> $UnsignedT {
-                 self.wrapping_abs() as $UnsignedT
-            }
-        }
-
-        doc_comment! {
-            concat!("Wrapping (modular) exponentiation. Computes `self.pow(exp)`,
-wrapping around at the boundary of the type.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(3", stringify!($SelfT), ".wrapping_pow(4), 81);
-assert_eq!(3i8.wrapping_pow(5), -13);
-assert_eq!(3i8.wrapping_pow(6), -39);",
-$EndFeature, "
-```"),
-            #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_pow(self, mut exp: u32) -> Self {
-                if exp == 0 {
-                    return 1;
-                }
-                let mut base = self;
-                let mut acc: Self = 1;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        acc = acc.wrapping_mul(base);
-                    }
-                    exp /= 2;
-                    base = base.wrapping_mul(base);
-                }
-
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
-                acc.wrapping_mul(base)
-            }
-        }
-
-        doc_comment! {
-            concat!("Calculates `self` + `rhs`
-
-Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would
-occur. If an overflow would have occurred then the wrapped value is returned.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "
-assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));
-assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($SelfT),
-"::MIN, true));", $EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
-                let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT);
-                (a as Self, b)
-            }
-        }
-
-        doc_comment! {
-            concat!("Calculates `self` - `rhs`
-
-Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow
-would occur. If an overflow would have occurred then the wrapped value is returned.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "
-assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));
-assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($SelfT),
-"::MAX, true));", $EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
-                let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT);
-                (a as Self, b)
-            }
-        }
-
-        doc_comment! {
-            concat!("Calculates the multiplication of `self` and `rhs`.
-
-Returns a tuple of the multiplication along with a boolean indicating whether an arithmetic overflow
-would occur. If an overflow would have occurred then the wrapped value is returned.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(5", stringify!($SelfT), ".overflowing_mul(2), (10, false));
-assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true));",
-$EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
-                let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT);
-                (a as Self, b)
-            }
-        }
-
-        doc_comment! {
-            concat!("Calculates the divisor when `self` is divided by `rhs`.
-
-Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would
-occur. If an overflow would occur then self is returned.
-
-# Panics
-
-This function will panic if `rhs` is 0.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "
-assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));
-assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div(-1), (", stringify!($SelfT),
-"::MIN, true));",
-$EndFeature, "
-```"),
-            #[inline]
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
-                if unlikely!(self == Self::MIN && rhs == -1) {
-                    (self, true)
-                } else {
-                    (self / rhs, false)
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`.
-
-Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would
-occur. If an overflow would occur then `self` is returned.
-
-# Panics
-
-This function will panic if `rhs` is 0.
-
-# Examples
-
-Basic usage:
-
-```
-assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));
-assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringify!($SelfT),
-"::MIN, true));
-```"),
-            #[inline]
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
-                if unlikely!(self == Self::MIN && rhs == -1) {
-                    (self, true)
-                } else {
-                    (self.div_euclid(rhs), false)
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Calculates the remainder when `self` is divided by `rhs`.
-
-Returns a tuple of the remainder after dividing along with a boolean indicating whether an
-arithmetic overflow would occur. If an overflow would occur then 0 is returned.
-
-# Panics
-
-This function will panic if `rhs` is 0.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "
-assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));
-assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem(-1), (0, true));",
-$EndFeature, "
-```"),
-            #[inline]
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
-                if unlikely!(self == Self::MIN && rhs == -1) {
-                    (0, true)
-                } else {
-                    (self % rhs, false)
-                }
+        /// Calculates the remainder when `self` is divided by `rhs`.
+        ///
+        /// Returns a tuple of the remainder after dividing along with a boolean indicating whether an
+        /// arithmetic overflow would occur. If an overflow would occur then 0 is returned.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        ///
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem(-1), (0, true));")]
+        /// ```
+        #[inline]
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
+            if unlikely!(self == Self::MIN && rhs == -1) {
+                (0, true)
+            } else {
+                (self % rhs, false)
             }
         }
 
 
-        doc_comment! {
-            concat!("Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`.
-
-Returns a tuple of the remainder after dividing along with a boolean indicating whether an
-arithmetic overflow would occur. If an overflow would occur then 0 is returned.
-
-# Panics
-
-This function will panic if `rhs` is 0.
-
-# Examples
-
-Basic usage:
-
-```
-assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));
-assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true));
-```"),
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
-                if unlikely!(self == Self::MIN && rhs == -1) {
-                    (0, true)
-                } else {
-                    (self.rem_euclid(rhs), false)
-                }
+        /// Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`.
+        ///
+        /// Returns a tuple of the remainder after dividing along with a boolean indicating whether an
+        /// arithmetic overflow would occur. If an overflow would occur then 0 is returned.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true));")]
+        /// ```
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
+            if unlikely!(self == Self::MIN && rhs == -1) {
+                (0, true)
+            } else {
+                (self.rem_euclid(rhs), false)
             }
         }
 
 
-        doc_comment! {
-            concat!("Negates self, overflowing if this is equal to the minimum value.
-
-Returns a tuple of the negated version of self along with a boolean indicating whether an overflow
-happened. If `self` is the minimum value (e.g., `i32::MIN` for values of type `i32`), then the
-minimum value will be returned again and `true` will be returned for an overflow happening.
-
-# Examples
-
-Basic usage:
-
-```
-assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2, false));
-assert_eq!(", stringify!($SelfT), "::MIN.overflowing_neg(), (", stringify!($SelfT),
-"::MIN, true));", $EndFeature, "
-```"),
-            #[inline]
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[allow(unused_attributes)]
-            pub const fn overflowing_neg(self) -> (Self, bool) {
-                if unlikely!(self == Self::MIN) {
-                    (Self::MIN, true)
-                } else {
-                    (-self, false)
-                }
+        /// Negates self, overflowing if this is equal to the minimum value.
+        ///
+        /// Returns a tuple of the negated version of self along with a boolean indicating whether an overflow
+        /// happened. If `self` is the minimum value (e.g., `i32::MIN` for values of type `i32`), then the
+        /// minimum value will be returned again and `true` will be returned for an overflow happening.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_neg(), (", stringify!($SelfT), "::MIN, true));")]
+        /// ```
+        #[inline]
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[allow(unused_attributes)]
+        pub const fn overflowing_neg(self) -> (Self, bool) {
+            if unlikely!(self == Self::MIN) {
+                (Self::MIN, true)
+            } else {
+                (-self, false)
             }
         }
 
-        doc_comment! {
-            concat!("Shifts self left by `rhs` bits.
-
-Returns a tuple of the shifted version of self along with a boolean indicating whether the shift
-value was larger than or equal to the number of bits. If the shift value is too large, then value is
-masked (N-1) where N is the number of bits, and this value is then used to perform the shift.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(0x1", stringify!($SelfT),".overflowing_shl(4), (0x10, false));
-assert_eq!(0x1i32.overflowing_shl(36), (0x10, true));",
-$EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
-                (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
-            }
+        /// Shifts self left by `rhs` bits.
+        ///
+        /// Returns a tuple of the shifted version of self along with a boolean indicating whether the shift
+        /// value was larger than or equal to the number of bits. If the shift value is too large, then value is
+        /// masked (N-1) where N is the number of bits, and this value is then used to perform the shift.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(0x1", stringify!($SelfT),".overflowing_shl(4), (0x10, false));")]
+        /// assert_eq!(0x1i32.overflowing_shl(36), (0x10, true));
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
         }
 
-        doc_comment! {
-            concat!("Shifts self right by `rhs` bits.
-
-Returns a tuple of the shifted version of self along with a boolean indicating whether the shift
-value was larger than or equal to the number of bits. If the shift value is too large, then value is
-masked (N-1) where N is the number of bits, and this value is then used to perform the shift.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(4), (0x1, false));
-assert_eq!(0x10i32.overflowing_shr(36), (0x1, true));",
-$EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
-                (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
-            }
+        /// Shifts self right by `rhs` bits.
+        ///
+        /// Returns a tuple of the shifted version of self along with a boolean indicating whether the shift
+        /// value was larger than or equal to the number of bits. If the shift value is too large, then value is
+        /// masked (N-1) where N is the number of bits, and this value is then used to perform the shift.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(4), (0x1, false));")]
+        /// assert_eq!(0x10i32.overflowing_shr(36), (0x1, true));
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
         }
 
-        doc_comment! {
-            concat!("Computes the absolute value of `self`.
-
-Returns a tuple of the absolute version of self along with a boolean indicating whether an overflow
-happened. If self is the minimum value (e.g., ", stringify!($SelfT), "::MIN for values of type
- ", stringify!($SelfT), "), then the minimum value will be returned again and true will be returned
-for an overflow happening.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(10", stringify!($SelfT), ".overflowing_abs(), (10, false));
-assert_eq!((-10", stringify!($SelfT), ").overflowing_abs(), (10, false));
-assert_eq!((", stringify!($SelfT), "::MIN).overflowing_abs(), (", stringify!($SelfT),
-"::MIN, true));",
-$EndFeature, "
-```"),
-            #[stable(feature = "no_panic_abs", since = "1.13.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[inline]
-            pub const fn overflowing_abs(self) -> (Self, bool) {
-                (self.wrapping_abs(), self == Self::MIN)
-            }
+        /// Computes the absolute value of `self`.
+        ///
+        /// Returns a tuple of the absolute version of self along with a boolean indicating whether an overflow
+        /// happened. If self is the minimum value
+        #[doc = concat!("(e.g., ", stringify!($SelfT), "::MIN for values of type ", stringify!($SelfT), "),")]
+        /// then the minimum value will be returned again and true will be returned
+        /// for an overflow happening.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".overflowing_abs(), (10, false));")]
+        #[doc = concat!("assert_eq!((-10", stringify!($SelfT), ").overflowing_abs(), (10, false));")]
+        #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN).overflowing_abs(), (", stringify!($SelfT), "::MIN, true));")]
+        /// ```
+        #[stable(feature = "no_panic_abs", since = "1.13.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[inline]
+        pub const fn overflowing_abs(self) -> (Self, bool) {
+            (self.wrapping_abs(), self == Self::MIN)
         }
 
-        doc_comment! {
-            concat!("Raises self to the power of `exp`, using exponentiation by squaring.
+        /// Raises self to the power of `exp`, using exponentiation by squaring.
+        ///
+        /// Returns a tuple of the exponentiation along with a bool indicating
+        /// whether an overflow happened.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".overflowing_pow(4), (81, false));")]
+        /// assert_eq!(3i8.overflowing_pow(5), (-13, true));
+        /// ```
+        #[stable(feature = "no_panic_pow", since = "1.34.0")]
+        #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
+            if exp == 0 {
+                return (1,false);
+            }
+            let mut base = self;
+            let mut acc: Self = 1;
+            let mut overflown = false;
+            // Scratch space for storing results of overflowing_mul.
+            let mut r;
 
-Returns a tuple of the exponentiation along with a bool indicating
-whether an overflow happened.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(3", stringify!($SelfT), ".overflowing_pow(4), (81, false));
-assert_eq!(3i8.overflowing_pow(5), (-13, true));",
-$EndFeature, "
-```"),
-            #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
-                if exp == 0 {
-                    return (1,false);
-                }
-                let mut base = self;
-                let mut acc: Self = 1;
-                let mut overflown = false;
-                // Scratch space for storing results of overflowing_mul.
-                let mut r;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        r = acc.overflowing_mul(base);
-                        acc = r.0;
-                        overflown |= r.1;
-                    }
-                    exp /= 2;
-                    r = base.overflowing_mul(base);
-                    base = r.0;
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    r = acc.overflowing_mul(base);
+                    acc = r.0;
                     overflown |= r.1;
                 }
+                exp /= 2;
+                r = base.overflowing_mul(base);
+                base = r.0;
+                overflown |= r.1;
+            }
 
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
-                r = acc.overflowing_mul(base);
-                r.1 |= overflown;
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
+            r = acc.overflowing_mul(base);
+            r.1 |= overflown;
+            r
+        }
+
+        /// Raises self to the power of `exp`, using exponentiation by squaring.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let x: ", stringify!($SelfT), " = 2; // or any other integer type")]
+        ///
+        /// assert_eq!(x.pow(5), 32);
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        pub const fn pow(self, mut exp: u32) -> Self {
+            if exp == 0 {
+                return 1;
+            }
+            let mut base = self;
+            let mut acc = 1;
+
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    acc = acc * base;
+                }
+                exp /= 2;
+                base = base * base;
+            }
+
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
+            acc * base
+        }
+
+        /// Calculates the quotient of Euclidean division of `self` by `rhs`.
+        ///
+        /// This computes the integer `n` such that `self = n * rhs + self.rem_euclid(rhs)`,
+        /// with `0 <= self.rem_euclid(rhs) < rhs`.
+        ///
+        /// In other words, the result is `self / rhs` rounded to the integer `n`
+        /// such that `self >= n * rhs`.
+        /// If `self > 0`, this is equal to round towards zero (the default in Rust);
+        /// if `self < 0`, this is equal to round towards +/- infinity.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0 or the division results in overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let a: ", stringify!($SelfT), " = 7; // or any other integer type")]
+        /// let b = 4;
+        ///
+        /// assert_eq!(a.div_euclid(b), 1); // 7 >= 4 * 1
+        /// assert_eq!(a.div_euclid(-b), -1); // 7 >= -4 * -1
+        /// assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2
+        /// assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2
+        /// ```
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        pub const fn div_euclid(self, rhs: Self) -> Self {
+            let q = self / rhs;
+            if self % rhs < 0 {
+                return if rhs > 0 { q - 1 } else { q + 1 }
+            }
+            q
+        }
+
+
+        /// Calculates the least nonnegative remainder of `self (mod rhs)`.
+        ///
+        /// This is done as if by the Euclidean division algorithm -- given
+        /// `r = self.rem_euclid(rhs)`, `self = rhs * self.div_euclid(rhs) + r`, and
+        /// `0 <= r < abs(rhs)`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0 or the division results in overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let a: ", stringify!($SelfT), " = 7; // or any other integer type")]
+        /// let b = 4;
+        ///
+        /// assert_eq!(a.rem_euclid(b), 3);
+        /// assert_eq!((-a).rem_euclid(b), 1);
+        /// assert_eq!(a.rem_euclid(-b), 3);
+        /// assert_eq!((-a).rem_euclid(-b), 1);
+        /// ```
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        pub const fn rem_euclid(self, rhs: Self) -> Self {
+            let r = self % rhs;
+            if r < 0 {
+                if rhs < 0 {
+                    r - rhs
+                } else {
+                    r + rhs
+                }
+            } else {
                 r
             }
         }
 
-        doc_comment! {
-            concat!("Raises self to the power of `exp`, using exponentiation by squaring.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let x: ", stringify!($SelfT), " = 2; // or any other integer type
-
-assert_eq!(x.pow(5), 32);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            #[rustc_inherit_overflow_checks]
-            pub const fn pow(self, mut exp: u32) -> Self {
-                if exp == 0 {
-                    return 1;
-                }
-                let mut base = self;
-                let mut acc = 1;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        acc = acc * base;
-                    }
-                    exp /= 2;
-                    base = base * base;
-                }
-
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
-                acc * base
+        /// Computes the absolute value of `self`.
+        ///
+        /// # Overflow behavior
+        ///
+        /// The absolute value of
+        #[doc = concat!("`", stringify!($SelfT), "::MIN`")]
+        /// cannot be represented as an
+        #[doc = concat!("`", stringify!($SelfT), "`,")]
+        /// and attempting to calculate it will cause an overflow. This means
+        /// that code in debug mode will trigger a panic on this case and
+        /// optimized code will return
+        #[doc = concat!("`", stringify!($SelfT), "::MIN`")]
+        /// without a panic.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".abs(), 10);")]
+        #[doc = concat!("assert_eq!((-10", stringify!($SelfT), ").abs(), 10);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[allow(unused_attributes)]
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        pub const fn abs(self) -> Self {
+            // Note that the #[inline] above means that the overflow
+            // semantics of the subtraction depend on the crate we're being
+            // inlined into.
+            if self.is_negative() {
+                -self
+            } else {
+                self
             }
         }
 
-        doc_comment! {
-            concat!("Calculates the quotient of Euclidean division of `self` by `rhs`.
-
-This computes the integer `n` such that `self = n * rhs + self.rem_euclid(rhs)`,
-with `0 <= self.rem_euclid(rhs) < rhs`.
-
-In other words, the result is `self / rhs` rounded to the integer `n`
-such that `self >= n * rhs`.
-If `self > 0`, this is equal to round towards zero (the default in Rust);
-if `self < 0`, this is equal to round towards +/- infinity.
-
-# Panics
-
-This function will panic if `rhs` is 0 or the division results in overflow.
-
-# Examples
-
-Basic usage:
-
-```
-let a: ", stringify!($SelfT), " = 7; // or any other integer type
-let b = 4;
-
-assert_eq!(a.div_euclid(b), 1); // 7 >= 4 * 1
-assert_eq!(a.div_euclid(-b), -1); // 7 >= -4 * -1
-assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2
-assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2
-```"),
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            #[rustc_inherit_overflow_checks]
-            pub const fn div_euclid(self, rhs: Self) -> Self {
-                let q = self / rhs;
-                if self % rhs < 0 {
-                    return if rhs > 0 { q - 1 } else { q + 1 }
-                }
-                q
+        /// Returns a number representing sign of `self`.
+        ///
+        ///  - `0` if the number is zero
+        ///  - `1` if the number is positive
+        ///  - `-1` if the number is negative
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".signum(), 1);")]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".signum(), 0);")]
+        #[doc = concat!("assert_eq!((-10", stringify!($SelfT), ").signum(), -1);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_sign", since = "1.47.0")]
+        #[inline]
+        pub const fn signum(self) -> Self {
+            match self {
+                n if n > 0 =>  1,
+                0          =>  0,
+                _          => -1,
             }
         }
 
+        /// Returns `true` if `self` is positive and `false` if the number is zero or
+        /// negative.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert!(10", stringify!($SelfT), ".is_positive());")]
+        #[doc = concat!("assert!(!(-10", stringify!($SelfT), ").is_positive());")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[inline]
+        pub const fn is_positive(self) -> bool { self > 0 }
 
-        doc_comment! {
-            concat!("Calculates the least nonnegative remainder of `self (mod rhs)`.
+        /// Returns `true` if `self` is negative and `false` if the number is zero or
+        /// positive.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert!((-10", stringify!($SelfT), ").is_negative());")]
+        #[doc = concat!("assert!(!10", stringify!($SelfT), ".is_negative());")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+        #[inline]
+        pub const fn is_negative(self) -> bool { self < 0 }
 
-This is done as if by the Euclidean division algorithm -- given
-`r = self.rem_euclid(rhs)`, `self = rhs * self.div_euclid(rhs) + r`, and
-`0 <= r < abs(rhs)`.
-
-# Panics
-
-This function will panic if `rhs` is 0 or the division results in overflow.
-
-# Examples
-
-Basic usage:
-
-```
-let a: ", stringify!($SelfT), " = 7; // or any other integer type
-let b = 4;
-
-assert_eq!(a.rem_euclid(b), 3);
-assert_eq!((-a).rem_euclid(b), 1);
-assert_eq!(a.rem_euclid(-b), 3);
-assert_eq!((-a).rem_euclid(-b), 1);
-```"),
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            #[rustc_inherit_overflow_checks]
-            pub const fn rem_euclid(self, rhs: Self) -> Self {
-                let r = self % rhs;
-                if r < 0 {
-                    if rhs < 0 {
-                        r - rhs
-                    } else {
-                        r + rhs
-                    }
-                } else {
-                    r
-                }
-            }
+        /// Return the memory representation of this integer as a byte array in
+        /// big-endian (network) byte order.
+        ///
+        #[doc = $to_xe_bytes_doc]
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes();")]
+        #[doc = concat!("assert_eq!(bytes, ", $be_bytes, ");")]
+        /// ```
+        #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
+        #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        #[inline]
+        pub const fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            self.to_be().to_ne_bytes()
         }
 
-        doc_comment! {
-            concat!("Computes the absolute value of `self`.
-
-# Overflow behavior
-
-The absolute value of `", stringify!($SelfT), "::MIN` cannot be represented as an
-`", stringify!($SelfT), "`, and attempting to calculate it will cause an overflow. This means that
-code in debug mode will trigger a panic on this case and optimized code will return `",
-stringify!($SelfT), "::MIN` without a panic.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(10", stringify!($SelfT), ".abs(), 10);
-assert_eq!((-10", stringify!($SelfT), ").abs(), 10);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[allow(unused_attributes)]
-            #[inline]
-            #[rustc_inherit_overflow_checks]
-            pub const fn abs(self) -> Self {
-                // Note that the #[inline] above means that the overflow
-                // semantics of the subtraction depend on the crate we're being
-                // inlined into.
-                if self.is_negative() {
-                    -self
-                } else {
-                    self
-                }
-            }
+        /// Return the memory representation of this integer as a byte array in
+        /// little-endian byte order.
+        ///
+        #[doc = $to_xe_bytes_doc]
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes();")]
+        #[doc = concat!("assert_eq!(bytes, ", $le_bytes, ");")]
+        /// ```
+        #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
+        #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        #[inline]
+        pub const fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            self.to_le().to_ne_bytes()
         }
 
-        doc_comment! {
-            concat!("Returns a number representing sign of `self`.
-
- - `0` if the number is zero
- - `1` if the number is positive
- - `-1` if the number is negative
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(10", stringify!($SelfT), ".signum(), 1);
-assert_eq!(0", stringify!($SelfT), ".signum(), 0);
-assert_eq!((-10", stringify!($SelfT), ").signum(), -1);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_sign", since = "1.47.0")]
-            #[inline]
-            pub const fn signum(self) -> Self {
-                match self {
-                    n if n > 0 =>  1,
-                    0          =>  0,
-                    _          => -1,
-                }
-            }
+        /// Return the memory representation of this integer as a byte array in
+        /// native byte order.
+        ///
+        /// As the target platform's native endianness is used, portable code
+        /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate,
+        /// instead.
+        ///
+        #[doc = $to_xe_bytes_doc]
+        ///
+        /// [`to_be_bytes`]: #method.to_be_bytes
+        /// [`to_le_bytes`]: #method.to_le_bytes
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes();")]
+        /// assert_eq!(
+        ///     bytes,
+        ///     if cfg!(target_endian = "big") {
+        #[doc = concat!("        ", $be_bytes)]
+        ///     } else {
+        #[doc = concat!("        ", $le_bytes)]
+        ///     }
+        /// );
+        /// ```
+        #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
+        #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        // SAFETY: const sound because integers are plain old datatypes so we can always
+        // transmute them to arrays of bytes
+        #[rustc_allow_const_fn_unstable(const_fn_transmute)]
+        #[inline]
+        pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            // SAFETY: integers are plain old datatypes so we can always transmute them to
+            // arrays of bytes
+            unsafe { mem::transmute(self) }
         }
 
-        doc_comment! {
-            concat!("Returns `true` if `self` is positive and `false` if the number is zero or
-negative.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert!(10", stringify!($SelfT), ".is_positive());
-assert!(!(-10", stringify!($SelfT), ").is_positive());",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[inline]
-            pub const fn is_positive(self) -> bool { self > 0 }
+        /// Return the memory representation of this integer as a byte array in
+        /// native byte order.
+        ///
+        /// [`to_ne_bytes`] should be preferred over this whenever possible.
+        ///
+        /// [`to_ne_bytes`]: #method.to_ne_bytes
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(num_as_ne_bytes)]
+        #[doc = concat!("let num = ", $swap_op, stringify!($SelfT), ";")]
+        /// let bytes = num.as_ne_bytes();
+        /// assert_eq!(
+        ///     bytes,
+        ///     if cfg!(target_endian = "big") {
+        #[doc = concat!("        &", $be_bytes)]
+        ///     } else {
+        #[doc = concat!("        &", $le_bytes)]
+        ///     }
+        /// );
+        /// ```
+        #[unstable(feature = "num_as_ne_bytes", issue = "76976")]
+        #[inline]
+        pub fn as_ne_bytes(&self) -> &[u8; mem::size_of::<Self>()] {
+            // SAFETY: integers are plain old datatypes so we can always transmute them to
+            // arrays of bytes
+            unsafe { &*(self as *const Self as *const _) }
         }
 
-        doc_comment! {
-            concat!("Returns `true` if `self` is negative and `false` if the number is zero or
-positive.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert!((-10", stringify!($SelfT), ").is_negative());
-assert!(!10", stringify!($SelfT), ".is_negative());",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
-            #[inline]
-            pub const fn is_negative(self) -> bool { self < 0 }
+        /// Create an integer value from its representation as a byte array in
+        /// big endian.
+        ///
+        #[doc = $to_xe_bytes_doc]
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, ");")]
+        #[doc = concat!("assert_eq!(value, ", $swap_op, ");")]
+        /// ```
+        ///
+        /// When starting from a slice rather than an array, fallible conversion APIs can be used:
+        ///
+        /// ```
+        /// use std::convert::TryInto;
+        ///
+        #[doc = concat!("fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")]
+        #[doc = concat!("    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")]
+        ///     *input = rest;
+        #[doc = concat!("    ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())")]
+        /// }
+        /// ```
+        #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
+        #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        #[inline]
+        pub const fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            Self::from_be(Self::from_ne_bytes(bytes))
         }
 
-        doc_comment! {
-            concat!("Return the memory representation of this integer as a byte array in
-big-endian (network) byte order.
-",
-$to_xe_bytes_doc,
-"
-# Examples
-
-```
-let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes();
-assert_eq!(bytes, ", $be_bytes, ");
-```"),
-            #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
-            #[inline]
-            pub const fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
-                self.to_be().to_ne_bytes()
-            }
+        /// Create an integer value from its representation as a byte array in
+        /// little endian.
+        ///
+        #[doc = $to_xe_bytes_doc]
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, ");")]
+        #[doc = concat!("assert_eq!(value, ", $swap_op, ");")]
+        /// ```
+        ///
+        /// When starting from a slice rather than an array, fallible conversion APIs can be used:
+        ///
+        /// ```
+        /// use std::convert::TryInto;
+        ///
+        #[doc = concat!("fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")]
+        #[doc = concat!("    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")]
+        ///     *input = rest;
+        #[doc = concat!("    ", stringify!($SelfT), "::from_le_bytes(int_bytes.try_into().unwrap())")]
+        /// }
+        /// ```
+        #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
+        #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        #[inline]
+        pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            Self::from_le(Self::from_ne_bytes(bytes))
         }
 
-doc_comment! {
-            concat!("Return the memory representation of this integer as a byte array in
-little-endian byte order.
-",
-$to_xe_bytes_doc,
-"
-# Examples
-
-```
-let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes();
-assert_eq!(bytes, ", $le_bytes, ");
-```"),
-            #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
-            #[inline]
-            pub const fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
-                self.to_le().to_ne_bytes()
-            }
+        /// Create an integer value from its memory representation as a byte
+        /// array in native endianness.
+        ///
+        /// As the target platform's native endianness is used, portable code
+        /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
+        /// appropriate instead.
+        ///
+        /// [`from_be_bytes`]: #method.from_be_bytes
+        /// [`from_le_bytes`]: #method.from_le_bytes
+        ///
+        #[doc = $to_xe_bytes_doc]
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") {")]
+        #[doc = concat!("    ", $be_bytes)]
+        /// } else {
+        #[doc = concat!("    ", $le_bytes)]
+        /// });
+        #[doc = concat!("assert_eq!(value, ", $swap_op, ");")]
+        /// ```
+        ///
+        /// When starting from a slice rather than an array, fallible conversion APIs can be used:
+        ///
+        /// ```
+        /// use std::convert::TryInto;
+        ///
+        #[doc = concat!("fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")]
+        #[doc = concat!("    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")]
+        ///     *input = rest;
+        #[doc = concat!("    ", stringify!($SelfT), "::from_ne_bytes(int_bytes.try_into().unwrap())")]
+        /// }
+        /// ```
+        #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
+        #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        // SAFETY: const sound because integers are plain old datatypes so we can always
+        // transmute to them
+        #[rustc_allow_const_fn_unstable(const_fn_transmute)]
+        #[inline]
+        pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            // SAFETY: integers are plain old datatypes so we can always transmute to them
+            unsafe { mem::transmute(bytes) }
         }
 
-        doc_comment! {
-            concat!("
-Return the memory representation of this integer as a byte array in
-native byte order.
-
-As the target platform's native endianness is used, portable code
-should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate,
-instead.
-",
-$to_xe_bytes_doc,
-"
-[`to_be_bytes`]: #method.to_be_bytes
-[`to_le_bytes`]: #method.to_le_bytes
-
-# Examples
-
-```
-let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes();
-assert_eq!(
-    bytes,
-    if cfg!(target_endian = \"big\") {
-        ", $be_bytes, "
-    } else {
-        ", $le_bytes, "
-    }
-);
-```"),
-            #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
-            // SAFETY: const sound because integers are plain old datatypes so we can always
-            // transmute them to arrays of bytes
-            #[rustc_allow_const_fn_unstable(const_fn_transmute)]
-            #[inline]
-            pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
-                // SAFETY: integers are plain old datatypes so we can always transmute them to
-                // arrays of bytes
-                unsafe { mem::transmute(self) }
-            }
+        /// **This method is soft-deprecated.**
+        ///
+        /// Although using it won’t cause a compilation warning, new code should use
+        #[doc = concat!("[`", stringify!($SelfT), "::MIN", "`](#associatedconstant.MIN)")]
+        /// instead.
+        ///
+        /// Returns the smallest value that can be represented by this integer type.
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[inline(always)]
+        #[rustc_promotable]
+        #[rustc_const_stable(feature = "const_min_value", since = "1.32.0")]
+        pub const fn min_value() -> Self {
+            Self::MIN
         }
 
-        doc_comment! {
-            concat!("
-Return the memory representation of this integer as a byte array in
-native byte order.
-
-[`to_ne_bytes`] should be preferred over this whenever possible.
-
-[`to_ne_bytes`]: #method.to_ne_bytes
-",
-
-"
-# Examples
-
-```
-#![feature(num_as_ne_bytes)]
-let num = ", $swap_op, stringify!($SelfT), ";
-let bytes = num.as_ne_bytes();
-assert_eq!(
-    bytes,
-    if cfg!(target_endian = \"big\") {
-        &", $be_bytes, "
-    } else {
-        &", $le_bytes, "
-    }
-);
-```"),
-            #[unstable(feature = "num_as_ne_bytes", issue = "76976")]
-            #[inline]
-            pub fn as_ne_bytes(&self) -> &[u8; mem::size_of::<Self>()] {
-                // SAFETY: integers are plain old datatypes so we can always transmute them to
-                // arrays of bytes
-                unsafe { &*(self as *const Self as *const _) }
-            }
-        }
-
-doc_comment! {
-            concat!("Create an integer value from its representation as a byte array in
-big endian.
-",
-$from_xe_bytes_doc,
-"
-# Examples
-
-```
-let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, ");
-assert_eq!(value, ", $swap_op, ");
-```
-
-When starting from a slice rather than an array, fallible conversion APIs can be used:
-
-```
-use std::convert::TryInto;
-
-fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
-    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
-    *input = rest;
-    ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())
-}
-```"),
-            #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
-            #[inline]
-            pub const fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
-                Self::from_be(Self::from_ne_bytes(bytes))
-            }
-        }
-
-doc_comment! {
-            concat!("
-Create an integer value from its representation as a byte array in
-little endian.
-",
-$from_xe_bytes_doc,
-"
-# Examples
-
-```
-let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, ");
-assert_eq!(value, ", $swap_op, ");
-```
-
-When starting from a slice rather than an array, fallible conversion APIs can be used:
-
-```
-use std::convert::TryInto;
-
-fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
-    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
-    *input = rest;
-    ", stringify!($SelfT), "::from_le_bytes(int_bytes.try_into().unwrap())
-}
-```"),
-            #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
-            #[inline]
-            pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
-                Self::from_le(Self::from_ne_bytes(bytes))
-            }
-        }
-
-        doc_comment! {
-            concat!("Create an integer value from its memory representation as a byte
-array in native endianness.
-
-As the target platform's native endianness is used, portable code
-likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
-appropriate instead.
-
-[`from_be_bytes`]: #method.from_be_bytes
-[`from_le_bytes`]: #method.from_le_bytes
-",
-$from_xe_bytes_doc,
-"
-# Examples
-
-```
-let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") {
-    ", $be_bytes, "
-} else {
-    ", $le_bytes, "
-});
-assert_eq!(value, ", $swap_op, ");
-```
-
-When starting from a slice rather than an array, fallible conversion APIs can be used:
-
-```
-use std::convert::TryInto;
-
-fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
-    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
-    *input = rest;
-    ", stringify!($SelfT), "::from_ne_bytes(int_bytes.try_into().unwrap())
-}
-```"),
-            #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
-            // SAFETY: const sound because integers are plain old datatypes so we can always
-            // transmute to them
-            #[rustc_allow_const_fn_unstable(const_fn_transmute)]
-            #[inline]
-            pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
-                // SAFETY: integers are plain old datatypes so we can always transmute to them
-                unsafe { mem::transmute(bytes) }
-            }
-        }
-
-        doc_comment! {
-            concat!("**This method is soft-deprecated.**
-
-Although using it won’t cause a compilation warning,
-new code should use [`", stringify!($SelfT), "::MIN", "`](#associatedconstant.MIN) instead.
-
-Returns the smallest value that can be represented by this integer type."),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[inline(always)]
-            #[rustc_promotable]
-            #[rustc_const_stable(feature = "const_min_value", since = "1.32.0")]
-            pub const fn min_value() -> Self {
-                Self::MIN
-            }
-        }
-
-        doc_comment! {
-            concat!("**This method is soft-deprecated.**
-
-Although using it won’t cause a compilation warning,
-new code should use [`", stringify!($SelfT), "::MAX", "`](#associatedconstant.MAX) instead.
-
-Returns the largest value that can be represented by this integer type."),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[inline(always)]
-            #[rustc_promotable]
-            #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")]
-            pub const fn max_value() -> Self {
-                Self::MAX
-            }
+        /// **This method is soft-deprecated.**
+        ///
+        /// Although using it won’t cause a compilation warning, new code should use
+        #[doc = concat!("[`", stringify!($SelfT), "::MAX", "`](#associatedconstant.MAX)")]
+        /// instead.
+        ///
+        /// Returns the largest value that can be represented by this integer type.
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[inline(always)]
+        #[rustc_promotable]
+        #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")]
+        pub const fn max_value() -> Self {
+            Self::MAX
         }
     }
 }
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 9f5ae57..6bdfa18 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -23,13 +23,6 @@
     };
 }
 
-macro_rules! doc_comment {
-    ($x:expr, $($tt:tt)*) => {
-        #[doc = $x]
-        $($tt)*
-    };
-}
-
 // All these modules are technically private and only exposed for coretests:
 pub mod bignum;
 pub mod dec2flt;
@@ -95,26 +88,26 @@
 
 #[lang = "i8"]
 impl i8 {
-    int_impl! { i8, i8, u8, 8, -128, 127, "", "", 2, "-0x7e", "0xa", "0x12", "0x12", "0x48",
+    int_impl! { i8, i8, u8, 8, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48",
     "[0x12]", "[0x12]", "", "" }
 }
 
 #[lang = "i16"]
 impl i16 {
-    int_impl! { i16, i16, u16, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234", "0x3412",
+    int_impl! { i16, i16, u16, 16, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412",
     "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
 }
 
 #[lang = "i32"]
 impl i32 {
-    int_impl! { i32, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301",
+    int_impl! { i32, i32, u32, 32, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
     "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
     "[0x12, 0x34, 0x56, 0x78]", "", "" }
 }
 
 #[lang = "i64"]
 impl i64 {
-    int_impl! { i64, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "", 12,
+    int_impl! { i64, i64, u64, 64, -9223372036854775808, 9223372036854775807, 12,
     "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
     "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
     "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" }
@@ -123,7 +116,7 @@
 #[lang = "i128"]
 impl i128 {
     int_impl! { i128, i128, u128, 128, -170141183460469231731687303715884105728,
-    170141183460469231731687303715884105727, "", "", 16,
+    170141183460469231731687303715884105727, 16,
     "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
     "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48",
     "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
@@ -135,7 +128,7 @@
 #[cfg(target_pointer_width = "16")]
 #[lang = "isize"]
 impl isize {
-    int_impl! { isize, i16, usize, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234",
+    int_impl! { isize, i16, usize, 16, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234",
     "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
 }
@@ -143,7 +136,7 @@
 #[cfg(target_pointer_width = "32")]
 #[lang = "isize"]
 impl isize {
-    int_impl! { isize, i32, usize, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301",
+    int_impl! { isize, i32, usize, 32, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
     "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
     "[0x12, 0x34, 0x56, 0x78]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
@@ -152,7 +145,7 @@
 #[cfg(target_pointer_width = "64")]
 #[lang = "isize"]
 impl isize {
-    int_impl! { isize, i64, usize, 64, -9223372036854775808, 9223372036854775807, "", "",
+    int_impl! { isize, i64, usize, 64, -9223372036854775808, 9223372036854775807,
     12, "0xaa00000000006e1", "0x6e10aa",  "0x1234567890123456", "0x5634129078563412",
      "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
      "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
@@ -161,7 +154,7 @@
 
 #[lang = "u8"]
 impl u8 {
-    uint_impl! { u8, u8, 8, 255, "", "", 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
+    uint_impl! { u8, u8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
     "[0x12]", "", "" }
 
     /// Checks if the value is within the ASCII range.
@@ -660,19 +653,19 @@
 
 #[lang = "u16"]
 impl u16 {
-    uint_impl! { u16, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
+    uint_impl! { u16, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
     "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
 }
 
 #[lang = "u32"]
 impl u32 {
-    uint_impl! { u32, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678",
+    uint_impl! { u32, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
     "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
 }
 
 #[lang = "u64"]
 impl u64 {
-    uint_impl! { u64, u64, 64, 18446744073709551615, "", "", 12, "0xaa00000000006e1", "0x6e10aa",
+    uint_impl! { u64, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
     "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
     "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
     "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
@@ -681,7 +674,7 @@
 
 #[lang = "u128"]
 impl u128 {
-    uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, "", "", 16,
+    uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, 16,
     "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
     "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48",
     "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
@@ -694,14 +687,14 @@
 #[cfg(target_pointer_width = "16")]
 #[lang = "usize"]
 impl usize {
-    uint_impl! { usize, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
+    uint_impl! { usize, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
     "[0x34, 0x12]", "[0x12, 0x34]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
 }
 #[cfg(target_pointer_width = "32")]
 #[lang = "usize"]
 impl usize {
-    uint_impl! { usize, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678",
+    uint_impl! { usize, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
     "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
 }
@@ -709,7 +702,7 @@
 #[cfg(target_pointer_width = "64")]
 #[lang = "usize"]
 impl usize {
-    uint_impl! { usize, u64, 64, 18446744073709551615, "", "", 12, "0xaa00000000006e1", "0x6e10aa",
+    uint_impl! { usize, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
     "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
     "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
      "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 5eb7002..111feb7 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -8,13 +8,6 @@
 use super::{IntErrorKind, ParseIntError};
 use crate::intrinsics;
 
-macro_rules! doc_comment {
-    ($x:expr, $($tt:tt)*) => {
-        #[doc = $x]
-        $($tt)*
-    };
-}
-
 macro_rules! impl_nonzero_fmt {
     ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
         $(
@@ -32,24 +25,21 @@
 macro_rules! nonzero_integers {
     ( $( #[$stability: meta] $Ty: ident($Int: ty); )+ ) => {
         $(
-            doc_comment! {
-                concat!("An integer that is known not to equal zero.
-
-This enables some memory layout optimization.
-For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:
-
-```rust
-use std::mem::size_of;
-assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int),
-">());
-```"),
-                #[$stability]
-                #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
-                #[repr(transparent)]
-                #[rustc_layout_scalar_valid_range_start(1)]
-                #[rustc_nonnull_optimization_guaranteed]
-                pub struct $Ty($Int);
-            }
+            /// An integer that is known not to equal zero.
+            ///
+            /// This enables some memory layout optimization.
+            #[doc = concat!("For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:")]
+            ///
+            /// ```rust
+            /// use std::mem::size_of;
+            #[doc = concat!("assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int), ">());")]
+            /// ```
+            #[$stability]
+            #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+            #[repr(transparent)]
+            #[rustc_layout_scalar_valid_range_start(1)]
+            #[rustc_nonnull_optimization_guaranteed]
+            pub struct $Ty($Int);
 
             impl $Ty {
                 /// Creates a non-zero without checking the value.
@@ -90,13 +80,10 @@
 
             #[stable(feature = "from_nonzero", since = "1.31.0")]
             impl From<$Ty> for $Int {
-                doc_comment! {
-                    concat!(
-"Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`"),
-                    #[inline]
-                    fn from(nonzero: $Ty) -> Self {
-                        nonzero.0
-                    }
+                #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")]
+                #[inline]
+                fn from(nonzero: $Ty) -> Self {
+                    nonzero.0
                 }
             }
 
@@ -195,53 +182,49 @@
     ( $( $Ty: ident($Uint: ty) , $LeadingTestExpr:expr ;)+ ) => {
         $(
             impl $Ty {
-                doc_comment! {
-                    concat!("Returns the number of leading zeros in the binary representation of `self`.
-
-On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(nonzero_leading_trailing_zeros)]
-let n = std::num::", stringify!($Ty), "::new(", stringify!($LeadingTestExpr), ").unwrap();
-
-assert_eq!(n.leading_zeros(), 0);
-```"),
-                    #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
-                    #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
-                    #[inline]
-                    pub const fn leading_zeros(self) -> u32 {
-                        // SAFETY: since `self` can not be zero it is safe to call ctlz_nonzero
-                        unsafe { intrinsics::ctlz_nonzero(self.0 as $Uint) as u32 }
-                    }
+                /// Returns the number of leading zeros in the binary representation of `self`.
+                ///
+                /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided.
+                ///
+                /// # Examples
+                ///
+                /// Basic usage:
+                ///
+                /// ```
+                /// #![feature(nonzero_leading_trailing_zeros)]
+                #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($LeadingTestExpr), ").unwrap();")]
+                ///
+                /// assert_eq!(n.leading_zeros(), 0);
+                /// ```
+                #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
+                #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
+                #[inline]
+                pub const fn leading_zeros(self) -> u32 {
+                    // SAFETY: since `self` can not be zero it is safe to call ctlz_nonzero
+                    unsafe { intrinsics::ctlz_nonzero(self.0 as $Uint) as u32 }
                 }
 
-                doc_comment! {
-                    concat!("Returns the number of trailing zeros in the binary representation
-of `self`.
-
-On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(nonzero_leading_trailing_zeros)]
-let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();
-
-assert_eq!(n.trailing_zeros(), 3);
-```"),
-                    #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
-                    #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
-                    #[inline]
-                    pub const fn trailing_zeros(self) -> u32 {
-                        // SAFETY: since `self` can not be zero it is safe to call cttz_nonzero
-                        unsafe { intrinsics::cttz_nonzero(self.0 as $Uint) as u32 }
-                    }
+                /// Returns the number of trailing zeros in the binary representation
+                /// of `self`.
+                ///
+                /// On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided.
+                ///
+                /// # Examples
+                ///
+                /// Basic usage:
+                ///
+                /// ```
+                /// #![feature(nonzero_leading_trailing_zeros)]
+                #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")]
+                ///
+                /// assert_eq!(n.trailing_zeros(), 3);
+                /// ```
+                #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
+                #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
+                #[inline]
+                pub const fn trailing_zeros(self) -> u32 {
+                    // SAFETY: since `self` can not be zero it is safe to call cttz_nonzero
+                    unsafe { intrinsics::cttz_nonzero(self.0 as $Uint) as u32 }
                 }
 
             }
@@ -303,3 +286,43 @@
     NonZeroU128(u128);
     NonZeroUsize(usize);
 }
+
+macro_rules! nonzero_unsigned_is_power_of_two {
+    ( $( $Ty: ident )+ ) => {
+        $(
+            impl $Ty {
+
+                /// Returns `true` if and only if `self == (1 << k)` for some `k`.
+                ///
+                /// On many architectures, this function can perform better than `is_power_of_two()`
+                /// on the underlying integer type, as special handling of zero can be avoided.
+                ///
+                /// # Examples
+                ///
+                /// Basic usage:
+                ///
+                /// ```
+                /// #![feature(nonzero_is_power_of_two)]
+                ///
+                #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")]
+                /// assert!(eight.is_power_of_two());
+                #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")]
+                /// assert!(!ten.is_power_of_two());
+                /// ```
+                #[unstable(feature = "nonzero_is_power_of_two", issue = "81106")]
+                #[inline]
+                pub const fn is_power_of_two(self) -> bool {
+                    // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here.
+                    // On the basic x86-64 target, this saves 3 instructions for the zero check.
+                    // On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction
+                    // compared to the `POPCNT` implementation on the underlying integer type.
+
+                    intrinsics::ctpop(self.get()) < 2
+                }
+
+            }
+        )+
+    }
+}
+
+nonzero_unsigned_is_power_of_two! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize }
diff --git a/library/core/src/num/shells/int_macros.rs b/library/core/src/num/shells/int_macros.rs
index ffd30b0..5f8bb64 100644
--- a/library/core/src/num/shells/int_macros.rs
+++ b/library/core/src/num/shells/int_macros.rs
@@ -1,49 +1,44 @@
 #![doc(hidden)]
 
-macro_rules! doc_comment {
-    ($x:expr, $($tt:tt)*) => {
-        #[doc = $x]
-        $($tt)*
-    };
-}
-
 macro_rules! int_module {
     ($T:ident) => (int_module!($T, #[stable(feature = "rust1", since = "1.0.0")]););
     ($T:ident, #[$attr:meta]) => (
-        doc_comment! {
-            concat!("The smallest value that can be represented by this integer type.
-Use [`", stringify!($T), "::MIN", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MIN) instead.
+        #[doc = concat!(
+            "The smallest value that can be represented by this integer type. Use ",
+            "[`", stringify!($T), "::MIN", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MIN)",
+            " instead.",
+        )]
+        ///
+        /// # Examples
+        ///
+        /// ```rust
+        /// // deprecated way
+        #[doc = concat!("let min = std::", stringify!($T), "::MIN;")]
+        ///
+        /// // intended way
+        #[doc = concat!("let min = ", stringify!($T), "::MIN;")]
+        /// ```
+        ///
+        #[$attr]
+        pub const MIN: $T = $T::MIN;
 
-# Examples
-
-```rust
-// deprecated way
-let min = std::", stringify!($T), "::MIN;
-
-// intended way
-let min = ", stringify!($T), "::MIN;
-```
-"),
-            #[$attr]
-            pub const MIN: $T = $T::MIN;
-        }
-
-        doc_comment! {
-            concat!("The largest value that can be represented by this integer type.
-Use [`", stringify!($T), "::MAX", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MAX) instead.
-
-# Examples
-
-```rust
-// deprecated way
-let max = std::", stringify!($T), "::MAX;
-
-// intended way
-let max = ", stringify!($T), "::MAX;
-```
-"),
-            #[$attr]
-            pub const MAX: $T = $T::MAX;
-        }
+        #[doc = concat!(
+            "The largest value that can be represented by this integer type. Use ",
+            "[`", stringify!($T), "::MAX", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MAX)",
+            " instead.",
+        )]
+        ///
+        /// # Examples
+        ///
+        /// ```rust
+        /// // deprecated way
+        #[doc = concat!("let max = std::", stringify!($T), "::MAX;")]
+        ///
+        /// // intended way
+        #[doc = concat!("let max = ", stringify!($T), "::MAX;")]
+        /// ```
+        ///
+        #[$attr]
+        pub const MAX: $T = $T::MAX;
     )
 }
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index ae8fc18..8f141a3f 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1,928 +1,842 @@
 macro_rules! uint_impl {
-    ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr,
+    ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr,
         $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
         $reversed:expr, $le_bytes:expr, $be_bytes:expr,
         $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => {
-        doc_comment! {
-            concat!("The smallest value that can be represented by this integer type.
+        /// The smallest value that can be represented by this integer type.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN, 0);")]
+        /// ```
+        #[stable(feature = "assoc_int_consts", since = "1.43.0")]
+        pub const MIN: Self = 0;
 
-# Examples
+        /// The largest value that can be represented by this integer type.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($MaxV), ");")]
+        /// ```
+        #[stable(feature = "assoc_int_consts", since = "1.43.0")]
+        pub const MAX: Self = !0;
 
-Basic usage:
+        /// The size of this integer type in bits.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_bits_const)]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
+        /// ```
+        #[unstable(feature = "int_bits_const", issue = "76904")]
+        pub const BITS: u32 = $BITS;
 
-```
-", $Feature, "assert_eq!(", stringify!($SelfT), "::MIN, 0);", $EndFeature, "
-```"),
-            #[stable(feature = "assoc_int_consts", since = "1.43.0")]
-            pub const MIN: Self = 0;
+        /// Converts a string slice in a given base to an integer.
+        ///
+        /// The string is expected to be an optional `+` sign
+        /// followed by digits.
+        /// Leading and trailing whitespace represent an error.
+        /// Digits are a subset of these characters, depending on `radix`:
+        ///
+        /// * `0-9`
+        /// * `a-z`
+        /// * `A-Z`
+        ///
+        /// # Panics
+        ///
+        /// This function panics if `radix` is not in the range from 2 to 36.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_str_radix(\"A\", 16), Ok(10));")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
+            from_str_radix(src, radix)
         }
 
-        doc_comment! {
-            concat!("The largest value that can be represented by this integer type.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($MaxV), ");",
-$EndFeature, "
-```"),
-            #[stable(feature = "assoc_int_consts", since = "1.43.0")]
-            pub const MAX: Self = !0;
+        /// Returns the number of ones in the binary representation of `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = 0b01001100", stringify!($SelfT), ";")]
+        ///
+        /// assert_eq!(n.count_ones(), 3);
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
+        #[doc(alias = "popcount")]
+        #[doc(alias = "popcnt")]
+        #[inline]
+        pub const fn count_ones(self) -> u32 {
+            intrinsics::ctpop(self as $ActualT) as u32
         }
 
-        doc_comment! {
-            concat!("The size of this integer type in bits.
-
-# Examples
-
-```
-", $Feature, "#![feature(int_bits_const)]
-assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");",
-$EndFeature, "
-```"),
-            #[unstable(feature = "int_bits_const", issue = "76904")]
-            pub const BITS: u32 = $BITS;
+        /// Returns the number of zeros in the binary representation of `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.count_zeros(), 0);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
+        #[inline]
+        pub const fn count_zeros(self) -> u32 {
+            (!self).count_ones()
         }
 
-        doc_comment! {
-            concat!("Converts a string slice in a given base to an integer.
+        /// Returns the number of leading zeros in the binary representation of `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = ", stringify!($SelfT), "::MAX >> 2;")]
+        ///
+        /// assert_eq!(n.leading_zeros(), 2);
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
+        #[inline]
+        pub const fn leading_zeros(self) -> u32 {
+            intrinsics::ctlz(self as $ActualT) as u32
+        }
 
-The string is expected to be an optional `+` sign
-followed by digits.
-Leading and trailing whitespace represent an error.
-Digits are a subset of these characters, depending on `radix`:
+        /// Returns the number of trailing zeros in the binary representation
+        /// of `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = 0b0101000", stringify!($SelfT), ";")]
+        ///
+        /// assert_eq!(n.trailing_zeros(), 3);
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
+        #[inline]
+        pub const fn trailing_zeros(self) -> u32 {
+            intrinsics::cttz(self) as u32
+        }
 
-* `0-9`
-* `a-z`
-* `A-Z`
+        /// Returns the number of leading ones in the binary representation of `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = !(", stringify!($SelfT), "::MAX >> 2);")]
+        ///
+        /// assert_eq!(n.leading_ones(), 2);
+        /// ```
+        #[stable(feature = "leading_trailing_ones", since = "1.46.0")]
+        #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")]
+        #[inline]
+        pub const fn leading_ones(self) -> u32 {
+            (!self).leading_zeros()
+        }
 
-# Panics
+        /// Returns the number of trailing ones in the binary representation
+        /// of `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = 0b1010111", stringify!($SelfT), ";")]
+        ///
+        /// assert_eq!(n.trailing_ones(), 3);
+        /// ```
+        #[stable(feature = "leading_trailing_ones", since = "1.46.0")]
+        #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")]
+        #[inline]
+        pub const fn trailing_ones(self) -> u32 {
+            (!self).trailing_zeros()
+        }
 
-This function panics if `radix` is not in the range from 2 to 36.
+        /// Shifts the bits to the left by a specified amount, `n`,
+        /// wrapping the truncated bits to the end of the resulting integer.
+        ///
+        /// Please note this isn't the same operation as the `<<` shifting operator!
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = ", $rot_op, stringify!($SelfT), ";")]
+        #[doc = concat!("let m = ", $rot_result, ";")]
+        ///
+        #[doc = concat!("assert_eq!(n.rotate_left(", $rot, "), m);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn rotate_left(self, n: u32) -> Self {
+            intrinsics::rotate_left(self, n as $SelfT)
+        }
 
-# Examples
+        /// Shifts the bits to the right by a specified amount, `n`,
+        /// wrapping the truncated bits to the beginning of the resulting
+        /// integer.
+        ///
+        /// Please note this isn't the same operation as the `>>` shifting operator!
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = ", $rot_result, stringify!($SelfT), ";")]
+        #[doc = concat!("let m = ", $rot_op, ";")]
+        ///
+        #[doc = concat!("assert_eq!(n.rotate_right(", $rot, "), m);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn rotate_right(self, n: u32) -> Self {
+            intrinsics::rotate_right(self, n as $SelfT)
+        }
 
-Basic usage:
+        /// Reverses the byte order of the integer.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = ", $swap_op, stringify!($SelfT), ";")]
+        /// let m = n.swap_bytes();
+        ///
+        #[doc = concat!("assert_eq!(m, ", $swapped, ");")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
+        #[inline]
+        pub const fn swap_bytes(self) -> Self {
+            intrinsics::bswap(self as $ActualT) as Self
+        }
 
-```
-", $Feature, "assert_eq!(", stringify!($SelfT), "::from_str_radix(\"A\", 16), Ok(10));",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
-                from_str_radix(src, radix)
+        /// Reverses the order of bits in the integer. The least significant bit becomes the most significant bit,
+        ///                 second least-significant bit becomes second most-significant bit, etc.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = ", $swap_op, stringify!($SelfT), ";")]
+        /// let m = n.reverse_bits();
+        ///
+        #[doc = concat!("assert_eq!(m, ", $reversed, ");")]
+        #[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")]
+        /// ```
+        #[stable(feature = "reverse_bits", since = "1.37.0")]
+        #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
+        #[inline]
+        #[must_use]
+        pub const fn reverse_bits(self) -> Self {
+            intrinsics::bitreverse(self as $ActualT) as Self
+        }
+
+        /// Converts an integer from big endian to the target's endianness.
+        ///
+        /// On big endian this is a no-op. On little endian the bytes are
+        /// swapped.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")]
+        ///
+        /// if cfg!(target_endian = "big") {
+        #[doc = concat!("    assert_eq!(", stringify!($SelfT), "::from_be(n), n)")]
+        /// } else {
+        #[doc = concat!("    assert_eq!(", stringify!($SelfT), "::from_be(n), n.swap_bytes())")]
+        /// }
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
+        #[inline]
+        pub const fn from_be(x: Self) -> Self {
+            #[cfg(target_endian = "big")]
+            {
+                x
+            }
+            #[cfg(not(target_endian = "big"))]
+            {
+                x.swap_bytes()
             }
         }
 
-        doc_comment! {
-            concat!("Returns the number of ones in the binary representation of `self`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = 0b01001100", stringify!($SelfT), ";
-
-assert_eq!(n.count_ones(), 3);", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
-            #[doc(alias = "popcount")]
-            #[doc(alias = "popcnt")]
-            #[inline]
-            pub const fn count_ones(self) -> u32 {
-                intrinsics::ctpop(self as $ActualT) as u32
+        /// Converts an integer from little endian to the target's endianness.
+        ///
+        /// On little endian this is a no-op. On big endian the bytes are
+        /// swapped.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")]
+        ///
+        /// if cfg!(target_endian = "little") {
+        #[doc = concat!("    assert_eq!(", stringify!($SelfT), "::from_le(n), n)")]
+        /// } else {
+        #[doc = concat!("    assert_eq!(", stringify!($SelfT), "::from_le(n), n.swap_bytes())")]
+        /// }
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
+        #[inline]
+        pub const fn from_le(x: Self) -> Self {
+            #[cfg(target_endian = "little")]
+            {
+                x
+            }
+            #[cfg(not(target_endian = "little"))]
+            {
+                x.swap_bytes()
             }
         }
 
-        doc_comment! {
-            concat!("Returns the number of zeros in the binary representation of `self`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX.count_zeros(), 0);", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
-            #[inline]
-            pub const fn count_zeros(self) -> u32 {
-                (!self).count_ones()
+        /// Converts `self` to big endian from the target's endianness.
+        ///
+        /// On big endian this is a no-op. On little endian the bytes are
+        /// swapped.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")]
+        ///
+        /// if cfg!(target_endian = "big") {
+        ///     assert_eq!(n.to_be(), n)
+        /// } else {
+        ///     assert_eq!(n.to_be(), n.swap_bytes())
+        /// }
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
+        #[inline]
+        pub const fn to_be(self) -> Self { // or not to be?
+            #[cfg(target_endian = "big")]
+            {
+                self
+            }
+            #[cfg(not(target_endian = "big"))]
+            {
+                self.swap_bytes()
             }
         }
 
-        doc_comment! {
-            concat!("Returns the number of leading zeros in the binary representation of `self`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = ", stringify!($SelfT), "::MAX >> 2;
-
-assert_eq!(n.leading_zeros(), 2);", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
-            #[inline]
-            pub const fn leading_zeros(self) -> u32 {
-                intrinsics::ctlz(self as $ActualT) as u32
+        /// Converts `self` to little endian from the target's endianness.
+        ///
+        /// On little endian this is a no-op. On big endian the bytes are
+        /// swapped.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")]
+        ///
+        /// if cfg!(target_endian = "little") {
+        ///     assert_eq!(n.to_le(), n)
+        /// } else {
+        ///     assert_eq!(n.to_le(), n.swap_bytes())
+        /// }
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
+        #[inline]
+        pub const fn to_le(self) -> Self {
+            #[cfg(target_endian = "little")]
+            {
+                self
+            }
+            #[cfg(not(target_endian = "little"))]
+            {
+                self.swap_bytes()
             }
         }
 
-        doc_comment! {
-            concat!("Returns the number of trailing zeros in the binary representation
-of `self`.
+        /// Checked integer addition. Computes `self + rhs`, returning `None`
+        /// if overflow occurred.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!(
+            "assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(1), ",
+            "Some(", stringify!($SelfT), "::MAX - 1));"
+        )]
+        #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_add(self, rhs: Self) -> Option<Self> {
+            let (a, b) = self.overflowing_add(rhs);
+            if unlikely!(b) {None} else {Some(a)}
+        }
 
-# Examples
+        /// Unchecked integer addition. Computes `self + rhs`, assuming overflow
+        /// cannot occur. This results in undefined behavior when
+        #[doc = concat!("`self + rhs > ", stringify!($SelfT), "::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`.")]
+        #[unstable(
+            feature = "unchecked_math",
+            reason = "niche optimization path",
+            issue = "none",
+        )]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub unsafe fn unchecked_add(self, rhs: Self) -> Self {
+            // SAFETY: the caller must uphold the safety contract for
+            // `unchecked_add`.
+            unsafe { intrinsics::unchecked_add(self, rhs) }
+        }
 
-Basic usage:
+        /// Checked integer subtraction. Computes `self - rhs`, returning
+        /// `None` if overflow occurred.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub(1), Some(0));")]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".checked_sub(1), None);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
+            let (a, b) = self.overflowing_sub(rhs);
+            if unlikely!(b) {None} else {Some(a)}
+        }
 
-```
-", $Feature, "let n = 0b0101000", stringify!($SelfT), ";
+        /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
+        /// cannot occur. This results in undefined behavior when
+        #[doc = concat!("`self - rhs > ", stringify!($SelfT), "::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`.")]
+        #[unstable(
+            feature = "unchecked_math",
+            reason = "niche optimization path",
+            issue = "none",
+        )]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub unsafe fn unchecked_sub(self, rhs: Self) -> Self {
+            // SAFETY: the caller must uphold the safety contract for
+            // `unchecked_sub`.
+            unsafe { intrinsics::unchecked_sub(self, rhs) }
+        }
 
-assert_eq!(n.trailing_zeros(), 3);", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
-            #[inline]
-            pub const fn trailing_zeros(self) -> u32 {
-                intrinsics::cttz(self) as u32
+        /// Checked integer multiplication. Computes `self * rhs`, returning
+        /// `None` if overflow occurred.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_mul(1), Some(5));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
+            let (a, b) = self.overflowing_mul(rhs);
+            if unlikely!(b) {None} else {Some(a)}
+        }
+
+        /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
+        /// cannot occur. This results in undefined behavior when
+        #[doc = concat!("`self * rhs > ", stringify!($SelfT), "::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`.")]
+        #[unstable(
+            feature = "unchecked_math",
+            reason = "niche optimization path",
+            issue = "none",
+        )]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub unsafe fn unchecked_mul(self, rhs: Self) -> Self {
+            // SAFETY: the caller must uphold the safety contract for
+            // `unchecked_mul`.
+            unsafe { intrinsics::unchecked_mul(self, rhs) }
+        }
+
+        /// Checked integer division. Computes `self / rhs`, returning `None`
+        /// if `rhs == 0`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(128", stringify!($SelfT), ".checked_div(2), Some(64));")]
+        #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_div(self, rhs: Self) -> Option<Self> {
+            if unlikely!(rhs == 0) {
+                None
+            } else {
+                // SAFETY: div by zero has been checked above and unsigned types have no other
+                // failure modes for division
+                Some(unsafe { intrinsics::unchecked_div(self, rhs) })
             }
         }
 
-        doc_comment! {
-            concat!("Returns the number of leading ones in the binary representation of `self`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = !(", stringify!($SelfT), "::MAX >> 2);
-
-assert_eq!(n.leading_ones(), 2);", $EndFeature, "
-```"),
-            #[stable(feature = "leading_trailing_ones", since = "1.46.0")]
-            #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")]
-            #[inline]
-            pub const fn leading_ones(self) -> u32 {
-                (!self).leading_zeros()
+        /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None`
+        /// if `rhs == 0`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(128", stringify!($SelfT), ".checked_div_euclid(2), Some(64));")]
+        #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None);")]
+        /// ```
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
+            if unlikely!(rhs == 0) {
+                None
+            } else {
+                Some(self.div_euclid(rhs))
             }
         }
 
-        doc_comment! {
-            concat!("Returns the number of trailing ones in the binary representation
-of `self`.
 
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = 0b1010111", stringify!($SelfT), ";
-
-assert_eq!(n.trailing_ones(), 3);", $EndFeature, "
-```"),
-            #[stable(feature = "leading_trailing_ones", since = "1.46.0")]
-            #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")]
-            #[inline]
-            pub const fn trailing_ones(self) -> u32 {
-                (!self).trailing_zeros()
+        /// Checked integer remainder. Computes `self % rhs`, returning `None`
+        /// if `rhs == 0`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(2), Some(1));")]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
+            if unlikely!(rhs == 0) {
+                None
+            } else {
+                // SAFETY: div by zero has been checked above and unsigned types have no other
+                // failure modes for division
+                Some(unsafe { intrinsics::unchecked_rem(self, rhs) })
             }
         }
 
-        doc_comment! {
-            concat!("Shifts the bits to the left by a specified amount, `n`,
-wrapping the truncated bits to the end of the resulting integer.
-
-Please note this isn't the same operation as the `<<` shifting operator!
-
-# Examples
-
-Basic usage:
-
-```
-let n = ", $rot_op, stringify!($SelfT), ";
-let m = ", $rot_result, ";
-
-assert_eq!(n.rotate_left(", $rot, "), m);
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn rotate_left(self, n: u32) -> Self {
-                intrinsics::rotate_left(self, n as $SelfT)
+        /// Checked Euclidean modulo. Computes `self.rem_euclid(rhs)`, returning `None`
+        /// if `rhs == 0`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));")]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);")]
+        /// ```
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
+            if unlikely!(rhs == 0) {
+                None
+            } else {
+                Some(self.rem_euclid(rhs))
             }
         }
 
-        doc_comment! {
-            concat!("Shifts the bits to the right by a specified amount, `n`,
-wrapping the truncated bits to the beginning of the resulting
-integer.
-
-Please note this isn't the same operation as the `>>` shifting operator!
-
-# Examples
-
-Basic usage:
-
-```
-let n = ", $rot_result, stringify!($SelfT), ";
-let m = ", $rot_op, ";
-
-assert_eq!(n.rotate_right(", $rot, "), m);
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn rotate_right(self, n: u32) -> Self {
-                intrinsics::rotate_right(self, n as $SelfT)
-            }
+        /// Checked negation. Computes `-self`, returning `None` unless `self ==
+        /// 0`.
+        ///
+        /// Note that negating any positive integer will overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".checked_neg(), Some(0));")]
+        #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_neg(), None);")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
+        #[inline]
+        pub const fn checked_neg(self) -> Option<Self> {
+            let (a, b) = self.overflowing_neg();
+            if unlikely!(b) {None} else {Some(a)}
         }
 
-        doc_comment! {
-            concat!("
-Reverses the byte order of the integer.
-
-# Examples
-
-Basic usage:
-
-```
-let n = ", $swap_op, stringify!($SelfT), ";
-let m = n.swap_bytes();
-
-assert_eq!(m, ", $swapped, ");
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
-            #[inline]
-            pub const fn swap_bytes(self) -> Self {
-                intrinsics::bswap(self as $ActualT) as Self
-            }
+        /// Checked shift left. Computes `self << rhs`, returning `None`
+        /// if `rhs` is larger than or equal to the number of bits in `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".checked_shl(4), Some(0x10));")]
+        #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shl(129), None);")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
+            let (a, b) = self.overflowing_shl(rhs);
+            if unlikely!(b) {None} else {Some(a)}
         }
 
-        doc_comment! {
-            concat!("Reverses the order of bits in the integer. The least significant bit becomes the most significant bit,
-                second least-significant bit becomes second most-significant bit, etc.
-
-# Examples
-
-Basic usage:
-
-```
-let n = ", $swap_op, stringify!($SelfT), ";
-let m = n.reverse_bits();
-
-assert_eq!(m, ", $reversed, ");
-assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());
-```"),
-            #[stable(feature = "reverse_bits", since = "1.37.0")]
-            #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
-            #[inline]
-            #[must_use]
-            pub const fn reverse_bits(self) -> Self {
-                intrinsics::bitreverse(self as $ActualT) as Self
-            }
+        /// Checked shift right. Computes `self >> rhs`, returning `None`
+        /// if `rhs` is larger than or equal to the number of bits in `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shr(4), Some(0x1));")]
+        #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shr(129), None);")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
+            let (a, b) = self.overflowing_shr(rhs);
+            if unlikely!(b) {None} else {Some(a)}
         }
 
-        doc_comment! {
-            concat!("Converts an integer from big endian to the target's endianness.
+        /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if
+        /// overflow occurred.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_pow(5), Some(32));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);")]
+        /// ```
+        #[stable(feature = "no_panic_pow", since = "1.34.0")]
+        #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
+            if exp == 0 {
+                return Some(1);
+            }
+            let mut base = self;
+            let mut acc: Self = 1;
 
-On big endian this is a no-op. On little endian the bytes are
-swapped.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = 0x1A", stringify!($SelfT), ";
-
-if cfg!(target_endian = \"big\") {
-    assert_eq!(", stringify!($SelfT), "::from_be(n), n)
-} else {
-    assert_eq!(", stringify!($SelfT), "::from_be(n), n.swap_bytes())
-}", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
-            #[inline]
-            pub const fn from_be(x: Self) -> Self {
-                #[cfg(target_endian = "big")]
-                {
-                    x
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    acc = try_opt!(acc.checked_mul(base));
                 }
-                #[cfg(not(target_endian = "big"))]
-                {
-                    x.swap_bytes()
-                }
+                exp /= 2;
+                base = try_opt!(base.checked_mul(base));
+            }
+
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
+
+            Some(try_opt!(acc.checked_mul(base)))
+        }
+
+        /// Saturating integer addition. Computes `self + rhs`, saturating at
+        /// the numeric bounds instead of overflowing.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_add(127), ", stringify!($SelfT), "::MAX);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
+        #[inline]
+        pub const fn saturating_add(self, rhs: Self) -> Self {
+            intrinsics::saturating_add(self, rhs)
+        }
+
+        /// Saturating integer subtraction. Computes `self - rhs`, saturating
+        /// at the numeric bounds instead of overflowing.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_sub(27), 73);")]
+        #[doc = concat!("assert_eq!(13", stringify!($SelfT), ".saturating_sub(127), 0);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
+        #[inline]
+        pub const fn saturating_sub(self, rhs: Self) -> Self {
+            intrinsics::saturating_sub(self, rhs)
+        }
+
+        /// Saturating integer multiplication. Computes `self * rhs`,
+        /// saturating at the numeric bounds instead of overflowing.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".saturating_mul(10), 20);")]
+        #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($SelfT),"::MAX);")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn saturating_mul(self, rhs: Self) -> Self {
+            match self.checked_mul(rhs) {
+                Some(x) => x,
+                None => Self::MAX,
             }
         }
 
-        doc_comment! {
-            concat!("Converts an integer from little endian to the target's endianness.
-
-On little endian this is a no-op. On big endian the bytes are
-swapped.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = 0x1A", stringify!($SelfT), ";
-
-if cfg!(target_endian = \"little\") {
-    assert_eq!(", stringify!($SelfT), "::from_le(n), n)
-} else {
-    assert_eq!(", stringify!($SelfT), "::from_le(n), n.swap_bytes())
-}", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
-            #[inline]
-            pub const fn from_le(x: Self) -> Self {
-                #[cfg(target_endian = "little")]
-                {
-                    x
-                }
-                #[cfg(not(target_endian = "little"))]
-                {
-                    x.swap_bytes()
-                }
+        /// Saturating integer exponentiation. Computes `self.pow(exp)`,
+        /// saturating at the numeric bounds instead of overflowing.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(4", stringify!($SelfT), ".saturating_pow(3), 64);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT), "::MAX);")]
+        /// ```
+        #[stable(feature = "no_panic_pow", since = "1.34.0")]
+        #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn saturating_pow(self, exp: u32) -> Self {
+            match self.checked_pow(exp) {
+                Some(x) => x,
+                None => Self::MAX,
             }
         }
 
-        doc_comment! {
-            concat!("Converts `self` to big endian from the target's endianness.
-
-On big endian this is a no-op. On little endian the bytes are
-swapped.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = 0x1A", stringify!($SelfT), ";
-
-if cfg!(target_endian = \"big\") {
-    assert_eq!(n.to_be(), n)
-} else {
-    assert_eq!(n.to_be(), n.swap_bytes())
-}", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
-            #[inline]
-            pub const fn to_be(self) -> Self { // or not to be?
-                #[cfg(target_endian = "big")]
-                {
-                    self
-                }
-                #[cfg(not(target_endian = "big"))]
-                {
-                    self.swap_bytes()
-                }
-            }
+        /// Wrapping (modular) addition. Computes `self + rhs`,
+        /// wrapping around at the boundary of the type.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(200", stringify!($SelfT), ".wrapping_add(55), 255);")]
+        #[doc = concat!("assert_eq!(200", stringify!($SelfT), ".wrapping_add(", stringify!($SelfT), "::MAX), 199);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_add(self, rhs: Self) -> Self {
+            intrinsics::wrapping_add(self, rhs)
         }
 
-        doc_comment! {
-            concat!("Converts `self` to little endian from the target's endianness.
-
-On little endian this is a no-op. On big endian the bytes are
-swapped.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "let n = 0x1A", stringify!($SelfT), ";
-
-if cfg!(target_endian = \"little\") {
-    assert_eq!(n.to_le(), n)
-} else {
-    assert_eq!(n.to_le(), n.swap_bytes())
-}", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
-            #[inline]
-            pub const fn to_le(self) -> Self {
-                #[cfg(target_endian = "little")]
-                {
-                    self
-                }
-                #[cfg(not(target_endian = "little"))]
-                {
-                    self.swap_bytes()
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked integer addition. Computes `self + rhs`, returning `None`
-if overflow occurred.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(1), ",
-"Some(", stringify!($SelfT), "::MAX - 1));
-assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_add(self, rhs: Self) -> Option<Self> {
-                let (a, b) = self.overflowing_add(rhs);
-                if unlikely!(b) {None} else {Some(a)}
-            }
-        }
-
-        doc_comment! {
-            concat!("Unchecked integer addition. Computes `self + rhs`, assuming overflow
-cannot occur. This results in undefined behavior when `self + rhs > ", stringify!($SelfT),
-"::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`."),
-            #[unstable(
-                feature = "unchecked_math",
-                reason = "niche optimization path",
-                issue = "none",
-            )]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub unsafe fn unchecked_add(self, rhs: Self) -> Self {
-                // SAFETY: the caller must uphold the safety contract for
-                // `unchecked_add`.
-                unsafe { intrinsics::unchecked_add(self, rhs) }
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked integer subtraction. Computes `self - rhs`, returning
-`None` if overflow occurred.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(1", stringify!($SelfT), ".checked_sub(1), Some(0));
-assert_eq!(0", stringify!($SelfT), ".checked_sub(1), None);", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
-                let (a, b) = self.overflowing_sub(rhs);
-                if unlikely!(b) {None} else {Some(a)}
-            }
-        }
-
-        doc_comment! {
-            concat!("Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
-cannot occur. This results in undefined behavior when `self - rhs > ", stringify!($SelfT),
-"::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`."),
-            #[unstable(
-                feature = "unchecked_math",
-                reason = "niche optimization path",
-                issue = "none",
-            )]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub unsafe fn unchecked_sub(self, rhs: Self) -> Self {
-                // SAFETY: the caller must uphold the safety contract for
-                // `unchecked_sub`.
-                unsafe { intrinsics::unchecked_sub(self, rhs) }
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked integer multiplication. Computes `self * rhs`, returning
-`None` if overflow occurred.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(5", stringify!($SelfT), ".checked_mul(1), Some(5));
-assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
-                let (a, b) = self.overflowing_mul(rhs);
-                if unlikely!(b) {None} else {Some(a)}
-            }
-        }
-
-        doc_comment! {
-            concat!("Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
-cannot occur. This results in undefined behavior when `self * rhs > ", stringify!($SelfT),
-"::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`."),
-            #[unstable(
-                feature = "unchecked_math",
-                reason = "niche optimization path",
-                issue = "none",
-            )]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub unsafe fn unchecked_mul(self, rhs: Self) -> Self {
-                // SAFETY: the caller must uphold the safety contract for
-                // `unchecked_mul`.
-                unsafe { intrinsics::unchecked_mul(self, rhs) }
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked integer division. Computes `self / rhs`, returning `None`
-if `rhs == 0`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(128", stringify!($SelfT), ".checked_div(2), Some(64));
-assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_div(self, rhs: Self) -> Option<Self> {
-                if unlikely!(rhs == 0) {
-                    None
-                } else {
-                    // SAFETY: div by zero has been checked above and unsigned types have no other
-                    // failure modes for division
-                    Some(unsafe { intrinsics::unchecked_div(self, rhs) })
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None`
-if `rhs == 0`.
-
-# Examples
-
-Basic usage:
-
-```
-assert_eq!(128", stringify!($SelfT), ".checked_div_euclid(2), Some(64));
-assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None);
-```"),
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
-                if unlikely!(rhs == 0) {
-                    None
-                } else {
-                    Some(self.div_euclid(rhs))
-                }
-            }
-        }
-
-
-        doc_comment! {
-            concat!("Checked integer remainder. Computes `self % rhs`, returning `None`
-if `rhs == 0`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(5", stringify!($SelfT), ".checked_rem(2), Some(1));
-assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
-                if unlikely!(rhs == 0) {
-                    None
-                } else {
-                    // SAFETY: div by zero has been checked above and unsigned types have no other
-                    // failure modes for division
-                    Some(unsafe { intrinsics::unchecked_rem(self, rhs) })
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked Euclidean modulo. Computes `self.rem_euclid(rhs)`, returning `None`
-if `rhs == 0`.
-
-# Examples
-
-Basic usage:
-
-```
-assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));
-assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);
-```"),
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
-                if unlikely!(rhs == 0) {
-                    None
-                } else {
-                    Some(self.rem_euclid(rhs))
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked negation. Computes `-self`, returning `None` unless `self ==
-0`.
-
-Note that negating any positive integer will overflow.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(0", stringify!($SelfT), ".checked_neg(), Some(0));
-assert_eq!(1", stringify!($SelfT), ".checked_neg(), None);", $EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
-            #[inline]
-            pub const fn checked_neg(self) -> Option<Self> {
-                let (a, b) = self.overflowing_neg();
-                if unlikely!(b) {None} else {Some(a)}
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked shift left. Computes `self << rhs`, returning `None`
-if `rhs` is larger than or equal to the number of bits in `self`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(0x1", stringify!($SelfT), ".checked_shl(4), Some(0x10));
-assert_eq!(0x10", stringify!($SelfT), ".checked_shl(129), None);", $EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
-                let (a, b) = self.overflowing_shl(rhs);
-                if unlikely!(b) {None} else {Some(a)}
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked shift right. Computes `self >> rhs`, returning `None`
-if `rhs` is larger than or equal to the number of bits in `self`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(0x10", stringify!($SelfT), ".checked_shr(4), Some(0x1));
-assert_eq!(0x10", stringify!($SelfT), ".checked_shr(129), None);", $EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
-                let (a, b) = self.overflowing_shr(rhs);
-                if unlikely!(b) {None} else {Some(a)}
-            }
-        }
-
-        doc_comment! {
-            concat!("Checked exponentiation. Computes `self.pow(exp)`, returning `None` if
-overflow occurred.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(2", stringify!($SelfT), ".checked_pow(5), Some(32));
-assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);", $EndFeature, "
-```"),
-            #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
-                if exp == 0 {
-                    return Some(1);
-                }
-                let mut base = self;
-                let mut acc: Self = 1;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        acc = try_opt!(acc.checked_mul(base));
-                    }
-                    exp /= 2;
-                    base = try_opt!(base.checked_mul(base));
-                }
-
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
-
-                Some(try_opt!(acc.checked_mul(base)))
-            }
-        }
-
-        doc_comment! {
-            concat!("Saturating integer addition. Computes `self + rhs`, saturating at
-the numeric bounds instead of overflowing.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);
-assert_eq!(", stringify!($SelfT), "::MAX.saturating_add(127), ", stringify!($SelfT), "::MAX);",
-$EndFeature, "
-```"),
-
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
-            #[inline]
-            pub const fn saturating_add(self, rhs: Self) -> Self {
-                intrinsics::saturating_add(self, rhs)
-            }
-        }
-
-        doc_comment! {
-            concat!("Saturating integer subtraction. Computes `self - rhs`, saturating
-at the numeric bounds instead of overflowing.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_sub(27), 73);
-assert_eq!(13", stringify!($SelfT), ".saturating_sub(127), 0);", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
-            #[inline]
-            pub const fn saturating_sub(self, rhs: Self) -> Self {
-                intrinsics::saturating_sub(self, rhs)
-            }
-        }
-
-        doc_comment! {
-            concat!("Saturating integer multiplication. Computes `self * rhs`,
-saturating at the numeric bounds instead of overflowing.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "
-assert_eq!(2", stringify!($SelfT), ".saturating_mul(10), 20);
-assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($SelfT),
-"::MAX);", $EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn saturating_mul(self, rhs: Self) -> Self {
-                match self.checked_mul(rhs) {
-                    Some(x) => x,
-                    None => Self::MAX,
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Saturating integer exponentiation. Computes `self.pow(exp)`,
-saturating at the numeric bounds instead of overflowing.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "
-assert_eq!(4", stringify!($SelfT), ".saturating_pow(3), 64);
-assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT), "::MAX);",
-$EndFeature, "
-```"),
-            #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn saturating_pow(self, exp: u32) -> Self {
-                match self.checked_pow(exp) {
-                    Some(x) => x,
-                    None => Self::MAX,
-                }
-            }
-        }
-
-        doc_comment! {
-            concat!("Wrapping (modular) addition. Computes `self + rhs`,
-wrapping around at the boundary of the type.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(200", stringify!($SelfT), ".wrapping_add(55), 255);
-assert_eq!(200", stringify!($SelfT), ".wrapping_add(", stringify!($SelfT), "::MAX), 199);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_add(self, rhs: Self) -> Self {
-                intrinsics::wrapping_add(self, rhs)
-            }
-        }
-
-        doc_comment! {
-            concat!("Wrapping (modular) subtraction. Computes `self - rhs`,
-wrapping around at the boundary of the type.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_sub(100), 0);
-assert_eq!(100", stringify!($SelfT), ".wrapping_sub(", stringify!($SelfT), "::MAX), 101);",
-$EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_sub(self, rhs: Self) -> Self {
-                intrinsics::wrapping_sub(self, rhs)
-            }
+        /// Wrapping (modular) subtraction. Computes `self - rhs`,
+        /// wrapping around at the boundary of the type.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_sub(100), 0);")]
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_sub(", stringify!($SelfT), "::MAX), 101);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_sub(self, rhs: Self) -> Self {
+            intrinsics::wrapping_sub(self, rhs)
         }
 
         /// Wrapping (modular) multiplication. Computes `self *
@@ -948,108 +862,100 @@
             intrinsics::wrapping_mul(self, rhs)
         }
 
-        doc_comment! {
-            concat!("Wrapping (modular) division. Computes `self / rhs`.
-Wrapped division on unsigned types is just normal division.
-There's no way wrapping could ever happen.
-This function exists, so that all operations
-are accounted for in the wrapping operations.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_div(10), 10);", $EndFeature, "
-```"),
-            #[stable(feature = "num_wrapping", since = "1.2.0")]
-            #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_div(self, rhs: Self) -> Self {
-                self / rhs
-            }
+        /// Wrapping (modular) division. Computes `self / rhs`.
+        /// Wrapped division on unsigned types is just normal division.
+        /// There's no way wrapping could ever happen.
+        /// This function exists, so that all operations
+        /// are accounted for in the wrapping operations.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_div(10), 10);")]
+        /// ```
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_div(self, rhs: Self) -> Self {
+            self / rhs
         }
 
-        doc_comment! {
-            concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`.
-Wrapped division on unsigned types is just normal division.
-There's no way wrapping could ever happen.
-This function exists, so that all operations
-are accounted for in the wrapping operations.
-Since, for the positive integers, all common
-definitions of division are equal, this
-is exactly equal to `self.wrapping_div(rhs)`.
-
-# Examples
-
-Basic usage:
-
-```
-assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);
-```"),
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_div_euclid(self, rhs: Self) -> Self {
-                self / rhs
-            }
+        /// Wrapping Euclidean division. Computes `self.div_euclid(rhs)`.
+        /// Wrapped division on unsigned types is just normal division.
+        /// There's no way wrapping could ever happen.
+        /// This function exists, so that all operations
+        /// are accounted for in the wrapping operations.
+        /// Since, for the positive integers, all common
+        /// definitions of division are equal, this
+        /// is exactly equal to `self.wrapping_div(rhs)`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);")]
+        /// ```
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_div_euclid(self, rhs: Self) -> Self {
+            self / rhs
         }
 
-        doc_comment! {
-            concat!("Wrapping (modular) remainder. Computes `self % rhs`.
-Wrapped remainder calculation on unsigned types is
-just the regular remainder calculation.
-There's no way wrapping could ever happen.
-This function exists, so that all operations
-are accounted for in the wrapping operations.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_rem(10), 0);", $EndFeature, "
-```"),
-            #[stable(feature = "num_wrapping", since = "1.2.0")]
-            #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_rem(self, rhs: Self) -> Self {
-                self % rhs
-            }
+        /// Wrapping (modular) remainder. Computes `self % rhs`.
+        /// Wrapped remainder calculation on unsigned types is
+        /// just the regular remainder calculation.
+        /// There's no way wrapping could ever happen.
+        /// This function exists, so that all operations
+        /// are accounted for in the wrapping operations.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_rem(10), 0);")]
+        /// ```
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_rem(self, rhs: Self) -> Self {
+            self % rhs
         }
 
-        doc_comment! {
-            concat!("Wrapping Euclidean modulo. Computes `self.rem_euclid(rhs)`.
-Wrapped modulo calculation on unsigned types is
-just the regular remainder calculation.
-There's no way wrapping could ever happen.
-This function exists, so that all operations
-are accounted for in the wrapping operations.
-Since, for the positive integers, all common
-definitions of division are equal, this
-is exactly equal to `self.wrapping_rem(rhs)`.
-
-# Examples
-
-Basic usage:
-
-```
-assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);
-```"),
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self {
-                self % rhs
-            }
+        /// Wrapping Euclidean modulo. Computes `self.rem_euclid(rhs)`.
+        /// Wrapped modulo calculation on unsigned types is
+        /// just the regular remainder calculation.
+        /// There's no way wrapping could ever happen.
+        /// This function exists, so that all operations
+        /// are accounted for in the wrapping operations.
+        /// Since, for the positive integers, all common
+        /// definitions of division are equal, this
+        /// is exactly equal to `self.wrapping_rem(rhs)`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);")]
+        /// ```
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self {
+            self % rhs
         }
 
         /// Wrapping (modular) negation. Computes `-self`,
@@ -1080,167 +986,156 @@
             self.overflowing_neg().0
         }
 
-        doc_comment! {
-            concat!("Panic-free bitwise shift-left; yields `self << mask(rhs)`,
-where `mask` removes any high-order bits of `rhs` that
-would cause the shift to exceed the bitwidth of the type.
-
-Note that this is *not* the same as a rotate-left; the
-RHS of a wrapping shift-left is restricted to the range
-of the type, rather than the bits shifted out of the LHS
-being returned to the other end. The primitive integer
-types all implement a [`rotate_left`](#method.rotate_left) function,
-which may be what you want instead.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(1", stringify!($SelfT), ".wrapping_shl(7), 128);
-assert_eq!(1", stringify!($SelfT), ".wrapping_shl(128), 1);", $EndFeature, "
-```"),
-            #[stable(feature = "num_wrapping", since = "1.2.0")]
-            #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_shl(self, rhs: u32) -> Self {
-                // SAFETY: the masking by the bitsize of the type ensures that we do not shift
-                // out of bounds
-                unsafe {
-                    intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
-                }
+        /// Panic-free bitwise shift-left; yields `self << mask(rhs)`,
+        /// where `mask` removes any high-order bits of `rhs` that
+        /// would cause the shift to exceed the bitwidth of the type.
+        ///
+        /// Note that this is *not* the same as a rotate-left; the
+        /// RHS of a wrapping shift-left is restricted to the range
+        /// of the type, rather than the bits shifted out of the LHS
+        /// being returned to the other end. The primitive integer
+        /// types all implement a [`rotate_left`](#method.rotate_left) function,
+        /// which may be what you want instead.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_shl(7), 128);")]
+        #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_shl(128), 1);")]
+        /// ```
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_shl(self, rhs: u32) -> Self {
+            // SAFETY: the masking by the bitsize of the type ensures that we do not shift
+            // out of bounds
+            unsafe {
+                intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
             }
         }
 
-        doc_comment! {
-            concat!("Panic-free bitwise shift-right; yields `self >> mask(rhs)`,
-where `mask` removes any high-order bits of `rhs` that
-would cause the shift to exceed the bitwidth of the type.
-
-Note that this is *not* the same as a rotate-right; the
-RHS of a wrapping shift-right is restricted to the range
-of the type, rather than the bits shifted out of the LHS
-being returned to the other end. The primitive integer
-types all implement a [`rotate_right`](#method.rotate_right) function,
-which may be what you want instead.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(128", stringify!($SelfT), ".wrapping_shr(7), 1);
-assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);", $EndFeature, "
-```"),
-            #[stable(feature = "num_wrapping", since = "1.2.0")]
-            #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_shr(self, rhs: u32) -> Self {
-                // SAFETY: the masking by the bitsize of the type ensures that we do not shift
-                // out of bounds
-                unsafe {
-                    intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
-                }
+        /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`,
+        /// where `mask` removes any high-order bits of `rhs` that
+        /// would cause the shift to exceed the bitwidth of the type.
+        ///
+        /// Note that this is *not* the same as a rotate-right; the
+        /// RHS of a wrapping shift-right is restricted to the range
+        /// of the type, rather than the bits shifted out of the LHS
+        /// being returned to the other end. The primitive integer
+        /// types all implement a [`rotate_right`](#method.rotate_right) function,
+        /// which may be what you want instead.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(128", stringify!($SelfT), ".wrapping_shr(7), 1);")]
+        #[doc = concat!("assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);")]
+        /// ```
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_shr(self, rhs: u32) -> Self {
+            // SAFETY: the masking by the bitsize of the type ensures that we do not shift
+            // out of bounds
+            unsafe {
+                intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
             }
         }
 
-        doc_comment! {
-            concat!("Wrapping (modular) exponentiation. Computes `self.pow(exp)`,
-wrapping around at the boundary of the type.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(3", stringify!($SelfT), ".wrapping_pow(5), 243);
-assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, "
-```"),
-            #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn wrapping_pow(self, mut exp: u32) -> Self {
-                if exp == 0 {
-                    return 1;
-                }
-                let mut base = self;
-                let mut acc: Self = 1;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        acc = acc.wrapping_mul(base);
-                    }
-                    exp /= 2;
-                    base = base.wrapping_mul(base);
-                }
-
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
-                acc.wrapping_mul(base)
+        /// Wrapping (modular) exponentiation. Computes `self.pow(exp)`,
+        /// wrapping around at the boundary of the type.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".wrapping_pow(5), 243);")]
+        /// assert_eq!(3u8.wrapping_pow(6), 217);
+        /// ```
+        #[stable(feature = "no_panic_pow", since = "1.34.0")]
+        #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_pow(self, mut exp: u32) -> Self {
+            if exp == 0 {
+                return 1;
             }
+            let mut base = self;
+            let mut acc: Self = 1;
+
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    acc = acc.wrapping_mul(base);
+                }
+                exp /= 2;
+                base = base.wrapping_mul(base);
+            }
+
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
+            acc.wrapping_mul(base)
         }
 
-        doc_comment! {
-            concat!("Calculates `self` + `rhs`
-
-Returns a tuple of the addition along with a boolean indicating
-whether an arithmetic overflow would occur. If an overflow would
-have occurred then the wrapped value is returned.
-
-# Examples
-
-Basic usage
-
-```
-", $Feature, "
-assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));
-assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));", $EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
-                let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT);
-                (a as Self, b)
-            }
+        /// Calculates `self` + `rhs`
+        ///
+        /// Returns a tuple of the addition along with a boolean indicating
+        /// whether an arithmetic overflow would occur. If an overflow would
+        /// have occurred then the wrapped value is returned.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        ///
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+            let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT);
+            (a as Self, b)
         }
 
-        doc_comment! {
-            concat!("Calculates `self` - `rhs`
-
-Returns a tuple of the subtraction along with a boolean indicating
-whether an arithmetic overflow would occur. If an overflow would
-have occurred then the wrapped value is returned.
-
-# Examples
-
-Basic usage
-
-```
-", $Feature, "
-assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));
-assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));",
-$EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
-                let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT);
-                (a as Self, b)
-            }
+        /// Calculates `self` - `rhs`
+        ///
+        /// Returns a tuple of the subtraction along with a boolean indicating
+        /// whether an arithmetic overflow would occur. If an overflow would
+        /// have occurred then the wrapped value is returned.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        ///
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));")]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
+            let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT);
+            (a as Self, b)
         }
 
         /// Calculates the multiplication of `self` and `rhs`.
@@ -1270,269 +1165,251 @@
             (a as Self, b)
         }
 
-        doc_comment! {
-            concat!("Calculates the divisor when `self` is divided by `rhs`.
-
-Returns a tuple of the divisor along with a boolean indicating
-whether an arithmetic overflow would occur. Note that for unsigned
-integers overflow never occurs, so the second value is always
-`false`.
-
-# Panics
-
-This function will panic if `rhs` is 0.
-
-# Examples
-
-Basic usage
-
-```
-", $Feature, "assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));", $EndFeature, "
-```"),
-            #[inline]
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
-                (self / rhs, false)
-            }
+        /// Calculates the divisor when `self` is divided by `rhs`.
+        ///
+        /// Returns a tuple of the divisor along with a boolean indicating
+        /// whether an arithmetic overflow would occur. Note that for unsigned
+        /// integers overflow never occurs, so the second value is always
+        /// `false`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));")]
+        /// ```
+        #[inline]
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
+            (self / rhs, false)
         }
 
-        doc_comment! {
-            concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`.
-
-Returns a tuple of the divisor along with a boolean indicating
-whether an arithmetic overflow would occur. Note that for unsigned
-integers overflow never occurs, so the second value is always
-`false`.
-Since, for the positive integers, all common
-definitions of division are equal, this
-is exactly equal to `self.overflowing_div(rhs)`.
-
-# Panics
-
-This function will panic if `rhs` is 0.
-
-# Examples
-
-Basic usage
-
-```
-assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));
-```"),
-            #[inline]
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
-                (self / rhs, false)
-            }
+        /// Calculates the quotient of Euclidean division `self.div_euclid(rhs)`.
+        ///
+        /// Returns a tuple of the divisor along with a boolean indicating
+        /// whether an arithmetic overflow would occur. Note that for unsigned
+        /// integers overflow never occurs, so the second value is always
+        /// `false`.
+        /// Since, for the positive integers, all common
+        /// definitions of division are equal, this
+        /// is exactly equal to `self.overflowing_div(rhs)`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));")]
+        /// ```
+        #[inline]
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
+            (self / rhs, false)
         }
 
-        doc_comment! {
-            concat!("Calculates the remainder when `self` is divided by `rhs`.
-
-Returns a tuple of the remainder after dividing along with a boolean
-indicating whether an arithmetic overflow would occur. Note that for
-unsigned integers overflow never occurs, so the second value is
-always `false`.
-
-# Panics
-
-This function will panic if `rhs` is 0.
-
-# Examples
-
-Basic usage
-
-```
-", $Feature, "assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));", $EndFeature, "
-```"),
-            #[inline]
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
-                (self % rhs, false)
-            }
+        /// Calculates the remainder when `self` is divided by `rhs`.
+        ///
+        /// Returns a tuple of the remainder after dividing along with a boolean
+        /// indicating whether an arithmetic overflow would occur. Note that for
+        /// unsigned integers overflow never occurs, so the second value is
+        /// always `false`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));")]
+        /// ```
+        #[inline]
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
+            (self % rhs, false)
         }
 
-        doc_comment! {
-            concat!("Calculates the remainder `self.rem_euclid(rhs)` as if by Euclidean division.
-
-Returns a tuple of the modulo after dividing along with a boolean
-indicating whether an arithmetic overflow would occur. Note that for
-unsigned integers overflow never occurs, so the second value is
-always `false`.
-Since, for the positive integers, all common
-definitions of division are equal, this operation
-is exactly equal to `self.overflowing_rem(rhs)`.
-
-# Panics
-
-This function will panic if `rhs` is 0.
-
-# Examples
-
-Basic usage
-
-```
-assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));
-```"),
-            #[inline]
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
-                (self % rhs, false)
-            }
+        /// Calculates the remainder `self.rem_euclid(rhs)` as if by Euclidean division.
+        ///
+        /// Returns a tuple of the modulo after dividing along with a boolean
+        /// indicating whether an arithmetic overflow would occur. Note that for
+        /// unsigned integers overflow never occurs, so the second value is
+        /// always `false`.
+        /// Since, for the positive integers, all common
+        /// definitions of division are equal, this operation
+        /// is exactly equal to `self.overflowing_rem(rhs)`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));")]
+        /// ```
+        #[inline]
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
+            (self % rhs, false)
         }
 
-        doc_comment! {
-            concat!("Negates self in an overflowing fashion.
-
-Returns `!self + 1` using wrapping operations to return the value
-that represents the negation of this unsigned value. Note that for
-positive unsigned values overflow always occurs, but negating 0 does
-not overflow.
-
-# Examples
-
-Basic usage
-
-```
-", $Feature, "assert_eq!(0", stringify!($SelfT), ".overflowing_neg(), (0, false));
-assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2i32 as ", stringify!($SelfT),
-", true));", $EndFeature, "
-```"),
-            #[inline]
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
-            pub const fn overflowing_neg(self) -> (Self, bool) {
-                ((!self).wrapping_add(1), self != 0)
-            }
+        /// Negates self in an overflowing fashion.
+        ///
+        /// Returns `!self + 1` using wrapping operations to return the value
+        /// that represents the negation of this unsigned value. Note that for
+        /// positive unsigned values overflow always occurs, but negating 0 does
+        /// not overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".overflowing_neg(), (0, false));")]
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2i32 as ", stringify!($SelfT), ", true));")]
+        /// ```
+        #[inline]
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
+        pub const fn overflowing_neg(self) -> (Self, bool) {
+            ((!self).wrapping_add(1), self != 0)
         }
 
-        doc_comment! {
-            concat!("Shifts self left by `rhs` bits.
-
-Returns a tuple of the shifted version of self along with a boolean
-indicating whether the shift value was larger than or equal to the
-number of bits. If the shift value is too large, then value is
-masked (N-1) where N is the number of bits, and this value is then
-used to perform the shift.
-
-# Examples
-
-Basic usage
-
-```
-", $Feature, "assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(4), (0x10, false));
-assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(132), (0x10, true));", $EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
-                (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
-            }
+        /// Shifts self left by `rhs` bits.
+        ///
+        /// Returns a tuple of the shifted version of self along with a boolean
+        /// indicating whether the shift value was larger than or equal to the
+        /// number of bits. If the shift value is too large, then value is
+        /// masked (N-1) where N is the number of bits, and this value is then
+        /// used to perform the shift.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(4), (0x10, false));")]
+        #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(132), (0x10, true));")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
         }
 
-        doc_comment! {
-            concat!("Shifts self right by `rhs` bits.
-
-Returns a tuple of the shifted version of self along with a boolean
-indicating whether the shift value was larger than or equal to the
-number of bits. If the shift value is too large, then value is
-masked (N-1) where N is the number of bits, and this value is then
-used to perform the shift.
-
-# Examples
-
-Basic usage
-
-```
-", $Feature, "assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(4), (0x1, false));
-assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));", $EndFeature, "
-```"),
-            #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
-                (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
-            }
+        /// Shifts self right by `rhs` bits.
+        ///
+        /// Returns a tuple of the shifted version of self along with a boolean
+        /// indicating whether the shift value was larger than or equal to the
+        /// number of bits. If the shift value is too large, then value is
+        /// masked (N-1) where N is the number of bits, and this value is then
+        /// used to perform the shift.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(4), (0x1, false));")]
+        #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));")]
+        /// ```
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
         }
 
-        doc_comment! {
-            concat!("Raises self to the power of `exp`, using exponentiation by squaring.
+        /// Raises self to the power of `exp`, using exponentiation by squaring.
+        ///
+        /// Returns a tuple of the exponentiation along with a bool indicating
+        /// whether an overflow happened.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".overflowing_pow(5), (243, false));")]
+        /// assert_eq!(3u8.overflowing_pow(6), (217, true));
+        /// ```
+        #[stable(feature = "no_panic_pow", since = "1.34.0")]
+        #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
+            if exp == 0{
+                return (1,false);
+            }
+            let mut base = self;
+            let mut acc: Self = 1;
+            let mut overflown = false;
+            // Scratch space for storing results of overflowing_mul.
+            let mut r;
 
-Returns a tuple of the exponentiation along with a bool indicating
-whether an overflow happened.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(3", stringify!($SelfT), ".overflowing_pow(5), (243, false));
-assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, "
-```"),
-            #[stable(feature = "no_panic_pow", since = "1.34.0")]
-            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
-                if exp == 0{
-                    return (1,false);
-                }
-                let mut base = self;
-                let mut acc: Self = 1;
-                let mut overflown = false;
-                // Scratch space for storing results of overflowing_mul.
-                let mut r;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        r = acc.overflowing_mul(base);
-                        acc = r.0;
-                        overflown |= r.1;
-                    }
-                    exp /= 2;
-                    r = base.overflowing_mul(base);
-                    base = r.0;
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    r = acc.overflowing_mul(base);
+                    acc = r.0;
                     overflown |= r.1;
                 }
-
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
-                r = acc.overflowing_mul(base);
-                r.1 |= overflown;
-
-                r
+                exp /= 2;
+                r = base.overflowing_mul(base);
+                base = r.0;
+                overflown |= r.1;
             }
+
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
+            r = acc.overflowing_mul(base);
+            r.1 |= overflown;
+
+            r
         }
 
-        doc_comment! {
-            concat!("Raises self to the power of `exp`, using exponentiation by squaring.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(2", stringify!($SelfT), ".pow(5), 32);", $EndFeature, "
-```"),
+        /// Raises self to the power of `exp`, using exponentiation by squaring.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".pow(5), 32);")]
+        /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
         #[must_use = "this returns the result of the operation, \
@@ -1560,84 +1437,77 @@
             // needless overflow.
             acc * base
         }
-    }
 
-        doc_comment! {
-            concat!("Performs Euclidean division.
-
-Since, for the positive integers, all common
-definitions of division are equal, this
-is exactly equal to `self / rhs`.
-
-# Panics
-
-This function will panic if `rhs` is 0.
-
-# Examples
-
-Basic usage:
-
-```
-assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer type
-```"),
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            #[rustc_inherit_overflow_checks]
-            pub const fn div_euclid(self, rhs: Self) -> Self {
-                self / rhs
-            }
+        /// Performs Euclidean division.
+        ///
+        /// Since, for the positive integers, all common
+        /// definitions of division are equal, this
+        /// is exactly equal to `self / rhs`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer type")]
+        /// ```
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        pub const fn div_euclid(self, rhs: Self) -> Self {
+            self / rhs
         }
 
 
-        doc_comment! {
-            concat!("Calculates the least remainder of `self (mod rhs)`.
-
-Since, for the positive integers, all common
-definitions of division are equal, this
-is exactly equal to `self % rhs`.
-
-# Panics
-
-This function will panic if `rhs` is 0.
-
-# Examples
-
-Basic usage:
-
-```
-assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type
-```"),
-            #[stable(feature = "euclidean_division", since = "1.38.0")]
-            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
-            #[must_use = "this returns the result of the operation, \
-                          without modifying the original"]
-            #[inline]
-            #[rustc_inherit_overflow_checks]
-            pub const fn rem_euclid(self, rhs: Self) -> Self {
-                self % rhs
-            }
+        /// Calculates the least remainder of `self (mod rhs)`.
+        ///
+        /// Since, for the positive integers, all common
+        /// definitions of division are equal, this
+        /// is exactly equal to `self % rhs`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type")]
+        /// ```
+        #[stable(feature = "euclidean_division", since = "1.38.0")]
+        #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        pub const fn rem_euclid(self, rhs: Self) -> Self {
+            self % rhs
         }
 
-        doc_comment! {
-            concat!("Returns `true` if and only if `self == 2^k` for some `k`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert!(16", stringify!($SelfT), ".is_power_of_two());
-assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_is_power_of_two", since = "1.32.0")]
-            #[inline]
-            pub const fn is_power_of_two(self) -> bool {
-                self.count_ones() == 1
-            }
+        /// Returns `true` if and only if `self == 2^k` for some `k`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert!(16", stringify!($SelfT), ".is_power_of_two());")]
+        #[doc = concat!("assert!(!10", stringify!($SelfT), ".is_power_of_two());")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_is_power_of_two", since = "1.32.0")]
+        #[inline]
+        pub const fn is_power_of_two(self) -> bool {
+            self.count_ones() == 1
         }
 
         // Returns one less than next power of two.
@@ -1663,332 +1533,302 @@
             <$SelfT>::MAX >> z
         }
 
-        doc_comment! {
-            concat!("Returns the smallest power of two greater than or equal to `self`.
-
-When return value overflows (i.e., `self > (1 << (N-1))` for type
-`uN`), it panics in debug mode and return value is wrapped to 0 in
-release mode (the only situation in which method can return 0).
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(2", stringify!($SelfT), ".next_power_of_two(), 2);
-assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);", $EndFeature, "
-```"),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
-            #[inline]
-            #[rustc_inherit_overflow_checks]
-            pub const fn next_power_of_two(self) -> Self {
-                self.one_less_than_next_power_of_two() + 1
-            }
+        /// Returns the smallest power of two greater than or equal to `self`.
+        ///
+        /// When return value overflows (i.e., `self > (1 << (N-1))` for type
+        /// `uN`), it panics in debug mode and return value is wrapped to 0 in
+        /// release mode (the only situation in which method can return 0).
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".next_power_of_two(), 2);")]
+        #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);")]
+        /// ```
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        pub const fn next_power_of_two(self) -> Self {
+            self.one_less_than_next_power_of_two() + 1
         }
 
-        doc_comment! {
-            concat!("Returns the smallest power of two greater than or equal to `n`. If
-the next power of two is greater than the type's maximum value,
-`None` is returned, otherwise the power of two is wrapped in `Some`.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(2", stringify!($SelfT),
-".checked_next_power_of_two(), Some(2));
-assert_eq!(3", stringify!($SelfT), ".checked_next_power_of_two(), Some(4));
-assert_eq!(", stringify!($SelfT), "::MAX.checked_next_power_of_two(), None);",
-$EndFeature, "
-```"),
-            #[inline]
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
-            pub const fn checked_next_power_of_two(self) -> Option<Self> {
-                self.one_less_than_next_power_of_two().checked_add(1)
-            }
+        /// Returns the smallest power of two greater than or equal to `n`. If
+        /// the next power of two is greater than the type's maximum value,
+        /// `None` is returned, otherwise the power of two is wrapped in `Some`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_next_power_of_two(), Some(2));")]
+        #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".checked_next_power_of_two(), Some(4));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_next_power_of_two(), None);")]
+        /// ```
+        #[inline]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
+        pub const fn checked_next_power_of_two(self) -> Option<Self> {
+            self.one_less_than_next_power_of_two().checked_add(1)
         }
 
-        doc_comment! {
-            concat!("Returns the smallest power of two greater than or equal to `n`. If
-the next power of two is greater than the type's maximum value,
-the return value is wrapped to `0`.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_next_power_of_two)]
-", $Feature, "
-assert_eq!(2", stringify!($SelfT), ".wrapping_next_power_of_two(), 2);
-assert_eq!(3", stringify!($SelfT), ".wrapping_next_power_of_two(), 4);
-assert_eq!(", stringify!($SelfT), "::MAX.wrapping_next_power_of_two(), 0);",
-$EndFeature, "
-```"),
-            #[unstable(feature = "wrapping_next_power_of_two", issue = "32463",
-                       reason = "needs decision on wrapping behaviour")]
-            #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
-            pub const fn wrapping_next_power_of_two(self) -> Self {
-                self.one_less_than_next_power_of_two().wrapping_add(1)
-            }
+        /// Returns the smallest power of two greater than or equal to `n`. If
+        /// the next power of two is greater than the type's maximum value,
+        /// the return value is wrapped to `0`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(wrapping_next_power_of_two)]
+        ///
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".wrapping_next_power_of_two(), 2);")]
+        #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".wrapping_next_power_of_two(), 4);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_next_power_of_two(), 0);")]
+        /// ```
+        #[unstable(feature = "wrapping_next_power_of_two", issue = "32463",
+                   reason = "needs decision on wrapping behaviour")]
+        #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
+        pub const fn wrapping_next_power_of_two(self) -> Self {
+            self.one_less_than_next_power_of_two().wrapping_add(1)
         }
 
-        doc_comment! {
-            concat!("Return the memory representation of this integer as a byte array in
-big-endian (network) byte order.
-",
-$to_xe_bytes_doc,
-"
-# Examples
-
-```
-let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes();
-assert_eq!(bytes, ", $be_bytes, ");
-```"),
-            #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
-            #[inline]
-            pub const fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
-                self.to_be().to_ne_bytes()
-            }
+        /// Return the memory representation of this integer as a byte array in
+        /// big-endian (network) byte order.
+        ///
+        #[doc = $to_xe_bytes_doc]
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes();")]
+        #[doc = concat!("assert_eq!(bytes, ", $be_bytes, ");")]
+        /// ```
+        #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
+        #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        #[inline]
+        pub const fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            self.to_be().to_ne_bytes()
         }
 
-        doc_comment! {
-            concat!("Return the memory representation of this integer as a byte array in
-little-endian byte order.
-",
-$to_xe_bytes_doc,
-"
-# Examples
-
-```
-let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes();
-assert_eq!(bytes, ", $le_bytes, ");
-```"),
-            #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
-            #[inline]
-            pub const fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
-                self.to_le().to_ne_bytes()
-            }
+        /// Return the memory representation of this integer as a byte array in
+        /// little-endian byte order.
+        ///
+        #[doc = $to_xe_bytes_doc]
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes();")]
+        #[doc = concat!("assert_eq!(bytes, ", $le_bytes, ");")]
+        /// ```
+        #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
+        #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        #[inline]
+        pub const fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            self.to_le().to_ne_bytes()
         }
 
-        doc_comment! {
-            concat!("
-Return the memory representation of this integer as a byte array in
-native byte order.
-
-As the target platform's native endianness is used, portable code
-should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate,
-instead.
-",
-$to_xe_bytes_doc,
-"
-[`to_be_bytes`]: #method.to_be_bytes
-[`to_le_bytes`]: #method.to_le_bytes
-
-# Examples
-
-```
-let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes();
-assert_eq!(
-    bytes,
-    if cfg!(target_endian = \"big\") {
-        ", $be_bytes, "
-    } else {
-        ", $le_bytes, "
-    }
-);
-```"),
-            #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
-            // SAFETY: const sound because integers are plain old datatypes so we can always
-            // transmute them to arrays of bytes
-            #[rustc_allow_const_fn_unstable(const_fn_transmute)]
-            #[inline]
-            pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
-                // SAFETY: integers are plain old datatypes so we can always transmute them to
-                // arrays of bytes
-                unsafe { mem::transmute(self) }
-            }
+        /// Return the memory representation of this integer as a byte array in
+        /// native byte order.
+        ///
+        /// As the target platform's native endianness is used, portable code
+        /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate,
+        /// instead.
+        ///
+        #[doc = $to_xe_bytes_doc]
+        ///
+        /// [`to_be_bytes`]: #method.to_be_bytes
+        /// [`to_le_bytes`]: #method.to_le_bytes
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes();")]
+        /// assert_eq!(
+        ///     bytes,
+        ///     if cfg!(target_endian = "big") {
+        #[doc = concat!("        ", $be_bytes)]
+        ///     } else {
+        #[doc = concat!("        ", $le_bytes)]
+        ///     }
+        /// );
+        /// ```
+        #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
+        #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        // SAFETY: const sound because integers are plain old datatypes so we can always
+        // transmute them to arrays of bytes
+        #[rustc_allow_const_fn_unstable(const_fn_transmute)]
+        #[inline]
+        pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            // SAFETY: integers are plain old datatypes so we can always transmute them to
+            // arrays of bytes
+            unsafe { mem::transmute(self) }
         }
 
-        doc_comment! {
-            concat!("
-Return the memory representation of this integer as a byte array in
-native byte order.
-
-[`to_ne_bytes`] should be preferred over this whenever possible.
-
-[`to_ne_bytes`]: #method.to_ne_bytes
-",
-
-"
-# Examples
-
-```
-#![feature(num_as_ne_bytes)]
-let num = ", $swap_op, stringify!($SelfT), ";
-let bytes = num.as_ne_bytes();
-assert_eq!(
-    bytes,
-    if cfg!(target_endian = \"big\") {
-        &", $be_bytes, "
-    } else {
-        &", $le_bytes, "
-    }
-);
-```"),
-            #[unstable(feature = "num_as_ne_bytes", issue = "76976")]
-            #[inline]
-            pub fn as_ne_bytes(&self) -> &[u8; mem::size_of::<Self>()] {
-                // SAFETY: integers are plain old datatypes so we can always transmute them to
-                // arrays of bytes
-                unsafe { &*(self as *const Self as *const _) }
-            }
+        /// Return the memory representation of this integer as a byte array in
+        /// native byte order.
+        ///
+        /// [`to_ne_bytes`] should be preferred over this whenever possible.
+        ///
+        /// [`to_ne_bytes`]: #method.to_ne_bytes
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(num_as_ne_bytes)]
+        #[doc = concat!("let num = ", $swap_op, stringify!($SelfT), ";")]
+        /// let bytes = num.as_ne_bytes();
+        /// assert_eq!(
+        ///     bytes,
+        ///     if cfg!(target_endian = "big") {
+        #[doc = concat!("        &", $be_bytes)]
+        ///     } else {
+        #[doc = concat!("        &", $le_bytes)]
+        ///     }
+        /// );
+        /// ```
+        #[unstable(feature = "num_as_ne_bytes", issue = "76976")]
+        #[inline]
+        pub fn as_ne_bytes(&self) -> &[u8; mem::size_of::<Self>()] {
+            // SAFETY: integers are plain old datatypes so we can always transmute them to
+            // arrays of bytes
+            unsafe { &*(self as *const Self as *const _) }
         }
 
-        doc_comment! {
-            concat!("Create a native endian integer value from its representation
-as a byte array in big endian.
-",
-$from_xe_bytes_doc,
-"
-# Examples
-
-```
-let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, ");
-assert_eq!(value, ", $swap_op, ");
-```
-
-When starting from a slice rather than an array, fallible conversion APIs can be used:
-
-```
-use std::convert::TryInto;
-
-fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
-    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
-    *input = rest;
-    ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())
-}
-```"),
-            #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
-            #[inline]
-            pub const fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
-                Self::from_be(Self::from_ne_bytes(bytes))
-            }
+        /// Create a native endian integer value from its representation
+        /// as a byte array in big endian.
+        ///
+        #[doc = $from_xe_bytes_doc]
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, ");")]
+        #[doc = concat!("assert_eq!(value, ", $swap_op, ");")]
+        /// ```
+        ///
+        /// When starting from a slice rather than an array, fallible conversion APIs can be used:
+        ///
+        /// ```
+        /// use std::convert::TryInto;
+        ///
+        #[doc = concat!("fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")]
+        #[doc = concat!("    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")]
+        ///     *input = rest;
+        #[doc = concat!("    ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())")]
+        /// }
+        /// ```
+        #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
+        #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        #[inline]
+        pub const fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            Self::from_be(Self::from_ne_bytes(bytes))
         }
 
-        doc_comment! {
-            concat!("
-Create a native endian integer value from its representation
-as a byte array in little endian.
-",
-$from_xe_bytes_doc,
-"
-# Examples
-
-```
-let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, ");
-assert_eq!(value, ", $swap_op, ");
-```
-
-When starting from a slice rather than an array, fallible conversion APIs can be used:
-
-```
-use std::convert::TryInto;
-
-fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
-    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
-    *input = rest;
-    ", stringify!($SelfT), "::from_le_bytes(int_bytes.try_into().unwrap())
-}
-```"),
-            #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
-            #[inline]
-            pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
-                Self::from_le(Self::from_ne_bytes(bytes))
-            }
+        /// Create a native endian integer value from its representation
+        /// as a byte array in little endian.
+        ///
+        #[doc = $from_xe_bytes_doc]
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, ");")]
+        #[doc = concat!("assert_eq!(value, ", $swap_op, ");")]
+        /// ```
+        ///
+        /// When starting from a slice rather than an array, fallible conversion APIs can be used:
+        ///
+        /// ```
+        /// use std::convert::TryInto;
+        ///
+        #[doc = concat!("fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")]
+        #[doc = concat!("    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")]
+        ///     *input = rest;
+        #[doc = concat!("    ", stringify!($SelfT), "::from_le_bytes(int_bytes.try_into().unwrap())")]
+        /// }
+        /// ```
+        #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
+        #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        #[inline]
+        pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            Self::from_le(Self::from_ne_bytes(bytes))
         }
 
-        doc_comment! {
-            concat!("Create a native endian integer value from its memory representation
-as a byte array in native endianness.
-
-As the target platform's native endianness is used, portable code
-likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
-appropriate instead.
-
-[`from_be_bytes`]: #method.from_be_bytes
-[`from_le_bytes`]: #method.from_le_bytes
-",
-$from_xe_bytes_doc,
-"
-# Examples
-
-```
-let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") {
-    ", $be_bytes, "
-} else {
-    ", $le_bytes, "
-});
-assert_eq!(value, ", $swap_op, ");
-```
-
-When starting from a slice rather than an array, fallible conversion APIs can be used:
-
-```
-use std::convert::TryInto;
-
-fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
-    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
-    *input = rest;
-    ", stringify!($SelfT), "::from_ne_bytes(int_bytes.try_into().unwrap())
-}
-```"),
-            #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
-            // SAFETY: const sound because integers are plain old datatypes so we can always
-            // transmute to them
-            #[rustc_allow_const_fn_unstable(const_fn_transmute)]
-            #[inline]
-            pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
-                // SAFETY: integers are plain old datatypes so we can always transmute to them
-                unsafe { mem::transmute(bytes) }
-            }
+        /// Create a native endian integer value from its memory representation
+        /// as a byte array in native endianness.
+        ///
+        /// As the target platform's native endianness is used, portable code
+        /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
+        /// appropriate instead.
+        ///
+        /// [`from_be_bytes`]: #method.from_be_bytes
+        /// [`from_le_bytes`]: #method.from_le_bytes
+        ///
+        #[doc = $from_xe_bytes_doc]
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") {")]
+        #[doc = concat!("    ", $be_bytes, "")]
+        /// } else {
+        #[doc = concat!("    ", $le_bytes, "")]
+        /// });
+        #[doc = concat!("assert_eq!(value, ", $swap_op, ");")]
+        /// ```
+        ///
+        /// When starting from a slice rather than an array, fallible conversion APIs can be used:
+        ///
+        /// ```
+        /// use std::convert::TryInto;
+        ///
+        #[doc = concat!("fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")]
+        #[doc = concat!("    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")]
+        ///     *input = rest;
+        #[doc = concat!("    ", stringify!($SelfT), "::from_ne_bytes(int_bytes.try_into().unwrap())")]
+        /// }
+        /// ```
+        #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
+        #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        // SAFETY: const sound because integers are plain old datatypes so we can always
+        // transmute to them
+        #[rustc_allow_const_fn_unstable(const_fn_transmute)]
+        #[inline]
+        pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            // SAFETY: integers are plain old datatypes so we can always transmute to them
+            unsafe { mem::transmute(bytes) }
         }
 
-        doc_comment! {
-            concat!("**This method is soft-deprecated.**
+        /// **This method is soft-deprecated.**
+        ///
+        /// Although using it won’t cause compilation warning, new code should use
+        #[doc = concat!("[`", stringify!($SelfT), "::MIN", "`](#associatedconstant.MIN)")]
+        /// instead.
+        ///
+        /// Returns the smallest value that can be represented by this integer type.
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_promotable]
+        #[inline(always)]
+        #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")]
+        pub const fn min_value() -> Self { Self::MIN }
 
-Although using it won’t cause compilation warning,
-new code should use [`", stringify!($SelfT), "::MIN", "`](#associatedconstant.MIN) instead.
-
-Returns the smallest value that can be represented by this integer type."),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_promotable]
-            #[inline(always)]
-            #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")]
-            pub const fn min_value() -> Self { Self::MIN }
-        }
-
-        doc_comment! {
-            concat!("**This method is soft-deprecated.**
-
-Although using it won’t cause compilation warning,
-new code should use [`", stringify!($SelfT), "::MAX", "`](#associatedconstant.MAX) instead.
-
-Returns the largest value that can be represented by this integer type."),
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_promotable]
-            #[inline(always)]
-            #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")]
-            pub const fn max_value() -> Self { Self::MAX }
-        }
+        /// **This method is soft-deprecated.**
+        ///
+        /// Although using it won’t cause compilation warning, new code should use
+        #[doc = concat!("[`", stringify!($SelfT), "::MAX", "`](#associatedconstant.MAX)")]
+        /// instead.
+        ///
+        /// Returns the largest value that can be represented by this integer type.
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_promotable]
+        #[inline(always)]
+        #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")]
+        pub const fn max_value() -> Self { Self::MAX }
     }
 }
diff --git a/library/core/src/num/wrapping.rs b/library/core/src/num/wrapping.rs
index 77c9a93..f1b9dab 100644
--- a/library/core/src/num/wrapping.rs
+++ b/library/core/src/num/wrapping.rs
@@ -403,105 +403,94 @@
 macro_rules! wrapping_int_impl {
     ($($t:ty)*) => ($(
         impl Wrapping<$t> {
-            doc_comment! {
-                concat!("Returns the smallest value that can be represented by this integer type.
+            /// Returns the smallest value that can be represented by this integer type.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("assert_eq!(<Wrapping<", stringify!($t), ">>::MIN, Wrapping(", stringify!($t), "::MIN));")]
+            /// ```
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub const MIN: Self = Self(<$t>::MIN);
 
-# Examples
+            /// Returns the largest value that can be represented by this integer type.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("assert_eq!(<Wrapping<", stringify!($t), ">>::MAX, Wrapping(", stringify!($t), "::MAX));")]
+            /// ```
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub const MAX: Self = Self(<$t>::MAX);
 
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-assert_eq!(<Wrapping<", stringify!($t), ">>::MIN, Wrapping(", stringify!($t), "::MIN));
-```"),
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub const MIN: Self = Self(<$t>::MIN);
+            /// Returns the number of ones in the binary representation of `self`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("let n = Wrapping(0b01001100", stringify!($t), ");")]
+            ///
+            /// assert_eq!(n.count_ones(), 3);
+            /// ```
+            #[inline]
+            #[doc(alias = "popcount")]
+            #[doc(alias = "popcnt")]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub const fn count_ones(self) -> u32 {
+                self.0.count_ones()
             }
 
-            doc_comment! {
-                concat!("Returns the largest value that can be represented by this integer type.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-assert_eq!(<Wrapping<", stringify!($t), ">>::MAX, Wrapping(", stringify!($t), "::MAX));
-```"),
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub const MAX: Self = Self(<$t>::MAX);
+            /// Returns the number of zeros in the binary representation of `self`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("assert_eq!(Wrapping(!0", stringify!($t), ").count_zeros(), 0);")]
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub const fn count_zeros(self) -> u32 {
+                self.0.count_zeros()
             }
 
-            doc_comment! {
-                concat!("Returns the number of ones in the binary representation of `self`.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-let n = Wrapping(0b01001100", stringify!($t), ");
-
-assert_eq!(n.count_ones(), 3);
-```"),
-                #[inline]
-                #[doc(alias = "popcount")]
-                #[doc(alias = "popcnt")]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub const fn count_ones(self) -> u32 {
-                    self.0.count_ones()
-                }
-            }
-
-            doc_comment! {
-                concat!("Returns the number of zeros in the binary representation of `self`.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-assert_eq!(Wrapping(!0", stringify!($t), ").count_zeros(), 0);
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub const fn count_zeros(self) -> u32 {
-                    self.0.count_zeros()
-                }
-            }
-
-            doc_comment! {
-                concat!("Returns the number of trailing zeros in the binary representation
-of `self`.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-let n = Wrapping(0b0101000", stringify!($t), ");
-
-assert_eq!(n.trailing_zeros(), 3);
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub const fn trailing_zeros(self) -> u32 {
-                    self.0.trailing_zeros()
-                }
+            /// Returns the number of trailing zeros in the binary representation of `self`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("let n = Wrapping(0b0101000", stringify!($t), ");")]
+            ///
+            /// assert_eq!(n.trailing_zeros(), 3);
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub const fn trailing_zeros(self) -> u32 {
+                self.0.trailing_zeros()
             }
 
             /// Shifts the bits to the left by a specified amount, `n`,
@@ -608,150 +597,140 @@
                 Wrapping(self.0.reverse_bits())
             }
 
-            doc_comment! {
-                concat!("Converts an integer from big endian to the target's endianness.
-
-On big endian this is a no-op. On little endian the bytes are
-swapped.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-let n = Wrapping(0x1A", stringify!($t), ");
-
-if cfg!(target_endian = \"big\") {
-    assert_eq!(<Wrapping<", stringify!($t), ">>::from_be(n), n)
-} else {
-    assert_eq!(<Wrapping<", stringify!($t), ">>::from_be(n), n.swap_bytes())
-}
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub const fn from_be(x: Self) -> Self {
-                    Wrapping(<$t>::from_be(x.0))
-                }
+            /// Converts an integer from big endian to the target's endianness.
+            ///
+            /// On big endian this is a no-op. On little endian the bytes are
+            /// swapped.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("let n = Wrapping(0x1A", stringify!($t), ");")]
+            ///
+            /// if cfg!(target_endian = "big") {
+            #[doc = concat!("    assert_eq!(<Wrapping<", stringify!($t), ">>::from_be(n), n)")]
+            /// } else {
+            #[doc = concat!("    assert_eq!(<Wrapping<", stringify!($t), ">>::from_be(n), n.swap_bytes())")]
+            /// }
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub const fn from_be(x: Self) -> Self {
+                Wrapping(<$t>::from_be(x.0))
             }
 
-            doc_comment! {
-                concat!("Converts an integer from little endian to the target's endianness.
-
-On little endian this is a no-op. On big endian the bytes are
-swapped.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-let n = Wrapping(0x1A", stringify!($t), ");
-
-if cfg!(target_endian = \"little\") {
-    assert_eq!(<Wrapping<", stringify!($t), ">>::from_le(n), n)
-} else {
-    assert_eq!(<Wrapping<", stringify!($t), ">>::from_le(n), n.swap_bytes())
-}
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub const fn from_le(x: Self) -> Self {
-                    Wrapping(<$t>::from_le(x.0))
-                }
+            /// Converts an integer from little endian to the target's endianness.
+            ///
+            /// On little endian this is a no-op. On big endian the bytes are
+            /// swapped.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("let n = Wrapping(0x1A", stringify!($t), ");")]
+            ///
+            /// if cfg!(target_endian = "little") {
+            #[doc = concat!("    assert_eq!(<Wrapping<", stringify!($t), ">>::from_le(n), n)")]
+            /// } else {
+            #[doc = concat!("    assert_eq!(<Wrapping<", stringify!($t), ">>::from_le(n), n.swap_bytes())")]
+            /// }
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub const fn from_le(x: Self) -> Self {
+                Wrapping(<$t>::from_le(x.0))
             }
 
-            doc_comment! {
-                concat!("Converts `self` to big endian from the target's endianness.
-
-On big endian this is a no-op. On little endian the bytes are
-swapped.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-let n = Wrapping(0x1A", stringify!($t), ");
-
-if cfg!(target_endian = \"big\") {
-    assert_eq!(n.to_be(), n)
-} else {
-    assert_eq!(n.to_be(), n.swap_bytes())
-}
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub const fn to_be(self) -> Self {
-                    Wrapping(self.0.to_be())
-                }
+            /// Converts `self` to big endian from the target's endianness.
+            ///
+            /// On big endian this is a no-op. On little endian the bytes are
+            /// swapped.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("let n = Wrapping(0x1A", stringify!($t), ");")]
+            ///
+            /// if cfg!(target_endian = "big") {
+            ///     assert_eq!(n.to_be(), n)
+            /// } else {
+            ///     assert_eq!(n.to_be(), n.swap_bytes())
+            /// }
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub const fn to_be(self) -> Self {
+                Wrapping(self.0.to_be())
             }
 
-            doc_comment! {
-                concat!("Converts `self` to little endian from the target's endianness.
-
-On little endian this is a no-op. On big endian the bytes are
-swapped.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-let n = Wrapping(0x1A", stringify!($t), ");
-
-if cfg!(target_endian = \"little\") {
-    assert_eq!(n.to_le(), n)
-} else {
-    assert_eq!(n.to_le(), n.swap_bytes())
-}
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub const fn to_le(self) -> Self {
-                    Wrapping(self.0.to_le())
-                }
+            /// Converts `self` to little endian from the target's endianness.
+            ///
+            /// On little endian this is a no-op. On big endian the bytes are
+            /// swapped.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("let n = Wrapping(0x1A", stringify!($t), ");")]
+            ///
+            /// if cfg!(target_endian = "little") {
+            ///     assert_eq!(n.to_le(), n)
+            /// } else {
+            ///     assert_eq!(n.to_le(), n.swap_bytes())
+            /// }
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub const fn to_le(self) -> Self {
+                Wrapping(self.0.to_le())
             }
 
-        doc_comment! {
-            concat!("Raises self to the power of `exp`, using exponentiation by squaring.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-assert_eq!(Wrapping(3", stringify!($t), ").pow(4), Wrapping(81));
-```
-
-Results that are too large are wrapped:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-assert_eq!(Wrapping(3i8).pow(5), Wrapping(-13));
-assert_eq!(Wrapping(3i8).pow(6), Wrapping(-39));
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn pow(self, exp: u32) -> Self {
-                    Wrapping(self.0.wrapping_pow(exp))
-                }
+            /// Raises self to the power of `exp`, using exponentiation by squaring.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("assert_eq!(Wrapping(3", stringify!($t), ").pow(4), Wrapping(81));")]
+            /// ```
+            ///
+            /// Results that are too large are wrapped:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            /// assert_eq!(Wrapping(3i8).pow(5), Wrapping(-13));
+            /// assert_eq!(Wrapping(3i8).pow(6), Wrapping(-39));
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn pow(self, exp: u32) -> Self {
+                Wrapping(self.0.wrapping_pow(exp))
             }
         }
     )*)
@@ -762,124 +741,114 @@
 macro_rules! wrapping_int_impl_signed {
     ($($t:ty)*) => ($(
         impl Wrapping<$t> {
-            doc_comment! {
-                concat!("Returns the number of leading zeros in the binary representation of `self`.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-let n = Wrapping(", stringify!($t), "::MAX) >> 2;
-
-assert_eq!(n.leading_zeros(), 3);
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub const fn leading_zeros(self) -> u32 {
-                    self.0.leading_zeros()
-                }
+            /// Returns the number of leading zeros in the binary representation of `self`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("let n = Wrapping(", stringify!($t), "::MAX) >> 2;")]
+            ///
+            /// assert_eq!(n.leading_zeros(), 3);
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub const fn leading_zeros(self) -> u32 {
+                self.0.leading_zeros()
             }
 
-            doc_comment! {
-                concat!("Computes the absolute value of `self`, wrapping around at
-the boundary of the type.
-
-The only case where such wrapping can occur is when one takes the absolute value of the negative
-minimal value for the type this is a positive value that is too large to represent in the type. In
-such a case, this function returns `MIN` itself.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-assert_eq!(Wrapping(100", stringify!($t), ").abs(), Wrapping(100));
-assert_eq!(Wrapping(-100", stringify!($t), ").abs(), Wrapping(100));
-assert_eq!(Wrapping(", stringify!($t), "::MIN).abs(), Wrapping(", stringify!($t), "::MIN));
-assert_eq!(Wrapping(-128i8).abs().0 as u8, 128u8);
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn abs(self) -> Wrapping<$t> {
-                    Wrapping(self.0.wrapping_abs())
-                }
+            /// Computes the absolute value of `self`, wrapping around at
+            /// the boundary of the type.
+            ///
+            /// The only case where such wrapping can occur is when one takes the absolute value of the negative
+            /// minimal value for the type this is a positive value that is too large to represent in the type. In
+            /// such a case, this function returns `MIN` itself.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("assert_eq!(Wrapping(100", stringify!($t), ").abs(), Wrapping(100));")]
+            #[doc = concat!("assert_eq!(Wrapping(-100", stringify!($t), ").abs(), Wrapping(100));")]
+            #[doc = concat!("assert_eq!(Wrapping(", stringify!($t), "::MIN).abs(), Wrapping(", stringify!($t), "::MIN));")]
+            /// assert_eq!(Wrapping(-128i8).abs().0 as u8, 128u8);
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn abs(self) -> Wrapping<$t> {
+                Wrapping(self.0.wrapping_abs())
             }
 
-            doc_comment! {
-                concat!("Returns a number representing sign of `self`.
-
- - `0` if the number is zero
- - `1` if the number is positive
- - `-1` if the number is negative
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-assert_eq!(Wrapping(10", stringify!($t), ").signum(), Wrapping(1));
-assert_eq!(Wrapping(0", stringify!($t), ").signum(), Wrapping(0));
-assert_eq!(Wrapping(-10", stringify!($t), ").signum(), Wrapping(-1));
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn signum(self) -> Wrapping<$t> {
-                    Wrapping(self.0.signum())
-                }
+            /// Returns a number representing sign of `self`.
+            ///
+            ///  - `0` if the number is zero
+            ///  - `1` if the number is positive
+            ///  - `-1` if the number is negative
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("assert_eq!(Wrapping(10", stringify!($t), ").signum(), Wrapping(1));")]
+            #[doc = concat!("assert_eq!(Wrapping(0", stringify!($t), ").signum(), Wrapping(0));")]
+            #[doc = concat!("assert_eq!(Wrapping(-10", stringify!($t), ").signum(), Wrapping(-1));")]
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn signum(self) -> Wrapping<$t> {
+                Wrapping(self.0.signum())
             }
 
-            doc_comment! {
-                concat!("Returns `true` if `self` is positive and `false` if the number is zero or
-negative.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-assert!(Wrapping(10", stringify!($t), ").is_positive());
-assert!(!Wrapping(-10", stringify!($t), ").is_positive());
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub const fn is_positive(self) -> bool {
-                    self.0.is_positive()
-                }
+            /// Returns `true` if `self` is positive and `false` if the number is zero or
+            /// negative.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("assert!(Wrapping(10", stringify!($t), ").is_positive());")]
+            #[doc = concat!("assert!(!Wrapping(-10", stringify!($t), ").is_positive());")]
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub const fn is_positive(self) -> bool {
+                self.0.is_positive()
             }
 
-            doc_comment! {
-                concat!("Returns `true` if `self` is negative and `false` if the number is zero or
-positive.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-assert!(Wrapping(-10", stringify!($t), ").is_negative());
-assert!(!Wrapping(10", stringify!($t), ").is_negative());
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub const fn is_negative(self) -> bool {
-                    self.0.is_negative()
-                }
+            /// Returns `true` if `self` is negative and `false` if the number is zero or
+            /// positive.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("assert!(Wrapping(-10", stringify!($t), ").is_negative());")]
+            #[doc = concat!("assert!(!Wrapping(10", stringify!($t), ").is_negative());")]
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub const fn is_negative(self) -> bool {
+                self.0.is_negative()
             }
         }
     )*)
@@ -890,73 +859,67 @@
 macro_rules! wrapping_int_impl_unsigned {
     ($($t:ty)*) => ($(
         impl Wrapping<$t> {
-            doc_comment! {
-                concat!("Returns the number of leading zeros in the binary representation of `self`.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-let n = Wrapping(", stringify!($t), "::MAX) >> 2;
-
-assert_eq!(n.leading_zeros(), 2);
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub const fn leading_zeros(self) -> u32 {
-                    self.0.leading_zeros()
-                }
+            /// Returns the number of leading zeros in the binary representation of `self`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("let n = Wrapping(", stringify!($t), "::MAX) >> 2;")]
+            ///
+            /// assert_eq!(n.leading_zeros(), 2);
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub const fn leading_zeros(self) -> u32 {
+                self.0.leading_zeros()
             }
 
-            doc_comment! {
-                concat!("Returns `true` if and only if `self == 2^k` for some `k`.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_int_impl)]
-use std::num::Wrapping;
-
-assert!(Wrapping(16", stringify!($t), ").is_power_of_two());
-assert!(!Wrapping(10", stringify!($t), ").is_power_of_two());
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn is_power_of_two(self) -> bool {
-                    self.0.is_power_of_two()
-                }
+            /// Returns `true` if and only if `self == 2^k` for some `k`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("assert!(Wrapping(16", stringify!($t), ").is_power_of_two());")]
+            #[doc = concat!("assert!(!Wrapping(10", stringify!($t), ").is_power_of_two());")]
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn is_power_of_two(self) -> bool {
+                self.0.is_power_of_two()
             }
 
-            doc_comment! {
-                concat!("Returns the smallest power of two greater than or equal to `self`.
-
-When return value overflows (i.e., `self > (1 << (N-1))` for type
-`uN`), overflows to `2^N = 0`.
-
-# Examples
-
-Basic usage:
-
-```
-#![feature(wrapping_next_power_of_two)]
-use std::num::Wrapping;
-
-assert_eq!(Wrapping(2", stringify!($t), ").next_power_of_two(), Wrapping(2));
-assert_eq!(Wrapping(3", stringify!($t), ").next_power_of_two(), Wrapping(4));
-assert_eq!(Wrapping(200_u8).next_power_of_two(), Wrapping(0));
-```"),
-                #[inline]
-                #[unstable(feature = "wrapping_next_power_of_two", issue = "32463",
-                           reason = "needs decision on wrapping behaviour")]
-                pub fn next_power_of_two(self) -> Self {
-                    Wrapping(self.0.wrapping_next_power_of_two())
-                }
+            /// Returns the smallest power of two greater than or equal to `self`.
+            ///
+            /// When return value overflows (i.e., `self > (1 << (N-1))` for type
+            /// `uN`), overflows to `2^N = 0`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_next_power_of_two)]
+            /// use std::num::Wrapping;
+            ///
+            #[doc = concat!("assert_eq!(Wrapping(2", stringify!($t), ").next_power_of_two(), Wrapping(2));")]
+            #[doc = concat!("assert_eq!(Wrapping(3", stringify!($t), ").next_power_of_two(), Wrapping(4));")]
+            #[doc = concat!("assert_eq!(Wrapping(200_u8).next_power_of_two(), Wrapping(0));")]
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_next_power_of_two", issue = "32463",
+                       reason = "needs decision on wrapping behaviour")]
+            pub fn next_power_of_two(self) -> Self {
+                Wrapping(self.0.wrapping_next_power_of_two())
             }
         }
     )*)
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index 1d67e65..0571dc7 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -678,6 +678,29 @@
     Unbounded,
 }
 
+#[unstable(feature = "bound_as_ref", issue = "80996")]
+impl<T> Bound<T> {
+    /// Converts from `&Bound<T>` to `Bound<&T>`.
+    #[inline]
+    pub fn as_ref(&self) -> Bound<&T> {
+        match *self {
+            Included(ref x) => Included(x),
+            Excluded(ref x) => Excluded(x),
+            Unbounded => Unbounded,
+        }
+    }
+
+    /// Converts from `&mut Bound<T>` to `Bound<&T>`.
+    #[inline]
+    pub fn as_mut(&mut self) -> Bound<&mut T> {
+        match *self {
+            Included(ref mut x) => Included(x),
+            Excluded(ref mut x) => Excluded(x),
+            Unbounded => Unbounded,
+        }
+    }
+}
+
 impl<T: Clone> Bound<&T> {
     /// Map a `Bound<&T>` to a `Bound<T>` by cloning the contents of the bound.
     ///
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 1afa30f..0051c9e 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -512,7 +512,6 @@
     /// result of a function call, it is recommended to use [`ok_or_else`], which is
     /// lazily evaluated.
     ///
-    /// [`Result<T, E>`]: Result
     /// [`Ok(v)`]: Ok
     /// [`Err(err)`]: Err
     /// [`Some(v)`]: Some
@@ -539,7 +538,6 @@
     /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to
     /// [`Ok(v)`] and [`None`] to [`Err(err())`].
     ///
-    /// [`Result<T, E>`]: Result
     /// [`Ok(v)`]: Ok
     /// [`Err(err())`]: Err
     /// [`Some(v)`]: Some
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 0b9c733..b2de0e1 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -349,7 +349,6 @@
 //! mutable reference even when you just have [`Pin`]`<&mut Self>` (such as in your own
 //! [`poll`] implementation).
 //!
-//! [`Pin<P>`]: Pin
 //! [`Deref`]: crate::ops::Deref
 //! [`DerefMut`]: crate::ops::DerefMut
 //! [`mem::swap`]: crate::mem::swap
@@ -364,7 +363,6 @@
 //! [`RefCell<T>`]: crate::cell::RefCell
 //! [`drop`]: Drop::drop
 //! [`VecDeque<T>`]: ../../std/collections/struct.VecDeque.html
-//! [`Option<T>`]: Option
 //! [`Some(v)`]: Some
 //! [`ptr::write`]: crate::ptr::write
 //! [`Future`]: crate::future::Future
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 807f114..d2e1bac 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -883,12 +883,19 @@
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn write<T>(dst: *mut T, src: T) {
-    if cfg!(debug_assertions) && !is_aligned_and_not_null(dst) {
-        // Not panicking to keep codegen impact smaller.
-        abort();
+    // We are calling the intrinsics directly to avoid function calls in the generated code
+    // as `intrinsics::copy_nonoverlapping` is a wrapper function.
+    extern "rust-intrinsic" {
+        fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
     }
-    // SAFETY: the caller must uphold the safety contract for `move_val_init`.
-    unsafe { intrinsics::move_val_init(&mut *dst, src) }
+
+    // SAFETY: the caller must guarantee that `dst` is valid for writes.
+    // `dst` cannot overlap `src` because the caller has mutable access
+    // to `dst` while `src` is owned by this function.
+    unsafe {
+        copy_nonoverlapping(&src as *const T, dst, 1);
+        intrinsics::forget(src);
+    }
 }
 
 /// Overwrites a memory location with the given value without reading or
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 0b4ca2b..d6d1762 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -368,8 +368,6 @@
     /// Converts `self` into an [`Option<T>`], consuming `self`,
     /// and discarding the error, if any.
     ///
-    /// [`Option<T>`]: Option
-    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -395,8 +393,6 @@
     /// Converts `self` into an [`Option<E>`], consuming `self`,
     /// and discarding the success value, if any.
     ///
-    /// [`Option<E>`]: Option
-    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1009,8 +1005,6 @@
     /// Panics if the value is an [`Ok`], with a custom panic message provided
     /// by the [`Ok`]'s value.
     ///
-    ///
-    ///
     /// # Examples
     ///
     /// ```{.should_panic}
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index e373936..5066426 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -1,3 +1,4 @@
+// ignore-tidy-filelength
 //! Definitions of a bunch of iterators for `[T]`.
 
 #[macro_use] // import iterator! and forward_iterator!
@@ -50,7 +51,7 @@
 /// Basic usage:
 ///
 /// ```
-/// // First, we declare a type which has `iter` method to get the `Iter` struct (&[usize here]):
+/// // First, we declare a type which has `iter` method to get the `Iter` struct (`&[usize]` here):
 /// let slice = &[1, 2, 3];
 ///
 /// // Then, we iterate over it:
@@ -111,7 +112,7 @@
     ///
     /// ```
     /// // First, we declare a type which has the `iter` method to get the `Iter`
-    /// // struct (&[usize here]):
+    /// // struct (`&[usize]` here):
     /// let slice = &[1, 2, 3];
     ///
     /// // Then, we get the iterator:
@@ -166,7 +167,7 @@
 ///
 /// ```
 /// // First, we declare a type which has `iter_mut` method to get the `IterMut`
-/// // struct (&[usize here]):
+/// // struct (`&[usize]` here):
 /// let mut slice = &mut [1, 2, 3];
 ///
 /// // Then, we iterate over it and increment each element value:
@@ -245,7 +246,7 @@
     ///
     /// ```
     /// // First, we declare a type which has `iter_mut` method to get the `IterMut`
-    /// // struct (&[usize here]):
+    /// // struct (`&[usize]` here):
     /// let mut slice = &mut [1, 2, 3];
     ///
     /// {
@@ -445,15 +446,13 @@
 /// # Example
 ///
 /// ```
-/// #![feature(split_inclusive)]
-///
 /// let slice = [10, 40, 33, 20];
 /// let mut iter = slice.split_inclusive(|num| num % 3 == 0);
 /// ```
 ///
 /// [`split_inclusive`]: ../../std/primitive.slice.html#method.split_inclusive
 /// [slices]: ../../std/primitive.slice.html
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 pub struct SplitInclusive<'a, T: 'a, P>
 where
     P: FnMut(&T) -> bool,
@@ -470,7 +469,7 @@
     }
 }
 
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 impl<T: fmt::Debug, P> fmt::Debug for SplitInclusive<'_, T, P>
 where
     P: FnMut(&T) -> bool,
@@ -484,7 +483,7 @@
 }
 
 // FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 impl<T, P> Clone for SplitInclusive<'_, T, P>
 where
     P: Clone + FnMut(&T) -> bool,
@@ -494,7 +493,7 @@
     }
 }
 
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 impl<'a, T, P> Iterator for SplitInclusive<'a, T, P>
 where
     P: FnMut(&T) -> bool,
@@ -523,7 +522,7 @@
     }
 }
 
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 impl<'a, T, P> DoubleEndedIterator for SplitInclusive<'a, T, P>
 where
     P: FnMut(&T) -> bool,
@@ -548,7 +547,7 @@
     }
 }
 
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 impl<T, P> FusedIterator for SplitInclusive<'_, T, P> where P: FnMut(&T) -> bool {}
 
 /// An iterator over the mutable subslices of the vector which are separated
@@ -688,15 +687,13 @@
 /// # Example
 ///
 /// ```
-/// #![feature(split_inclusive)]
-///
 /// let mut v = [10, 40, 30, 20, 60, 50];
 /// let iter = v.split_inclusive_mut(|num| *num % 3 == 0);
 /// ```
 ///
 /// [`split_inclusive_mut`]: ../../std/primitive.slice.html#method.split_inclusive_mut
 /// [slices]: ../../std/primitive.slice.html
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 pub struct SplitInclusiveMut<'a, T: 'a, P>
 where
     P: FnMut(&T) -> bool,
@@ -713,7 +710,7 @@
     }
 }
 
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 impl<T: fmt::Debug, P> fmt::Debug for SplitInclusiveMut<'_, T, P>
 where
     P: FnMut(&T) -> bool,
@@ -726,7 +723,7 @@
     }
 }
 
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 impl<'a, T, P> Iterator for SplitInclusiveMut<'a, T, P>
 where
     P: FnMut(&T) -> bool,
@@ -766,7 +763,7 @@
     }
 }
 
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 impl<'a, T, P> DoubleEndedIterator for SplitInclusiveMut<'a, T, P>
 where
     P: FnMut(&T) -> bool,
@@ -800,7 +797,7 @@
     }
 }
 
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 impl<T, P> FusedIterator for SplitInclusiveMut<'_, T, P> where P: FnMut(&T) -> bool {}
 
 /// An iterator over subslices separated by elements that match a predicate
@@ -2967,3 +2964,176 @@
         false
     }
 }
+
+/// An iterator over slice in (non-overlapping) chunks separated by a predicate.
+///
+/// This struct is created by the [`group_by`] method on [slices].
+///
+/// [`group_by`]: ../../std/primitive.slice.html#method.group_by
+/// [slices]: ../../std/primitive.slice.html
+#[unstable(feature = "slice_group_by", issue = "80552")]
+pub struct GroupBy<'a, T: 'a, P> {
+    slice: &'a [T],
+    predicate: P,
+}
+
+#[unstable(feature = "slice_group_by", issue = "80552")]
+impl<'a, T: 'a, P> GroupBy<'a, T, P> {
+    pub(super) fn new(slice: &'a [T], predicate: P) -> Self {
+        GroupBy { slice, predicate }
+    }
+}
+
+#[unstable(feature = "slice_group_by", issue = "80552")]
+impl<'a, T: 'a, P> Iterator for GroupBy<'a, T, P>
+where
+    P: FnMut(&T, &T) -> bool,
+{
+    type Item = &'a [T];
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.slice.is_empty() {
+            None
+        } else {
+            let mut len = 1;
+            let mut iter = self.slice.windows(2);
+            while let Some([l, r]) = iter.next() {
+                if (self.predicate)(l, r) { len += 1 } else { break }
+            }
+            let (head, tail) = self.slice.split_at(len);
+            self.slice = tail;
+            Some(head)
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.slice.is_empty() { (0, Some(0)) } else { (1, Some(self.slice.len())) }
+    }
+
+    #[inline]
+    fn last(mut self) -> Option<Self::Item> {
+        self.next_back()
+    }
+}
+
+#[unstable(feature = "slice_group_by", issue = "80552")]
+impl<'a, T: 'a, P> DoubleEndedIterator for GroupBy<'a, T, P>
+where
+    P: FnMut(&T, &T) -> bool,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<Self::Item> {
+        if self.slice.is_empty() {
+            None
+        } else {
+            let mut len = 1;
+            let mut iter = self.slice.windows(2);
+            while let Some([l, r]) = iter.next_back() {
+                if (self.predicate)(l, r) { len += 1 } else { break }
+            }
+            let (head, tail) = self.slice.split_at(self.slice.len() - len);
+            self.slice = head;
+            Some(tail)
+        }
+    }
+}
+
+#[unstable(feature = "slice_group_by", issue = "80552")]
+impl<'a, T: 'a, P> FusedIterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool {}
+
+#[unstable(feature = "slice_group_by", issue = "80552")]
+impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupBy<'a, T, P> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("GroupBy").field("slice", &self.slice).finish()
+    }
+}
+
+/// An iterator over slice in (non-overlapping) mutable chunks separated
+/// by a predicate.
+///
+/// This struct is created by the [`group_by_mut`] method on [slices].
+///
+/// [`group_by_mut`]: ../../std/primitive.slice.html#method.group_by_mut
+/// [slices]: ../../std/primitive.slice.html
+#[unstable(feature = "slice_group_by", issue = "80552")]
+pub struct GroupByMut<'a, T: 'a, P> {
+    slice: &'a mut [T],
+    predicate: P,
+}
+
+#[unstable(feature = "slice_group_by", issue = "80552")]
+impl<'a, T: 'a, P> GroupByMut<'a, T, P> {
+    pub(super) fn new(slice: &'a mut [T], predicate: P) -> Self {
+        GroupByMut { slice, predicate }
+    }
+}
+
+#[unstable(feature = "slice_group_by", issue = "80552")]
+impl<'a, T: 'a, P> Iterator for GroupByMut<'a, T, P>
+where
+    P: FnMut(&T, &T) -> bool,
+{
+    type Item = &'a mut [T];
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.slice.is_empty() {
+            None
+        } else {
+            let mut len = 1;
+            let mut iter = self.slice.windows(2);
+            while let Some([l, r]) = iter.next() {
+                if (self.predicate)(l, r) { len += 1 } else { break }
+            }
+            let slice = mem::take(&mut self.slice);
+            let (head, tail) = slice.split_at_mut(len);
+            self.slice = tail;
+            Some(head)
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.slice.is_empty() { (0, Some(0)) } else { (1, Some(self.slice.len())) }
+    }
+
+    #[inline]
+    fn last(mut self) -> Option<Self::Item> {
+        self.next_back()
+    }
+}
+
+#[unstable(feature = "slice_group_by", issue = "80552")]
+impl<'a, T: 'a, P> DoubleEndedIterator for GroupByMut<'a, T, P>
+where
+    P: FnMut(&T, &T) -> bool,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<Self::Item> {
+        if self.slice.is_empty() {
+            None
+        } else {
+            let mut len = 1;
+            let mut iter = self.slice.windows(2);
+            while let Some([l, r]) = iter.next_back() {
+                if (self.predicate)(l, r) { len += 1 } else { break }
+            }
+            let slice = mem::take(&mut self.slice);
+            let (head, tail) = slice.split_at_mut(slice.len() - len);
+            self.slice = head;
+            Some(tail)
+        }
+    }
+}
+
+#[unstable(feature = "slice_group_by", issue = "80552")]
+impl<'a, T: 'a, P> FusedIterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool {}
+
+#[unstable(feature = "slice_group_by", issue = "80552")]
+impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupByMut<'a, T, P> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("GroupByMut").field("slice", &self.slice).finish()
+    }
+}
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index bb10143..de8d7fc 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -57,7 +57,10 @@
 #[unstable(feature = "array_windows", issue = "75027")]
 pub use iter::ArrayWindows;
 
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[unstable(feature = "slice_group_by", issue = "80552")]
+pub use iter::{GroupBy, GroupByMut};
+
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 pub use iter::{SplitInclusive, SplitInclusiveMut};
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -886,6 +889,46 @@
     }
 
     /// Splits the slice into a slice of `N`-element arrays,
+    /// assuming that there's no remainder.
+    ///
+    /// # Safety
+    ///
+    /// This may only be called when
+    /// - The slice splits exactly into `N`-element chunks (aka `self.len() % N == 0`).
+    /// - `N != 0`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_as_chunks)]
+    /// let slice: &[char] = &['l', 'o', 'r', 'e', 'm', '!'];
+    /// let chunks: &[[char; 1]] =
+    ///     // SAFETY: 1-element chunks never have remainder
+    ///     unsafe { slice.as_chunks_unchecked() };
+    /// assert_eq!(chunks, &[['l'], ['o'], ['r'], ['e'], ['m'], ['!']]);
+    /// let chunks: &[[char; 3]] =
+    ///     // SAFETY: The slice length (6) is a multiple of 3
+    ///     unsafe { slice.as_chunks_unchecked() };
+    /// assert_eq!(chunks, &[['l', 'o', 'r'], ['e', 'm', '!']]);
+    ///
+    /// // These would be unsound:
+    /// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked() // The slice length is not a multiple of 5
+    /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked() // Zero-length chunks are never allowed
+    /// ```
+    #[unstable(feature = "slice_as_chunks", issue = "74985")]
+    #[inline]
+    pub unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
+        debug_assert_ne!(N, 0);
+        debug_assert_eq!(self.len() % N, 0);
+        let new_len =
+            // SAFETY: Our precondition is exactly what's needed to call this
+            unsafe { crate::intrinsics::exact_div(self.len(), N) };
+        // SAFETY: We cast a slice of `new_len * N` elements into
+        // a slice of `new_len` many `N` elements chunks.
+        unsafe { from_raw_parts(self.as_ptr().cast(), new_len) }
+    }
+
+    /// Splits the slice into a slice of `N`-element arrays,
     /// starting at the beginning of the slice,
     /// and a remainder slice with length strictly less than `N`.
     ///
@@ -909,12 +952,42 @@
         assert_ne!(N, 0);
         let len = self.len() / N;
         let (multiple_of_n, remainder) = self.split_at(len * N);
-        // SAFETY: We cast a slice of `len * N` elements into
-        // a slice of `len` many `N` elements chunks.
-        let array_slice: &[[T; N]] = unsafe { from_raw_parts(multiple_of_n.as_ptr().cast(), len) };
+        // SAFETY: We already panicked for zero, and ensured by construction
+        // that the length of the subslice is a multiple of N.
+        let array_slice = unsafe { multiple_of_n.as_chunks_unchecked() };
         (array_slice, remainder)
     }
 
+    /// Splits the slice into a slice of `N`-element arrays,
+    /// starting at the end of the slice,
+    /// and a remainder slice with length strictly less than `N`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `N` is 0. This check will most probably get changed to a compile time
+    /// error before this method gets stabilized.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_as_chunks)]
+    /// let slice = ['l', 'o', 'r', 'e', 'm'];
+    /// let (remainder, chunks) = slice.as_rchunks();
+    /// assert_eq!(remainder, &['l']);
+    /// assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]);
+    /// ```
+    #[unstable(feature = "slice_as_chunks", issue = "74985")]
+    #[inline]
+    pub fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) {
+        assert_ne!(N, 0);
+        let len = self.len() / N;
+        let (remainder, multiple_of_n) = self.split_at(self.len() - len * N);
+        // SAFETY: We already panicked for zero, and ensured by construction
+        // that the length of the subslice is a multiple of N.
+        let array_slice = unsafe { multiple_of_n.as_chunks_unchecked() };
+        (remainder, array_slice)
+    }
+
     /// Returns an iterator over `N` elements of the slice at a time, starting at the
     /// beginning of the slice.
     ///
@@ -950,6 +1023,48 @@
     }
 
     /// Splits the slice into a slice of `N`-element arrays,
+    /// assuming that there's no remainder.
+    ///
+    /// # Safety
+    ///
+    /// This may only be called when
+    /// - The slice splits exactly into `N`-element chunks (aka `self.len() % N == 0`).
+    /// - `N != 0`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_as_chunks)]
+    /// let slice: &mut [char] = &mut ['l', 'o', 'r', 'e', 'm', '!'];
+    /// let chunks: &mut [[char; 1]] =
+    ///     // SAFETY: 1-element chunks never have remainder
+    ///     unsafe { slice.as_chunks_unchecked_mut() };
+    /// chunks[0] = ['L'];
+    /// assert_eq!(chunks, &[['L'], ['o'], ['r'], ['e'], ['m'], ['!']]);
+    /// let chunks: &mut [[char; 3]] =
+    ///     // SAFETY: The slice length (6) is a multiple of 3
+    ///     unsafe { slice.as_chunks_unchecked_mut() };
+    /// chunks[1] = ['a', 'x', '?'];
+    /// assert_eq!(slice, &['L', 'o', 'r', 'a', 'x', '?']);
+    ///
+    /// // These would be unsound:
+    /// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked_mut() // The slice length is not a multiple of 5
+    /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked_mut() // Zero-length chunks are never allowed
+    /// ```
+    #[unstable(feature = "slice_as_chunks", issue = "74985")]
+    #[inline]
+    pub unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
+        debug_assert_ne!(N, 0);
+        debug_assert_eq!(self.len() % N, 0);
+        let new_len =
+            // SAFETY: Our precondition is exactly what's needed to call this
+            unsafe { crate::intrinsics::exact_div(self.len(), N) };
+        // SAFETY: We cast a slice of `new_len * N` elements into
+        // a slice of `new_len` many `N` elements chunks.
+        unsafe { from_raw_parts_mut(self.as_mut_ptr().cast(), new_len) }
+    }
+
+    /// Splits the slice into a slice of `N`-element arrays,
     /// starting at the beginning of the slice,
     /// and a remainder slice with length strictly less than `N`.
     ///
@@ -979,13 +1094,48 @@
         assert_ne!(N, 0);
         let len = self.len() / N;
         let (multiple_of_n, remainder) = self.split_at_mut(len * N);
-        let array_slice: &mut [[T; N]] =
-            // SAFETY: We cast a slice of `len * N` elements into
-            // a slice of `len` many `N` elements chunks.
-            unsafe { from_raw_parts_mut(multiple_of_n.as_mut_ptr().cast(), len) };
+        // SAFETY: We already panicked for zero, and ensured by construction
+        // that the length of the subslice is a multiple of N.
+        let array_slice = unsafe { multiple_of_n.as_chunks_unchecked_mut() };
         (array_slice, remainder)
     }
 
+    /// Splits the slice into a slice of `N`-element arrays,
+    /// starting at the end of the slice,
+    /// and a remainder slice with length strictly less than `N`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `N` is 0. This check will most probably get changed to a compile time
+    /// error before this method gets stabilized.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_as_chunks)]
+    /// let v = &mut [0, 0, 0, 0, 0];
+    /// let mut count = 1;
+    ///
+    /// let (remainder, chunks) = v.as_rchunks_mut();
+    /// remainder[0] = 9;
+    /// for chunk in chunks {
+    ///     *chunk = [count; 2];
+    ///     count += 1;
+    /// }
+    /// assert_eq!(v, &[9, 1, 1, 2, 2]);
+    /// ```
+    #[unstable(feature = "slice_as_chunks", issue = "74985")]
+    #[inline]
+    pub fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) {
+        assert_ne!(N, 0);
+        let len = self.len() / N;
+        let (remainder, multiple_of_n) = self.split_at_mut(self.len() - len * N);
+        // SAFETY: We already panicked for zero, and ensured by construction
+        // that the length of the subslice is a multiple of N.
+        let array_slice = unsafe { multiple_of_n.as_chunks_unchecked_mut() };
+        (remainder, array_slice)
+    }
+
     /// Returns an iterator over `N` elements of the slice at a time, starting at the
     /// beginning of the slice.
     ///
@@ -1208,6 +1358,96 @@
         RChunksExactMut::new(self, chunk_size)
     }
 
+    /// Returns an iterator over the slice producing non-overlapping runs
+    /// of elements using the predicate to separate them.
+    ///
+    /// The predicate is called on two elements following themselves,
+    /// it means the predicate is called on `slice[0]` and `slice[1]`
+    /// then on `slice[1]` and `slice[2]` and so on.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_group_by)]
+    ///
+    /// let slice = &[1, 1, 1, 3, 3, 2, 2, 2];
+    ///
+    /// let mut iter = slice.group_by(|a, b| a == b);
+    ///
+    /// assert_eq!(iter.next(), Some(&[1, 1, 1][..]));
+    /// assert_eq!(iter.next(), Some(&[3, 3][..]));
+    /// assert_eq!(iter.next(), Some(&[2, 2, 2][..]));
+    /// assert_eq!(iter.next(), None);
+    /// ```
+    ///
+    /// This method can be used to extract the sorted subslices:
+    ///
+    /// ```
+    /// #![feature(slice_group_by)]
+    ///
+    /// let slice = &[1, 1, 2, 3, 2, 3, 2, 3, 4];
+    ///
+    /// let mut iter = slice.group_by(|a, b| a <= b);
+    ///
+    /// assert_eq!(iter.next(), Some(&[1, 1, 2, 3][..]));
+    /// assert_eq!(iter.next(), Some(&[2, 3][..]));
+    /// assert_eq!(iter.next(), Some(&[2, 3, 4][..]));
+    /// assert_eq!(iter.next(), None);
+    /// ```
+    #[unstable(feature = "slice_group_by", issue = "80552")]
+    #[inline]
+    pub fn group_by<F>(&self, pred: F) -> GroupBy<'_, T, F>
+    where
+        F: FnMut(&T, &T) -> bool,
+    {
+        GroupBy::new(self, pred)
+    }
+
+    /// Returns an iterator over the slice producing non-overlapping mutable
+    /// runs of elements using the predicate to separate them.
+    ///
+    /// The predicate is called on two elements following themselves,
+    /// it means the predicate is called on `slice[0]` and `slice[1]`
+    /// then on `slice[1]` and `slice[2]` and so on.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_group_by)]
+    ///
+    /// let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2];
+    ///
+    /// let mut iter = slice.group_by_mut(|a, b| a == b);
+    ///
+    /// assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
+    /// assert_eq!(iter.next(), Some(&mut [3, 3][..]));
+    /// assert_eq!(iter.next(), Some(&mut [2, 2, 2][..]));
+    /// assert_eq!(iter.next(), None);
+    /// ```
+    ///
+    /// This method can be used to extract the sorted subslices:
+    ///
+    /// ```
+    /// #![feature(slice_group_by)]
+    ///
+    /// let slice = &mut [1, 1, 2, 3, 2, 3, 2, 3, 4];
+    ///
+    /// let mut iter = slice.group_by_mut(|a, b| a <= b);
+    ///
+    /// assert_eq!(iter.next(), Some(&mut [1, 1, 2, 3][..]));
+    /// assert_eq!(iter.next(), Some(&mut [2, 3][..]));
+    /// assert_eq!(iter.next(), Some(&mut [2, 3, 4][..]));
+    /// assert_eq!(iter.next(), None);
+    /// ```
+    #[unstable(feature = "slice_group_by", issue = "80552")]
+    #[inline]
+    pub fn group_by_mut<F>(&mut self, pred: F) -> GroupByMut<'_, T, F>
+    where
+        F: FnMut(&T, &T) -> bool,
+    {
+        GroupByMut::new(self, pred)
+    }
+
     /// Divides one slice into two at an index.
     ///
     /// The first will contain all indices from `[0, mid)` (excluding
@@ -1264,14 +1504,11 @@
     ///
     /// ```
     /// let mut v = [1, 0, 3, 0, 5, 6];
-    /// // scoped to restrict the lifetime of the borrows
-    /// {
-    ///     let (left, right) = v.split_at_mut(2);
-    ///     assert_eq!(left, [1, 0]);
-    ///     assert_eq!(right, [3, 0, 5, 6]);
-    ///     left[1] = 2;
-    ///     right[1] = 4;
-    /// }
+    /// let (left, right) = v.split_at_mut(2);
+    /// assert_eq!(left, [1, 0]);
+    /// assert_eq!(right, [3, 0, 5, 6]);
+    /// left[1] = 2;
+    /// right[1] = 4;
     /// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1456,7 +1693,6 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(split_inclusive)]
     /// let slice = [10, 40, 33, 20];
     /// let mut iter = slice.split_inclusive(|num| num % 3 == 0);
     ///
@@ -1470,7 +1706,6 @@
     /// That slice will be the last item returned by the iterator.
     ///
     /// ```
-    /// #![feature(split_inclusive)]
     /// let slice = [3, 10, 40, 33];
     /// let mut iter = slice.split_inclusive(|num| num % 3 == 0);
     ///
@@ -1478,7 +1713,7 @@
     /// assert_eq!(iter.next().unwrap(), &[10, 40, 33]);
     /// assert!(iter.next().is_none());
     /// ```
-    #[unstable(feature = "split_inclusive", issue = "72360")]
+    #[stable(feature = "split_inclusive", since = "1.51.0")]
     #[inline]
     pub fn split_inclusive<F>(&self, pred: F) -> SplitInclusive<'_, T, F>
     where
@@ -1494,7 +1729,6 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(split_inclusive)]
     /// let mut v = [10, 40, 30, 20, 60, 50];
     ///
     /// for group in v.split_inclusive_mut(|num| *num % 3 == 0) {
@@ -1503,7 +1737,7 @@
     /// }
     /// assert_eq!(v, [10, 40, 1, 20, 1, 1]);
     /// ```
-    #[unstable(feature = "split_inclusive", issue = "72360")]
+    #[stable(feature = "split_inclusive", since = "1.51.0")]
     #[inline]
     pub fn split_inclusive_mut<F>(&mut self, pred: F) -> SplitInclusiveMut<'_, T, F>
     where
@@ -1779,19 +2013,24 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_strip)]
     /// let v = &[10, 40, 30];
     /// assert_eq!(v.strip_prefix(&[10]), Some(&[40, 30][..]));
     /// assert_eq!(v.strip_prefix(&[10, 40]), Some(&[30][..]));
     /// assert_eq!(v.strip_prefix(&[50]), None);
     /// assert_eq!(v.strip_prefix(&[10, 50]), None);
+    ///
+    /// let prefix : &str = "he";
+    /// assert_eq!(b"hello".strip_prefix(prefix.as_bytes()),
+    ///            Some(b"llo".as_ref()));
     /// ```
     #[must_use = "returns the subslice without modifying the original"]
-    #[unstable(feature = "slice_strip", issue = "73413")]
-    pub fn strip_prefix(&self, prefix: &[T]) -> Option<&[T]>
+    #[stable(feature = "slice_strip", since = "1.51.0")]
+    pub fn strip_prefix<P: SlicePattern<Item = T> + ?Sized>(&self, prefix: &P) -> Option<&[T]>
     where
         T: PartialEq,
     {
+        // This function will need rewriting if and when SlicePattern becomes more sophisticated.
+        let prefix = prefix.as_slice();
         let n = prefix.len();
         if n <= self.len() {
             let (head, tail) = self.split_at(n);
@@ -1812,7 +2051,6 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_strip)]
     /// let v = &[10, 40, 30];
     /// assert_eq!(v.strip_suffix(&[30]), Some(&[10, 40][..]));
     /// assert_eq!(v.strip_suffix(&[40, 30]), Some(&[10][..]));
@@ -1820,11 +2058,13 @@
     /// assert_eq!(v.strip_suffix(&[50, 30]), None);
     /// ```
     #[must_use = "returns the subslice without modifying the original"]
-    #[unstable(feature = "slice_strip", issue = "73413")]
-    pub fn strip_suffix(&self, suffix: &[T]) -> Option<&[T]>
+    #[stable(feature = "slice_strip", since = "1.51.0")]
+    pub fn strip_suffix<P: SlicePattern<Item = T> + ?Sized>(&self, suffix: &P) -> Option<&[T]>
     where
         T: PartialEq,
     {
+        // This function will need rewriting if and when SlicePattern becomes more sophisticated.
+        let suffix = suffix.as_slice();
         let (len, n) = (self.len(), suffix.len());
         if n <= len {
             let (head, tail) = self.split_at(len - n);
@@ -3217,3 +3457,35 @@
         &mut []
     }
 }
+
+#[unstable(feature = "slice_pattern", reason = "stopgap trait for slice patterns", issue = "56345")]
+/// Patterns in slices - currently, only used by `strip_prefix` and `strip_suffix`.  At a future
+/// point, we hope to generalise `core::str::Pattern` (which at the time of writing is limited to
+/// `str`) to slices, and then this trait will be replaced or abolished.
+pub trait SlicePattern {
+    /// The element type of the slice being matched on.
+    type Item;
+
+    /// Currently, the consumers of `SlicePattern` need a slice.
+    fn as_slice(&self) -> &[Self::Item];
+}
+
+#[stable(feature = "slice_strip", since = "1.51.0")]
+impl<T> SlicePattern for [T] {
+    type Item = T;
+
+    #[inline]
+    fn as_slice(&self) -> &[Self::Item] {
+        self
+    }
+}
+
+#[stable(feature = "slice_strip", since = "1.51.0")]
+impl<T, const N: usize> SlicePattern for [T; N] {
+    type Item = T;
+
+    #[inline]
+    fn as_slice(&self) -> &[Self::Item] {
+        self
+    }
+}
diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs
index 0920930..117db6e 100644
--- a/library/core/src/slice/raw.rs
+++ b/library/core/src/slice/raw.rs
@@ -103,7 +103,7 @@
 ///
 /// Behavior is undefined if any of the following conditions are violated:
 ///
-/// * `data` must be [valid] for boths reads and writes for `len * mem::size_of::<T>()` many bytes,
+/// * `data` must be [valid] for both reads and writes for `len * mem::size_of::<T>()` many bytes,
 ///   and it must be properly aligned. This means in particular:
 ///
 ///     * The entire memory range of this slice must be contained within a single allocated object!
diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs
index 28cd350..8b952ea 100644
--- a/library/core/src/str/iter.rs
+++ b/library/core/src/str/iter.rs
@@ -1174,7 +1174,7 @@
 /// See its documentation for more.
 ///
 /// [`split_inclusive`]: str::split_inclusive
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 pub struct SplitInclusive<'a, P: Pattern<'a>>(pub(super) SplitInternal<'a, P>);
 
 #[stable(feature = "split_whitespace", since = "1.1.0")]
@@ -1239,7 +1239,7 @@
 #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
 impl FusedIterator for SplitAsciiWhitespace<'_> {}
 
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 impl<'a, P: Pattern<'a>> Iterator for SplitInclusive<'a, P> {
     type Item = &'a str;
 
@@ -1249,7 +1249,7 @@
     }
 }
 
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 impl<'a, P: Pattern<'a, Searcher: fmt::Debug>> fmt::Debug for SplitInclusive<'a, P> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("SplitInclusive").field("0", &self.0).finish()
@@ -1257,14 +1257,14 @@
 }
 
 // FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 impl<'a, P: Pattern<'a, Searcher: Clone>> Clone for SplitInclusive<'a, P> {
     fn clone(&self) -> Self {
         SplitInclusive(self.0.clone())
     }
 }
 
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator
     for SplitInclusive<'a, P>
 {
@@ -1274,7 +1274,7 @@
     }
 }
 
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {}
 
 impl<'a, P: Pattern<'a>> SplitInclusive<'a, P> {
@@ -1284,7 +1284,6 @@
     ///
     /// ```
     /// #![feature(str_split_inclusive_as_str)]
-    /// #![feature(split_inclusive)]
     /// let mut split = "Mary had a little lamb".split_inclusive(' ');
     /// assert_eq!(split.as_str(), "Mary had a little lamb");
     /// split.next();
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index ba495a1..6a35378 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -65,7 +65,7 @@
 #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
 pub use iter::SplitAsciiWhitespace;
 
-#[unstable(feature = "split_inclusive", issue = "72360")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 use iter::SplitInclusive;
 
 #[unstable(feature = "str_internals", issue = "none")]
@@ -1227,7 +1227,6 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(split_inclusive)]
     /// let v: Vec<&str> = "Mary had a little lamb\nlittle lamb\nlittle lamb."
     ///     .split_inclusive('\n').collect();
     /// assert_eq!(v, ["Mary had a little lamb\n", "little lamb\n", "little lamb."]);
@@ -1238,12 +1237,11 @@
     /// That substring will be the last item returned by the iterator.
     ///
     /// ```
-    /// #![feature(split_inclusive)]
     /// let v: Vec<&str> = "Mary had a little lamb\nlittle lamb\nlittle lamb.\n"
     ///     .split_inclusive('\n').collect();
     /// assert_eq!(v, ["Mary had a little lamb\n", "little lamb\n", "little lamb.\n"]);
     /// ```
-    #[unstable(feature = "split_inclusive", issue = "72360")]
+    #[stable(feature = "split_inclusive", since = "1.51.0")]
     #[inline]
     pub fn split_inclusive<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitInclusive<'a, P> {
         SplitInclusive(SplitInternal {
@@ -2175,7 +2173,7 @@
     /// helps the inference algorithm understand specifically which type
     /// you're trying to parse into.
     ///
-    /// `parse` can parse any type that implements the [`FromStr`] trait.
+    /// `parse` can parse into any type that implements the [`FromStr`] trait.
 
     ///
     /// # Errors
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index e4b99e1..81c9e1d 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -120,21 +120,6 @@
 
 use crate::hint::spin_loop;
 
-/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock").
-///
-/// This function is expected to be deprecated in favor of
-/// [`hint::spin_loop`].
-///
-/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
-/// do anything at all.
-///
-/// [`hint::spin_loop`]: crate::hint::spin_loop
-#[inline]
-#[stable(feature = "spin_loop_hint", since = "1.24.0")]
-pub fn spin_loop_hint() {
-    spin_loop()
-}
-
 /// A boolean type which can be safely shared between threads.
 ///
 /// This type has the same in-memory representation as a [`bool`].
@@ -809,7 +794,7 @@
     /// ```ignore (extern-declaration)
     /// # fn main() {
     /// use std::sync::atomic::AtomicBool;
-    /// extern {
+    /// extern "C" {
     ///     fn my_atomic_op(arg: *mut bool);
     /// }
     ///
@@ -1372,12 +1357,9 @@
 
         #[$stable_from]
         impl From<$int_type> for $atomic_type {
-            doc_comment! {
-                concat!(
-"Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`."),
-                #[inline]
-                fn from(v: $int_type) -> Self { Self::new(v) }
-            }
+            #[doc = concat!("Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`.")]
+            #[inline]
+            fn from(v: $int_type) -> Self { Self::new(v) }
         }
 
         #[$stable_debug]
@@ -1392,744 +1374,703 @@
         unsafe impl Sync for $atomic_type {}
 
         impl $atomic_type {
-            doc_comment! {
-                concat!("Creates a new atomic integer.
+            /// Creates a new atomic integer.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")]
+            ///
+            #[doc = concat!("let atomic_forty_two = ", stringify!($atomic_type), "::new(42);")]
+            /// ```
+            #[inline]
+            #[$stable]
+            #[$const_stable]
+            pub const fn new(v: $int_type) -> Self {
+                Self {v: UnsafeCell::new(v)}
+            }
 
-# Examples
+            /// Returns a mutable reference to the underlying integer.
+            ///
+            /// This is safe because the mutable reference guarantees that no other threads are
+            /// concurrently accessing the atomic data.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let mut some_var = ", stringify!($atomic_type), "::new(10);")]
+            /// assert_eq!(*some_var.get_mut(), 10);
+            /// *some_var.get_mut() = 5;
+            /// assert_eq!(some_var.load(Ordering::SeqCst), 5);
+            /// ```
+            #[inline]
+            #[$stable_access]
+            pub fn get_mut(&mut self) -> &mut $int_type {
+                self.v.get_mut()
+            }
 
-```
-", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";
+            #[doc = concat!("Get atomic access to a `&mut ", stringify!($int_type), "`.")]
+            ///
+            #[doc = if_not_8_bit! {
+                $int_type,
+                concat!(
+                    "**Note:** This function is only available on targets where `",
+                    stringify!($int_type), "` has an alignment of ", $align, " bytes."
+                )
+            }]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// #![feature(atomic_from_mut)]
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            /// let mut some_int = 123;
+            #[doc = concat!("let a = ", stringify!($atomic_type), "::from_mut(&mut some_int);")]
+            /// a.store(100, Ordering::Relaxed);
+            /// assert_eq!(some_int, 100);
+            /// ```
+            ///
+            #[inline]
+            #[$cfg_align]
+            #[unstable(feature = "atomic_from_mut", issue = "76314")]
+            pub fn from_mut(v: &mut $int_type) -> &Self {
+                use crate::mem::align_of;
+                let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
+                // SAFETY:
+                //  - the mutable reference guarantees unique ownership.
+                //  - the alignment of `$int_type` and `Self` is the
+                //    same, as promised by $cfg_align and verified above.
+                unsafe { &*(v as *mut $int_type as *mut Self) }
+            }
 
-let atomic_forty_two = ", stringify!($atomic_type), "::new(42);
-```"),
-                #[inline]
-                #[$stable]
-                #[$const_stable]
-                pub const fn new(v: $int_type) -> Self {
-                    Self {v: UnsafeCell::new(v)}
+            /// Consumes the atomic and returns the contained value.
+            ///
+            /// This is safe because passing `self` by value guarantees that no other threads are
+            /// concurrently accessing the atomic data.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")]
+            ///
+            #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
+            /// assert_eq!(some_var.into_inner(), 5);
+            /// ```
+            #[inline]
+            #[$stable_access]
+            #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")]
+            pub const fn into_inner(self) -> $int_type {
+                self.v.into_inner()
+            }
+
+            /// Loads a value from the atomic integer.
+            ///
+            /// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
+            /// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
+            ///
+            /// # Panics
+            ///
+            /// Panics if `order` is [`Release`] or [`AcqRel`].
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
+            ///
+            /// assert_eq!(some_var.load(Ordering::Relaxed), 5);
+            /// ```
+            #[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) }
+            }
+
+            /// Stores a value into the atomic integer.
+            ///
+            /// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
+            ///  Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
+            ///
+            /// # Panics
+            ///
+            /// Panics if `order` is [`Acquire`] or [`AcqRel`].
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
+            ///
+            /// some_var.store(10, Ordering::Relaxed);
+            /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
+            /// ```
+            #[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); }
+            }
+
+            /// Stores a value into the atomic integer, returning the previous value.
+            ///
+            /// `swap` takes an [`Ordering`] argument which describes the memory ordering
+            /// of this operation. All ordering modes are possible. Note that using
+            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
+            /// using [`Release`] makes the load part [`Relaxed`].
+            ///
+            /// **Note**: This method is only available on platforms that support atomic operations on
+            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
+            ///
+            /// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
+            /// ```
+            #[inline]
+            #[$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) }
+            }
+
+            /// Stores a value into the atomic integer if the current value is the same as
+            /// the `current` value.
+            ///
+            /// The return value is always the previous value. If it is equal to `current`, then the
+            /// value was updated.
+            ///
+            /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
+            /// ordering of this operation. Notice that even when using [`AcqRel`], the operation
+            /// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
+            /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
+            /// happens, and using [`Release`] makes the load part [`Relaxed`].
+            ///
+            /// **Note**: This method is only available on platforms that support atomic operations on
+            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            ///
+            /// # Migrating to `compare_exchange` and `compare_exchange_weak`
+            ///
+            /// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
+            /// memory orderings:
+            ///
+            /// Original | Success | Failure
+            /// -------- | ------- | -------
+            /// Relaxed  | Relaxed | Relaxed
+            /// Acquire  | Acquire | Acquire
+            /// Release  | Release | Relaxed
+            /// AcqRel   | AcqRel  | Acquire
+            /// SeqCst   | SeqCst  | SeqCst
+            ///
+            /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
+            /// which allows the compiler to generate better assembly code when the compare and swap
+            /// is used in a loop.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
+            ///
+            /// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
+            /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
+            ///
+            /// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
+            /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
+            /// ```
+            #[inline]
+            #[$stable]
+            #[rustc_deprecated(
+                since = "1.50.0",
+                reason = "Use `compare_exchange` or `compare_exchange_weak` instead")
+            ]
+            #[$cfg_cas]
+            pub fn compare_and_swap(&self,
+                                    current: $int_type,
+                                    new: $int_type,
+                                    order: Ordering) -> $int_type {
+                match self.compare_exchange(current,
+                                            new,
+                                            order,
+                                            strongest_failure_ordering(order)) {
+                    Ok(x) => x,
+                    Err(x) => x,
                 }
             }
 
-            doc_comment! {
-                concat!("Returns a mutable reference to the underlying integer.
+            /// Stores a value into the atomic integer if the current value is the same as
+            /// the `current` value.
+            ///
+            /// The return value is a result indicating whether the new value was written and
+            /// containing the previous value. On success this value is guaranteed to be equal to
+            /// `current`.
+            ///
+            /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
+            /// ordering of this operation. `success` describes the required ordering for the
+            /// read-modify-write operation that takes place if the comparison with `current` succeeds.
+            /// `failure` describes the required ordering for the load operation that takes place when
+            /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
+            /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
+            /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]
+            /// and must be equivalent to or weaker than the success ordering.
+            ///
+            /// **Note**: This method is only available on platforms that support atomic operations on
+            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
+            ///
+            /// assert_eq!(some_var.compare_exchange(5, 10,
+            ///                                      Ordering::Acquire,
+            ///                                      Ordering::Relaxed),
+            ///            Ok(5));
+            /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
+            ///
+            /// assert_eq!(some_var.compare_exchange(6, 12,
+            ///                                      Ordering::SeqCst,
+            ///                                      Ordering::Acquire),
+            ///            Err(10));
+            /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
+            /// ```
+            #[inline]
+            #[$stable_cxchg]
+            #[$cfg_cas]
+            pub fn compare_exchange(&self,
+                                    current: $int_type,
+                                    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) }
+            }
 
-This is safe because the mutable reference guarantees that no other threads are
-concurrently accessing the atomic data.
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let mut some_var = ", stringify!($atomic_type), "::new(10);
-assert_eq!(*some_var.get_mut(), 10);
-*some_var.get_mut() = 5;
-assert_eq!(some_var.load(Ordering::SeqCst), 5);
-```"),
-                #[inline]
-                #[$stable_access]
-                pub fn get_mut(&mut self) -> &mut $int_type {
-                    self.v.get_mut()
+            /// Stores a value into the atomic integer if the current value is the same as
+            /// the `current` value.
+            ///
+            #[doc = concat!("Unlike [`", stringify!($atomic_type), "::compare_exchange`],")]
+            /// this function is allowed to spuriously fail even
+            /// when the comparison succeeds, which can result in more efficient code on some
+            /// platforms. The return value is a result indicating whether the new value was
+            /// written and containing the previous value.
+            ///
+            /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
+            /// ordering of this operation. `success` describes the required ordering for the
+            /// read-modify-write operation that takes place if the comparison with `current` succeeds.
+            /// `failure` describes the required ordering for the load operation that takes place when
+            /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
+            /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
+            /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]
+            /// and must be equivalent to or weaker than the success ordering.
+            ///
+            /// **Note**: This method is only available on platforms that support atomic operations on
+            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let val = ", stringify!($atomic_type), "::new(4);")]
+            ///
+            /// let mut old = val.load(Ordering::Relaxed);
+            /// loop {
+            ///     let new = old * 2;
+            ///     match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
+            ///         Ok(_) => break,
+            ///         Err(x) => old = x,
+            ///     }
+            /// }
+            /// ```
+            #[inline]
+            #[$stable_cxchg]
+            #[$cfg_cas]
+            pub fn compare_exchange_weak(&self,
+                                         current: $int_type,
+                                         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)
                 }
             }
 
-            doc_comment! {
-                concat!("Get atomic access to a `&mut ", stringify!($int_type), "`.
-
-",
-if_not_8_bit! {
-    $int_type,
-    concat!(
-        "**Note:** This function is only available on targets where `",
-        stringify!($int_type), "` has an alignment of ", $align, " bytes."
-    )
-},
-"
-
-# Examples
-
-```
-#![feature(atomic_from_mut)]
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let mut some_int = 123;
-let a = ", stringify!($atomic_type), "::from_mut(&mut some_int);
-a.store(100, Ordering::Relaxed);
-assert_eq!(some_int, 100);
-```
-                "),
-                #[inline]
-                #[$cfg_align]
-                #[unstable(feature = "atomic_from_mut", issue = "76314")]
-                pub fn from_mut(v: &mut $int_type) -> &Self {
-                    use crate::mem::align_of;
-                    let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
-                    // SAFETY:
-                    //  - the mutable reference guarantees unique ownership.
-                    //  - the alignment of `$int_type` and `Self` is the
-                    //    same, as promised by $cfg_align and verified above.
-                    unsafe { &*(v as *mut $int_type as *mut Self) }
-                }
+            /// Adds to the current value, returning the previous value.
+            ///
+            /// This operation wraps around on overflow.
+            ///
+            /// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering
+            /// of this operation. All ordering modes are possible. Note that using
+            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
+            /// using [`Release`] makes the load part [`Relaxed`].
+            ///
+            /// **Note**: This method is only available on platforms that support atomic operations on
+            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0);")]
+            /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
+            /// assert_eq!(foo.load(Ordering::SeqCst), 10);
+            /// ```
+            #[inline]
+            #[$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) }
             }
 
-            doc_comment! {
-                concat!("Consumes the atomic and returns the contained value.
-
-This is safe because passing `self` by value guarantees that no other threads are
-concurrently accessing the atomic data.
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";
-
-let some_var = ", stringify!($atomic_type), "::new(5);
-assert_eq!(some_var.into_inner(), 5);
-```"),
-                #[inline]
-                #[$stable_access]
-                #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")]
-                pub const fn into_inner(self) -> $int_type {
-                    self.v.into_inner()
-                }
+            /// Subtracts from the current value, returning the previous value.
+            ///
+            /// This operation wraps around on overflow.
+            ///
+            /// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
+            /// of this operation. All ordering modes are possible. Note that using
+            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
+            /// using [`Release`] makes the load part [`Relaxed`].
+            ///
+            /// **Note**: This method is only available on platforms that support atomic operations on
+            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(20);")]
+            /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
+            /// assert_eq!(foo.load(Ordering::SeqCst), 10);
+            /// ```
+            #[inline]
+            #[$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) }
             }
 
-            doc_comment! {
-                concat!("Loads a value from the atomic integer.
-
-`load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
-Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
-
-# Panics
-
-Panics if `order` is [`Release`] or [`AcqRel`].
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let some_var = ", stringify!($atomic_type), "::new(5);
-
-assert_eq!(some_var.load(Ordering::Relaxed), 5);
-```"),
-                #[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) }
-                }
+            /// Bitwise "and" with the current value.
+            ///
+            /// Performs a bitwise "and" operation on the current value and the argument `val`, and
+            /// sets the new value to the result.
+            ///
+            /// Returns the previous value.
+            ///
+            /// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
+            /// of this operation. All ordering modes are possible. Note that using
+            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
+            /// using [`Release`] makes the load part [`Relaxed`].
+            ///
+            /// **Note**: This method is only available on platforms that support atomic operations on
+            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
+            /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
+            /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
+            /// ```
+            #[inline]
+            #[$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) }
             }
 
-            doc_comment! {
-                concat!("Stores a value into the atomic integer.
-
-`store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
- Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
-
-# Panics
-
-Panics if `order` is [`Acquire`] or [`AcqRel`].
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let some_var = ", stringify!($atomic_type), "::new(5);
-
-some_var.store(10, Ordering::Relaxed);
-assert_eq!(some_var.load(Ordering::Relaxed), 10);
-```"),
-                #[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); }
-                }
+            /// Bitwise "nand" with the current value.
+            ///
+            /// Performs a bitwise "nand" operation on the current value and the argument `val`, and
+            /// sets the new value to the result.
+            ///
+            /// Returns the previous value.
+            ///
+            /// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
+            /// of this operation. All ordering modes are possible. Note that using
+            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
+            /// using [`Release`] makes the load part [`Relaxed`].
+            ///
+            /// **Note**: This method is only available on platforms that support atomic operations on
+            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0x13);")]
+            /// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
+            /// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
+            /// ```
+            #[inline]
+            #[$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) }
             }
 
-            doc_comment! {
-                concat!("Stores a value into the atomic integer, returning the previous value.
-
-`swap` takes an [`Ordering`] argument which describes the memory ordering
-of this operation. All ordering modes are possible. Note that using
-[`Acquire`] makes the store part of this operation [`Relaxed`], and
-using [`Release`] makes the load part [`Relaxed`].
-
-**Note**: This method is only available on platforms that support atomic
-operations on [`", $s_int_type, "`](", $int_ref, ").
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let some_var = ", stringify!($atomic_type), "::new(5);
-
-assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
-```"),
-                #[inline]
-                #[$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) }
-                }
+            /// Bitwise "or" with the current value.
+            ///
+            /// Performs a bitwise "or" operation on the current value and the argument `val`, and
+            /// sets the new value to the result.
+            ///
+            /// Returns the previous value.
+            ///
+            /// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
+            /// of this operation. All ordering modes are possible. Note that using
+            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
+            /// using [`Release`] makes the load part [`Relaxed`].
+            ///
+            /// **Note**: This method is only available on platforms that support atomic operations on
+            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
+            /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
+            /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
+            /// ```
+            #[inline]
+            #[$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) }
             }
 
-            doc_comment! {
-                concat!("Stores a value into the atomic integer if the current value is the same as
-the `current` value.
+            /// Bitwise "xor" with the current value.
+            ///
+            /// Performs a bitwise "xor" operation on the current value and the argument `val`, and
+            /// sets the new value to the result.
+            ///
+            /// Returns the previous value.
+            ///
+            /// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
+            /// of this operation. All ordering modes are possible. Note that using
+            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
+            /// using [`Release`] makes the load part [`Relaxed`].
+            ///
+            /// **Note**: This method is only available on platforms that support atomic operations on
+            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
+            /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
+            /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
+            /// ```
+            #[inline]
+            #[$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) }
+            }
 
-The return value is always the previous value. If it is equal to `current`, then the
-value was updated.
-
-`compare_and_swap` also takes an [`Ordering`] argument which describes the memory
-ordering of this operation. Notice that even when using [`AcqRel`], the operation
-might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
-Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
-happens, and using [`Release`] makes the load part [`Relaxed`].
-
-**Note**: This method is only available on platforms that support atomic
-operations on [`", $s_int_type, "`](", $int_ref, ").
-
-# Migrating to `compare_exchange` and `compare_exchange_weak`
-
-`compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
-memory orderings:
-
-Original | Success | Failure
--------- | ------- | -------
-Relaxed  | Relaxed | Relaxed
-Acquire  | Acquire | Acquire
-Release  | Release | Relaxed
-AcqRel   | AcqRel  | Acquire
-SeqCst   | SeqCst  | SeqCst
-
-`compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
-which allows the compiler to generate better assembly code when the compare and swap
-is used in a loop.
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let some_var = ", stringify!($atomic_type), "::new(5);
-
-assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
-assert_eq!(some_var.load(Ordering::Relaxed), 10);
-
-assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
-assert_eq!(some_var.load(Ordering::Relaxed), 10);
-```"),
-                #[inline]
-                #[$stable]
-                #[rustc_deprecated(
-                    since = "1.50.0",
-                    reason = "Use `compare_exchange` or `compare_exchange_weak` instead")
-                ]
-                #[$cfg_cas]
-                pub fn compare_and_swap(&self,
-                                        current: $int_type,
-                                        new: $int_type,
-                                        order: Ordering) -> $int_type {
-                    match self.compare_exchange(current,
-                                                new,
-                                                order,
-                                                strongest_failure_ordering(order)) {
-                        Ok(x) => x,
-                        Err(x) => x,
+            /// Fetches the value, and applies a function to it that returns an optional
+            /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
+            /// `Err(previous_value)`.
+            ///
+            /// Note: This may call the function multiple times if the value has been changed from other threads in
+            /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
+            /// only once to the stored value.
+            ///
+            /// `fetch_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
+            /// The first describes the required ordering for when the operation finally succeeds while the second
+            /// describes the required ordering for loads. These correspond to the success and failure orderings of
+            #[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange`]")]
+            /// respectively.
+            ///
+            /// Using [`Acquire`] as success ordering makes the store part
+            /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
+            /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]
+            /// and must be equivalent to or weaker than the success ordering.
+            ///
+            /// **Note**: This method is only available on platforms that support atomic operations on
+            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            ///
+            /// # Examples
+            ///
+            /// ```rust
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")]
+            /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
+            /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
+            /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
+            /// assert_eq!(x.load(Ordering::SeqCst), 9);
+            /// ```
+            #[inline]
+            #[stable(feature = "no_more_cas", since = "1.45.0")]
+            #[$cfg_cas]
+            pub fn fetch_update<F>(&self,
+                                   set_order: Ordering,
+                                   fetch_order: Ordering,
+                                   mut f: F) -> Result<$int_type, $int_type>
+            where F: FnMut($int_type) -> Option<$int_type> {
+                let mut prev = self.load(fetch_order);
+                while let Some(next) = f(prev) {
+                    match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
+                        x @ Ok(_) => return x,
+                        Err(next_prev) => prev = next_prev
                     }
                 }
+                Err(prev)
             }
 
-            doc_comment! {
-                concat!("Stores a value into the atomic integer if the current value is the same as
-the `current` value.
-
-The return value is a result indicating whether the new value was written and
-containing the previous value. On success this value is guaranteed to be equal to
-`current`.
-
-`compare_exchange` takes two [`Ordering`] arguments to describe the memory
-ordering of this operation. `success` describes the required ordering for the
-read-modify-write operation that takes place if the comparison with `current` succeeds.
-`failure` describes the required ordering for the load operation that takes place when
-the comparison fails. Using [`Acquire`] as success ordering makes the store part
-of this operation [`Relaxed`], and using [`Release`] makes the successful load
-[`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]
-and must be equivalent to or weaker than the success ordering.
-
-**Note**: This method is only available on platforms that support atomic
-operations on [`", $s_int_type, "`](", $int_ref, ").
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let some_var = ", stringify!($atomic_type), "::new(5);
-
-assert_eq!(some_var.compare_exchange(5, 10,
-                                     Ordering::Acquire,
-                                     Ordering::Relaxed),
-           Ok(5));
-assert_eq!(some_var.load(Ordering::Relaxed), 10);
-
-assert_eq!(some_var.compare_exchange(6, 12,
-                                     Ordering::SeqCst,
-                                     Ordering::Acquire),
-           Err(10));
-assert_eq!(some_var.load(Ordering::Relaxed), 10);
-```"),
-                #[inline]
-                #[$stable_cxchg]
-                #[$cfg_cas]
-                pub fn compare_exchange(&self,
-                                        current: $int_type,
-                                        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) }
-                }
+            /// Maximum with the current value.
+            ///
+            /// Finds the maximum of the current value and the argument `val`, and
+            /// sets the new value to the result.
+            ///
+            /// Returns the previous value.
+            ///
+            /// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering
+            /// of this operation. All ordering modes are possible. Note that using
+            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
+            /// using [`Release`] makes the load part [`Relaxed`].
+            ///
+            /// **Note**: This method is only available on platforms that support atomic operations on
+            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
+            /// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
+            /// assert_eq!(foo.load(Ordering::SeqCst), 42);
+            /// ```
+            ///
+            /// If you want to obtain the maximum value in one step, you can use the following:
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
+            /// let bar = 42;
+            /// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
+            /// assert!(max_foo == 42);
+            /// ```
+            #[inline]
+            #[stable(feature = "atomic_min_max", since = "1.45.0")]
+            #[$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) }
             }
 
-            doc_comment! {
-                concat!("Stores a value into the atomic integer if the current value is the same as
-the `current` value.
-
-Unlike [`", stringify!($atomic_type), "::compare_exchange`], this function is allowed to spuriously fail even
-when the comparison succeeds, which can result in more efficient code on some
-platforms. The return value is a result indicating whether the new value was
-written and containing the previous value.
-
-`compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
-ordering of this operation. `success` describes the required ordering for the
-read-modify-write operation that takes place if the comparison with `current` succeeds.
-`failure` describes the required ordering for the load operation that takes place when
-the comparison fails. Using [`Acquire`] as success ordering makes the store part
-of this operation [`Relaxed`], and using [`Release`] makes the successful load
-[`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]
-and must be equivalent to or weaker than the success ordering.
-
-**Note**: This method is only available on platforms that support atomic
-operations on [`", $s_int_type, "`](", $int_ref, ").
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let val = ", stringify!($atomic_type), "::new(4);
-
-let mut old = val.load(Ordering::Relaxed);
-loop {
-    let new = old * 2;
-    match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
-        Ok(_) => break,
-        Err(x) => old = x,
-    }
-}
-```"),
-                #[inline]
-                #[$stable_cxchg]
-                #[$cfg_cas]
-                pub fn compare_exchange_weak(&self,
-                                             current: $int_type,
-                                             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)
-                    }
-                }
+            /// Minimum with the current value.
+            ///
+            /// Finds the minimum of the current value and the argument `val`, and
+            /// sets the new value to the result.
+            ///
+            /// Returns the previous value.
+            ///
+            /// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering
+            /// of this operation. All ordering modes are possible. Note that using
+            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
+            /// using [`Release`] makes the load part [`Relaxed`].
+            ///
+            /// **Note**: This method is only available on platforms that support atomic operations on
+            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
+            /// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
+            /// assert_eq!(foo.load(Ordering::Relaxed), 23);
+            /// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
+            /// assert_eq!(foo.load(Ordering::Relaxed), 22);
+            /// ```
+            ///
+            /// If you want to obtain the minimum value in one step, you can use the following:
+            ///
+            /// ```
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
+            ///
+            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
+            /// let bar = 12;
+            /// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
+            /// assert_eq!(min_foo, 12);
+            /// ```
+            #[inline]
+            #[stable(feature = "atomic_min_max", since = "1.45.0")]
+            #[$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) }
             }
 
-            doc_comment! {
-                concat!("Adds to the current value, returning the previous value.
-
-This operation wraps around on overflow.
-
-`fetch_add` takes an [`Ordering`] argument which describes the memory ordering
-of this operation. All ordering modes are possible. Note that using
-[`Acquire`] makes the store part of this operation [`Relaxed`], and
-using [`Release`] makes the load part [`Relaxed`].
-
-**Note**: This method is only available on platforms that support atomic
-operations on [`", $s_int_type, "`](", $int_ref, ").
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let foo = ", stringify!($atomic_type), "::new(0);
-assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
-assert_eq!(foo.load(Ordering::SeqCst), 10);
-```"),
-                #[inline]
-                #[$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) }
-                }
-            }
-
-            doc_comment! {
-                concat!("Subtracts from the current value, returning the previous value.
-
-This operation wraps around on overflow.
-
-`fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
-of this operation. All ordering modes are possible. Note that using
-[`Acquire`] makes the store part of this operation [`Relaxed`], and
-using [`Release`] makes the load part [`Relaxed`].
-
-**Note**: This method is only available on platforms that support atomic
-operations on [`", $s_int_type, "`](", $int_ref, ").
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let foo = ", stringify!($atomic_type), "::new(20);
-assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
-assert_eq!(foo.load(Ordering::SeqCst), 10);
-```"),
-                #[inline]
-                #[$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) }
-                }
-            }
-
-            doc_comment! {
-                concat!("Bitwise \"and\" with the current value.
-
-Performs a bitwise \"and\" operation on the current value and the argument `val`, and
-sets the new value to the result.
-
-Returns the previous value.
-
-`fetch_and` takes an [`Ordering`] argument which describes the memory ordering
-of this operation. All ordering modes are possible. Note that using
-[`Acquire`] makes the store part of this operation [`Relaxed`], and
-using [`Release`] makes the load part [`Relaxed`].
-
-**Note**: This method is only available on platforms that support atomic
-operations on [`", $s_int_type, "`](", $int_ref, ").
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let foo = ", stringify!($atomic_type), "::new(0b101101);
-assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
-assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
-```"),
-                #[inline]
-                #[$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) }
-                }
-            }
-
-            doc_comment! {
-                concat!("Bitwise \"nand\" with the current value.
-
-Performs a bitwise \"nand\" operation on the current value and the argument `val`, and
-sets the new value to the result.
-
-Returns the previous value.
-
-`fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
-of this operation. All ordering modes are possible. Note that using
-[`Acquire`] makes the store part of this operation [`Relaxed`], and
-using [`Release`] makes the load part [`Relaxed`].
-
-**Note**: This method is only available on platforms that support atomic
-operations on [`", $s_int_type, "`](", $int_ref, ").
-
-# Examples
-
-```
-", $extra_feature, "
-use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let foo = ", stringify!($atomic_type), "::new(0x13);
-assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
-assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
-```"),
-                #[inline]
-                #[$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) }
-                }
-            }
-
-            doc_comment! {
-                concat!("Bitwise \"or\" with the current value.
-
-Performs a bitwise \"or\" operation on the current value and the argument `val`, and
-sets the new value to the result.
-
-Returns the previous value.
-
-`fetch_or` takes an [`Ordering`] argument which describes the memory ordering
-of this operation. All ordering modes are possible. Note that using
-[`Acquire`] makes the store part of this operation [`Relaxed`], and
-using [`Release`] makes the load part [`Relaxed`].
-
-**Note**: This method is only available on platforms that support atomic
-operations on [`", $s_int_type, "`](", $int_ref, ").
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let foo = ", stringify!($atomic_type), "::new(0b101101);
-assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
-assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
-```"),
-                #[inline]
-                #[$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) }
-                }
-            }
-
-            doc_comment! {
-                concat!("Bitwise \"xor\" with the current value.
-
-Performs a bitwise \"xor\" operation on the current value and the argument `val`, and
-sets the new value to the result.
-
-Returns the previous value.
-
-`fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
-of this operation. All ordering modes are possible. Note that using
-[`Acquire`] makes the store part of this operation [`Relaxed`], and
-using [`Release`] makes the load part [`Relaxed`].
-
-**Note**: This method is only available on platforms that support atomic
-operations on [`", $s_int_type, "`](", $int_ref, ").
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let foo = ", stringify!($atomic_type), "::new(0b101101);
-assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
-assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
-```"),
-                #[inline]
-                #[$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) }
-                }
-            }
-
-            doc_comment! {
-                concat!("Fetches the value, and applies a function to it that returns an optional
-new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
-`Err(previous_value)`.
-
-Note: This may call the function multiple times if the value has been changed from other threads in
-the meantime, as long as the function returns `Some(_)`, but the function will have been applied
-only once to the stored value.
-
-`fetch_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
-The first describes the required ordering for when the operation finally succeeds while the second
-describes the required ordering for loads. These correspond to the success and failure orderings of
-[`", stringify!($atomic_type), "::compare_exchange`] respectively.
-
-Using [`Acquire`] as success ordering makes the store part
-of this operation [`Relaxed`], and using [`Release`] makes the final successful load
-[`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]
-and must be equivalent to or weaker than the success ordering.
-
-**Note**: This method is only available on platforms that support atomic
-operations on [`", $s_int_type, "`](", $int_ref, ").
-
-# Examples
-
-```rust
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let x = ", stringify!($atomic_type), "::new(7);
-assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
-assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
-assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
-assert_eq!(x.load(Ordering::SeqCst), 9);
-```"),
-                #[inline]
-                #[stable(feature = "no_more_cas", since = "1.45.0")]
-                #[$cfg_cas]
-                pub fn fetch_update<F>(&self,
-                                       set_order: Ordering,
-                                       fetch_order: Ordering,
-                                       mut f: F) -> Result<$int_type, $int_type>
-                where F: FnMut($int_type) -> Option<$int_type> {
-                    let mut prev = self.load(fetch_order);
-                    while let Some(next) = f(prev) {
-                        match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
-                            x @ Ok(_) => return x,
-                            Err(next_prev) => prev = next_prev
-                        }
-                    }
-                    Err(prev)
-                }
-            }
-
-            doc_comment! {
-                concat!("Maximum with the current value.
-
-Finds the maximum of the current value and the argument `val`, and
-sets the new value to the result.
-
-Returns the previous value.
-
-`fetch_max` takes an [`Ordering`] argument which describes the memory ordering
-of this operation. All ordering modes are possible. Note that using
-[`Acquire`] makes the store part of this operation [`Relaxed`], and
-using [`Release`] makes the load part [`Relaxed`].
-
-**Note**: This method is only available on platforms that support atomic
-operations on [`", $s_int_type, "`](", $int_ref, ").
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let foo = ", stringify!($atomic_type), "::new(23);
-assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
-assert_eq!(foo.load(Ordering::SeqCst), 42);
-```
-
-If you want to obtain the maximum value in one step, you can use the following:
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let foo = ", stringify!($atomic_type), "::new(23);
-let bar = 42;
-let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
-assert!(max_foo == 42);
-```"),
-                #[inline]
-                #[stable(feature = "atomic_min_max", since = "1.45.0")]
-                #[$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) }
-                }
-            }
-
-            doc_comment! {
-                concat!("Minimum with the current value.
-
-Finds the minimum of the current value and the argument `val`, and
-sets the new value to the result.
-
-Returns the previous value.
-
-`fetch_min` takes an [`Ordering`] argument which describes the memory ordering
-of this operation. All ordering modes are possible. Note that using
-[`Acquire`] makes the store part of this operation [`Relaxed`], and
-using [`Release`] makes the load part [`Relaxed`].
-
-**Note**: This method is only available on platforms that support atomic
-operations on [`", $s_int_type, "`](", $int_ref, ").
-
-# Examples
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let foo = ", stringify!($atomic_type), "::new(23);
-assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
-assert_eq!(foo.load(Ordering::Relaxed), 23);
-assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
-assert_eq!(foo.load(Ordering::Relaxed), 22);
-```
-
-If you want to obtain the minimum value in one step, you can use the following:
-
-```
-", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
-
-let foo = ", stringify!($atomic_type), "::new(23);
-let bar = 12;
-let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
-assert_eq!(min_foo, 12);
-```"),
-                #[inline]
-                #[stable(feature = "atomic_min_max", since = "1.45.0")]
-                #[$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) }
-                }
-            }
-
-            doc_comment! {
-                concat!("Returns a mutable pointer to the underlying integer.
-
-Doing non-atomic reads and writes on the resulting integer can be a data race.
-This method is mostly useful for FFI, where the function signature may use
-`*mut ", stringify!($int_type), "` instead of `&", stringify!($atomic_type), "`.
-
-Returning an `*mut` pointer from a shared reference to this atomic is safe because the
-atomic types work with interior mutability. All modifications of an atomic change the value
-through a shared reference, and can do so safely as long as they use atomic operations. Any
-use of the returned raw pointer requires an `unsafe` block and still has to uphold the same
-restriction: operations on it must be atomic.
-
-# Examples
-
-```ignore (extern-declaration)
-# fn main() {
-", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";
-
-extern {
-    fn my_atomic_op(arg: *mut ", stringify!($int_type), ");
-}
-
-let mut atomic = ", stringify!($atomic_type), "::new(1);
-",
-// SAFETY: Safe as long as `my_atomic_op` is atomic.
-"unsafe {
-    my_atomic_op(atomic.as_mut_ptr());
-}
-# }
-```"),
-                #[inline]
-                #[unstable(feature = "atomic_mut_ptr",
-                       reason = "recently added",
-                       issue = "66893")]
-                pub fn as_mut_ptr(&self) -> *mut $int_type {
-                    self.v.get()
-                }
+            /// Returns a mutable pointer to the underlying integer.
+            ///
+            /// Doing non-atomic reads and writes on the resulting integer can be a data race.
+            /// This method is mostly useful for FFI, where the function signature may use
+            #[doc = concat!("`*mut ", stringify!($int_type), "` instead of `&", stringify!($atomic_type), "`.")]
+            ///
+            /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
+            /// atomic types work with interior mutability. All modifications of an atomic change the value
+            /// through a shared reference, and can do so safely as long as they use atomic operations. Any
+            /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same
+            /// restriction: operations on it must be atomic.
+            ///
+            /// # Examples
+            ///
+            /// ```ignore (extern-declaration)
+            /// # fn main() {
+            #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")]
+            ///
+            /// extern "C" {
+            #[doc = concat!("    fn my_atomic_op(arg: *mut ", stringify!($int_type), ");")]
+            /// }
+            ///
+            #[doc = concat!("let mut atomic = ", stringify!($atomic_type), "::new(1);")]
+            ///
+            // SAFETY: Safe as long as `my_atomic_op` is atomic.
+            /// unsafe {
+            ///     my_atomic_op(atomic.as_mut_ptr());
+            /// }
+            /// # }
+            /// ```
+            #[inline]
+            #[unstable(feature = "atomic_mut_ptr",
+                   reason = "recently added",
+                   issue = "66893")]
+            pub fn as_mut_ptr(&self) -> *mut $int_type {
+                self.v.get()
             }
         }
     }
@@ -2835,3 +2776,15 @@
         fmt::Pointer::fmt(&self.load(Ordering::SeqCst), f)
     }
 }
+
+/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock").
+///
+/// This function is deprecated in favor of [`hint::spin_loop`].
+///
+/// [`hint::spin_loop`]: crate::hint::spin_loop
+#[inline]
+#[stable(feature = "spin_loop_hint", since = "1.24.0")]
+#[rustc_deprecated(since = "1.51.0", reason = "use hint::spin_loop instead")]
+pub fn spin_loop_hint() {
+    spin_loop()
+}
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 6851f3f..42c9d9f 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -84,7 +84,7 @@
 
 impl<T, E> Poll<Option<Result<T, E>>> {
     /// Changes the success value of this `Poll` with the closure provided.
-    #[unstable(feature = "poll_map", issue = "63514")]
+    #[stable(feature = "poll_map", since = "1.51.0")]
     pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
     where
         F: FnOnce(T) -> U,
@@ -98,7 +98,7 @@
     }
 
     /// Changes the error value of this `Poll` with the closure provided.
-    #[unstable(feature = "poll_map", issue = "63514")]
+    #[stable(feature = "poll_map", since = "1.51.0")]
     pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
     where
         F: FnOnce(E) -> U,
diff --git a/library/core/tests/iter.rs b/library/core/tests/iter.rs
index 7376e78..bc5421b 100644
--- a/library/core/tests/iter.rs
+++ b/library/core/tests/iter.rs
@@ -2,6 +2,7 @@
 
 use core::cell::Cell;
 use core::convert::TryFrom;
+use core::iter::TrustedRandomAccess;
 use core::iter::*;
 
 /// An iterator wrapper that panics whenever `next` or `next_back` is called
@@ -602,6 +603,26 @@
 }
 
 #[test]
+fn test_zip_trusted_random_access_composition() {
+    let a = [0, 1, 2, 3, 4];
+    let b = a;
+    let c = a;
+
+    let a = a.iter().copied();
+    let b = b.iter().copied();
+    let mut c = c.iter().copied();
+    c.next();
+
+    let mut z1 = a.zip(b);
+    assert_eq!(z1.next().unwrap(), (0, 0));
+
+    let mut z2 = z1.zip(c);
+    fn assert_trusted_random_access<T: TrustedRandomAccess>(_a: &T) {}
+    assert_trusted_random_access(&z2);
+    assert_eq!(z2.next().unwrap(), ((1, 1), 1));
+}
+
+#[test]
 fn test_iterator_step_by() {
     // Identity
     let mut it = (0..).step_by(1).take(3);
@@ -3508,6 +3529,12 @@
 
 #[test]
 fn test_intersperse() {
+    let v = std::iter::empty().intersperse(0u32).collect::<Vec<_>>();
+    assert_eq!(v, vec![]);
+
+    let v = std::iter::once(1).intersperse(0).collect::<Vec<_>>();
+    assert_eq!(v, vec![1]);
+
     let xs = ["a", "", "b", "c"];
     let v: Vec<&str> = xs.iter().map(|x| x.clone()).intersperse(", ").collect();
     let text: String = v.concat();
@@ -3520,6 +3547,9 @@
 
 #[test]
 fn test_intersperse_size_hint() {
+    let iter = std::iter::empty::<i32>().intersperse(0);
+    assert_eq!(iter.size_hint(), (0, Some(0)));
+
     let xs = ["a", "", "b", "c"];
     let mut iter = xs.iter().map(|x| x.clone()).intersperse(", ");
     assert_eq!(iter.size_hint(), (7, Some(7)));
@@ -3587,3 +3617,24 @@
     iter.try_for_each(|item| if item == "b" { None } else { Some(()) });
     assert_eq!(iter.next(), None);
 }
+
+#[test]
+fn test_intersperse_with() {
+    #[derive(PartialEq, Debug)]
+    struct NotClone {
+        u: u32,
+    }
+    let r = vec![NotClone { u: 0 }, NotClone { u: 1 }]
+        .into_iter()
+        .intersperse_with(|| NotClone { u: 2 })
+        .collect::<Vec<_>>();
+    assert_eq!(r, vec![NotClone { u: 0 }, NotClone { u: 2 }, NotClone { u: 1 }]);
+
+    let mut ctr = 100;
+    let separator = || {
+        ctr *= 2;
+        ctr
+    };
+    let r = (0..3).intersperse_with(separator).collect::<Vec<_>>();
+    assert_eq!(r, vec![0, 200, 1, 400, 2]);
+}
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index fba3294..98f5982 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -36,6 +36,8 @@
 #![feature(raw)]
 #![feature(sort_internals)]
 #![feature(slice_partition_at_index)]
+#![feature(maybe_uninit_uninit_array)]
+#![feature(maybe_uninit_array_assume_init)]
 #![feature(maybe_uninit_extra)]
 #![feature(maybe_uninit_write_slice)]
 #![feature(min_specialization)]
@@ -72,6 +74,8 @@
 #![feature(nonzero_leading_trailing_zeros)]
 #![feature(const_option)]
 #![feature(integer_atomics)]
+#![feature(slice_group_by)]
+#![feature(trusted_random_access)]
 #![deny(unsafe_op_in_unsafe_fn)]
 
 extern crate test;
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index 79ca2bb..2279a16 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -141,6 +141,20 @@
 }
 
 #[test]
+fn uninit_array_assume_init() {
+    let mut array: [MaybeUninit<i16>; 5] = MaybeUninit::uninit_array();
+    array[0].write(3);
+    array[1].write(1);
+    array[2].write(4);
+    array[3].write(1);
+    array[4].write(5);
+
+    let array = unsafe { MaybeUninit::array_assume_init(array) };
+
+    assert_eq!(array, [3, 1, 4, 1, 5]);
+}
+
+#[test]
 fn uninit_write_slice() {
     let mut dst = [MaybeUninit::new(255); 64];
     let src = [0; 64];
diff --git a/library/core/tests/num/dec2flt/mod.rs b/library/core/tests/num/dec2flt/mod.rs
index 1c172f4..32f05d1 100644
--- a/library/core/tests/num/dec2flt/mod.rs
+++ b/library/core/tests/num/dec2flt/mod.rs
@@ -21,7 +21,6 @@
     }};
 }
 
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
 #[test]
 fn ordinary() {
     test_literal!(1.0);
@@ -38,7 +37,6 @@
     test_literal!(2.2250738585072014e-308);
 }
 
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
 #[test]
 fn special_code_paths() {
     test_literal!(36893488147419103229.0); // 2^65 - 3, triggers half-to-even with even significand
diff --git a/library/core/tests/num/dec2flt/rawfp.rs b/library/core/tests/num/dec2flt/rawfp.rs
index c098b9c..34a3720 100644
--- a/library/core/tests/num/dec2flt/rawfp.rs
+++ b/library/core/tests/num/dec2flt/rawfp.rs
@@ -81,7 +81,6 @@
     assert_eq!(rounded.k, adjusted_k + 1);
 }
 
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
 #[test]
 fn prev_float_monotonic() {
     let mut x = 1.0;
@@ -117,7 +116,6 @@
     assert_eq!(next_float(f64::INFINITY), f64::INFINITY);
 }
 
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
 #[test]
 fn next_prev_identity() {
     for &x in &SOME_FLOATS {
@@ -128,7 +126,6 @@
     }
 }
 
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
 #[test]
 fn next_float_monotonic() {
     let mut x = 0.49999999999999;
diff --git a/library/core/tests/num/flt2dec/strategy/dragon.rs b/library/core/tests/num/flt2dec/strategy/dragon.rs
index 3d985c6..fc2e724 100644
--- a/library/core/tests/num/flt2dec/strategy/dragon.rs
+++ b/library/core/tests/num/flt2dec/strategy/dragon.rs
@@ -13,7 +13,6 @@
     }
 }
 
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
 #[test]
 fn shortest_sanity_test() {
     f64_shortest_sanity_test(format_shortest);
diff --git a/library/core/tests/num/flt2dec/strategy/grisu.rs b/library/core/tests/num/flt2dec/strategy/grisu.rs
index 7e6c8ad..b59a3b9 100644
--- a/library/core/tests/num/flt2dec/strategy/grisu.rs
+++ b/library/core/tests/num/flt2dec/strategy/grisu.rs
@@ -33,7 +33,6 @@
     }
 }
 
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
 #[test]
 fn shortest_sanity_test() {
     f64_shortest_sanity_test(format_shortest);
diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
index 012ab4e..e66a73a 100644
--- a/library/core/tests/num/mod.rs
+++ b/library/core/tests/num/mod.rs
@@ -29,6 +29,8 @@
 mod bignum;
 mod dec2flt;
 mod flt2dec;
+mod ops;
+mod wrapping;
 
 mod nan;
 
diff --git a/library/core/tests/num/ops.rs b/library/core/tests/num/ops.rs
new file mode 100644
index 0000000..9979cc8
--- /dev/null
+++ b/library/core/tests/num/ops.rs
@@ -0,0 +1,244 @@
+use core::ops::*;
+
+// For types L and R, checks that a trait implementation exists for
+//   * binary ops: L op R, L op &R, &L op R and &L op &R
+//   * assign ops: &mut L op R, &mut L op &R
+macro_rules! impl_defined {
+    ($op:ident, $method:ident($lhs:literal, $rhs:literal), $result:literal, $lt:ty, $rt:ty) => {
+        let lhs = $lhs as $lt;
+        let rhs = $rhs as $rt;
+        assert_eq!($result as $lt, $op::$method(lhs, rhs));
+        assert_eq!($result as $lt, $op::$method(lhs, &rhs));
+        assert_eq!($result as $lt, $op::$method(&lhs, rhs));
+        assert_eq!($result as $lt, $op::$method(&lhs, &rhs));
+    };
+    ($op:ident, $method:ident(&mut $lhs:literal, $rhs:literal), $result:literal, $lt:ty, $rt:ty) => {
+        let rhs = $rhs as $rt;
+        let mut lhs = $lhs as $lt;
+        $op::$method(&mut lhs, rhs);
+        assert_eq!($result as $lt, lhs);
+
+        let mut lhs = $lhs as $lt;
+        $op::$method(&mut lhs, &rhs);
+        assert_eq!($result as $lt, lhs);
+    };
+}
+
+// For all specified types T, checks that a trait implementation exists for
+//   * binary ops: T op T, T op &T, &T op T and &T op &T
+//   * assign ops: &mut T op T, &mut T op &T
+//   * unary ops: op T and op &T
+macro_rules! impls_defined {
+    ($op:ident, $method:ident($lhs:literal, $rhs:literal), $result:literal, $($t:ty),+) => {$(
+        impl_defined!($op, $method($lhs, $rhs), $result, $t, $t);
+    )+};
+    ($op:ident, $method:ident(&mut $lhs:literal, $rhs:literal), $result:literal, $($t:ty),+) => {$(
+        impl_defined!($op, $method(&mut $lhs, $rhs), $result, $t, $t);
+    )+};
+    ($op:ident, $method:ident($operand:literal), $result:literal, $($t:ty),+) => {$(
+        let operand = $operand as $t;
+        assert_eq!($result as $t, $op::$method(operand));
+        assert_eq!($result as $t, $op::$method(&operand));
+    )+};
+}
+
+macro_rules! test_op {
+    ($fn_name:ident, $op:ident::$method:ident($lhs:literal, $rhs:literal), $result:literal, $($t:ty),+) => {
+        #[test]
+        fn $fn_name() {
+            impls_defined!($op, $method($lhs, $rhs), $result, $($t),+);
+        }
+    };
+    ($fn_name:ident, $op:ident::$method:ident(&mut $lhs:literal, $rhs:literal), $result:literal, $($t:ty),+) => {
+        #[test]
+        fn $fn_name() {
+            impls_defined!($op, $method(&mut $lhs, $rhs), $result, $($t),+);
+        }
+    };
+    ($fn_name:ident, $op:ident::$method:ident($lhs:literal), $result:literal, $($t:ty),+) => {
+        #[test]
+        fn $fn_name() {
+            impls_defined!($op, $method($lhs), $result, $($t),+);
+        }
+    };
+}
+
+test_op!(test_neg_defined, Neg::neg(0), 0, i8, i16, i32, i64, f32, f64);
+#[cfg(not(target_os = "emscripten"))]
+test_op!(test_neg_defined_128, Neg::neg(0), 0, i128);
+
+test_op!(test_not_defined_bool, Not::not(true), false, bool);
+
+macro_rules! test_arith_op {
+    ($fn_name:ident, $op:ident::$method:ident($lhs:literal, $rhs:literal)) => {
+        #[test]
+        fn $fn_name() {
+            impls_defined!(
+                $op,
+                $method($lhs, $rhs),
+                0,
+                i8,
+                i16,
+                i32,
+                i64,
+                isize,
+                u8,
+                u16,
+                u32,
+                u64,
+                usize,
+                f32,
+                f64
+            );
+            #[cfg(not(target_os = "emscripten"))]
+            impls_defined!($op, $method($lhs, $rhs), 0, i128, u128);
+        }
+    };
+    ($fn_name:ident, $op:ident::$method:ident(&mut $lhs:literal, $rhs:literal)) => {
+        #[test]
+        fn $fn_name() {
+            impls_defined!(
+                $op,
+                $method(&mut $lhs, $rhs),
+                0,
+                i8,
+                i16,
+                i32,
+                i64,
+                isize,
+                u8,
+                u16,
+                u32,
+                u64,
+                usize,
+                f32,
+                f64
+            );
+            #[cfg(not(target_os = "emscripten"))]
+            impls_defined!($op, $method(&mut $lhs, $rhs), 0, i128, u128);
+        }
+    };
+}
+
+test_arith_op!(test_add_defined, Add::add(0, 0));
+test_arith_op!(test_add_assign_defined, AddAssign::add_assign(&mut 0, 0));
+test_arith_op!(test_sub_defined, Sub::sub(0, 0));
+test_arith_op!(test_sub_assign_defined, SubAssign::sub_assign(&mut 0, 0));
+test_arith_op!(test_mul_defined, Mul::mul(0, 0));
+test_arith_op!(test_mul_assign_defined, MulAssign::mul_assign(&mut 0, 0));
+test_arith_op!(test_div_defined, Div::div(0, 1));
+test_arith_op!(test_div_assign_defined, DivAssign::div_assign(&mut 0, 1));
+test_arith_op!(test_rem_defined, Rem::rem(0, 1));
+test_arith_op!(test_rem_assign_defined, RemAssign::rem_assign(&mut 0, 1));
+
+macro_rules! test_bitop {
+    ($test_name:ident, $op:ident::$method:ident) => {
+        #[test]
+        fn $test_name() {
+            impls_defined!(
+                $op,
+                $method(0, 0),
+                0,
+                i8,
+                i16,
+                i32,
+                i64,
+                isize,
+                u8,
+                u16,
+                u32,
+                u64,
+                usize
+            );
+            #[cfg(not(target_os = "emscripten"))]
+            impls_defined!($op, $method(0, 0), 0, i128, u128);
+            impls_defined!($op, $method(false, false), false, bool);
+        }
+    };
+}
+macro_rules! test_bitop_assign {
+    ($test_name:ident, $op:ident::$method:ident) => {
+        #[test]
+        fn $test_name() {
+            impls_defined!(
+                $op,
+                $method(&mut 0, 0),
+                0,
+                i8,
+                i16,
+                i32,
+                i64,
+                isize,
+                u8,
+                u16,
+                u32,
+                u64,
+                usize
+            );
+            #[cfg(not(target_os = "emscripten"))]
+            impls_defined!($op, $method(&mut 0, 0), 0, i128, u128);
+            impls_defined!($op, $method(&mut false, false), false, bool);
+        }
+    };
+}
+
+test_bitop!(test_bitand_defined, BitAnd::bitand);
+test_bitop_assign!(test_bitand_assign_defined, BitAndAssign::bitand_assign);
+test_bitop!(test_bitor_defined, BitOr::bitor);
+test_bitop_assign!(test_bitor_assign_defined, BitOrAssign::bitor_assign);
+test_bitop!(test_bitxor_defined, BitXor::bitxor);
+test_bitop_assign!(test_bitxor_assign_defined, BitXorAssign::bitxor_assign);
+
+macro_rules! test_shift_inner {
+    ($op:ident::$method:ident, $lt:ty, $($rt:ty),+) => {
+        $(impl_defined!($op, $method(0,0), 0, $lt, $rt);)+
+    };
+    ($op:ident::$method:ident, $lt:ty) => {
+        test_shift_inner!($op::$method, $lt, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
+        #[cfg(not(target_os = "emscripten"))]
+        test_shift_inner!($op::$method, $lt, i128, u128);
+    };
+}
+
+macro_rules! test_shift {
+    ($op:ident::$method:ident, $($lt:ty),+) => {
+        $(test_shift_inner!($op::$method, $lt);)+
+    };
+    ($test_name:ident, $op:ident::$method:ident) => {
+        #[test]
+        fn $test_name() {
+            test_shift!($op::$method, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
+            #[cfg(not(target_os = "emscripten"))]
+            test_shift!($op::$method, i128, u128);
+        }
+    };
+}
+
+macro_rules! test_shift_assign_inner {
+    ($op:ident::$method:ident, $lt:ty, $($rt:ty),+) => {
+        $(impl_defined!($op, $method(&mut 0,0), 0, $lt, $rt);)+
+    };
+    ($op:ident::$method:ident, $lt:ty) => {
+        test_shift_assign_inner!($op::$method, $lt, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
+        #[cfg(not(target_os = "emscripten"))]
+        test_shift_assign_inner!($op::$method, $lt, i128, u128);
+    };
+}
+
+macro_rules! test_shift_assign {
+    ($op:ident::$method:ident, $($lt:ty),+) => {
+        $(test_shift_assign_inner!($op::$method, $lt);)+
+    };
+    ($test_name:ident, $op:ident::$method:ident) => {
+        #[test]
+        fn $test_name() {
+            test_shift_assign!($op::$method, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
+            #[cfg(not(target_os = "emscripten"))]
+            test_shift_assign!($op::$method, i128, u128);
+        }
+    };
+}
+test_shift!(test_shl_defined, Shl::shl);
+test_shift_assign!(test_shl_assign_defined, ShlAssign::shl_assign);
+test_shift!(test_shr_defined, Shr::shr);
+test_shift_assign!(test_shr_assign_defined, ShrAssign::shr_assign);
diff --git a/library/core/tests/num/wrapping.rs b/library/core/tests/num/wrapping.rs
index 01defab2..c4fb321 100644
--- a/library/core/tests/num/wrapping.rs
+++ b/library/core/tests/num/wrapping.rs
@@ -26,9 +26,9 @@
 }
 
 macro_rules! wrapping_test {
-    ($type:ty, $min:expr, $max:expr) => {
+    ($fn_name:ident, $type:ty, $min:expr, $max:expr) => {
         #[test]
-        fn wrapping_$type() {
+        fn $fn_name() {
             let zero: Wrapping<$type> = Wrapping(0);
             let one: Wrapping<$type> = Wrapping(1);
             let min: Wrapping<$type> = Wrapping($min);
@@ -60,23 +60,24 @@
     };
 }
 
-wrapping_test!(i8, i8::MIN, i8::MAX);
-wrapping_test!(i16, i16::MIN, i16::MAX);
-wrapping_test!(i32, i32::MIN, i32::MAX);
-wrapping_test!(i64, i64::MIN, i64::MAX);
+wrapping_test!(test_wrapping_i8, i8, i8::MIN, i8::MAX);
+wrapping_test!(test_wrapping_i16, i16, i16::MIN, i16::MAX);
+wrapping_test!(test_wrapping_i32, i32, i32::MIN, i32::MAX);
+wrapping_test!(test_wrapping_i64, i64, i64::MIN, i64::MAX);
 #[cfg(not(target_os = "emscripten"))]
-wrapping_test!(i128, i128::MIN, i128::MAX);
-wrapping_test!(isize, isize::MIN, isize::MAX);
-wrapping_test!(u8, u8::MIN, u8::MAX);
-wrapping_test!(u16, u16::MIN, u16::MAX);
-wrapping_test!(u32, u32::MIN, u32::MAX);
-wrapping_test!(u64, u64::MIN, u64::MAX);
+wrapping_test!(test_wrapping_i128, i128, i128::MIN, i128::MAX);
+wrapping_test!(test_wrapping_isize, isize, isize::MIN, isize::MAX);
+wrapping_test!(test_wrapping_u8, u8, u8::MIN, u8::MAX);
+wrapping_test!(test_wrapping_u16, u16, u16::MIN, u16::MAX);
+wrapping_test!(test_wrapping_u32, u32, u32::MIN, u32::MAX);
+wrapping_test!(test_wrapping_u64, u64, u64::MIN, u64::MAX);
 #[cfg(not(target_os = "emscripten"))]
-wrapping_test!(u128, u128::MIN, u128::MAX);
-wrapping_test!(usize, usize::MIN, usize::MAX);
+wrapping_test!(test_wrapping_u128, u128, u128::MIN, u128::MAX);
+wrapping_test!(test_wrapping_usize, usize, usize::MIN, usize::MAX);
 
 // Don't warn about overflowing ops on 32-bit platforms
 #[cfg_attr(target_pointer_width = "32", allow(const_err))]
+#[test]
 fn wrapping_int_api() {
     assert_eq!(i8::MAX.wrapping_add(1), i8::MIN);
     assert_eq!(i16::MAX.wrapping_add(1), i16::MIN);
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 71d00b5..1c73876 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -17,7 +17,7 @@
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
 libc = { version = "0.2.79", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.35" }
+compiler_builtins = { version = "0.1.39" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.9.0", default-features = false, features = ['rustc-dep-of-std'] }
@@ -60,7 +60,7 @@
 profiler = ["profiler_builtins"]
 compiler-builtins-c = ["alloc/compiler-builtins-c"]
 compiler-builtins-mem = ["alloc/compiler-builtins-mem"]
-compiler-builtins-asm = ["alloc/compiler-builtins-asm"]
+compiler-builtins-no-asm = ["alloc/compiler-builtins-no-asm"]
 compiler-builtins-mangled-names = ["alloc/compiler-builtins-mangled-names"]
 llvm-libunwind = ["unwind/llvm-libunwind"]
 system-llvm-libunwind = ["unwind/system-llvm-libunwind"]
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index 8491ff4..843ef09 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -166,8 +166,9 @@
         match old_layout.size() {
             0 => self.alloc_impl(new_layout, zeroed),
 
-            // SAFETY: `new_size` is non-zero as `old_size` is greater than or equal to `new_size`
-            // as required by safety conditions. Other conditions must be upheld by the caller
+            // SAFETY: `new_size` is non-zero as `new_size` is greater than or equal to `old_size`
+            // as required by safety conditions and the `old_size == 0` case was handled in the
+            // previous match arm. Other conditions must be upheld by the caller
             old_size if old_layout.align() == new_layout.align() => unsafe {
                 let new_size = new_layout.size();
 
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index 7e8e0a6..95e18ef 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -95,11 +95,12 @@
 // a backtrace or actually symbolizing it.
 
 use crate::backtrace_rs::{self, BytesOrWideString};
+use crate::cell::UnsafeCell;
 use crate::env;
 use crate::ffi::c_void;
 use crate::fmt;
 use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
-use crate::sync::Mutex;
+use crate::sync::Once;
 use crate::sys_common::backtrace::{lock, output_filename};
 use crate::vec::Vec;
 
@@ -132,7 +133,7 @@
 enum Inner {
     Unsupported,
     Disabled,
-    Captured(Mutex<Capture>),
+    Captured(LazilyResolvedCapture),
 }
 
 struct Capture {
@@ -171,12 +172,11 @@
 
 impl fmt::Debug for Backtrace {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut capture = match &self.inner {
+        let capture = match &self.inner {
             Inner::Unsupported => return fmt.write_str("<unsupported>"),
             Inner::Disabled => return fmt.write_str("<disabled>"),
-            Inner::Captured(c) => c.lock().unwrap(),
+            Inner::Captured(c) => c.force(),
         };
-        capture.resolve();
 
         let frames = &capture.frames[capture.actual_start..];
 
@@ -331,7 +331,7 @@
         let inner = if frames.is_empty() {
             Inner::Unsupported
         } else {
-            Inner::Captured(Mutex::new(Capture {
+            Inner::Captured(LazilyResolvedCapture::new(Capture {
                 actual_start: actual_start.unwrap_or(0),
                 frames,
                 resolved: false,
@@ -355,12 +355,11 @@
 
 impl fmt::Display for Backtrace {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut capture = match &self.inner {
+        let capture = match &self.inner {
             Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
             Inner::Disabled => return fmt.write_str("disabled backtrace"),
-            Inner::Captured(c) => c.lock().unwrap(),
+            Inner::Captured(c) => c.force(),
         };
-        capture.resolve();
 
         let full = fmt.alternate();
         let (frames, style) = if full {
@@ -404,6 +403,33 @@
     }
 }
 
+struct LazilyResolvedCapture {
+    sync: Once,
+    capture: UnsafeCell<Capture>,
+}
+
+impl LazilyResolvedCapture {
+    fn new(capture: Capture) -> Self {
+        LazilyResolvedCapture { sync: Once::new(), capture: UnsafeCell::new(capture) }
+    }
+
+    fn force(&self) -> &Capture {
+        self.sync.call_once(|| {
+            // SAFETY: This exclusive reference can't overlap with any others
+            // `Once` guarantees callers will block until this closure returns
+            // `Once` also guarantees only a single caller will enter this closure
+            unsafe { &mut *self.capture.get() }.resolve();
+        });
+
+        // SAFETY: This shared reference can't overlap with the exclusive reference above
+        unsafe { &*self.capture.get() }
+    }
+}
+
+// SAFETY: Access to the inner value is synchronized using a thread-safe `Once`
+// So long as `Capture` is `Sync`, `LazilyResolvedCapture` is too
+unsafe impl Sync for LazilyResolvedCapture where Capture: Sync {}
+
 impl Capture {
     fn resolve(&mut self) {
         // If we're already resolved, nothing to do!
diff --git a/library/std/src/backtrace/tests.rs b/library/std/src/backtrace/tests.rs
index f5f74d1..31cf0f7 100644
--- a/library/std/src/backtrace/tests.rs
+++ b/library/std/src/backtrace/tests.rs
@@ -3,7 +3,7 @@
 #[test]
 fn test_debug() {
     let backtrace = Backtrace {
-        inner: Inner::Captured(Mutex::new(Capture {
+        inner: Inner::Captured(LazilyResolvedCapture::new(Capture {
             actual_start: 1,
             resolved: true,
             frames: vec![
@@ -54,4 +54,7 @@
     \n]";
 
     assert_eq!(format!("{:#?}", backtrace), expected);
+
+    // Format the backtrace a second time, just to make sure lazily resolved state is stable
+    assert_eq!(format!("{:#?}", backtrace), expected);
 }
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 0680b1f..829fc38 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -52,6 +52,9 @@
 /// hash, as determined by the [`Hash`] trait, or its equality, as determined by
 /// the [`Eq`] trait, changes while it is in the map. This is normally only
 /// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
+/// The behavior resulting from such a logic error is not specified, but will
+/// not result in undefined behavior. This could include panics, incorrect results,
+/// aborts, memory leaks, and non-termination.
 ///
 /// The hash table implementation is a Rust port of Google's [SwissTable].
 /// The original C++ version of SwissTable can be found [here], and this
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index f49e580..baa3026 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -37,7 +37,9 @@
 /// item's hash, as determined by the [`Hash`] trait, or its equality, as
 /// determined by the [`Eq`] trait, changes while it is in the set. This is
 /// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or
-/// unsafe code.
+/// unsafe code. The behavior resulting from such a logic error is not
+/// specified, but will not result in undefined behavior. This could include
+/// panics, incorrect results, aborts, memory leaks, and non-termination.
 ///
 /// # Examples
 ///
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index 0044e59..ca83c40 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -42,8 +42,6 @@
 /// via [`Error::source()`]. This makes it possible for the high-level
 /// module to provide its own errors while also revealing some of the
 /// implementation for debugging via `source` chains.
-///
-/// [`Result<T, E>`]: Result
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Error: Debug + Display {
     /// The lower-level source of this error, if any.
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index 60b642a..230ef0b 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -86,7 +86,7 @@
 /// use std::ffi::CString;
 /// use std::os::raw::c_char;
 ///
-/// extern {
+/// extern "C" {
 ///     fn my_printer(s: *const c_char);
 /// }
 ///
@@ -144,7 +144,7 @@
 /// use std::ffi::CStr;
 /// use std::os::raw::c_char;
 ///
-/// extern { fn my_string() -> *const c_char; }
+/// extern "C" { fn my_string() -> *const c_char; }
 ///
 /// unsafe {
 ///     let slice = CStr::from_ptr(my_string());
@@ -159,7 +159,7 @@
 /// use std::os::raw::c_char;
 ///
 /// fn work(data: &CStr) {
-///     extern { fn work_with(data: *const c_char); }
+///     extern "C" { fn work_with(data: *const c_char); }
 ///
 ///     unsafe { work_with(data.as_ptr()) }
 /// }
@@ -174,7 +174,7 @@
 /// use std::ffi::CStr;
 /// use std::os::raw::c_char;
 ///
-/// extern { fn my_string() -> *const c_char; }
+/// extern "C" { fn my_string() -> *const c_char; }
 ///
 /// fn my_string_safe() -> String {
 ///     unsafe {
@@ -359,7 +359,7 @@
     /// use std::ffi::CString;
     /// use std::os::raw::c_char;
     ///
-    /// extern { fn puts(s: *const c_char); }
+    /// extern "C" { fn puts(s: *const c_char); }
     ///
     /// let to_print = CString::new("Hello!").expect("CString::new failed");
     /// unsafe {
@@ -465,7 +465,7 @@
     /// use std::ffi::CString;
     /// use std::os::raw::c_char;
     ///
-    /// extern {
+    /// extern "C" {
     ///     fn some_extern_function(s: *mut c_char);
     /// }
     ///
@@ -1147,7 +1147,7 @@
     /// use std::ffi::CStr;
     /// use std::os::raw::c_char;
     ///
-    /// extern {
+    /// extern "C" {
     ///     fn my_string() -> *const c_char;
     /// }
     ///
diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs
index 16c18d6..8bae3da 100644
--- a/library/std/src/io/buffered/bufreader.rs
+++ b/library/std/src/io/buffered/bufreader.rs
@@ -271,6 +271,20 @@
         Ok(nread)
     }
 
+    // Small read_exacts from a BufReader are extremely common when used with a deserializer.
+    // The default implementation calls read in a loop, which results in surprisingly poor code
+    // generation for the common path where the buffer has enough bytes to fill the passed-in
+    // buffer.
+    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
+        if self.buffer().len() >= buf.len() {
+            buf.copy_from_slice(&self.buffer()[..buf.len()]);
+            self.consume(buf.len());
+            return Ok(());
+        }
+
+        crate::io::default_read_exact(self, buf)
+    }
+
     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
         if self.pos == self.cap && total_len >= self.buf.len() {
diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs
index 66a64f6..f6c2b49 100644
--- a/library/std/src/io/buffered/tests.rs
+++ b/library/std/src/io/buffered/tests.rs
@@ -444,6 +444,18 @@
 }
 
 #[bench]
+fn bench_buffered_reader_small_reads(b: &mut test::Bencher) {
+    let data = (0..u8::MAX).cycle().take(1024 * 4).collect::<Vec<_>>();
+    b.iter(|| {
+        let mut reader = BufReader::new(&data[..]);
+        let mut buf = [0u8; 4];
+        for _ in 0..1024 {
+            reader.read_exact(&mut buf).unwrap();
+        }
+    });
+}
+
+#[bench]
 fn bench_buffered_writer(b: &mut test::Bencher) {
     b.iter(|| BufWriter::new(io::sink()));
 }
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index dfbf6c3..c87a565 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -240,7 +240,6 @@
 //!
 //! [`File`]: crate::fs::File
 //! [`TcpStream`]: crate::net::TcpStream
-//! [`Vec<T>`]: Vec
 //! [`io::stdout`]: stdout
 //! [`io::Result`]: self::Result
 //! [`?` operator]: ../../book/appendix-02-operators.html
@@ -367,7 +366,6 @@
 {
     let start_len = buf.len();
     let mut g = Guard { len: buf.len(), buf };
-    let ret;
     loop {
         if g.len == g.buf.len() {
             unsafe {
@@ -386,21 +384,20 @@
             }
         }
 
-        match r.read(&mut g.buf[g.len..]) {
-            Ok(0) => {
-                ret = Ok(g.len - start_len);
-                break;
+        let buf = &mut g.buf[g.len..];
+        match r.read(buf) {
+            Ok(0) => return Ok(g.len - start_len),
+            Ok(n) => {
+                // We can't allow bogus values from read. If it is too large, the returned vec could have its length
+                // set past its capacity, or if it overflows the vec could be shortened which could create an invalid
+                // string if this is called via read_to_string.
+                assert!(n <= buf.len());
+                g.len += n;
             }
-            Ok(n) => g.len += n,
             Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
-            Err(e) => {
-                ret = Err(e);
-                break;
-            }
+            Err(e) => return Err(e),
         }
     }
-
-    ret
 }
 
 pub(crate) fn default_read_vectored<F>(read: F, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>
@@ -419,6 +416,25 @@
     write(buf)
 }
 
+pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [u8]) -> Result<()> {
+    while !buf.is_empty() {
+        match this.read(buf) {
+            Ok(0) => break,
+            Ok(n) => {
+                let tmp = buf;
+                buf = &mut tmp[n..];
+            }
+            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
+            Err(e) => return Err(e),
+        }
+    }
+    if !buf.is_empty() {
+        Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
+    } else {
+        Ok(())
+    }
+}
+
 /// The `Read` trait allows for reading bytes from a source.
 ///
 /// Implementors of the `Read` trait are called 'readers'.
@@ -769,23 +785,8 @@
     /// }
     /// ```
     #[stable(feature = "read_exact", since = "1.6.0")]
-    fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
-        while !buf.is_empty() {
-            match self.read(buf) {
-                Ok(0) => break,
-                Ok(n) => {
-                    let tmp = buf;
-                    buf = &mut tmp[n..];
-                }
-                Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
-                Err(e) => return Err(e),
-            }
-        }
-        if !buf.is_empty() {
-            Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
-        } else {
-            Ok(())
-        }
+    fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
+        default_read_exact(self, buf)
     }
 
     /// Creates a "by reference" adaptor for this instance of `Read`.
@@ -945,6 +946,54 @@
     }
 }
 
+/// Read all bytes from a [reader][Read] into a new [`String`].
+///
+/// This is a convenience function for [`Read::read_to_string`]. Using this
+/// function avoids having to create a variable first and provides more type
+/// safety since you can only get the buffer out if there were no errors. (If you
+/// use [`Read::read_to_string`] you have to remember to check whether the read
+/// succeeded because otherwise your buffer will be empty or only partially full.)
+///
+/// # Performance
+///
+/// The downside of this function's increased ease of use and type safety is
+/// that it gives you less control over performance. For example, you can't
+/// pre-allocate memory like you can using [`String::with_capacity`] and
+/// [`Read::read_to_string`]. Also, you can't re-use the buffer if an error
+/// occurs while reading.
+///
+/// In many cases, this function's performance will be adequate and the ease of use
+/// and type safety tradeoffs will be worth it. However, there are cases where you
+/// need more control over performance, and in those cases you should definitely use
+/// [`Read::read_to_string`] directly.
+///
+/// # Errors
+///
+/// This function forces you to handle errors because the output (the `String`)
+/// is wrapped in a [`Result`]. See [`Read::read_to_string`] for the errors
+/// that can occur. If any error occurs, you will get an [`Err`], so you
+/// don't have to worry about your buffer being empty or partially full.
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(io_read_to_string)]
+///
+/// # use std::io;
+/// fn main() -> io::Result<()> {
+///     let stdin = io::read_to_string(&mut io::stdin())?;
+///     println!("Stdin was:");
+///     println!("{}", stdin);
+///     Ok(())
+/// }
+/// ```
+#[unstable(feature = "io_read_to_string", issue = "80218")]
+pub fn read_to_string<R: Read>(reader: &mut R) -> Result<String> {
+    let mut buf = String::new();
+    reader.read_to_string(&mut buf)?;
+    Ok(buf)
+}
+
 /// A buffer type used with `Read::read_vectored`.
 ///
 /// It is semantically a wrapper around an `&mut [u8]`, but is guaranteed to be
@@ -1984,7 +2033,6 @@
     /// also yielded an error.
     ///
     /// [`io::Result`]: self::Result
-    /// [`Vec<u8>`]: Vec
     /// [`read_until`]: BufRead::read_until
     ///
     /// # Examples
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index 417a54e..6b06539 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -401,7 +401,7 @@
 ///
 /// ```rust
 /// #[no_mangle]
-/// pub extern fn callable_from_c(x: i32) -> bool {
+/// pub extern "C" fn callable_from_c(x: i32) -> bool {
 ///     x % 3 == 0
 /// }
 /// ```
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 2c6f03f..15ef5d1 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -307,7 +307,6 @@
 #![feature(slice_internals)]
 #![feature(slice_ptr_get)]
 #![feature(slice_ptr_len)]
-#![feature(slice_strip)]
 #![feature(staged_api)]
 #![feature(std_internals)]
 #![feature(stdsimd)]
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 8a75c1d..243761e 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1775,7 +1775,6 @@
     /// Any non-Unicode sequences are replaced with
     /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
     ///
-    /// [`Cow<str>`]: Cow
     /// [U+FFFD]: super::char::REPLACEMENT_CHARACTER
     ///
     /// # Examples
diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs
index 0fbd6b6..26302d0 100644
--- a/library/std/src/prelude/v1.rs
+++ b/library/std/src/prelude/v1.rs
@@ -41,17 +41,17 @@
 pub use core::prelude::v1::{
     asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
     format_args_nl, global_asm, include, include_bytes, include_str, line, llvm_asm, log_syntax,
-    module_path, option_env, stringify, trace_macros,
+    module_path, option_env, stringify, trace_macros, Clone, Copy, Debug, Default, Eq, Hash, Ord,
+    PartialEq, PartialOrd,
 };
 
-// FIXME: Attribute and derive macros are not documented because for them rustdoc generates
+// FIXME: Attribute and internal derive macros are not documented because for them rustdoc generates
 // dead links which fail link checker testing.
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow(deprecated)]
 #[doc(hidden)]
 pub use core::prelude::v1::{
-    bench, global_allocator, test, test_case, Clone, Copy, Debug, Default, Eq, Hash, Ord,
-    PartialEq, PartialOrd, RustcDecodable, RustcEncodable,
+    bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable,
 };
 
 #[unstable(
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index ec12e9f..876b2b8 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -11,8 +11,9 @@
 /// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc.,
 /// which allow us to perform boolean operations using `&`, `|` and `!`.
 ///
-/// `if` always demands a `bool` value. [`assert!`], which is an important macro in testing,
-/// checks whether an expression returns `true` and panics if it isn't.
+/// `if` requires a `bool` value as its conditional. [`assert!`], which is an
+/// important macro in testing, checks whether an expression is `true` and panics
+/// if it isn't.
 ///
 /// ```
 /// let bool_val = true & false | false;
@@ -25,7 +26,7 @@
 ///
 /// # Examples
 ///
-/// A trivial example of the usage of `bool`,
+/// A trivial example of the usage of `bool`:
 ///
 /// ```
 /// let praise_the_borrow_checker = true;
@@ -122,9 +123,9 @@
 /// `!`, if we have to call [`String::from_str`] for some reason the result will be a
 /// [`Result<String, !>`] which we can unpack like this:
 ///
-/// ```ignore (string-from-str-error-type-is-not-never-yet)
-/// #[feature(exhaustive_patterns)]
-/// // NOTE: this does not work today!
+/// ```
+/// #![feature(exhaustive_patterns)]
+/// use std::str::FromStr;
 /// let Ok(s) = String::from_str("hello");
 /// ```
 ///
@@ -184,9 +185,6 @@
 /// because `!` coerces to `Result<!, ConnectionError>` automatically.
 ///
 /// [`String::from_str`]: str::FromStr::from_str
-/// [`Result<String, !>`]: Result
-/// [`Result<T, !>`]: Result
-/// [`Result<!, E>`]: Result
 /// [`String`]: string::String
 /// [`FromStr`]: str::FromStr
 ///
diff --git a/library/std/src/sys/hermit/mutex.rs b/library/std/src/sys/hermit/mutex.rs
index f988a01..885389c 100644
--- a/library/std/src/sys/hermit/mutex.rs
+++ b/library/std/src/sys/hermit/mutex.rs
@@ -1,9 +1,10 @@
 use crate::cell::UnsafeCell;
 use crate::collections::VecDeque;
 use crate::ffi::c_void;
+use crate::hint;
 use crate::ops::{Deref, DerefMut, Drop};
 use crate::ptr;
-use crate::sync::atomic::{spin_loop_hint, AtomicUsize, Ordering};
+use crate::sync::atomic::{AtomicUsize, Ordering};
 use crate::sys::hermit::abi;
 
 /// This type provides a lock based on busy waiting to realize mutual exclusion
@@ -46,7 +47,7 @@
     fn obtain_lock(&self) {
         let ticket = self.queue.fetch_add(1, Ordering::SeqCst) + 1;
         while self.dequeue.load(Ordering::SeqCst) != ticket {
-            spin_loop_hint();
+            hint::spin_loop();
         }
     }
 
diff --git a/library/std/src/sys/sgx/waitqueue/spin_mutex.rs b/library/std/src/sys/sgx/waitqueue/spin_mutex.rs
index 9140041..7f1a671 100644
--- a/library/std/src/sys/sgx/waitqueue/spin_mutex.rs
+++ b/library/std/src/sys/sgx/waitqueue/spin_mutex.rs
@@ -2,8 +2,9 @@
 mod tests;
 
 use crate::cell::UnsafeCell;
+use crate::hint;
 use crate::ops::{Deref, DerefMut};
-use crate::sync::atomic::{spin_loop_hint, AtomicBool, Ordering};
+use crate::sync::atomic::{AtomicBool, Ordering};
 
 #[derive(Default)]
 pub struct SpinMutex<T> {
@@ -32,7 +33,7 @@
             match self.try_lock() {
                 None => {
                     while self.lock.load(Ordering::Relaxed) {
-                        spin_loop_hint()
+                        hint::spin_loop()
                     }
                 }
                 Some(guard) => return guard,
diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs
index 3615a8a..f4c67b2 100644
--- a/library/std/src/sys/unix/ext/process.rs
+++ b/library/std/src/sys/unix/ext/process.rs
@@ -9,6 +9,14 @@
 use crate::sys;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 
+mod private {
+    /// This trait being unreachable from outside the crate
+    /// prevents other implementations of the `ExitStatusExt` trait,
+    /// which allows potentially adding more trait methods in the future.
+    #[stable(feature = "none", since = "1.51.0")]
+    pub trait Sealed {}
+}
+
 /// Unix-specific extensions to the [`process::Command`] builder.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait CommandExt {
@@ -163,18 +171,48 @@
 }
 
 /// Unix-specific extensions to [`process::ExitStatus`].
+///
+/// This trait is sealed: it cannot be implemented outside the standard library.
+/// This is so that future additional methods are not breaking changes.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub trait ExitStatusExt {
+pub trait ExitStatusExt: private::Sealed {
     /// Creates a new `ExitStatus` from the raw underlying `i32` return value of
     /// a process.
     #[stable(feature = "exit_status_from", since = "1.12.0")]
     fn from_raw(raw: i32) -> Self;
 
     /// If the process was terminated by a signal, returns that signal.
+    ///
+    /// In other words, if `WIFSIGNALED`, this returns `WTERMSIG`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn signal(&self) -> Option<i32>;
+
+    /// If the process was terminated by a signal, says whether it dumped core.
+    #[unstable(feature = "unix_process_wait_more", issue = "80695")]
+    fn core_dumped(&self) -> bool;
+
+    /// If the process was stopped by a signal, returns that signal.
+    ///
+    /// In other words, if `WIFSTOPPED`, this returns `WSTOPSIG`.  This is only possible if the status came from
+    /// a `wait` system call which was passed `WUNTRACED`, was then converted into an `ExitStatus`.
+    #[unstable(feature = "unix_process_wait_more", issue = "80695")]
+    fn stopped_signal(&self) -> Option<i32>;
+
+    /// Whether the process was continued from a stopped status.
+    ///
+    /// Ie, `WIFCONTINUED`.  This is only possible if the status came from a `wait` system call
+    /// which was passed `WCONTINUED`, was then converted into an `ExitStatus`.
+    #[unstable(feature = "unix_process_wait_more", issue = "80695")]
+    fn continued(&self) -> bool;
+
+    /// Returns the underlying raw `wait` status.
+    #[unstable(feature = "unix_process_wait_more", issue = "80695")]
+    fn into_raw(self) -> i32;
 }
 
+#[stable(feature = "none", since = "1.51.0")]
+impl private::Sealed for process::ExitStatus {}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ExitStatusExt for process::ExitStatus {
     fn from_raw(raw: i32) -> Self {
@@ -184,6 +222,22 @@
     fn signal(&self) -> Option<i32> {
         self.as_inner().signal()
     }
+
+    fn core_dumped(&self) -> bool {
+        self.as_inner().core_dumped()
+    }
+
+    fn stopped_signal(&self) -> Option<i32> {
+        self.as_inner().stopped_signal()
+    }
+
+    fn continued(&self) -> bool {
+        self.as_inner().continued()
+    }
+
+    fn into_raw(self) -> i32 {
+        self.as_inner().into_raw().into()
+    }
 }
 
 #[stable(feature = "process_extensions", since = "1.2.0")]
diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs
index b64636c..0d4703d 100644
--- a/library/std/src/sys/unix/process/process_fuchsia.rs
+++ b/library/std/src/sys/unix/process/process_fuchsia.rs
@@ -245,6 +245,50 @@
     pub fn signal(&self) -> Option<i32> {
         None
     }
+
+    // FIXME: The actually-Unix implementation in process_unix.rs uses WSTOPSIG, WCOREDUMP et al.
+    // I infer from the implementation of `success`, `code` and `signal` above that these are not
+    // available on Fuchsia.
+    //
+    // It does not appear that Fuchsia is Unix-like enough to implement ExitStatus (or indeed many
+    // other things from std::os::unix) properly.  This veneer is always going to be a bodge.  So
+    // while I don't know if these implementations are actually correct, I think they will do for
+    // now at least.
+    pub fn core_dumped(&self) -> bool {
+        false
+    }
+    pub fn stopped_signal(&self) -> Option<i32> {
+        None
+    }
+    pub fn continued(&self) -> bool {
+        false
+    }
+
+    pub fn into_raw(&self) -> c_int {
+        // We don't know what someone who calls into_raw() will do with this value, but it should
+        // have the conventional Unix representation.  Despite the fact that this is not
+        // standardised in SuS or POSIX, all Unix systems encode the signal and exit status the
+        // same way.  (Ie the WIFEXITED, WEXITSTATUS etc. macros have identical behaviour on every
+        // Unix.)
+        //
+        // The caller of `std::os::unix::into_raw` is probably wanting a Unix exit status, and may
+        // do their own shifting and masking, or even pass the status to another computer running a
+        // different Unix variant.
+        //
+        // The other view would be to say that the caller on Fuchsia ought to know that `into_raw`
+        // will give a raw Fuchsia status (whatever that is - I don't know, personally).  That is
+        // not possible here becaause we must return a c_int because that's what Unix (including
+        // SuS and POSIX) say a wait status is, but Fuchsia apparently uses a u64, so it won't
+        // necessarily fit.
+        //
+        // It seems to me that that the right answer would be to provide std::os::fuchsia with its
+        // own ExitStatusExt, rather that trying to provide a not very convincing imitation of
+        // Unix.  Ie, std::os::unix::process:ExitStatusExt ought not to exist on Fuchsia.  But
+        // fixing this up that is beyond the scope of my efforts now.
+        let exit_status_as_if_unix: u8 = self.0.try_into().expect("Fuchsia process return code bigger than 8 bits, but std::os::unix::ExitStatusExt::into_raw() was called to try to convert the value into a traditional Unix-style wait status, which cannot represent values greater than 255.");
+        let wait_status_as_if_unix = (exit_status_as_if_unix as c_int) << 8;
+        wait_status_as_if_unix
+    }
 }
 
 /// Converts a raw `c_int` to a type-safe `ExitStatus` by wrapping it without copying.
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index a590c74..ddcb404 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -314,10 +314,20 @@
             ) -> libc::c_int
         }
         let addchdir = match self.get_cwd() {
-            Some(cwd) => match posix_spawn_file_actions_addchdir_np.get() {
-                Some(f) => Some((f, cwd)),
-                None => return Ok(None),
-            },
+            Some(cwd) => {
+                if cfg!(target_os = "macos") {
+                    // There is a bug in macOS where a relative executable
+                    // path like "../myprogram" will cause `posix_spawn` to
+                    // successfully launch the program, but erroneously return
+                    // ENOENT when used with posix_spawn_file_actions_addchdir_np
+                    // which was introduced in macOS 10.15.
+                    return Ok(None);
+                }
+                match posix_spawn_file_actions_addchdir_np.get() {
+                    Some(f) => Some((f, cwd)),
+                    None => return Ok(None),
+                }
+            }
             None => None,
         };
 
@@ -479,7 +489,23 @@
     }
 
     pub fn signal(&self) -> Option<i32> {
-        if !self.exited() { Some(libc::WTERMSIG(self.0)) } else { None }
+        if libc::WIFSIGNALED(self.0) { Some(libc::WTERMSIG(self.0)) } else { None }
+    }
+
+    pub fn core_dumped(&self) -> bool {
+        libc::WIFSIGNALED(self.0) && libc::WCOREDUMP(self.0)
+    }
+
+    pub fn stopped_signal(&self) -> Option<i32> {
+        if libc::WIFSTOPPED(self.0) { Some(libc::WSTOPSIG(self.0)) } else { None }
+    }
+
+    pub fn continued(&self) -> bool {
+        libc::WIFCONTINUED(self.0)
+    }
+
+    pub fn into_raw(&self) -> c_int {
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs
index e93a497..432fe4c 100644
--- a/library/std/src/sys/unix/weak.rs
+++ b/library/std/src/sys/unix/weak.rs
@@ -28,7 +28,7 @@
 
 macro_rules! weak {
     (fn $name:ident($($t:ty),*) -> $ret:ty) => (
-        static $name: crate::sys::weak::Weak<unsafe extern fn($($t),*) -> $ret> =
+        static $name: crate::sys::weak::Weak<unsafe extern "C" fn($($t),*) -> $ret> =
             crate::sys::weak::Weak::new(concat!(stringify!($name), '\0'));
     )
 }
diff --git a/library/std/src/sys/windows/ext/process.rs b/library/std/src/sys/windows/ext/process.rs
index 61e4c6a..7a92381 100644
--- a/library/std/src/sys/windows/ext/process.rs
+++ b/library/std/src/sys/windows/ext/process.rs
@@ -7,6 +7,14 @@
 use crate::sys;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 
+mod private {
+    /// This trait being unreachable from outside the crate
+    /// prevents other implementations of the `ExitStatusExt` trait,
+    /// which allows potentially adding more trait methods in the future.
+    #[stable(feature = "none", since = "1.51.0")]
+    pub trait Sealed {}
+}
+
 #[stable(feature = "process_extensions", since = "1.2.0")]
 impl FromRawHandle for process::Stdio {
     unsafe fn from_raw_handle(handle: RawHandle) -> process::Stdio {
@@ -73,8 +81,11 @@
 }
 
 /// Windows-specific extensions to [`process::ExitStatus`].
+///
+/// This trait is sealed: it cannot be implemented outside the standard library.
+/// This is so that future additional methods are not breaking changes.
 #[stable(feature = "exit_status_from", since = "1.12.0")]
-pub trait ExitStatusExt {
+pub trait ExitStatusExt: private::Sealed {
     /// Creates a new `ExitStatus` from the raw underlying `u32` return value of
     /// a process.
     #[stable(feature = "exit_status_from", since = "1.12.0")]
@@ -88,6 +99,9 @@
     }
 }
 
+#[stable(feature = "none", since = "1.51.0")]
+impl private::Sealed for process::ExitStatus {}
+
 /// Windows-specific extensions to the [`process::Command`] builder.
 #[stable(feature = "windows_process_extensions", since = "1.16.0")]
 pub trait CommandExt {
diff --git a/library/std/src/sys_common/fs.rs b/library/std/src/sys_common/fs.rs
index e30e801..6bdb26c 100644
--- a/library/std/src/sys_common/fs.rs
+++ b/library/std/src/sys_common/fs.rs
@@ -5,19 +5,21 @@
 use crate::path::Path;
 
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
-    if !from.is_file() {
+    let mut reader = fs::File::open(from)?;
+    let metadata = reader.metadata()?;
+
+    if !metadata.is_file() {
         return Err(Error::new(
             ErrorKind::InvalidInput,
             "the source path is not an existing regular file",
         ));
     }
 
-    let mut reader = fs::File::open(from)?;
     let mut writer = fs::File::create(to)?;
-    let perm = reader.metadata()?.permissions();
+    let perm = metadata.permissions();
 
     let ret = io::copy(&mut reader, &mut writer)?;
-    fs::set_permissions(to, perm)?;
+    writer.set_permissions(perm)?;
     Ok(ret)
 }
 
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 5d65f96..0d004a5 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -1186,32 +1186,37 @@
 /// the [`Error`](crate::error::Error) trait.
 ///
 /// Thus, a sensible way to handle a thread panic is to either:
-/// 1. `unwrap` the `Result<T>`, propagating the panic
+///
+/// 1. propagate the panic with [`std::panic::resume_unwind`]
 /// 2. or in case the thread is intended to be a subsystem boundary
 /// that is supposed to isolate system-level failures,
-/// match on the `Err` variant and handle the panic in an appropriate way.
+/// match on the `Err` variant and handle the panic in an appropriate way
 ///
 /// A thread that completes without panicking is considered to exit successfully.
 ///
 /// # Examples
 ///
+/// Matching on the result of a joined thread:
+///
 /// ```no_run
-/// use std::thread;
-/// use std::fs;
+/// use std::{fs, thread, panic};
 ///
 /// fn copy_in_thread() -> thread::Result<()> {
-///     thread::spawn(move || { fs::copy("foo.txt", "bar.txt").unwrap(); }).join()
+///     thread::spawn(|| {
+///         fs::copy("foo.txt", "bar.txt").unwrap();
+///     }).join()
 /// }
 ///
 /// fn main() {
 ///     match copy_in_thread() {
-///         Ok(_) => println!("this is fine"),
-///         Err(_) => println!("thread panicked"),
+///         Ok(_) => println!("copy succeeded"),
+///         Err(e) => panic::resume_unwind(e),
 ///     }
 /// }
 /// ```
 ///
 /// [`Result`]: crate::result::Result
+/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind
 #[stable(feature = "rust1", since = "1.0.0")]
 pub type Result<T> = crate::result::Result<T, Box<dyn Any + Send + 'static>>;
 
diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml
index d5804cc..2265574 100644
--- a/library/test/Cargo.toml
+++ b/library/test/Cargo.toml
@@ -26,7 +26,7 @@
 backtrace = ["std/backtrace"]
 compiler-builtins-c = ["std/compiler-builtins-c"]
 compiler-builtins-mem = ["std/compiler-builtins-mem"]
-compiler-builtins-asm = ["std/compiler-builtins-asm"]
+compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"]
 compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"]
 llvm-libunwind = ["std/llvm-libunwind"]
 system-llvm-libunwind = ["std/system-llvm-libunwind"]
diff --git a/library/unwind/build.rs b/library/unwind/build.rs
index fae760c..694e6b9 100644
--- a/library/unwind/build.rs
+++ b/library/unwind/build.rs
@@ -4,6 +4,10 @@
     println!("cargo:rerun-if-changed=build.rs");
     let target = env::var("TARGET").expect("TARGET was not set");
 
+    if cfg!(feature = "system-llvm-libunwind") {
+        return;
+    }
+
     if cfg!(feature = "llvm-libunwind")
         && ((target.contains("linux") && !target.contains("musl")) || target.contains("fuchsia"))
     {
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index b8bae69..5350c9e 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -393,7 +393,7 @@
 
         if self.rustc().startswith(self.bin_root()) and \
                 (not os.path.exists(self.rustc()) or
-                 self.program_out_of_date(self.rustc_stamp())):
+                 self.program_out_of_date(self.rustc_stamp(), self.date)):
             if os.path.exists(self.bin_root()):
                 shutil.rmtree(self.bin_root())
             tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz'
@@ -413,7 +413,7 @@
             lib_dir = "{}/lib".format(self.bin_root())
             for lib in os.listdir(lib_dir):
                 if lib.endswith(".so"):
-                    self.fix_bin_or_dylib("{}/{}".format(lib_dir, lib))
+                    self.fix_bin_or_dylib(os.path.join(lib_dir, lib), rpath_libz=True)
             with output(self.rustc_stamp()) as rust_stamp:
                 rust_stamp.write(self.date)
 
@@ -429,7 +429,7 @@
                 self.fix_bin_or_dylib("{}/bin/rustfmt".format(self.bin_root()))
                 self.fix_bin_or_dylib("{}/bin/cargo-fmt".format(self.bin_root()))
                 with output(self.rustfmt_stamp()) as rustfmt_stamp:
-                    rustfmt_stamp.write(self.date + self.rustfmt_channel)
+                    rustfmt_stamp.write(self.rustfmt_channel)
 
         if self.downloading_llvm():
             # We want the most recent LLVM submodule update to avoid downloading
@@ -451,17 +451,35 @@
                 "{}/src/bootstrap/download-ci-llvm-stamp".format(top_level),
             ]).decode(sys.getdefaultencoding()).strip()
             llvm_assertions = self.get_toml('assertions', 'llvm') == 'true'
+            llvm_root = self.llvm_root()
+            llvm_lib = os.path.join(llvm_root, "lib")
             if self.program_out_of_date(self.llvm_stamp(), llvm_sha + str(llvm_assertions)):
                 self._download_ci_llvm(llvm_sha, llvm_assertions)
                 for binary in ["llvm-config", "FileCheck"]:
-                    self.fix_bin_or_dylib("{}/bin/{}".format(self.llvm_root(), binary))
+                    self.fix_bin_or_dylib(os.path.join(llvm_root, "bin", binary), rpath_libz=True)
+                for lib in os.listdir(llvm_lib):
+                    if lib.endswith(".so"):
+                        self.fix_bin_or_dylib(os.path.join(llvm_lib, lib), rpath_libz=True)
                 with output(self.llvm_stamp()) as llvm_stamp:
-                    llvm_stamp.write(self.date + llvm_sha + str(llvm_assertions))
+                    llvm_stamp.write(llvm_sha + str(llvm_assertions))
 
     def downloading_llvm(self):
         opt = self.get_toml('download-ci-llvm', 'llvm')
+        # This is currently all tier 1 targets (since others may not have CI
+        # artifacts)
+        # https://doc.rust-lang.org/rustc/platform-support.html#tier-1
+        supported_platforms = [
+            "aarch64-unknown-linux-gnu",
+            "i686-pc-windows-gnu",
+            "i686-pc-windows-msvc",
+            "i686-unknown-linux-gnu",
+            "x86_64-unknown-linux-gnu",
+            "x86_64-apple-darwin",
+            "x86_64-pc-windows-gnu",
+            "x86_64-pc-windows-msvc",
+        ]
         return opt == "true" \
-            or (opt == "if-available" and self.build == "x86_64-unknown-linux-gnu")
+            or (opt == "if-available" and self.build in supported_platforms)
 
     def _download_stage0_helper(self, filename, pattern, tarball_suffix, date=None):
         if date is None:
@@ -487,7 +505,12 @@
         url = "https://ci-artifacts.rust-lang.org/rustc-builds/{}".format(llvm_sha)
         if llvm_assertions:
             url = url.replace('rustc-builds', 'rustc-builds-alt')
-        tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz'
+        # ci-artifacts are only stored as .xz, not .gz
+        if not support_xz():
+            print("error: XZ support is required to download LLVM")
+            print("help: consider disabling `download-ci-llvm` or using python3")
+            exit(1)
+        tarball_suffix = '.tar.xz'
         filename = "rust-dev-nightly-" + self.build + tarball_suffix
         tarball = os.path.join(rustc_cache, filename)
         if not os.path.exists(tarball):
@@ -496,7 +519,7 @@
                 match="rust-dev",
                 verbose=self.verbose)
 
-    def fix_bin_or_dylib(self, fname):
+    def fix_bin_or_dylib(self, fname, rpath_libz=False):
         """Modifies the interpreter section of 'fname' to fix the dynamic linker,
         or the RPATH section, to fix the dynamic library search path
 
@@ -566,20 +589,22 @@
             self.nix_deps_dir = nix_deps_dir
 
         patchelf = "{}/patchelf/bin/patchelf".format(nix_deps_dir)
+        patchelf_args = []
 
-        if fname.endswith(".so"):
-            # Dynamic library, patch RPATH to point to system dependencies.
+        if rpath_libz:
+            # Patch RPATH to add `zlib` dependency that stems from LLVM
             dylib_deps = ["zlib"]
             rpath_entries = [
                 # Relative default, all binary and dynamic libraries we ship
                 # appear to have this (even when `../lib` is redundant).
                 "$ORIGIN/../lib",
             ] + ["{}/{}/lib".format(nix_deps_dir, dep) for dep in dylib_deps]
-            patchelf_args = ["--set-rpath", ":".join(rpath_entries)]
-        else:
+            patchelf_args += ["--set-rpath", ":".join(rpath_entries)]
+        if not fname.endswith(".so"):
+            # Finally, set the corret .interp for binaries
             bintools_dir = "{}/stdenv.cc.bintools".format(nix_deps_dir)
             with open("{}/nix-support/dynamic-linker".format(bintools_dir)) as dynamic_linker:
-                patchelf_args = ["--set-interpreter", dynamic_linker.read().rstrip()]
+                patchelf_args += ["--set-interpreter", dynamic_linker.read().rstrip()]
 
         try:
             subprocess.check_output([patchelf] + patchelf_args + [fname])
@@ -618,12 +643,12 @@
         return os.path.join(self.llvm_root(), '.llvm-stamp')
 
 
-    def program_out_of_date(self, stamp_path, extra=""):
+    def program_out_of_date(self, stamp_path, key):
         """Check if the given program stamp is out of date"""
         if not os.path.exists(stamp_path) or self.clean:
             return True
         with open(stamp_path, 'r') as stamp:
-            return (self.date + extra) != stamp.read()
+            return key != stamp.read()
 
     def bin_root(self):
         """Return the binary root directory
diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py
index 0e941e1..6150711 100644
--- a/src/bootstrap/bootstrap_test.py
+++ b/src/bootstrap/bootstrap_test.py
@@ -70,6 +70,7 @@
         self.build.build_dir = self.container
         self.rustc_stamp_path = os.path.join(self.container, "stage0",
                                              ".rustc-stamp")
+        self.key = self.build.date + str(None)
 
     def tearDown(self):
         rmtree(self.container)
@@ -78,19 +79,19 @@
         """Return True when the stamp file does not exists"""
         if os.path.exists(self.rustc_stamp_path):
             os.unlink(self.rustc_stamp_path)
-        self.assertTrue(self.build.program_out_of_date(self.rustc_stamp_path))
+        self.assertTrue(self.build.program_out_of_date(self.rustc_stamp_path, self.key))
 
     def test_dates_are_different(self):
         """Return True when the dates are different"""
         with open(self.rustc_stamp_path, "w") as rustc_stamp:
-            rustc_stamp.write("2017-06-14")
-        self.assertTrue(self.build.program_out_of_date(self.rustc_stamp_path))
+            rustc_stamp.write("2017-06-14None")
+        self.assertTrue(self.build.program_out_of_date(self.rustc_stamp_path, self.key))
 
     def test_same_dates(self):
         """Return False both dates match"""
         with open(self.rustc_stamp_path, "w") as rustc_stamp:
-            rustc_stamp.write("2017-06-15")
-        self.assertFalse(self.build.program_out_of_date(self.rustc_stamp_path))
+            rustc_stamp.write("2017-06-15None")
+        self.assertFalse(self.build.program_out_of_date(self.rustc_stamp_path, self.key))
 
 
 if __name__ == '__main__':
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index c2abb01..62065e2 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -814,12 +814,22 @@
             cargo.env("REAL_LIBRARY_PATH", e);
         }
 
+        // Found with `rg "init_env_logger\("`. If anyone uses `init_env_logger`
+        // from out of tree it shouldn't matter, since x.py is only used for
+        // building in-tree.
+        let color_logs = ["RUSTDOC_LOG_COLOR", "RUSTC_LOG_COLOR", "RUST_LOG_COLOR"];
         match self.build.config.color {
             Color::Always => {
                 cargo.arg("--color=always");
+                for log in &color_logs {
+                    cargo.env(log, "always");
+                }
             }
             Color::Never => {
                 cargo.arg("--color=never");
+                for log in &color_logs {
+                    cargo.env(log, "never");
+                }
             }
             Color::Auto => {} // nothing to do
         }
@@ -1534,7 +1544,7 @@
     fn arg(&mut self, arg: &str) -> &mut Self {
         assert_eq!(arg.split(' ').count(), 1);
         if !self.0.is_empty() {
-            self.0.push_str(" ");
+            self.0.push(' ');
         }
         self.0.push_str(arg);
         self
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index 2b82f6c..6e65be9 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -74,9 +74,9 @@
         if let Some(ref inner) = self.inner {
             version.push_str(" (");
             version.push_str(&inner.short_sha);
-            version.push_str(" ");
+            version.push(' ');
             version.push_str(&inner.commit_date);
-            version.push_str(")");
+            version.push(')');
         }
         version
     }
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index f65b2b2..c19bb53 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -21,6 +21,16 @@
     }
 
     if let Subcommand::Clippy { fix, .. } = builder.config.cmd {
+        // disable the most spammy clippy lints
+        let ignored_lints = vec![
+            "many_single_char_names", // there are a lot in stdarch
+            "collapsible_if",
+            "type_complexity",
+            "missing_safety_doc", // almost 3K warnings
+            "too_many_arguments",
+            "needless_lifetimes", // people want to keep the lifetimes
+            "wrong_self_convention",
+        ];
         let mut args = vec![];
         if fix {
             #[rustfmt::skip]
@@ -33,6 +43,7 @@
             ]));
         }
         args.extend(strings(&["--", "--cap-lints", "warn"]));
+        args.extend(ignored_lints.iter().map(|lint| format!("-Aclippy::{}", lint)));
         args
     } else {
         vec![]
@@ -62,7 +73,7 @@
 
     fn run(self, builder: &Builder<'_>) {
         let target = self.target;
-        let compiler = builder.compiler(0, builder.config.build);
+        let compiler = builder.compiler(builder.top_stage, builder.config.build);
 
         let mut cargo = builder.cargo(
             compiler,
@@ -73,7 +84,10 @@
         );
         std_cargo(builder, target, compiler.stage, &mut cargo);
 
-        builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
+        builder.info(&format!(
+            "Checking stage{} std artifacts ({} -> {})",
+            builder.top_stage, &compiler.host, target
+        ));
         run_cargo(
             builder,
             cargo,
@@ -83,9 +97,13 @@
             true,
         );
 
-        let libdir = builder.sysroot_libdir(compiler, target);
-        let hostdir = builder.sysroot_libdir(compiler, compiler.host);
-        add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
+        // We skip populating the sysroot in non-zero stage because that'll lead
+        // to rlib/rmeta conflicts if std gets built during this session.
+        if compiler.stage == 0 {
+            let libdir = builder.sysroot_libdir(compiler, target);
+            let hostdir = builder.sysroot_libdir(compiler, compiler.host);
+            add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
+        }
 
         // Then run cargo again, once we've put the rmeta files for the library
         // crates into the sysroot. This is needed because e.g., core's tests
@@ -113,8 +131,8 @@
             }
 
             builder.info(&format!(
-                "Checking std test/bench/example targets ({} -> {})",
-                &compiler.host, target
+                "Checking stage{} std test/bench/example targets ({} -> {})",
+                builder.top_stage, &compiler.host, target
             ));
             run_cargo(
                 builder,
@@ -152,10 +170,20 @@
     /// the `compiler` targeting the `target` architecture. The artifacts
     /// created will also be linked into the sysroot directory.
     fn run(self, builder: &Builder<'_>) {
-        let compiler = builder.compiler(0, builder.config.build);
+        let compiler = builder.compiler(builder.top_stage, builder.config.build);
         let target = self.target;
 
-        builder.ensure(Std { target });
+        if compiler.stage != 0 {
+            // If we're not in stage 0, then we won't have a std from the beta
+            // compiler around. That means we need to make sure there's one in
+            // the sysroot for the compiler to find. Otherwise, we're going to
+            // fail when building crates that need to generate code (e.g., build
+            // scripts and their dependencies).
+            builder.ensure(crate::compile::Std { target: compiler.host, compiler });
+            builder.ensure(crate::compile::Std { target, compiler });
+        } else {
+            builder.ensure(Std { target });
+        }
 
         let mut cargo = builder.cargo(
             compiler,
@@ -176,7 +204,10 @@
             cargo.arg("-p").arg(krate.name);
         }
 
-        builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
+        builder.info(&format!(
+            "Checking stage{} compiler artifacts ({} -> {})",
+            builder.top_stage, &compiler.host, target
+        ));
         run_cargo(
             builder,
             cargo,
@@ -214,7 +245,7 @@
     }
 
     fn run(self, builder: &Builder<'_>) {
-        let compiler = builder.compiler(0, builder.config.build);
+        let compiler = builder.compiler(builder.top_stage, builder.config.build);
         let target = self.target;
         let backend = self.backend;
 
@@ -233,8 +264,8 @@
         rustc_cargo_env(builder, &mut cargo, target);
 
         builder.info(&format!(
-            "Checking {} artifacts ({} -> {})",
-            backend, &compiler.host.triple, target.triple
+            "Checking stage{} {} artifacts ({} -> {})",
+            builder.top_stage, backend, &compiler.host.triple, target.triple
         ));
 
         run_cargo(
@@ -269,7 +300,7 @@
             }
 
             fn run(self, builder: &Builder<'_>) {
-                let compiler = builder.compiler(0, builder.config.build);
+                let compiler = builder.compiler(builder.top_stage, builder.config.build);
                 let target = self.target;
 
                 builder.ensure(Rustc { target });
@@ -290,7 +321,8 @@
                 }
 
                 builder.info(&format!(
-                    "Checking {} artifacts ({} -> {})",
+                    "Checking stage{} {} artifacts ({} -> {})",
+                    builder.top_stage,
                     stringify!($name).to_lowercase(),
                     &compiler.host.triple,
                     target.triple
diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs
index f83dfe8..9b9df36 100644
--- a/src/bootstrap/clean.rs
+++ b/src/bootstrap/clean.rs
@@ -21,6 +21,7 @@
     } else {
         rm_rf(&build.out.join("tmp"));
         rm_rf(&build.out.join("dist"));
+        rm_rf(&build.out.join("bootstrap"));
 
         for host in &build.hosts {
             let entries = match build.out.join(host.triple).read_dir() {
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 2707a64..39700c0 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -188,14 +188,16 @@
         }
     } else if target.ends_with("-wasi") {
         let srcdir = builder.wasi_root(target).unwrap().join("lib/wasm32-wasi");
-        copy_and_stamp(
-            builder,
-            &libdir_self_contained,
-            &srcdir,
-            "crt1.o",
-            &mut target_deps,
-            DependencyType::TargetSelfContained,
-        );
+        for &obj in &["crt1.o", "crt1-reactor.o"] {
+            copy_and_stamp(
+                builder,
+                &libdir_self_contained,
+                &srcdir,
+                obj,
+                &mut target_deps,
+                DependencyType::TargetSelfContained,
+            );
+        }
     } else if target.contains("windows-gnu") {
         for obj in ["crt2.o", "dllcrt2.o"].iter() {
             let src = compiler_file(builder, builder.cc(target), target, obj);
@@ -356,15 +358,12 @@
         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());
+        if target == "x86_64-apple-darwin" || target == "aarch64-apple-darwin" {
+            // Update the library’s install name to reflect that it has has been renamed.
+            apple_darwin_update_library_name(&dst, &format!("@rpath/{}", &runtime.name));
+            // Upon renaming the install name, the code signature of the file will invalidate,
+            // so we will sign it again.
+            apple_darwin_sign_file(&dst);
         }
 
         target_deps.push(dst);
@@ -373,6 +372,27 @@
     target_deps
 }
 
+fn apple_darwin_update_library_name(library_path: &Path, new_name: &str) {
+    let status = Command::new("install_name_tool")
+        .arg("-id")
+        .arg(new_name)
+        .arg(library_path)
+        .status()
+        .expect("failed to execute `install_name_tool`");
+    assert!(status.success());
+}
+
+fn apple_darwin_sign_file(file_path: &Path) {
+    let status = Command::new("codesign")
+        .arg("-f") // Force to rewrite the existing signature
+        .arg("-s")
+        .arg("-")
+        .arg(file_path)
+        .status()
+        .expect("failed to execute `codesign`");
+    assert!(status.success());
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct StartupObjects {
     pub compiler: Compiler,
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index def8f21..ec1308a 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -148,6 +148,7 @@
     pub dist_sign_folder: Option<PathBuf>,
     pub dist_upload_addr: Option<String>,
     pub dist_gpg_password_file: Option<PathBuf>,
+    pub dist_compression_formats: Option<Vec<String>>,
 
     // libstd features
     pub backtrace: bool, // support for RUST_BACKTRACE
@@ -334,7 +335,7 @@
                     *x = Some(new);
                 }
             }
-        };
+        }
         do_merge(&mut self.build, build);
         do_merge(&mut self.install, install);
         do_merge(&mut self.llvm, llvm);
@@ -376,6 +377,7 @@
     configure_args: Option<Vec<String>>,
     local_rebuild: Option<bool>,
     print_step_timings: Option<bool>,
+    check_stage: Option<u32>,
     doc_stage: Option<u32>,
     build_stage: Option<u32>,
     test_stage: Option<u32>,
@@ -438,6 +440,7 @@
     upload_addr: Option<String>,
     src_tarball: Option<bool>,
     missing_tools: Option<bool>,
+    compression_formats: Option<Vec<String>>,
 }
 
 #[derive(Deserialize)]
@@ -674,6 +677,7 @@
 
         // See https://github.com/rust-lang/compiler-team/issues/326
         config.stage = match config.cmd {
+            Subcommand::Check { .. } => flags.stage.or(build.check_stage).unwrap_or(0),
             Subcommand::Doc { .. } => flags.stage.or(build.doc_stage).unwrap_or(0),
             Subcommand::Build { .. } => flags.stage.or(build.build_stage).unwrap_or(1),
             Subcommand::Test { .. } => flags.stage.or(build.test_stage).unwrap_or(1),
@@ -683,7 +687,6 @@
             // These are all bootstrap tools, which don't depend on the compiler.
             // The stage we pass shouldn't matter, but use 0 just in case.
             Subcommand::Clean { .. }
-            | Subcommand::Check { .. }
             | Subcommand::Clippy { .. }
             | Subcommand::Fix { .. }
             | Subcommand::Run { .. }
@@ -814,8 +817,10 @@
                 check_ci_llvm!(llvm.allow_old_toolchain);
                 check_ci_llvm!(llvm.polly);
 
-                // CI-built LLVM is shared
-                config.llvm_link_shared = true;
+                // CI-built LLVM can be either dynamic or static.
+                let ci_llvm = config.out.join(&*config.build.triple).join("ci-llvm");
+                let link_type = t!(std::fs::read_to_string(ci_llvm.join("link-type.txt")));
+                config.llvm_link_shared = link_type == "dynamic";
             }
 
             if config.llvm_thin_lto {
@@ -936,6 +941,7 @@
             config.dist_sign_folder = t.sign_folder.map(PathBuf::from);
             config.dist_gpg_password_file = t.gpg_password_file.map(PathBuf::from);
             config.dist_upload_addr = t.upload_addr;
+            config.dist_compression_formats = t.compression_formats;
             set(&mut config.rust_dist_src, t.src_tarball);
             set(&mut config.missing_tools, t.missing_tools);
         }
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 42f00ce..2cabaee 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -147,6 +147,8 @@
   "experimental LLVM targets to build")
 v("release-channel", "rust.channel", "the name of the release channel to build")
 v("release-description", "rust.description", "optional descriptive string for version output")
+v("dist-compression-formats", None,
+  "comma-separated list of compression formats to use")
 
 # Used on systems where "cc" is unavailable
 v("default-linker", "rust.default-linker", "the default linker")
@@ -349,6 +351,8 @@
     elif option.name == 'option-checking':
         # this was handled above
         pass
+    elif option.name == 'dist-compression-formats':
+        set('dist.compression-formats', value.split(','))
     else:
         raise RuntimeError("unhandled option {}".format(option.name))
 
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 0a79d09..af9c0fb 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -19,7 +19,7 @@
 use crate::cache::{Interned, INTERNER};
 use crate::compile;
 use crate::config::TargetSelection;
-use crate::tarball::{OverlayKind, Tarball};
+use crate::tarball::{GeneratedTarball, OverlayKind, Tarball};
 use crate::tool::{self, Tool};
 use crate::util::{exe, is_dylib, timeit};
 use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS};
@@ -51,7 +51,7 @@
 }
 
 impl Step for Docs {
-    type Output = Option<PathBuf>;
+    type Output = Option<GeneratedTarball>;
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -63,7 +63,7 @@
     }
 
     /// Builds the `rust-docs` installer component.
-    fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
+    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let host = self.host;
         if !builder.config.docs {
             return None;
@@ -86,7 +86,7 @@
 }
 
 impl Step for RustcDocs {
-    type Output = Option<PathBuf>;
+    type Output = Option<GeneratedTarball>;
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -98,7 +98,7 @@
     }
 
     /// Builds the `rustc-docs` installer component.
-    fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
+    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let host = self.host;
         if !builder.config.compiler_docs {
             return None;
@@ -267,7 +267,7 @@
 }
 
 impl Step for Mingw {
-    type Output = Option<PathBuf>;
+    type Output = Option<GeneratedTarball>;
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -282,7 +282,7 @@
     ///
     /// This contains all the bits and pieces to run the MinGW Windows targets
     /// without any extra installed software (e.g., we bundle gcc, libraries, etc).
-    fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
+    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let host = self.host;
         if !host.contains("pc-windows-gnu") {
             return None;
@@ -307,7 +307,7 @@
 }
 
 impl Step for Rustc {
-    type Output = PathBuf;
+    type Output = GeneratedTarball;
     const DEFAULT: bool = true;
     const ONLY_HOSTS: bool = true;
 
@@ -321,7 +321,7 @@
     }
 
     /// Creates the `rustc` installer component.
-    fn run(self, builder: &Builder<'_>) -> PathBuf {
+    fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
         let compiler = self.compiler;
         let host = self.compiler.host;
 
@@ -555,7 +555,7 @@
 }
 
 impl Step for Std {
-    type Output = Option<PathBuf>;
+    type Output = Option<GeneratedTarball>;
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -573,7 +573,7 @@
         });
     }
 
-    fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
+    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let compiler = self.compiler;
         let target = self.target;
 
@@ -601,7 +601,7 @@
 }
 
 impl Step for RustcDev {
-    type Output = Option<PathBuf>;
+    type Output = Option<GeneratedTarball>;
     const DEFAULT: bool = true;
     const ONLY_HOSTS: bool = true;
 
@@ -620,7 +620,7 @@
         });
     }
 
-    fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
+    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let compiler = self.compiler;
         let target = self.target;
         if skip_host_target_lib(builder, compiler) {
@@ -660,7 +660,7 @@
 }
 
 impl Step for Analysis {
-    type Output = Option<PathBuf>;
+    type Output = Option<GeneratedTarball>;
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -683,7 +683,7 @@
     }
 
     /// Creates a tarball of save-analysis metadata, if available.
-    fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
+    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let compiler = self.compiler;
         let target = self.target;
         assert!(builder.config.extended);
@@ -796,7 +796,7 @@
 
 impl Step for Src {
     /// The output path of the src installer tarball
-    type Output = PathBuf;
+    type Output = GeneratedTarball;
     const DEFAULT: bool = true;
     const ONLY_HOSTS: bool = true;
 
@@ -809,7 +809,7 @@
     }
 
     /// Creates the `rust-src` installer component
-    fn run(self, builder: &Builder<'_>) -> PathBuf {
+    fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
         let tarball = Tarball::new_targetless(builder, "rust-src");
 
         // A lot of tools expect the rust-src component to be entirely in this directory, so if you
@@ -848,7 +848,7 @@
 
 impl Step for PlainSourceTarball {
     /// Produces the location of the tarball generated
-    type Output = PathBuf;
+    type Output = GeneratedTarball;
     const DEFAULT: bool = true;
     const ONLY_HOSTS: bool = true;
 
@@ -862,7 +862,7 @@
     }
 
     /// Creates the plain source tarball
-    fn run(self, builder: &Builder<'_>) -> PathBuf {
+    fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
         let tarball = Tarball::new(builder, "rustc", "src");
         let plain_dst_src = tarball.image_dir();
 
@@ -941,7 +941,7 @@
 }
 
 impl Step for Cargo {
-    type Output = PathBuf;
+    type Output = GeneratedTarball;
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -959,7 +959,7 @@
         });
     }
 
-    fn run(self, builder: &Builder<'_>) -> PathBuf {
+    fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
         let compiler = self.compiler;
         let target = self.target;
 
@@ -995,7 +995,7 @@
 }
 
 impl Step for Rls {
-    type Output = Option<PathBuf>;
+    type Output = Option<GeneratedTarball>;
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -1013,7 +1013,7 @@
         });
     }
 
-    fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
+    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let compiler = self.compiler;
         let target = self.target;
         assert!(builder.config.extended);
@@ -1041,7 +1041,7 @@
 }
 
 impl Step for RustAnalyzer {
-    type Output = Option<PathBuf>;
+    type Output = Option<GeneratedTarball>;
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -1059,7 +1059,7 @@
         });
     }
 
-    fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
+    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let compiler = self.compiler;
         let target = self.target;
         assert!(builder.config.extended);
@@ -1090,7 +1090,7 @@
 }
 
 impl Step for Clippy {
-    type Output = PathBuf;
+    type Output = GeneratedTarball;
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -1108,7 +1108,7 @@
         });
     }
 
-    fn run(self, builder: &Builder<'_>) -> PathBuf {
+    fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
         let compiler = self.compiler;
         let target = self.target;
         assert!(builder.config.extended);
@@ -1140,7 +1140,7 @@
 }
 
 impl Step for Miri {
-    type Output = Option<PathBuf>;
+    type Output = Option<GeneratedTarball>;
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -1158,7 +1158,7 @@
         });
     }
 
-    fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
+    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let compiler = self.compiler;
         let target = self.target;
         assert!(builder.config.extended);
@@ -1193,7 +1193,7 @@
 }
 
 impl Step for Rustfmt {
-    type Output = Option<PathBuf>;
+    type Output = Option<GeneratedTarball>;
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -1211,7 +1211,7 @@
         });
     }
 
-    fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
+    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let compiler = self.compiler;
         let target = self.target;
 
@@ -1316,27 +1316,27 @@
             tarballs.push(mingw_installer.unwrap());
         }
 
-        let mut tarball = Tarball::new(builder, "rust", &target.triple);
-        let work = tarball.persist_work_dir();
-        tarball.combine(&tarballs);
+        let tarball = Tarball::new(builder, "rust", &target.triple);
+        let generated = tarball.combine(&tarballs);
 
         let tmp = tmpdir(builder).join("combined-tarball");
+        let work = generated.work_dir();
 
         let mut license = String::new();
         license += &builder.read(&builder.src.join("COPYRIGHT"));
         license += &builder.read(&builder.src.join("LICENSE-APACHE"));
         license += &builder.read(&builder.src.join("LICENSE-MIT"));
-        license.push_str("\n");
-        license.push_str("\n");
+        license.push('\n');
+        license.push('\n');
 
         let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
         let mut rtf = rtf.to_string();
-        rtf.push_str("\n");
+        rtf.push('\n');
         for line in license.lines() {
             rtf.push_str(line);
             rtf.push_str("\\line ");
         }
-        rtf.push_str("}");
+        rtf.push('}');
 
         fn filter(contents: &str, marker: &str) -> String {
             let start = format!("tool-{}-start", marker);
@@ -1800,19 +1800,11 @@
     }
 }
 
-/// Maybe add libLLVM.so to the given destination lib-dir. It will only have
-/// been built if LLVM tools are linked dynamically.
+/// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking.
 ///
-/// Note: This function does not yet support Windows, but we also don't support
-///       linking LLVM tools dynamically on Windows yet.
-fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) {
-    if !builder.config.llvm_link_shared {
-        // We do not need to copy LLVM files into the sysroot if it is not
-        // dynamically linked; it is already included into librustc_llvm
-        // statically.
-        return;
-    }
 
+/// Returns whether the files were actually copied.
+fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) -> bool {
     if let Some(config) = builder.config.target_config.get(&target) {
         if config.llvm_config.is_some() && !builder.config.llvm_from_ci {
             // If the LLVM was externally provided, then we don't currently copy
@@ -1828,7 +1820,7 @@
             //
             // If the LLVM is coming from ourselves (just from CI) though, we
             // still want to install it, as it otherwise won't be available.
-            return;
+            return false;
         }
     }
 
@@ -1837,31 +1829,48 @@
     // clear why this is the case, though. llvm-config will emit the versioned
     // paths and we don't want those in the sysroot (as we're expecting
     // unversioned paths).
-    if target.contains("apple-darwin") {
+    if target.contains("apple-darwin") && builder.config.llvm_link_shared {
         let src_libdir = builder.llvm_out(target).join("lib");
         let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
         if llvm_dylib_path.exists() {
             builder.install(&llvm_dylib_path, dst_libdir, 0o644);
         }
+        !builder.config.dry_run
     } else if let Ok(llvm_config) = crate::native::prebuilt_llvm_config(builder, target) {
-        let files = output(Command::new(llvm_config).arg("--libfiles"));
-        for file in files.lines() {
+        let mut cmd = Command::new(llvm_config);
+        cmd.arg("--libfiles");
+        builder.verbose(&format!("running {:?}", cmd));
+        let files = output(&mut cmd);
+        for file in files.trim_end().split(' ') {
             builder.install(Path::new(file), dst_libdir, 0o644);
         }
+        !builder.config.dry_run
+    } else {
+        false
     }
 }
 
 /// Maybe add libLLVM.so to the target lib-dir for linking.
 pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
     let dst_libdir = sysroot.join("lib/rustlib").join(&*target.triple).join("lib");
-    maybe_install_llvm(builder, target, &dst_libdir);
+    // We do not need to copy LLVM files into the sysroot if it is not
+    // dynamically linked; it is already included into librustc_llvm
+    // statically.
+    if builder.config.llvm_link_shared {
+        maybe_install_llvm(builder, target, &dst_libdir);
+    }
 }
 
 /// Maybe add libLLVM.so to the runtime lib-dir for rustc itself.
 pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
     let dst_libdir =
         sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target }));
-    maybe_install_llvm(builder, target, &dst_libdir);
+    // We do not need to copy LLVM files into the sysroot if it is not
+    // dynamically linked; it is already included into librustc_llvm
+    // statically.
+    if builder.config.llvm_link_shared {
+        maybe_install_llvm(builder, target, &dst_libdir);
+    }
 }
 
 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
@@ -1870,7 +1879,7 @@
 }
 
 impl Step for LlvmTools {
-    type Output = Option<PathBuf>;
+    type Output = Option<GeneratedTarball>;
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -1881,7 +1890,7 @@
         run.builder.ensure(LlvmTools { target: run.target });
     }
 
-    fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
+    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let target = self.target;
         assert!(builder.config.extended);
 
@@ -1924,7 +1933,7 @@
 }
 
 impl Step for RustDev {
-    type Output = Option<PathBuf>;
+    type Output = Option<GeneratedTarball>;
     const DEFAULT: bool = true;
     const ONLY_HOSTS: bool = true;
 
@@ -1936,7 +1945,7 @@
         run.builder.ensure(RustDev { target: run.target });
     }
 
-    fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
+    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let target = self.target;
 
         /* run only if llvm-config isn't used */
@@ -1973,7 +1982,10 @@
         // `$ORIGIN/../lib` can find it. It may also be used as a dependency
         // of `rustc-dev` to support the inherited `-lLLVM` when using the
         // compiler libraries.
-        maybe_install_llvm(builder, target, &tarball.image_dir().join("lib"));
+        let dst_libdir = tarball.image_dir().join("lib");
+        maybe_install_llvm(builder, target, &dst_libdir);
+        let link_type = if builder.config.llvm_link_shared { "dynamic" } else { "static" };
+        t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
 
         Some(tarball.generate())
     }
@@ -1989,7 +2001,7 @@
 }
 
 impl Step for BuildManifest {
-    type Output = PathBuf;
+    type Output = GeneratedTarball;
     const DEFAULT: bool = false;
     const ONLY_HOSTS: bool = true;
 
@@ -2001,7 +2013,7 @@
         run.builder.ensure(BuildManifest { target: run.target });
     }
 
-    fn run(self, builder: &Builder<'_>) -> PathBuf {
+    fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
         let build_manifest = builder.tool_exe(Tool::BuildManifest);
 
         let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
@@ -2021,7 +2033,7 @@
 }
 
 impl Step for ReproducibleArtifacts {
-    type Output = Option<PathBuf>;
+    type Output = Option<GeneratedTarball>;
     const DEFAULT: bool = true;
     const ONLY_HOSTS: bool = true;
 
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index b29ecd6..fb5b058 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
 Change this file to make users of the `download-ci-llvm` configuration download
 a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
 
-Last change is for: https://github.com/rust-lang/rust/pull/80087
+Last change is for: https://github.com/rust-lang/rust/pull/80932
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index d6a45f1..55062e1 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -614,14 +614,10 @@
         };
 
         if let Subcommand::Check { .. } = &cmd {
-            if matches.opt_str("stage").is_some() {
-                println!("--stage not supported for x.py check, always treated as stage 0");
-                process::exit(1);
-            }
             if matches.opt_str("keep-stage").is_some()
                 || matches.opt_str("keep-stage-std").is_some()
             {
-                println!("--keep-stage not supported for x.py check, only one stage available");
+                println!("--keep-stage not yet supported for x.py check");
                 process::exit(1);
             }
         }
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index 8f2b128..fd0acc3 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -5,141 +5,84 @@
 
 use std::env;
 use std::fs;
-use std::path::{Component, Path, PathBuf};
+use std::path::{Component, PathBuf};
 use std::process::Command;
 
 use build_helper::t;
 
-use crate::dist::{self, pkgname, sanitize_sh, tmpdir};
+use crate::dist::{self, sanitize_sh};
+use crate::tarball::GeneratedTarball;
 use crate::Compiler;
 
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::config::{Config, TargetSelection};
 
-pub fn install_docs(builder: &Builder<'_>, stage: u32, host: TargetSelection) {
-    install_sh(builder, "docs", "rust-docs", stage, Some(host));
-}
-
-pub fn install_std(builder: &Builder<'_>, stage: u32, target: TargetSelection) {
-    install_sh(builder, "std", "rust-std", stage, Some(target));
-}
-
-pub fn install_cargo(builder: &Builder<'_>, stage: u32, host: TargetSelection) {
-    install_sh(builder, "cargo", "cargo", stage, Some(host));
-}
-
-pub fn install_rls(builder: &Builder<'_>, stage: u32, host: TargetSelection) {
-    install_sh(builder, "rls", "rls", stage, Some(host));
-}
-
-pub fn install_rust_analyzer(builder: &Builder<'_>, stage: u32, host: TargetSelection) {
-    install_sh(builder, "rust-analyzer", "rust-analyzer", stage, Some(host));
-}
-
-pub fn install_clippy(builder: &Builder<'_>, stage: u32, host: TargetSelection) {
-    install_sh(builder, "clippy", "clippy", stage, Some(host));
-}
-pub fn install_miri(builder: &Builder<'_>, stage: u32, host: TargetSelection) {
-    install_sh(builder, "miri", "miri", stage, Some(host));
-}
-
-pub fn install_rustfmt(builder: &Builder<'_>, stage: u32, host: TargetSelection) {
-    install_sh(builder, "rustfmt", "rustfmt", stage, Some(host));
-}
-
-pub fn install_analysis(builder: &Builder<'_>, stage: u32, host: TargetSelection) {
-    install_sh(builder, "analysis", "rust-analysis", stage, Some(host));
-}
-
-pub fn install_src(builder: &Builder<'_>, stage: u32) {
-    install_sh(builder, "src", "rust-src", stage, None);
-}
-pub fn install_rustc(builder: &Builder<'_>, stage: u32, host: TargetSelection) {
-    install_sh(builder, "rustc", "rustc", stage, Some(host));
-}
-
 fn install_sh(
     builder: &Builder<'_>,
     package: &str,
-    name: &str,
     stage: u32,
     host: Option<TargetSelection>,
+    tarball: &GeneratedTarball,
 ) {
     builder.info(&format!("Install {} stage{} ({:?})", package, stage, host));
 
-    let prefix_default = PathBuf::from("/usr/local");
-    let sysconfdir_default = PathBuf::from("/etc");
-    let datadir_default = PathBuf::from("share");
-    let docdir_default = datadir_default.join("doc/rust");
-    let libdir_default = PathBuf::from("lib");
-    let mandir_default = datadir_default.join("man");
-    let prefix = builder.config.prefix.as_ref().unwrap_or(&prefix_default);
-    let sysconfdir = builder.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
-    let datadir = builder.config.datadir.as_ref().unwrap_or(&datadir_default);
-    let docdir = builder.config.docdir.as_ref().unwrap_or(&docdir_default);
-    let bindir = &builder.config.bindir;
-    let libdir = builder.config.libdir.as_ref().unwrap_or(&libdir_default);
-    let mandir = builder.config.mandir.as_ref().unwrap_or(&mandir_default);
-
-    let sysconfdir = prefix.join(sysconfdir);
-    let datadir = prefix.join(datadir);
-    let docdir = prefix.join(docdir);
-    let bindir = prefix.join(bindir);
-    let libdir = prefix.join(libdir);
-    let mandir = prefix.join(mandir);
-
-    let destdir = env::var_os("DESTDIR").map(PathBuf::from);
-
-    let prefix = add_destdir(&prefix, &destdir);
-    let sysconfdir = add_destdir(&sysconfdir, &destdir);
-    let datadir = add_destdir(&datadir, &destdir);
-    let docdir = add_destdir(&docdir, &destdir);
-    let bindir = add_destdir(&bindir, &destdir);
-    let libdir = add_destdir(&libdir, &destdir);
-    let mandir = add_destdir(&mandir, &destdir);
-
-    let prefix = {
-        fs::create_dir_all(&prefix)
-            .unwrap_or_else(|err| panic!("could not create {}: {}", prefix.display(), err));
-        fs::canonicalize(&prefix)
-            .unwrap_or_else(|err| panic!("could not canonicalize {}: {}", prefix.display(), err))
-    };
+    let prefix = default_path(&builder.config.prefix, "/usr/local");
+    let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc"));
+    let datadir = prefix.join(default_path(&builder.config.datadir, "share"));
+    let docdir = prefix.join(default_path(&builder.config.docdir, "share/doc"));
+    let mandir = prefix.join(default_path(&builder.config.mandir, "share/man"));
+    let libdir = prefix.join(default_path(&builder.config.libdir, "lib"));
+    let bindir = prefix.join(&builder.config.bindir); // Default in config.rs
 
     let empty_dir = builder.out.join("tmp/empty_dir");
-
     t!(fs::create_dir_all(&empty_dir));
-    let package_name = if let Some(host) = host {
-        format!("{}-{}", pkgname(builder, name), host.triple)
-    } else {
-        pkgname(builder, name)
-    };
 
     let mut cmd = Command::new("sh");
     cmd.current_dir(&empty_dir)
-        .arg(sanitize_sh(&tmpdir(builder).join(&package_name).join("install.sh")))
-        .arg(format!("--prefix={}", sanitize_sh(&prefix)))
-        .arg(format!("--sysconfdir={}", sanitize_sh(&sysconfdir)))
-        .arg(format!("--datadir={}", sanitize_sh(&datadir)))
-        .arg(format!("--docdir={}", sanitize_sh(&docdir)))
-        .arg(format!("--bindir={}", sanitize_sh(&bindir)))
-        .arg(format!("--libdir={}", sanitize_sh(&libdir)))
-        .arg(format!("--mandir={}", sanitize_sh(&mandir)))
+        .arg(sanitize_sh(&tarball.decompressed_output().join("install.sh")))
+        .arg(format!("--prefix={}", prepare_dir(prefix)))
+        .arg(format!("--sysconfdir={}", prepare_dir(sysconfdir)))
+        .arg(format!("--datadir={}", prepare_dir(datadir)))
+        .arg(format!("--docdir={}", prepare_dir(docdir)))
+        .arg(format!("--bindir={}", prepare_dir(bindir)))
+        .arg(format!("--libdir={}", prepare_dir(libdir)))
+        .arg(format!("--mandir={}", prepare_dir(mandir)))
         .arg("--disable-ldconfig");
     builder.run(&mut cmd);
     t!(fs::remove_dir_all(&empty_dir));
 }
 
-fn add_destdir(path: &Path, destdir: &Option<PathBuf>) -> PathBuf {
-    let mut ret = match *destdir {
-        Some(ref dest) => dest.clone(),
-        None => return path.to_path_buf(),
-    };
-    for part in path.components() {
-        if let Component::Normal(s) = part {
-            ret.push(s)
+fn default_path(config: &Option<PathBuf>, default: &str) -> PathBuf {
+    PathBuf::from(config.as_ref().cloned().unwrap_or_else(|| PathBuf::from(default)))
+}
+
+fn prepare_dir(mut path: PathBuf) -> String {
+    // The DESTDIR environment variable is a standard way to install software in a subdirectory
+    // while keeping the original directory structure, even if the prefix or other directories
+    // contain absolute paths.
+    //
+    // More information on the environment variable is available here:
+    // https://www.gnu.org/prep/standards/html_node/DESTDIR.html
+    if let Some(destdir) = env::var_os("DESTDIR").map(PathBuf::from) {
+        let without_destdir = path.clone();
+        path = destdir;
+        // Custom .join() which ignores disk roots.
+        for part in without_destdir.components() {
+            if let Component::Normal(s) = part {
+                path.push(s)
+            }
         }
     }
-    ret
+
+    // The installation command is not executed from the current directory, but from a temporary
+    // directory. To prevent relative paths from breaking this converts relative paths to absolute
+    // paths. std::fs::canonicalize is not used as that requires the path to actually be present.
+    if path.is_relative() {
+        path = std::env::current_dir().expect("failed to get the current directory").join(path);
+        assert!(path.is_absolute(), "could not make the path relative");
+    }
+
+    sanitize_sh(&path)
 }
 
 macro_rules! install {
@@ -191,25 +134,25 @@
 
 install!((self, builder, _config),
     Docs, "src/doc", _config.docs, only_hosts: false, {
-        builder.ensure(dist::Docs { host: self.target });
-        install_docs(builder, self.compiler.stage, self.target);
+        let tarball = builder.ensure(dist::Docs { host: self.target }).expect("missing docs");
+        install_sh(builder, "docs", self.compiler.stage, Some(self.target), &tarball);
     };
     Std, "library/std", true, only_hosts: false, {
         for target in &builder.targets {
-            builder.ensure(dist::Std {
+            let tarball = builder.ensure(dist::Std {
                 compiler: self.compiler,
                 target: *target
-            });
-            install_std(builder, self.compiler.stage, *target);
+            }).expect("missing std");
+            install_sh(builder, "std", self.compiler.stage, Some(*target), &tarball);
         }
     };
     Cargo, "cargo", Self::should_build(_config), only_hosts: true, {
-        builder.ensure(dist::Cargo { compiler: self.compiler, target: self.target });
-        install_cargo(builder, self.compiler.stage, self.target);
+        let tarball = builder.ensure(dist::Cargo { compiler: self.compiler, target: self.target });
+        install_sh(builder, "cargo", self.compiler.stage, Some(self.target), &tarball);
     };
     Rls, "rls", Self::should_build(_config), only_hosts: true, {
-        if builder.ensure(dist::Rls { compiler: self.compiler, target: self.target }).is_some() {
-            install_rls(builder, self.compiler.stage, self.target);
+        if let Some(tarball) = builder.ensure(dist::Rls { compiler: self.compiler, target: self.target }) {
+            install_sh(builder, "rls", self.compiler.stage, Some(self.target), &tarball);
         } else {
             builder.info(
                 &format!("skipping Install RLS stage{} ({})", self.compiler.stage, self.target),
@@ -217,16 +160,18 @@
         }
     };
     RustAnalyzer, "rust-analyzer", Self::should_build(_config), only_hosts: true, {
-        builder.ensure(dist::RustAnalyzer { compiler: self.compiler, target: self.target });
-        install_rust_analyzer(builder, self.compiler.stage, self.target);
+        let tarball = builder
+            .ensure(dist::RustAnalyzer { compiler: self.compiler, target: self.target })
+            .expect("missing rust-analyzer");
+        install_sh(builder, "rust-analyzer", self.compiler.stage, Some(self.target), &tarball);
     };
     Clippy, "clippy", Self::should_build(_config), only_hosts: true, {
-        builder.ensure(dist::Clippy { compiler: self.compiler, target: self.target });
-        install_clippy(builder, self.compiler.stage, self.target);
+        let tarball = builder.ensure(dist::Clippy { compiler: self.compiler, target: self.target });
+        install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball);
     };
     Miri, "miri", Self::should_build(_config), only_hosts: true, {
-        if builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }).is_some() {
-            install_miri(builder, self.compiler.stage, self.target);
+        if let Some(tarball) = builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }) {
+            install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
         } else {
             builder.info(
                 &format!("skipping Install miri stage{} ({})", self.compiler.stage, self.target),
@@ -234,11 +179,11 @@
         }
     };
     Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, {
-        if builder.ensure(dist::Rustfmt {
+        if let Some(tarball) = builder.ensure(dist::Rustfmt {
             compiler: self.compiler,
             target: self.target
-        }).is_some() {
-            install_rustfmt(builder, self.compiler.stage, self.target);
+        }) {
+            install_sh(builder, "rustfmt", self.compiler.stage, Some(self.target), &tarball);
         } else {
             builder.info(
                 &format!("skipping Install Rustfmt stage{} ({})", self.compiler.stage, self.target),
@@ -246,20 +191,20 @@
         }
     };
     Analysis, "analysis", Self::should_build(_config), only_hosts: false, {
-        builder.ensure(dist::Analysis {
+        let tarball = builder.ensure(dist::Analysis {
             // Find the actual compiler (handling the full bootstrap option) which
             // produced the save-analysis data because that data isn't copied
             // through the sysroot uplifting.
             compiler: builder.compiler_for(builder.top_stage, builder.config.build, self.target),
             target: self.target
-        });
-        install_analysis(builder, self.compiler.stage, self.target);
+        }).expect("missing analysis");
+        install_sh(builder, "analysis", self.compiler.stage, Some(self.target), &tarball);
     };
     Rustc, "src/librustc", true, only_hosts: true, {
-        builder.ensure(dist::Rustc {
+        let tarball = builder.ensure(dist::Rustc {
             compiler: builder.compiler(builder.top_stage, self.target),
         });
-        install_rustc(builder, self.compiler.stage, self.target);
+        install_sh(builder, "rustc", self.compiler.stage, Some(self.target), &tarball);
     };
 );
 
@@ -284,7 +229,7 @@
     }
 
     fn run(self, builder: &Builder<'_>) {
-        builder.ensure(dist::Src);
-        install_src(builder, self.stage);
+        let tarball = builder.ensure(dist::Src);
+        install_sh(builder, "src", self.stage, None, &tarball);
     }
 }
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index a47ddfb..88fdcfa 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -1083,7 +1083,7 @@
         if let Some(ref s) = self.config.description {
             version.push_str(" (");
             version.push_str(s);
-            version.push_str(")");
+            version.push(')');
         }
         version
     }
@@ -1144,7 +1144,7 @@
                     && (dep != "profiler_builtins"
                         || target
                             .map(|t| self.config.profiler_enabled(t))
-                            .unwrap_or(self.config.any_profiler_enabled()))
+                            .unwrap_or_else(|| self.config.any_profiler_enabled()))
                     && (dep != "rustc_codegen_llvm" || self.config.llvm_enabled())
                 {
                     list.push(*dep);
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index d716b23..609ac8b 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -171,7 +171,6 @@
             .define("LLVM_TARGETS_TO_BUILD", llvm_targets)
             .define("LLVM_EXPERIMENTAL_TARGETS_TO_BUILD", llvm_exp_targets)
             .define("LLVM_INCLUDE_EXAMPLES", "OFF")
-            .define("LLVM_INCLUDE_TESTS", "OFF")
             .define("LLVM_INCLUDE_DOCS", "OFF")
             .define("LLVM_INCLUDE_BENCHMARKS", "OFF")
             .define("LLVM_ENABLE_TERMINFO", "OFF")
@@ -802,6 +801,7 @@
     };
 
     match &*target.triple {
+        "aarch64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
         "aarch64-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]),
         "aarch64-unknown-linux-gnu" => {
             common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan"])
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index acb941d..08acc3d 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -163,7 +163,11 @@
             panic!("the iOS target is only supported on macOS");
         }
 
-        build.config.target_config.entry(*target).or_insert(Target::from_triple(&target.triple));
+        build
+            .config
+            .target_config
+            .entry(*target)
+            .or_insert_with(|| Target::from_triple(&target.triple));
 
         if target.contains("-none-") || target.contains("nvptx") {
             if build.no_std(*target) == Some(false) {
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index 2d4484c..7251477 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -89,7 +89,7 @@
         std::process::exit(1);
     }
 
-    let path = cfg_file.unwrap_or("config.toml".into());
+    let path = cfg_file.unwrap_or_else(|| "config.toml".into());
     let settings = format!(
         "# Includes one of the default files in src/bootstrap/defaults\n\
     profile = \"{}\"\n\
@@ -156,7 +156,7 @@
         io::stdout().flush()?;
         let mut input = String::new();
         io::stdin().read_line(&mut input)?;
-        if input == "" {
+        if input.is_empty() {
             eprintln!("EOF on stdin, when expecting answer to question.  Giving up.");
             std::process::exit(1);
         }
diff --git a/src/bootstrap/tarball.rs b/src/bootstrap/tarball.rs
index 0255f79..7fb0305 100644
--- a/src/bootstrap/tarball.rs
+++ b/src/bootstrap/tarball.rs
@@ -97,7 +97,6 @@
 
     include_target_in_component_name: bool,
     is_preview: bool,
-    delete_temp_dir: bool,
 }
 
 impl<'a> Tarball<'a> {
@@ -136,7 +135,6 @@
 
             include_target_in_component_name: false,
             is_preview: false,
-            delete_temp_dir: true,
         }
     }
 
@@ -198,12 +196,7 @@
         self.builder.cp_r(src.as_ref(), &dest);
     }
 
-    pub(crate) fn persist_work_dir(&mut self) -> PathBuf {
-        self.delete_temp_dir = false;
-        self.temp_dir.clone()
-    }
-
-    pub(crate) fn generate(self) -> PathBuf {
+    pub(crate) fn generate(self) -> GeneratedTarball {
         let mut component_name = self.component.clone();
         if self.is_preview {
             component_name.push_str("-preview");
@@ -227,20 +220,20 @@
         })
     }
 
-    pub(crate) fn combine(self, tarballs: &[PathBuf]) {
-        let mut input_tarballs = tarballs[0].as_os_str().to_os_string();
+    pub(crate) fn combine(self, tarballs: &[GeneratedTarball]) -> GeneratedTarball {
+        let mut input_tarballs = tarballs[0].path.as_os_str().to_os_string();
         for tarball in &tarballs[1..] {
             input_tarballs.push(",");
-            input_tarballs.push(tarball);
+            input_tarballs.push(&tarball.path);
         }
 
         self.run(|this, cmd| {
             cmd.arg("combine").arg("--input-tarballs").arg(input_tarballs);
             this.non_bare_args(cmd);
-        });
+        })
     }
 
-    pub(crate) fn bare(self) -> PathBuf {
+    pub(crate) fn bare(self) -> GeneratedTarball {
         // Bare tarballs should have the top level directory match the package
         // name, not "image". We rename the image directory just before passing
         // into rust-installer.
@@ -276,7 +269,7 @@
             .arg(crate::dist::distdir(self.builder));
     }
 
-    fn run(self, build_cli: impl FnOnce(&Tarball<'a>, &mut Command)) -> PathBuf {
+    fn run(self, build_cli: impl FnOnce(&Tarball<'a>, &mut Command)) -> GeneratedTarball {
         t!(std::fs::create_dir_all(&self.overlay_dir));
         self.builder.create(&self.overlay_dir.join("version"), &self.overlay.version(self.builder));
         if let Some(sha) = self.builder.rust_sha() {
@@ -294,11 +287,47 @@
 
         build_cli(&self, &mut cmd);
         cmd.arg("--work-dir").arg(&self.temp_dir);
-        self.builder.run(&mut cmd);
-        if self.delete_temp_dir {
-            t!(std::fs::remove_dir_all(&self.temp_dir));
+        if let Some(formats) = &self.builder.config.dist_compression_formats {
+            assert!(!formats.is_empty(), "dist.compression-formats can't be empty");
+            cmd.arg("--compression-formats").arg(formats.join(","));
         }
+        self.builder.run(&mut cmd);
 
-        crate::dist::distdir(self.builder).join(format!("{}.tar.gz", package_name))
+        // Use either the first compression format defined, or "gz" as the default.
+        let ext = self
+            .builder
+            .config
+            .dist_compression_formats
+            .as_ref()
+            .and_then(|formats| formats.get(0))
+            .map(|s| s.as_str())
+            .unwrap_or("gz");
+
+        GeneratedTarball {
+            path: crate::dist::distdir(self.builder).join(format!("{}.tar.{}", package_name, ext)),
+            decompressed_output: self.temp_dir.join(package_name),
+            work: self.temp_dir,
+        }
+    }
+}
+
+#[derive(Debug, Clone)]
+pub struct GeneratedTarball {
+    path: PathBuf,
+    decompressed_output: PathBuf,
+    work: PathBuf,
+}
+
+impl GeneratedTarball {
+    pub(crate) fn tarball(&self) -> &Path {
+        &self.path
+    }
+
+    pub(crate) fn decompressed_output(&self) -> &Path {
+        &self.decompressed_output
+    }
+
+    pub(crate) fn work_dir(&self) -> &Path {
+        &self.work
     }
 }
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 8592368..2e8c574 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1126,7 +1126,19 @@
                 Ok(path) => path,
                 Err(_) => p,
             })
-            .filter(|p| p.starts_with(suite_path) && (p.is_dir() || p.is_file()))
+            .filter(|p| p.starts_with(suite_path))
+            .filter(|p| {
+                let exists = p.is_dir() || p.is_file();
+                if !exists {
+                    if let Some(p) = p.to_str() {
+                        builder.info(&format!(
+                            "Warning: Skipping \"{}\": not a regular file or directory",
+                            p
+                        ));
+                    }
+                }
+                exists
+            })
             .filter_map(|p| {
                 // Since test suite paths are themselves directories, if we don't
                 // specify a directory or file, we'll get an empty string here
@@ -1135,7 +1147,7 @@
                 // flag is respected, so providing an empty --test-args conflicts with
                 // any following it.
                 match p.strip_prefix(suite_path).ok().and_then(|p| p.to_str()) {
-                    Some(s) if s != "" => Some(s),
+                    Some(s) if !s.is_empty() => Some(s),
                     _ => None,
                 }
             })
@@ -1962,8 +1974,8 @@
         builder.ensure(dist::Src);
 
         let mut cmd = Command::new("tar");
-        cmd.arg("-xzf")
-            .arg(builder.ensure(dist::PlainSourceTarball))
+        cmd.arg("-xf")
+            .arg(builder.ensure(dist::PlainSourceTarball).tarball())
             .arg("--strip-components=1")
             .current_dir(&dir);
         builder.run(&mut cmd);
@@ -1986,8 +1998,8 @@
         t!(fs::create_dir_all(&dir));
 
         let mut cmd = Command::new("tar");
-        cmd.arg("-xzf")
-            .arg(builder.ensure(dist::Src))
+        cmd.arg("-xf")
+            .arg(builder.ensure(dist::Src).tarball())
             .arg("--strip-components=1")
             .current_dir(&dir);
         builder.run(&mut cmd);
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 181a7fc..1958b6e 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -53,6 +53,11 @@
 RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-cargo-native-static"
 RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.codegen-units-std=1"
 
+# Only produce xz tarballs on CI. gz tarballs will be generated by the release
+# process by recompressing the existing xz ones. This decreases the storage
+# space required for CI artifacts.
+RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --dist-compression-formats=xz"
+
 if [ "$DIST_SRC" = "" ]; then
   RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-dist-src"
 fi
diff --git a/src/doc/book b/src/doc/book
index 5bb44f8..ac57a0d 160000
--- a/src/doc/book
+++ b/src/doc/book
@@ -1 +1 @@
-Subproject commit 5bb44f8b5b0aa105c8b22602e9b18800484afa21
+Subproject commit ac57a0ddd23d173b26731ccf939f3ba729753275
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
index ba34b8a..ceec19e 160000
--- a/src/doc/embedded-book
+++ b/src/doc/embedded-book
@@ -1 +1 @@
-Subproject commit ba34b8a968f9531d38c4dc4411d5568b7c076bfe
+Subproject commit ceec19e873be87c6ee5666b030c6bb612f889a96
diff --git a/src/doc/nomicon b/src/doc/nomicon
index a5a4844..a858499 160000
--- a/src/doc/nomicon
+++ b/src/doc/nomicon
@@ -1 +1 @@
-Subproject commit a5a48441d411f61556b57d762b03d6874afe575d
+Subproject commit a8584998eacdea7106a1dfafcbf6c1c06fcdf925
diff --git a/src/doc/reference b/src/doc/reference
index b278478..50af691 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit b278478b766178491a8b6f67afa4bcd6b64d977a
+Subproject commit 50af691f838937c300b47812d0507c6d88c14f97
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index 1cce073..03e23af 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit 1cce0737d6a7d3ceafb139b4a206861fb1dcb2ab
+Subproject commit 03e23af01f0b4f83a3a513da280e1ca92587f2ec
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index 93908e9..d03d5c7 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -31,7 +31,12 @@
 
 AddressSanitizer is supported on the following targets:
 
+* `aarch64-apple-darwin`
+* `aarch64-fuchsia`
+* `aarch64-unknown-linux-gnu`
 * `x86_64-apple-darwin`
+* `x86_64-fuchsia`
+* `x86_64-unknown-freebsd`
 * `x86_64-unknown-linux-gnu`
 
 AddressSanitizer works with non-instrumented code although it will impede its
@@ -169,10 +174,26 @@
 ==39249==ABORTING
 ```
 
+# LeakSanitizer
+
+LeakSanitizer is run-time memory leak detector.
+
+LeakSanitizer is supported on the following targets:
+
+* `aarch64-apple-darwin`
+* `aarch64-unknown-linux-gnu`
+* `x86_64-apple-darwin`
+* `x86_64-unknown-linux-gnu`
+
 # MemorySanitizer
 
-MemorySanitizer is detector of uninitialized reads. It is only supported on the
-`x86_64-unknown-linux-gnu` target.
+MemorySanitizer is detector of uninitialized reads.
+
+MemorySanitizer is supported on the following targets:
+
+* `aarch64-unknown-linux-gnu`
+* `x86_64-unknown-freebsd`
+* `x86_64-unknown-linux-gnu`
 
 MemorySanitizer requires all program code to be instrumented. C/C++ dependencies
 need to be recompiled using Clang with `-fsanitize=memory` option. Failing to
@@ -219,7 +240,10 @@
 ThreadSanitizer is a data race detection tool. It is supported on the following
 targets:
 
+* `aarch64-apple-darwin`
+* `aarch64-unknown-linux-gnu`
 * `x86_64-apple-darwin`
+* `x86_64-unknown-freebsd`
 * `x86_64-unknown-linux-gnu`
 
 To work correctly ThreadSanitizer needs to be "aware" of all synchronization
diff --git a/src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md b/src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md
index 98bcadd..8aca005 100644
--- a/src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md
+++ b/src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md
@@ -123,7 +123,7 @@
 ```shell
 $ rustup component add llvm-tools-preview
 $ cargo install cargo-binutils
-$ cargo profdata -- --help  # note the additional "--" preceeding the tool-specific arguments
+$ cargo profdata -- --help  # note the additional "--" preceding the tool-specific arguments
 ```
 
 ## Creating coverage reports
diff --git a/src/doc/unstable-book/src/language-features/link-args.md b/src/doc/unstable-book/src/language-features/link-args.md
index 2507197..da36e15 100644
--- a/src/doc/unstable-book/src/language-features/link-args.md
+++ b/src/doc/unstable-book/src/language-features/link-args.md
@@ -15,7 +15,7 @@
 #![feature(link_args)]
 
 #[link_args = "-foo -bar -baz"]
-extern {}
+extern "C" {}
 # fn main() {}
 ```
 
diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py
index 440181a..2f72336 100644
--- a/src/etc/htmldocck.py
+++ b/src/etc/htmldocck.py
@@ -218,7 +218,7 @@
 
 
 LINE_PATTERN = re.compile(r'''
-    (?<=(?<!\S)@)(?P<negated>!?)
+    (?<=(?<!\S))(?P<invalid>!?)@(?P<negated>!?)
     (?P<cmd>[A-Za-z]+(?:-[A-Za-z]+)*)
     (?P<args>.*)$
 ''', re.X | re.UNICODE)
@@ -233,6 +233,16 @@
 
             negated = (m.group('negated') == '!')
             cmd = m.group('cmd')
+            if m.group('invalid') == '!':
+                print_err(
+                    lineno,
+                    line,
+                    'Invalid command: `!@{0}{1}`, (help: try with `@!{1}`)'.format(
+                        '!' if negated else '',
+                        cmd,
+                    ),
+                )
+                continue
             args = m.group('args')
             if args and not args[:1].isspace():
                 print_err(lineno, line, 'Invalid template syntax')
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 2a8b6a3..83114a7 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -84,14 +84,14 @@
                         new_generics
                     });
 
-                let polarity;
+                let negative_polarity;
                 let new_generics = match result {
                     AutoTraitResult::PositiveImpl(new_generics) => {
-                        polarity = None;
+                        negative_polarity = false;
                         new_generics
                     }
                     AutoTraitResult::NegativeImpl => {
-                        polarity = Some(ImplPolarity::Negative);
+                        negative_polarity = true;
 
                         // For negative impls, we use the generic params, but *not* the predicates,
                         // from the original type. Otherwise, the displayed impl appears to be a
@@ -130,7 +130,7 @@
                         trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap()),
                         for_: ty.clean(self.cx),
                         items: Vec::new(),
-                        polarity,
+                        negative_polarity,
                         synthetic: true,
                         blanket_impl: None,
                     }),
@@ -313,12 +313,12 @@
         tcx: TyCtxt<'tcx>,
         pred: ty::Predicate<'tcx>,
     ) -> FxHashSet<GenericParamDef> {
-        let bound_predicate = pred.bound_atom();
+        let bound_predicate = pred.kind();
         let regions = match bound_predicate.skip_binder() {
-            ty::PredicateAtom::Trait(poly_trait_pred, _) => {
+            ty::PredicateKind::Trait(poly_trait_pred, _) => {
                 tcx.collect_referenced_late_bound_regions(&bound_predicate.rebind(poly_trait_pred))
             }
-            ty::PredicateAtom::Projection(poly_proj_pred) => {
+            ty::PredicateKind::Projection(poly_proj_pred) => {
                 tcx.collect_referenced_late_bound_regions(&bound_predicate.rebind(poly_proj_pred))
             }
             _ => return FxHashSet::default(),
@@ -351,8 +351,8 @@
                 if let Some(data) = ty_to_fn.get(&ty) {
                     let (poly_trait, output) =
                         (data.0.as_ref().expect("as_ref failed").clone(), data.1.as_ref().cloned());
-                    let new_ty = match &poly_trait.trait_ {
-                        &Type::ResolvedPath {
+                    let new_ty = match poly_trait.trait_ {
+                        Type::ResolvedPath {
                             ref path,
                             ref param_names,
                             ref did,
@@ -463,8 +463,8 @@
             .iter()
             .filter(|p| {
                 !orig_bounds.contains(p)
-                    || match p.skip_binders() {
-                        ty::PredicateAtom::Trait(pred, _) => pred.def_id() == sized_trait,
+                    || match p.kind().skip_binder() {
+                        ty::PredicateKind::Trait(pred, _) => pred.def_id() == sized_trait,
                         _ => false,
                     }
             })
@@ -738,11 +738,11 @@
     }
 
     fn is_fn_ty(&self, tcx: TyCtxt<'_>, ty: &Type) -> bool {
-        match &ty {
-            &&Type::ResolvedPath { ref did, .. } => {
-                *did == tcx.require_lang_item(LangItem::Fn, None)
-                    || *did == tcx.require_lang_item(LangItem::FnMut, None)
-                    || *did == tcx.require_lang_item(LangItem::FnOnce, None)
+        match ty {
+            &Type::ResolvedPath { did, .. } => {
+                did == tcx.require_lang_item(LangItem::Fn, None)
+                    || did == tcx.require_lang_item(LangItem::FnMut, None)
+                    || did == tcx.require_lang_item(LangItem::FnOnce, None)
             }
             _ => false,
         }
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index ba3eb00..f1c26fe 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -131,7 +131,7 @@
                             .in_definition_order()
                             .collect::<Vec<_>>()
                             .clean(self.cx),
-                        polarity: None,
+                        negative_polarity: false,
                         synthetic: false,
                         blanket_impl: Some(trait_ref.self_ty().clean(self.cx)),
                     }),
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 2f169d1..444b732 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -177,10 +177,7 @@
             Cfg::Any(ref sub_cfgs) | Cfg::All(ref sub_cfgs) => {
                 sub_cfgs.first().map(Cfg::should_capitalize_first_letter).unwrap_or(false)
             }
-            Cfg::Cfg(name, _) => match name {
-                sym::debug_assertions | sym::target_endian => true,
-                _ => false,
-            },
+            Cfg::Cfg(name, _) => name == sym::debug_assertions || name == sym::target_endian,
         }
     }
 
@@ -188,18 +185,13 @@
         match *self {
             Cfg::False | Cfg::True => false,
             Cfg::Any(..) | Cfg::All(..) | Cfg::Cfg(..) => true,
-            Cfg::Not(ref child) => match **child {
-                Cfg::Cfg(..) => true,
-                _ => false,
-            },
+            Cfg::Not(box Cfg::Cfg(..)) => true,
+            Cfg::Not(..) => false,
         }
     }
 
     fn should_use_with_in_description(&self) -> bool {
-        match *self {
-            Cfg::Cfg(name, _) if name == sym::target_feature => true,
-            _ => false,
-        }
+        matches!(self, Cfg::Cfg(sym::target_feature, _))
     }
 
     /// Attempt to simplify this cfg by assuming that `assume` is already known to be true, will
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index c168c56..916684b 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -121,7 +121,7 @@
     };
 
     let target_attrs = load_attrs(cx, did);
-    let attrs = merge_attrs(cx, Some(parent_module), target_attrs, attrs_clone);
+    let attrs = box merge_attrs(cx, Some(parent_module), target_attrs, attrs_clone);
 
     cx.renderinfo.borrow_mut().inlined.insert(did);
     let what_rustc_thinks = clean::Item::from_def_id_and_parts(did, Some(name), kind, cx);
@@ -169,7 +169,17 @@
         if !s.is_empty() { Some(s) } else { None }
     });
     let fqn = if let clean::TypeKind::Macro = kind {
-        vec![crate_name, relative.last().expect("relative was empty")]
+        // Check to see if it is a macro 2.0 or built-in macro
+        if matches!(
+            cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())),
+            LoadedMacro::MacroDef(def, _)
+                if matches!(&def.kind, ast::ItemKind::MacroDef(ast_def)
+                    if !ast_def.macro_rules)
+        ) {
+            once(crate_name).chain(relative).collect()
+        } else {
+            vec![crate_name, relative.last().expect("relative was empty")]
+        }
     } else {
         once(crate_name).chain(relative).collect()
     };
@@ -261,26 +271,12 @@
 
 fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef {
     let predicates = cx.tcx.explicit_predicates_of(did);
+    let type_ = cx.tcx.type_of(did).clean(cx);
 
     clean::Typedef {
-        type_: cx.tcx.type_of(did).clean(cx),
+        type_,
         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))
-}
-
-crate 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,
+        item_type: None,
     }
 }
 
@@ -362,18 +358,16 @@
     let impl_item = match did.as_local() {
         Some(did) => {
             let hir_id = tcx.hir().local_def_id_to_hir_id(did);
-            match tcx.hir().expect_item(hir_id).kind {
-                hir::ItemKind::Impl { self_ty, ref generics, ref items, .. } => {
-                    Some((self_ty, generics, items))
-                }
+            match &tcx.hir().expect_item(hir_id).kind {
+                hir::ItemKind::Impl(impl_) => Some(impl_),
                 _ => panic!("`DefID` passed to `build_impl` is not an `impl"),
             }
         }
         None => None,
     };
 
-    let for_ = match impl_item {
-        Some((self_ty, _, _)) => self_ty.clean(cx),
+    let for_ = match &impl_item {
+        Some(impl_) => impl_.self_ty.clean(cx),
         None => tcx.type_of(did).clean(cx),
     };
 
@@ -395,9 +389,13 @@
 
     let predicates = tcx.explicit_predicates_of(did);
     let (trait_items, generics) = match impl_item {
-        Some((_, generics, items)) => (
-            items.iter().map(|item| tcx.hir().impl_item(item.id).clean(cx)).collect::<Vec<_>>(),
-            generics.clean(cx),
+        Some(impl_) => (
+            impl_
+                .items
+                .iter()
+                .map(|item| tcx.hir().impl_item(item.id).clean(cx))
+                .collect::<Vec<_>>(),
+            impl_.generics.clean(cx),
         ),
         None => (
             tcx.associated_items(did)
@@ -442,73 +440,64 @@
             trait_,
             for_,
             items: trait_items,
-            polarity: Some(polarity.clean(cx)),
+            negative_polarity: polarity.clean(cx),
             synthetic: false,
             blanket_impl: None,
         }),
         cx,
     );
-    item.attrs = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
+    item.attrs = box merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
     debug!("merged_attrs={:?}", item.attrs);
     ret.push(item);
 }
 
 fn build_module(cx: &DocContext<'_>, did: DefId, visited: &mut FxHashSet<DefId>) -> clean::Module {
     let mut items = Vec::new();
-    fill_in(cx, did, &mut items, visited);
-    return clean::Module { items, is_crate: false };
 
-    fn fill_in(
-        cx: &DocContext<'_>,
-        did: DefId,
-        items: &mut Vec<clean::Item>,
-        visited: &mut FxHashSet<DefId>,
-    ) {
-        // If we're re-exporting a re-export it may actually re-export something in
-        // two namespaces, so the target may be listed twice. Make sure we only
-        // visit each node at most once.
-        for &item in cx.tcx.item_children(did).iter() {
-            if item.vis == ty::Visibility::Public {
-                if let Some(def_id) = item.res.mod_def_id() {
-                    if did == def_id || !visited.insert(def_id) {
-                        continue;
-                    }
+    // If we're re-exporting a re-export it may actually re-export something in
+    // two namespaces, so the target may be listed twice. Make sure we only
+    // visit each node at most once.
+    for &item in cx.tcx.item_children(did).iter() {
+        if item.vis == ty::Visibility::Public {
+            if let Some(def_id) = item.res.mod_def_id() {
+                if did == def_id || !visited.insert(def_id) {
+                    continue;
                 }
-                if let Res::PrimTy(p) = item.res {
-                    // Primitive types can't be inlined so generate an import instead.
-                    items.push(clean::Item {
-                        name: None,
-                        attrs: clean::Attributes::default(),
-                        source: clean::Span::dummy(),
-                        def_id: DefId::local(CRATE_DEF_INDEX),
-                        visibility: clean::Public,
-                        kind: box clean::ImportItem(clean::Import::new_simple(
-                            item.ident.name,
-                            clean::ImportSource {
-                                path: clean::Path {
-                                    global: false,
-                                    res: item.res,
-                                    segments: vec![clean::PathSegment {
-                                        name: clean::PrimitiveType::from(p).as_sym(),
-                                        args: clean::GenericArgs::AngleBracketed {
-                                            args: Vec::new(),
-                                            bindings: Vec::new(),
-                                        },
-                                    }],
-                                },
-                                did: None,
+            }
+            if let Res::PrimTy(p) = item.res {
+                // Primitive types can't be inlined so generate an import instead.
+                items.push(clean::Item {
+                    name: None,
+                    attrs: box clean::Attributes::default(),
+                    source: clean::Span::dummy(),
+                    def_id: DefId::local(CRATE_DEF_INDEX),
+                    visibility: clean::Public,
+                    kind: box clean::ImportItem(clean::Import::new_simple(
+                        item.ident.name,
+                        clean::ImportSource {
+                            path: clean::Path {
+                                global: false,
+                                res: item.res,
+                                segments: vec![clean::PathSegment {
+                                    name: clean::PrimitiveType::from(p).as_sym(),
+                                    args: clean::GenericArgs::AngleBracketed {
+                                        args: Vec::new(),
+                                        bindings: Vec::new(),
+                                    },
+                                }],
                             },
-                            true,
-                        )),
-                    });
-                } else if let Some(i) =
-                    try_inline(cx, did, item.res, item.ident.name, None, visited)
-                {
-                    items.extend(i)
-                }
+                            did: None,
+                        },
+                        true,
+                    )),
+                });
+            } else if let Some(i) = try_inline(cx, did, item.res, item.ident.name, None, visited) {
+                items.extend(i)
             }
         }
     }
+
+    clean::Module { items, is_crate: false }
 }
 
 crate fn print_inlined_const(cx: &DocContext<'_>, did: DefId) -> String {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 766b02a..3ddb2ad 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -219,7 +219,6 @@
 impl Clean<Item> for doctree::Module<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let mut items: Vec<Item> = vec![];
-        items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
         items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
         items.extend(self.mods.iter().map(|x| x.clean(cx)));
         items.extend(self.items.iter().map(|x| x.clean(cx)).flatten());
@@ -466,20 +465,20 @@
 
 impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
     fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
-        let bound_predicate = self.bound_atom();
+        let bound_predicate = self.kind();
         match bound_predicate.skip_binder() {
-            ty::PredicateAtom::Trait(pred, _) => Some(bound_predicate.rebind(pred).clean(cx)),
-            ty::PredicateAtom::RegionOutlives(pred) => pred.clean(cx),
-            ty::PredicateAtom::TypeOutlives(pred) => pred.clean(cx),
-            ty::PredicateAtom::Projection(pred) => Some(pred.clean(cx)),
+            ty::PredicateKind::Trait(pred, _) => Some(bound_predicate.rebind(pred).clean(cx)),
+            ty::PredicateKind::RegionOutlives(pred) => pred.clean(cx),
+            ty::PredicateKind::TypeOutlives(pred) => pred.clean(cx),
+            ty::PredicateKind::Projection(pred) => Some(pred.clean(cx)),
 
-            ty::PredicateAtom::Subtype(..)
-            | ty::PredicateAtom::WellFormed(..)
-            | ty::PredicateAtom::ObjectSafe(..)
-            | ty::PredicateAtom::ClosureKind(..)
-            | ty::PredicateAtom::ConstEvaluatable(..)
-            | ty::PredicateAtom::ConstEquate(..)
-            | ty::PredicateAtom::TypeWellFormedFromEnv(..) => panic!("not user writable"),
+            ty::PredicateKind::Subtype(..)
+            | ty::PredicateKind::WellFormed(..)
+            | ty::PredicateKind::ObjectSafe(..)
+            | ty::PredicateKind::ClosureKind(..)
+            | ty::PredicateKind::ConstEvaluatable(..)
+            | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"),
         }
     }
 }
@@ -607,11 +606,12 @@
                     synthetic,
                 },
             ),
-            hir::GenericParamKind::Const { ref ty } => (
+            hir::GenericParamKind::Const { ref ty, default: _ } => (
                 self.name.ident().name,
                 GenericParamDefKind::Const {
                     did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(),
                     ty: ty.clean(cx),
+                    // FIXME(const_generics_defaults): add `default` field here for docs
                 },
             ),
         };
@@ -639,10 +639,10 @@
         ///
         /// [`lifetime_to_generic_param`]: rustc_ast_lowering::LoweringContext::lifetime_to_generic_param
         fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
-            match param.kind {
-                hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided } => true,
-                _ => false,
-            }
+            matches!(
+                param.kind,
+                hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided }
+            )
         }
 
         let impl_trait_params = self
@@ -743,19 +743,19 @@
             .flat_map(|(p, _)| {
                 let mut projection = None;
                 let param_idx = (|| {
-                    let bound_p = p.bound_atom();
+                    let bound_p = p.kind();
                     match bound_p.skip_binder() {
-                        ty::PredicateAtom::Trait(pred, _constness) => {
+                        ty::PredicateKind::Trait(pred, _constness) => {
                             if let ty::Param(param) = pred.self_ty().kind() {
                                 return Some(param.index);
                             }
                         }
-                        ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
+                        ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
                             if let ty::Param(param) = ty.kind() {
                                 return Some(param.index);
                             }
                         }
-                        ty::PredicateAtom::Projection(p) => {
+                        ty::PredicateKind::Projection(p) => {
                             if let ty::Param(param) = p.projection_ty.self_ty().kind() {
                                 projection = Some(bound_p.rebind(p));
                                 return Some(param.index);
@@ -800,7 +800,7 @@
 
         for (param, mut bounds) in impl_trait {
             // Move trait bounds to the front.
-            bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b { false } else { true });
+            bounds.sort_by_key(|b| !matches!(b, GenericBound::TraitBound(..)));
 
             if let crate::core::ImplTraitParam::ParamIndex(idx) = param {
                 if let Some(proj) = impl_trait_proj.remove(&idx) {
@@ -941,7 +941,7 @@
                 .iter()
                 .enumerate()
                 .map(|(i, ty)| {
-                    let mut name = self.1.get(i).map(|ident| ident.name).unwrap_or(kw::Empty);
+                    let mut name = self.1.get(i).map_or(kw::Empty, |ident| ident.name);
                     if name.is_empty() {
                         name = kw::Underscore;
                     }
@@ -962,7 +962,7 @@
                 .iter()
                 .enumerate()
                 .map(|(i, ty)| Argument {
-                    name: name_from_pat(&body.params[i].pat),
+                    name: Symbol::intern(&rustc_hir_pretty::param_to_string(&body.params[i])),
                     type_: ty.clean(cx),
                 })
                 .collect(),
@@ -1000,7 +1000,7 @@
                     .iter()
                     .map(|t| Argument {
                         type_: t.clean(cx),
-                        name: names.next().map(|i| i.name).unwrap_or(kw::Empty),
+                        name: names.next().map_or(kw::Empty, |i| i.name),
                     })
                     .collect(),
             },
@@ -1118,10 +1118,17 @@
                     }
                     MethodItem(m, Some(self.defaultness))
                 }
-                hir::ImplItemKind::TyAlias(ref ty) => {
-                    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::TyAlias(ref hir_ty) => {
+                    let type_ = hir_ty.clean(cx);
+                    let item_type = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
+                    TypedefItem(
+                        Typedef {
+                            type_,
+                            generics: Generics::default(),
+                            item_type: Some(item_type),
+                        },
+                        true,
+                    )
                 }
             };
             Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx)
@@ -1267,13 +1274,13 @@
 
                     AssocTypeItem(bounds, ty.clean(cx))
                 } else {
+                    // FIXME: when could this happen? ASsociated items in inherent impls?
                     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_,
                             generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
-                            item_type,
+                            item_type: None,
                         },
                         true,
                     )
@@ -1320,7 +1327,7 @@
                 let mut ty_substs = FxHashMap::default();
                 let mut lt_substs = FxHashMap::default();
                 let mut ct_substs = FxHashMap::default();
-                let generic_args = provided_params.generic_args();
+                let generic_args = provided_params.args();
                 {
                     let mut indices: GenericParamCount = Default::default();
                     for param in generics.params.iter() {
@@ -1385,7 +1392,7 @@
                                 if let Some(ct) = const_ {
                                     ct_substs.insert(const_param_def_id.to_def_id(), ct.clean(cx));
                                 }
-                                // FIXME(const_generics:defaults)
+                                // FIXME(const_generics_defaults)
                                 indices.consts += 1;
                             }
                         }
@@ -1677,14 +1684,12 @@
                 let mut bounds = bounds
                     .iter()
                     .filter_map(|bound| {
-                        // Note: The substs of opaque types can contain unbound variables,
-                        // meaning that we have to use `ignore_quantifiers_with_unbound_vars` here.
-                        let bound_predicate = bound.bound_atom_with_opt_escaping(cx.tcx);
+                        let bound_predicate = bound.kind();
                         let trait_ref = match bound_predicate.skip_binder() {
-                            ty::PredicateAtom::Trait(tr, _constness) => {
+                            ty::PredicateKind::Trait(tr, _constness) => {
                                 bound_predicate.rebind(tr.trait_ref)
                             }
-                            ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
+                            ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
                                 if let Some(r) = reg.clean(cx) {
                                     regions.push(GenericBound::Outlives(r));
                                 }
@@ -1703,8 +1708,8 @@
                         let bounds: Vec<_> = bounds
                             .iter()
                             .filter_map(|bound| {
-                                if let ty::PredicateAtom::Projection(proj) =
-                                    bound.bound_atom_with_opt_escaping(cx.tcx).skip_binder()
+                                if let ty::PredicateKind::Projection(proj) =
+                                    bound.kind().skip_binder()
                                 {
                                     if proj.projection_ty.trait_ref(cx.tcx)
                                         == trait_ref.skip_binder()
@@ -1829,27 +1834,14 @@
     }
 }
 
-impl Clean<Item> for doctree::Variant<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> Item {
-        let what_rustc_thinks = Item::from_hir_id_and_parts(
-            self.id,
-            Some(self.name),
-            VariantItem(Variant { kind: self.def.clean(cx) }),
-            cx,
-        );
-        // don't show `pub` for variants, which are always public
-        Item { visibility: Inherited, ..what_rustc_thinks }
-    }
-}
-
 impl Clean<Item> for ty::VariantDef {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let kind = match self.ctor_kind {
-            CtorKind::Const => VariantKind::CLike,
-            CtorKind::Fn => VariantKind::Tuple(
+            CtorKind::Const => Variant::CLike,
+            CtorKind::Fn => Variant::Tuple(
                 self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect(),
             ),
-            CtorKind::Fictive => VariantKind::Struct(VariantStruct {
+            CtorKind::Fictive => Variant::Struct(VariantStruct {
                 struct_type: doctree::Plain,
                 fields_stripped: false,
                 fields: self
@@ -1866,25 +1858,21 @@
                     .collect(),
             }),
         };
-        let what_rustc_thinks = Item::from_def_id_and_parts(
-            self.def_id,
-            Some(self.ident.name),
-            VariantItem(Variant { kind }),
-            cx,
-        );
+        let what_rustc_thinks =
+            Item::from_def_id_and_parts(self.def_id, Some(self.ident.name), VariantItem(kind), cx);
         // don't show `pub` for fields, which are always public
         Item { visibility: Inherited, ..what_rustc_thinks }
     }
 }
 
-impl Clean<VariantKind> for hir::VariantData<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
+impl Clean<Variant> for hir::VariantData<'_> {
+    fn clean(&self, cx: &DocContext<'_>) -> Variant {
         match self {
-            hir::VariantData::Struct(..) => VariantKind::Struct(self.clean(cx)),
+            hir::VariantData::Struct(..) => Variant::Struct(self.clean(cx)),
             hir::VariantData::Tuple(..) => {
-                VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
+                Variant::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
             }
-            hir::VariantData::Unit(..) => VariantKind::CLike,
+            hir::VariantData::Unit(..) => Variant::CLike,
         }
     }
 }
@@ -1935,7 +1923,7 @@
 
 impl Clean<PathSegment> for hir::PathSegment<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> PathSegment {
-        PathSegment { name: self.ident.name, args: self.generic_args().clean(cx) }
+        PathSegment { name: self.ident.name, args: self.args().clean(cx) }
     }
 }
 
@@ -1986,11 +1974,15 @@
                     bounds: ty.bounds.clean(cx),
                     generics: ty.generics.clean(cx),
                 }),
-                ItemKind::TyAlias(ty, ref generics) => {
-                    let rustdoc_ty = ty.clean(cx);
-                    let item_type = rustdoc_ty.def_id().and_then(|did| inline::build_ty(cx, did));
+                ItemKind::TyAlias(hir_ty, ref generics) => {
+                    let rustdoc_ty = hir_ty.clean(cx);
+                    let ty = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
                     TypedefItem(
-                        Typedef { type_: rustdoc_ty, generics: generics.clean(cx), item_type },
+                        Typedef {
+                            type_: rustdoc_ty,
+                            generics: generics.clean(cx),
+                            item_type: Some(ty),
+                        },
                         false,
                     )
                 }
@@ -2015,12 +2007,12 @@
                     fields: variant_data.fields().clean(cx),
                     fields_stripped: false,
                 }),
-                ItemKind::Impl { .. } => return clean_impl(item, cx),
+                ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.hir_id, cx),
                 // proc macros can have a name set by attributes
                 ItemKind::Fn(ref sig, ref generics, body_id) => {
                     clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
                 }
-                hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
+                ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
                     let items = item_ids
                         .iter()
                         .map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx))
@@ -2039,6 +2031,9 @@
                 ItemKind::ExternCrate(orig_name) => {
                     return clean_extern_crate(item, name, orig_name, cx);
                 }
+                ItemKind::Use(path, kind) => {
+                    return clean_use_statement(item, name, path, kind, cx);
+                }
                 _ => unreachable!("not yet converted"),
             };
 
@@ -2049,7 +2044,7 @@
 
 impl Clean<Item> for hir::Variant<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
-        let kind = VariantItem(Variant { kind: self.data.clean(cx) });
+        let kind = VariantItem(self.data.clean(cx));
         let what_rustc_thinks =
             Item::from_hir_id_and_parts(self.id, Some(self.ident.name), kind, cx);
         // don't show `pub` for variants, which are always public
@@ -2057,28 +2052,24 @@
     }
 }
 
-impl Clean<ImplPolarity> for ty::ImplPolarity {
-    fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
+impl Clean<bool> for ty::ImplPolarity {
+    /// Returns whether the impl has negative polarity.
+    fn clean(&self, _: &DocContext<'_>) -> bool {
         match self {
             &ty::ImplPolarity::Positive |
             // FIXME: do we want to do something else here?
-            &ty::ImplPolarity::Reservation => ImplPolarity::Positive,
-            &ty::ImplPolarity::Negative => ImplPolarity::Negative,
+            &ty::ImplPolarity::Reservation => false,
+            &ty::ImplPolarity::Negative => true,
         }
     }
 }
 
-fn clean_impl(impl_: &hir::Item<'_>, cx: &DocContext<'_>) -> Vec<Item> {
+fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &DocContext<'_>) -> Vec<Item> {
     let mut ret = Vec::new();
-    let (trait_, items, for_, unsafety, generics) = match &impl_.kind {
-        hir::ItemKind::Impl { of_trait, items, self_ty, unsafety, generics, .. } => {
-            (of_trait, items, self_ty, *unsafety, generics)
-        }
-        _ => unreachable!(),
-    };
-    let trait_ = trait_.clean(cx);
-    let items = items.iter().map(|ii| cx.tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>();
-    let def_id = cx.tcx.hir().local_def_id(impl_.hir_id);
+    let trait_ = impl_.of_trait.clean(cx);
+    let items =
+        impl_.items.iter().map(|ii| cx.tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>();
+    let def_id = cx.tcx.hir().local_def_id(hir_id);
 
     // If this impl block is an implementation of the Deref trait, then we
     // need to try inlining the target's inherent impl blocks as well.
@@ -2091,24 +2082,24 @@
         .map(|did| cx.tcx.provided_trait_methods(did).map(|meth| meth.ident.name).collect())
         .unwrap_or_default();
 
-    let for_ = for_.clean(cx);
+    let for_ = impl_.self_ty.clean(cx);
     let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) {
         DefKind::TyAlias => Some(cx.tcx.type_of(did).clean(cx)),
         _ => None,
     });
     let make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| {
         let kind = ImplItem(Impl {
-            unsafety,
-            generics: generics.clean(cx),
+            unsafety: impl_.unsafety,
+            generics: impl_.generics.clean(cx),
             provided_trait_methods: provided.clone(),
             trait_,
             for_,
             items,
-            polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)),
+            negative_polarity: cx.tcx.impl_polarity(def_id).clean(cx),
             synthetic: false,
             blanket_impl: None,
         });
-        Item::from_hir_id_and_parts(impl_.hir_id, None, kind, cx)
+        Item::from_hir_id_and_parts(hir_id, None, kind, cx)
     };
     if let Some(type_alias) = type_alias {
         ret.push(make_item(trait_.clone(), type_alias, items.clone()));
@@ -2156,7 +2147,7 @@
     // FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason
     vec![Item {
         name: None,
-        attrs: krate.attrs.clean(cx),
+        attrs: box krate.attrs.clean(cx),
         source: krate.span.clean(cx),
         def_id: crate_def_id,
         visibility: krate.vis.clean(cx),
@@ -2164,91 +2155,97 @@
     }]
 }
 
-impl Clean<Vec<Item>> for doctree::Import<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
-        // We need this comparison because some imports (for std types for example)
-        // are "inserted" as well but directly by the compiler and they should not be
-        // taken into account.
-        if self.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) {
-            return Vec::new();
-        }
-
-        // We consider inlining the documentation of `pub use` statements, but we
-        // forcefully don't inline if this is not public or if the
-        // #[doc(no_inline)] attribute is present.
-        // Don't inline doc(hidden) imports so they can be stripped at a later stage.
-        let mut denied = !self.vis.node.is_pub()
-            || self.attrs.iter().any(|a| {
-                a.has_name(sym::doc)
-                    && match a.meta_item_list() {
-                        Some(l) => {
-                            attr::list_contains_name(&l, sym::no_inline)
-                                || attr::list_contains_name(&l, sym::hidden)
-                        }
-                        None => false,
-                    }
-            });
-        // Also check whether imports were asked to be inlined, in case we're trying to re-export a
-        // crate in Rust 2018+
-        let please_inline = self.attrs.lists(sym::doc).has_word(sym::inline);
-        let path = self.path.clean(cx);
-        let inner = if self.glob {
-            if !denied {
-                let mut visited = FxHashSet::default();
-                if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
-                    return items;
-                }
-            }
-            Import::new_glob(resolve_use_source(cx, path), true)
-        } else {
-            let name = self.name;
-            if !please_inline {
-                if let Res::Def(DefKind::Mod, did) = path.res {
-                    if !did.is_local() && did.index == CRATE_DEF_INDEX {
-                        // if we're `pub use`ing an extern crate root, don't inline it unless we
-                        // were specifically asked for it
-                        denied = true;
-                    }
-                }
-            }
-            if !denied {
-                let mut visited = FxHashSet::default();
-
-                if let Some(mut items) = inline::try_inline(
-                    cx,
-                    cx.tcx.parent_module(self.id).to_def_id(),
-                    path.res,
-                    name,
-                    Some(self.attrs),
-                    &mut visited,
-                ) {
-                    items.push(Item {
-                        name: None,
-                        attrs: self.attrs.clean(cx),
-                        source: self.span.clean(cx),
-                        def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
-                        visibility: self.vis.clean(cx),
-                        kind: box ImportItem(Import::new_simple(
-                            self.name,
-                            resolve_use_source(cx, path),
-                            false,
-                        )),
-                    });
-                    return items;
-                }
-            }
-            Import::new_simple(name, resolve_use_source(cx, path), true)
-        };
-
-        vec![Item {
-            name: None,
-            attrs: self.attrs.clean(cx),
-            source: self.span.clean(cx),
-            def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
-            visibility: self.vis.clean(cx),
-            kind: box ImportItem(inner),
-        }]
+fn clean_use_statement(
+    import: &hir::Item<'_>,
+    name: Symbol,
+    path: &hir::Path<'_>,
+    kind: hir::UseKind,
+    cx: &DocContext<'_>,
+) -> Vec<Item> {
+    // We need this comparison because some imports (for std types for example)
+    // are "inserted" as well but directly by the compiler and they should not be
+    // taken into account.
+    if import.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) {
+        return Vec::new();
     }
+
+    let (doc_meta_item, please_inline) = import.attrs.lists(sym::doc).get_word_attr(sym::inline);
+    let pub_underscore = import.vis.node.is_pub() && name == kw::Underscore;
+
+    if pub_underscore && please_inline {
+        rustc_errors::struct_span_err!(
+            cx.tcx.sess,
+            doc_meta_item.unwrap().span(),
+            E0780,
+            "anonymous imports cannot be inlined"
+        )
+        .span_label(import.span, "anonymous import")
+        .emit();
+    }
+
+    // We consider inlining the documentation of `pub use` statements, but we
+    // forcefully don't inline if this is not public or if the
+    // #[doc(no_inline)] attribute is present.
+    // Don't inline doc(hidden) imports so they can be stripped at a later stage.
+    let mut denied = !import.vis.node.is_pub()
+        || pub_underscore
+        || import.attrs.iter().any(|a| {
+            a.has_name(sym::doc)
+                && match a.meta_item_list() {
+                    Some(l) => {
+                        attr::list_contains_name(&l, sym::no_inline)
+                            || attr::list_contains_name(&l, sym::hidden)
+                    }
+                    None => false,
+                }
+        });
+
+    // Also check whether imports were asked to be inlined, in case we're trying to re-export a
+    // crate in Rust 2018+
+    let def_id = cx.tcx.hir().local_def_id(import.hir_id).to_def_id();
+    let path = path.clean(cx);
+    let inner = if kind == hir::UseKind::Glob {
+        if !denied {
+            let mut visited = FxHashSet::default();
+            if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
+                return items;
+            }
+        }
+        Import::new_glob(resolve_use_source(cx, path), true)
+    } else {
+        if !please_inline {
+            if let Res::Def(DefKind::Mod, did) = path.res {
+                if !did.is_local() && did.index == CRATE_DEF_INDEX {
+                    // if we're `pub use`ing an extern crate root, don't inline it unless we
+                    // were specifically asked for it
+                    denied = true;
+                }
+            }
+        }
+        if !denied {
+            let mut visited = FxHashSet::default();
+
+            if let Some(mut items) = inline::try_inline(
+                cx,
+                cx.tcx.parent_module(import.hir_id).to_def_id(),
+                path.res,
+                name,
+                Some(import.attrs),
+                &mut visited,
+            ) {
+                items.push(Item::from_def_id_and_parts(
+                    def_id,
+                    None,
+                    ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)),
+                    cx,
+                ));
+                return items;
+            }
+        }
+        Import::new_simple(name, resolve_use_source(cx, path), true)
+    };
+
+    vec![Item::from_def_id_and_parts(def_id, None, ImportItem(inner), cx)]
 }
 
 impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Symbol>) {
@@ -2311,18 +2308,19 @@
             )
         } else {
             let vis = item.vis.clean(cx);
+            let def_id = cx.tcx.hir().local_def_id(item.hir_id).to_def_id();
 
             if matchers.len() <= 1 {
                 format!(
                     "{}macro {}{} {{\n    ...\n}}",
-                    vis.print_with_space(cx.tcx),
+                    vis.print_with_space(cx.tcx, def_id),
                     name,
                     matchers.iter().map(|span| span.to_src(cx)).collect::<String>(),
                 )
             } else {
                 format!(
                     "{}macro {} {{\n{}}}",
-                    vis.print_with_space(cx.tcx),
+                    vis.print_with_space(cx.tcx, def_id),
                     name,
                     matchers
                         .iter()
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 16aaa9c..d4d0a8c 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -129,7 +129,7 @@
         .predicates
         .iter()
         .filter_map(|(pred, _)| {
-            if let ty::PredicateAtom::Trait(pred, _) = pred.skip_binders() {
+            if let ty::PredicateKind::Trait(pred, _) = pred.kind().skip_binder() {
                 if pred.trait_ref.self_ty() == self_ty { Some(pred.def_id()) } else { None }
             } else {
                 None
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 0f2baa9..666b11b 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -82,7 +82,7 @@
     crate source: Span,
     /// Not everything has a name. E.g., impls
     crate name: Option<Symbol>,
-    crate attrs: Attributes,
+    crate attrs: Box<Attributes>,
     crate visibility: Visibility,
     crate kind: Box<ItemKind>,
     crate def_id: DefId,
@@ -90,7 +90,7 @@
 
 // `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-rustc_data_structures::static_assert_size!(Item, 136);
+rustc_data_structures::static_assert_size!(Item, 48);
 
 impl fmt::Debug for Item {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -122,7 +122,7 @@
 
     /// Finds the `doc` attribute as a NameValue and returns the corresponding
     /// value found.
-    crate fn doc_value(&self) -> Option<&str> {
+    crate fn doc_value(&self) -> Option<String> {
         self.attrs.doc_value()
     }
 
@@ -159,7 +159,7 @@
             kind: box kind,
             name,
             source: source.clean(cx),
-            attrs: cx.tcx.get_attrs(def_id).clean(cx),
+            attrs: box cx.tcx.get_attrs(def_id).clean(cx),
             visibility: cx.tcx.visibility(def_id).clean(cx),
         }
     }
@@ -175,11 +175,11 @@
     }
 
     crate fn is_crate(&self) -> bool {
-        match *self.kind {
+        matches!(
+            *self.kind,
             StrippedItem(box ModuleItem(Module { is_crate: true, .. }))
-            | ModuleItem(Module { is_crate: true, .. }) => true,
-            _ => false,
-        }
+                | ModuleItem(Module { is_crate: true, .. })
+        )
     }
     crate fn is_mod(&self) -> bool {
         self.type_() == ItemType::Module
@@ -237,9 +237,7 @@
         match *self.kind {
             StructItem(ref _struct) => Some(_struct.fields_stripped),
             UnionItem(ref union) => Some(union.fields_stripped),
-            VariantItem(Variant { kind: VariantKind::Struct(ref vstruct) }) => {
-                Some(vstruct.fields_stripped)
-            }
+            VariantItem(Variant::Struct(ref vstruct)) => Some(vstruct.fields_stripped),
             _ => None,
         }
     }
@@ -293,7 +291,9 @@
         }
     }
 
-    /// See comments on next_def_id
+    /// See the documentation for [`next_def_id()`].
+    ///
+    /// [`next_def_id()`]: DocContext::next_def_id()
     crate fn is_fake(&self) -> bool {
         MAX_DEF_ID.with(|m| {
             m.borrow().get(&self.def_id.krate).map(|id| self.def_id >= *id).unwrap_or(false)
@@ -334,6 +334,10 @@
     ProcMacroItem(ProcMacro),
     PrimitiveItem(PrimitiveType),
     AssocConstItem(Type, Option<String>),
+    /// An associated item in a trait or trait impl.
+    ///
+    /// The bounds may be non-empty if there is a `where` clause.
+    /// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
     AssocTypeItem(Vec<GenericBound>, Option<Type>),
     /// An item that has been stripped by a rustdoc pass
     StrippedItem(Box<ItemKind>),
@@ -347,7 +351,7 @@
         match self {
             StructItem(s) => s.fields.iter(),
             UnionItem(u) => u.fields.iter(),
-            VariantItem(Variant { kind: VariantKind::Struct(v) }) => v.fields.iter(),
+            VariantItem(Variant::Struct(v)) => v.fields.iter(),
             EnumItem(e) => e.variants.iter(),
             TraitItem(t) => t.items.iter(),
             ImplItem(i) => i.items.iter(),
@@ -378,10 +382,7 @@
     }
 
     crate fn is_type_alias(&self) -> bool {
-        match *self {
-            ItemKind::TypedefItem(_, _) | ItemKind::AssocTypeItem(_, _) => true,
-            _ => false,
-        }
+        matches!(self, ItemKind::TypedefItem(..) | ItemKind::AssocTypeItem(..))
     }
 }
 
@@ -439,12 +440,22 @@
 crate trait NestedAttributesExt {
     /// Returns `true` if the attribute list contains a specific `Word`
     fn has_word(self, word: Symbol) -> bool;
+    fn get_word_attr(self, word: Symbol) -> (Option<ast::NestedMetaItem>, bool);
 }
 
-impl<I: IntoIterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
+impl<I: Iterator<Item = ast::NestedMetaItem> + IntoIterator<Item = ast::NestedMetaItem>>
+    NestedAttributesExt for I
+{
     fn has_word(self, word: Symbol) -> bool {
         self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
     }
+
+    fn get_word_attr(mut self, word: Symbol) -> (Option<ast::NestedMetaItem>, bool) {
+        match self.find(|attr| attr.is_word() && attr.has_name(word)) {
+            Some(a) => (Some(a), true),
+            None => (None, false),
+        }
+    }
 }
 
 /// A portion of documentation, extracted from a `#[doc]` attribute.
@@ -464,11 +475,13 @@
     /// This allows distinguishing between the original documentation and a pub re-export.
     /// If it is `None`, the item was not re-exported.
     crate parent_module: Option<DefId>,
-    crate doc: String,
+    crate doc: Symbol,
     crate kind: DocFragmentKind,
+    crate need_backline: bool,
+    crate indent: usize,
 }
 
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
 crate enum DocFragmentKind {
     /// A doc fragment created from a `///` or `//!` doc comment.
     SugaredDoc,
@@ -476,7 +489,33 @@
     RawDoc,
     /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
     /// given filename and the file contents.
-    Include { filename: String },
+    Include { filename: Symbol },
+}
+
+// The goal of this function is to apply the `DocFragment` transformations that are required when
+// transforming into the final markdown. So the transformations in here are:
+//
+// * Applying the computed indent to each lines in each doc fragment (a `DocFragment` can contain
+//   multiple lines in case of `#[doc = ""]`).
+// * Adding backlines between `DocFragment`s and adding an extra one if required (stored in the
+//   `need_backline` field).
+fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
+    let s = frag.doc.as_str();
+    let mut iter = s.lines().peekable();
+    while let Some(line) = iter.next() {
+        if line.chars().any(|c| !c.is_whitespace()) {
+            assert!(line.len() >= frag.indent);
+            out.push_str(&line[frag.indent..]);
+        } else {
+            out.push_str(line);
+        }
+        if iter.peek().is_some() {
+            out.push('\n');
+        }
+    }
+    if frag.need_backline {
+        out.push('\n');
+    }
 }
 
 impl<'a> FromIterator<&'a DocFragment> for String {
@@ -484,11 +523,18 @@
     where
         T: IntoIterator<Item = &'a DocFragment>,
     {
+        let mut prev_kind: Option<DocFragmentKind> = None;
         iter.into_iter().fold(String::new(), |mut acc, frag| {
-            if !acc.is_empty() {
+            if !acc.is_empty()
+                && prev_kind
+                    .take()
+                    .map(|p| matches!(p, DocFragmentKind::Include { .. }) && p != frag.kind)
+                    .unwrap_or(false)
+            {
                 acc.push('\n');
             }
-            acc.push_str(&frag.doc);
+            add_doc_fragment(&mut acc, &frag);
+            prev_kind = Some(frag.kind);
             acc
         })
     }
@@ -560,7 +606,7 @@
     /// Reads a `MetaItem` from within an attribute, looks for whether it is a
     /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
     /// its expansion.
-    crate fn extract_include(mi: &ast::MetaItem) -> Option<(String, String)> {
+    crate fn extract_include(mi: &ast::MetaItem) -> Option<(Symbol, Symbol)> {
         mi.meta_item_list().and_then(|list| {
             for meta in list {
                 if meta.has_name(sym::include) {
@@ -568,17 +614,17 @@
                     // `#[doc(include(file="filename", contents="file contents")]` so we need to
                     // look for that instead
                     return meta.meta_item_list().and_then(|list| {
-                        let mut filename: Option<String> = None;
-                        let mut contents: Option<String> = None;
+                        let mut filename: Option<Symbol> = None;
+                        let mut contents: Option<Symbol> = None;
 
                         for it in list {
                             if it.has_name(sym::file) {
                                 if let Some(name) = it.value_str() {
-                                    filename = Some(name.to_string());
+                                    filename = Some(name);
                                 }
                             } else if it.has_name(sym::contents) {
                                 if let Some(docs) = it.value_str() {
-                                    contents = Some(docs.to_string());
+                                    contents = Some(docs);
                                 }
                             }
                         }
@@ -617,15 +663,30 @@
         attrs: &[ast::Attribute],
         additional_attrs: Option<(&[ast::Attribute], DefId)>,
     ) -> Attributes {
-        let mut doc_strings = vec![];
+        let mut doc_strings: Vec<DocFragment> = vec![];
         let mut sp = None;
         let mut cfg = Cfg::True;
         let mut doc_line = 0;
 
+        fn update_need_backline(doc_strings: &mut Vec<DocFragment>, frag: &DocFragment) {
+            if let Some(prev) = doc_strings.last_mut() {
+                if matches!(prev.kind, DocFragmentKind::Include { .. })
+                    || prev.kind != frag.kind
+                    || prev.parent_module != frag.parent_module
+                {
+                    // add a newline for extra padding between segments
+                    prev.need_backline = prev.kind == DocFragmentKind::SugaredDoc
+                        || prev.kind == DocFragmentKind::RawDoc
+                } else {
+                    prev.need_backline = true;
+                }
+            }
+        }
+
         let clean_attr = |(attr, parent_module): (&ast::Attribute, _)| {
             if let Some(value) = attr.doc_str() {
                 trace!("got doc_str={:?}", value);
-                let value = beautify_doc_string(value).to_string();
+                let value = beautify_doc_string(value);
                 let kind = if attr.is_doc_comment() {
                     DocFragmentKind::SugaredDoc
                 } else {
@@ -633,14 +694,20 @@
                 };
 
                 let line = doc_line;
-                doc_line += value.lines().count();
-                doc_strings.push(DocFragment {
+                doc_line += value.as_str().lines().count();
+                let frag = DocFragment {
                     line,
                     span: attr.span,
                     doc: value,
                     kind,
                     parent_module,
-                });
+                    need_backline: false,
+                    indent: 0,
+                };
+
+                update_need_backline(&mut doc_strings, &frag);
+
+                doc_strings.push(frag);
 
                 if sp.is_none() {
                     sp = Some(attr.span);
@@ -658,14 +725,18 @@
                         } else if let Some((filename, contents)) = Attributes::extract_include(&mi)
                         {
                             let line = doc_line;
-                            doc_line += contents.lines().count();
-                            doc_strings.push(DocFragment {
+                            doc_line += contents.as_str().lines().count();
+                            let frag = DocFragment {
                                 line,
                                 span: attr.span,
                                 doc: contents,
                                 kind: DocFragmentKind::Include { filename },
-                                parent_module: parent_module,
-                            });
+                                parent_module,
+                                need_backline: false,
+                                indent: 0,
+                            };
+                            update_need_backline(&mut doc_strings, &frag);
+                            doc_strings.push(frag);
                         }
                     }
                 }
@@ -716,14 +787,41 @@
 
     /// Finds the `doc` attribute as a NameValue and returns the corresponding
     /// value found.
-    crate fn doc_value(&self) -> Option<&str> {
-        self.doc_strings.first().map(|s| s.doc.as_str())
+    crate fn doc_value(&self) -> Option<String> {
+        let mut iter = self.doc_strings.iter();
+
+        let ori = iter.next()?;
+        let mut out = String::new();
+        add_doc_fragment(&mut out, &ori);
+        while let Some(new_frag) = iter.next() {
+            if matches!(ori.kind, DocFragmentKind::Include { .. })
+                || new_frag.kind != ori.kind
+                || new_frag.parent_module != ori.parent_module
+            {
+                break;
+            }
+            add_doc_fragment(&mut out, &new_frag);
+        }
+        if out.is_empty() { None } else { Some(out) }
+    }
+
+    /// Return the doc-comments on this item, grouped by the module they came from.
+    ///
+    /// The module can be different if this is a re-export with added documentation.
+    crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap<Option<DefId>, String> {
+        let mut ret = FxHashMap::default();
+
+        for new_frag in self.doc_strings.iter() {
+            let out = ret.entry(new_frag.parent_module).or_default();
+            add_doc_fragment(out, &new_frag);
+        }
+        ret
     }
 
     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
     /// with newlines.
     crate fn collapsed_doc_value(&self) -> Option<String> {
-        if !self.doc_strings.is_empty() { Some(self.doc_strings.iter().collect()) } else { None }
+        if self.doc_strings.is_empty() { None } else { Some(self.doc_strings.iter().collect()) }
     }
 
     /// Gets links as a vector
@@ -740,7 +838,7 @@
                     Some(did) => {
                         if let Some((mut href, ..)) = href(did) {
                             if let Some(ref fragment) = *fragment {
-                                href.push_str("#");
+                                href.push('#');
                                 href.push_str(fragment);
                             }
                             Some(RenderedLink {
@@ -935,10 +1033,7 @@
 
 impl GenericParamDefKind {
     crate fn is_type(&self) -> bool {
-        match *self {
-            GenericParamDefKind::Type { .. } => true,
-            _ => false,
-        }
+        matches!(self, GenericParamDefKind::Type { .. })
     }
 
     // FIXME(eddyb) this either returns the default of a type parameter, or the
@@ -1131,6 +1226,7 @@
     BareFunction(Box<BareFunctionDecl>),
     Tuple(Vec<Type>),
     Slice(Box<Type>),
+    /// The `String` field is about the size or the constant representing the array's length.
     Array(Box<Type>, String),
     Never,
     RawPointer(Mutability, Box<Type>),
@@ -1282,15 +1378,12 @@
     }
 
     crate fn is_full_generic(&self) -> bool {
-        match *self {
-            Type::Generic(_) => true,
-            _ => false,
-        }
+        matches!(self, Type::Generic(_))
     }
 
     crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> {
         let (self_, trait_, name) = match self {
-            QPath { ref self_type, ref trait_, name } => (self_type, trait_, name),
+            QPath { self_type, trait_, name } => (self_type, trait_, name),
             _ => return None,
         };
         let trait_did = match **trait_ {
@@ -1624,12 +1717,7 @@
 }
 
 #[derive(Clone, Debug)]
-crate struct Variant {
-    crate kind: VariantKind,
-}
-
-#[derive(Clone, Debug)]
-crate enum VariantKind {
+crate enum Variant {
     CLike,
     Tuple(Vec<Type>),
     Struct(VariantStruct),
@@ -1718,7 +1806,12 @@
 crate struct Typedef {
     crate type_: Type,
     crate generics: Generics,
-    // Type of target item.
+    /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
+    /// alias instead of the final type. This will always have the final type, regardless of whether
+    /// `type_` came from HIR or from metadata.
+    ///
+    /// If `item_type.is_none()`, `type_` is guarenteed to come from metadata (and therefore hold the
+    /// final type).
     crate item_type: Option<Type>,
 }
 
@@ -1760,12 +1853,6 @@
     crate is_literal: bool,
 }
 
-#[derive(Clone, PartialEq, Debug)]
-crate enum ImplPolarity {
-    Positive,
-    Negative,
-}
-
 #[derive(Clone, Debug)]
 crate struct Impl {
     crate unsafety: hir::Unsafety,
@@ -1774,7 +1861,7 @@
     crate trait_: Option<Type>,
     crate for_: Type,
     crate items: Vec<Item>,
-    crate polarity: Option<ImplPolarity>,
+    crate negative_polarity: bool,
     crate synthetic: bool,
     crate blanket_impl: Option<Type>,
 }
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index a6c090c..0f5495c 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -14,7 +14,7 @@
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
-use rustc_middle::ty::{self, DefIdTree, Ty};
+use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
 use rustc_span::symbol::{kw, sym, Symbol};
 use std::mem;
 
@@ -179,12 +179,12 @@
     if arg.is_full_generic() {
         let arg_s = Symbol::intern(&arg.print().to_string());
         if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g {
-            &WherePredicate::BoundPredicate { ref ty, .. } => ty.def_id() == arg.def_id(),
+            WherePredicate::BoundPredicate { ty, .. } => ty.def_id() == arg.def_id(),
             _ => false,
         }) {
             let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
             for bound in bounds.iter() {
-                if let GenericBound::TraitBound(ref poly_trait, _) = *bound {
+                if let GenericBound::TraitBound(poly_trait, _) = bound {
                     for x in poly_trait.generic_params.iter() {
                         if !x.is_type() {
                             continue;
@@ -314,25 +314,6 @@
     Path { global: path.global, res: path.res, segments }
 }
 
-crate fn qpath_to_string(p: &hir::QPath<'_>) -> String {
-    let segments = match *p {
-        hir::QPath::Resolved(_, ref path) => &path.segments,
-        hir::QPath::TypeRelative(_, ref segment) => return segment.ident.to_string(),
-        hir::QPath::LangItem(lang_item, ..) => return lang_item.name().to_string(),
-    };
-
-    let mut s = String::new();
-    for (i, seg) in segments.iter().enumerate() {
-        if i > 0 {
-            s.push_str("::");
-        }
-        if seg.ident.name != kw::PathRoot {
-            s.push_str(&seg.ident.as_str());
-        }
-    }
-    s
-}
-
 crate fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut Vec<Item>) {
     let tcx = cx.tcx;
 
@@ -376,57 +357,6 @@
     }
 }
 
-crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
-    use rustc_hir::*;
-    debug!("trying to get a name from pattern: {:?}", p);
-
-    Symbol::intern(&match p.kind {
-        PatKind::Wild => return kw::Underscore,
-        PatKind::Binding(_, _, ident, _) => return ident.name,
-        PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
-        PatKind::Struct(ref name, ref fields, etc) => format!(
-            "{} {{ {}{} }}",
-            qpath_to_string(name),
-            fields
-                .iter()
-                .map(|fp| format!("{}: {}", fp.ident, name_from_pat(&fp.pat)))
-                .collect::<Vec<String>>()
-                .join(", "),
-            if etc { ", .." } else { "" }
-        ),
-        PatKind::Or(ref pats) => pats
-            .iter()
-            .map(|p| name_from_pat(&**p).to_string())
-            .collect::<Vec<String>>()
-            .join(" | "),
-        PatKind::Tuple(ref elts, _) => format!(
-            "({})",
-            elts.iter()
-                .map(|p| name_from_pat(&**p).to_string())
-                .collect::<Vec<String>>()
-                .join(", ")
-        ),
-        PatKind::Box(ref p) => return name_from_pat(&**p),
-        PatKind::Ref(ref p, _) => return name_from_pat(&**p),
-        PatKind::Lit(..) => {
-            warn!(
-                "tried to get argument name from PatKind::Lit, which is silly in function arguments"
-            );
-            return Symbol::intern("()");
-        }
-        PatKind::Range(..) => panic!(
-            "tried to get argument name from PatKind::Range, \
-             which is not allowed in function arguments"
-        ),
-        PatKind::Slice(ref begin, ref mid, ref end) => {
-            let begin = begin.iter().map(|p| name_from_pat(&**p).to_string());
-            let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
-            let end = end.iter().map(|p| name_from_pat(&**p).to_string());
-            format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
-        }
-    })
-}
-
 crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
     match n.val {
         ty::ConstKind::Unevaluated(def, _, promoted) => {
@@ -623,3 +553,24 @@
     *cx.impl_trait_bounds.borrow_mut() = old_bounds;
     r
 }
+
+/// Find the nearest parent module of a [`DefId`].
+///
+/// **Panics if the item it belongs to [is fake][Item::is_fake].**
+crate fn find_nearest_parent_module(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
+    if def_id.is_top_level_module() {
+        // The crate root has no parent. Use it as the root instead.
+        Some(def_id)
+    } else {
+        let mut current = def_id;
+        // The immediate parent might not always be a module.
+        // Find the first parent which is.
+        while let Some(parent) = tcx.parent(current) {
+            if tcx.def_kind(parent) == DefKind::Mod {
+                return Some(parent);
+            }
+            current = parent;
+        }
+        None
+    }
+}
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 2d58614..e43ea96 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -37,10 +37,7 @@
 
 impl OutputFormat {
     crate fn is_json(&self) -> bool {
-        match self {
-            OutputFormat::Json => true,
-            _ => false,
-        }
+        matches!(self, OutputFormat::Json)
     }
 }
 
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 7e85342..4db5a0b 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -120,14 +120,20 @@
         r
     }
 
-    // This is an ugly hack, but it's the simplest way to handle synthetic impls without greatly
-    // refactoring either librustdoc or librustc_middle. In particular, allowing new DefIds to be
-    // registered after the AST is constructed would require storing the defid mapping in a
-    // RefCell, decreasing the performance for normal compilation for very little gain.
-    //
-    // Instead, we construct 'fake' def ids, which start immediately after the last DefId.
-    // In the Debug impl for clean::Item, we explicitly check for fake
-    // def ids, as we'll end up with a panic if we use the DefId Debug impl for fake DefIds
+    /// Create a new "fake" [`DefId`].
+    ///
+    /// This is an ugly hack, but it's the simplest way to handle synthetic impls without greatly
+    /// refactoring either rustdoc or [`rustc_middle`]. In particular, allowing new [`DefId`]s
+    /// to be registered after the AST is constructed would require storing the [`DefId`] mapping
+    /// in a [`RefCell`], decreasing the performance for normal compilation for very little gain.
+    ///
+    /// Instead, we construct "fake" [`DefId`]s, which start immediately after the last `DefId`.
+    /// In the [`Debug`] impl for [`clean::Item`], we explicitly check for fake `DefId`s,
+    /// as we'll end up with a panic if we use the `DefId` `Debug` impl for fake `DefId`s.
+    ///
+    /// [`RefCell`]: std::cell::RefCell
+    /// [`Debug`]: std::fmt::Debug
+    /// [`clean::Item`]: crate::clean::types::Item
     crate fn next_def_id(&self, crate_num: CrateNum) -> DefId {
         let start_def_id = {
             let num_def_ids = if crate_num == LOCAL_CRATE {
@@ -428,16 +434,15 @@
         sess.time("load_extern_crates", || {
             for extern_name in &extern_names {
                 debug!("loading extern crate {}", extern_name);
-                resolver
+                if let Err(()) = resolver
                     .resolve_str_path_error(
                         DUMMY_SP,
                         extern_name,
                         TypeNS,
                         LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(),
-                    )
-                    .unwrap_or_else(|()| {
-                        panic!("Unable to resolve external crate {}", extern_name)
-                    });
+                  ) {
+                    warn!("unable to resolve external crate {} (do you have an unused `--extern` crate?)", extern_name)
+                  }
             }
         });
     });
@@ -525,7 +530,7 @@
     let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));
 
     if let Some(ref m) = krate.module {
-        if let None | Some("") = m.doc_value() {
+        if m.doc_value().map(|d| d.is_empty()).unwrap_or(true) {
             let help = "The following guide may be of use:\n\
                 https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html";
             tcx.struct_lint_node(
@@ -623,6 +628,9 @@
 
     ctxt.sess().abort_if_errors();
 
+    // The main crate doc comments are always collapsed.
+    krate.collapsed = true;
+
     (krate, ctxt.renderinfo.into_inner(), ctxt.render_options)
 }
 
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 02dd42c..3de97f2 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -500,6 +500,12 @@
                 }
             }
 
+            // Reset errors so that they won't be reported as compiler bugs when dropping the
+            // handler. Any errors in the tests will be reported when the test file is compiled,
+            // Note that we still need to cancel the errors above otherwise `DiagnosticBuilder`
+            // will panic on drop.
+            sess.span_diagnostic.reset_err_count();
+
             (found_main, found_extern_crate, found_macro)
         })
     });
@@ -636,15 +642,15 @@
         match state {
             PartitionState::Attrs => {
                 before.push_str(line);
-                before.push_str("\n");
+                before.push('\n');
             }
             PartitionState::Crates => {
                 crates.push_str(line);
-                crates.push_str("\n");
+                crates.push('\n');
             }
             PartitionState::Other => {
                 after.push_str(line);
-                after.push_str("\n");
+                after.push('\n');
             }
         }
     }
@@ -987,7 +993,6 @@
             self.collector.names.push(name);
         }
 
-        attrs.collapse_doc_comments();
         attrs.unindent_doc_comments();
         // The collapse-docs pass won't combine sugared/raw doc attributes, or included files with
         // anything else, this will combine them for us.
@@ -1027,8 +1032,8 @@
     }
 
     fn visit_item(&mut self, item: &'hir hir::Item<'_>) {
-        let name = if let hir::ItemKind::Impl { ref self_ty, .. } = item.kind {
-            rustc_hir_pretty::id_to_string(&self.map, self_ty.hir_id)
+        let name = if let hir::ItemKind::Impl(impl_) = &item.kind {
+            rustc_hir_pretty::id_to_string(&self.map, impl_.self_ty.hir_id)
         } else {
             item.ident.to_string()
         };
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index bc9f1cf..f90623c 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -2,7 +2,6 @@
 //! manner (and with prettier names) before cleaning.
 crate use self::StructType::*;
 
-use rustc_ast as ast;
 use rustc_span::{self, Span, Symbol};
 
 use rustc_hir as hir;
@@ -11,7 +10,6 @@
     crate name: Option<Symbol>,
     crate where_outer: Span,
     crate where_inner: Span,
-    crate imports: Vec<Import<'hir>>,
     crate mods: Vec<Module<'hir>>,
     crate id: hir::HirId,
     // (item, renamed)
@@ -28,7 +26,6 @@
             id: hir::CRATE_HIR_ID,
             where_outer: rustc_span::DUMMY_SP,
             where_inner: rustc_span::DUMMY_SP,
-            imports: Vec::new(),
             mods: Vec::new(),
             items: Vec::new(),
             foreigns: Vec::new(),
@@ -48,23 +45,6 @@
     Unit,
 }
 
-crate struct Variant<'hir> {
-    crate name: Symbol,
-    crate id: hir::HirId,
-    crate def: &'hir hir::VariantData<'hir>,
-}
-
-#[derive(Debug)]
-crate struct Import<'hir> {
-    crate name: Symbol,
-    crate id: hir::HirId,
-    crate vis: &'hir hir::Visibility<'hir>,
-    crate attrs: &'hir [ast::Attribute],
-    crate path: &'hir hir::Path<'hir>,
-    crate glob: bool,
-    crate span: Span,
-}
-
 crate fn struct_type_from_def(vdata: &hir::VariantData<'_>) -> StructType {
     match *vdata {
         hir::VariantData::Struct(..) => Plain,
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index c39cc3c..b2773a2 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -55,13 +55,13 @@
             }
             VariantItem(i) => {
                 let i2 = i.clone(); // this clone is small
-                match i.kind {
-                    VariantKind::Struct(mut j) => {
+                match i {
+                    Variant::Struct(mut j) => {
                         let num_fields = j.fields.len();
                         j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
                         j.fields_stripped |= num_fields != j.fields.len()
                             || j.fields.iter().any(|f| f.is_stripped());
-                        VariantItem(Variant { kind: VariantKind::Struct(j), ..i2 })
+                        VariantItem(Variant::Struct(j))
                     }
                     _ => VariantItem(i2),
                 }
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 899d61d..c1f8b12 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -316,7 +316,7 @@
                             path: path.join("::"),
                             desc: item
                                 .doc_value()
-                                .map_or_else(|| String::new(), short_markdown_summary),
+                                .map_or_else(String::new, |x| short_markdown_summary(&x.as_str())),
                             parent,
                             parent_idx: None,
                             search_type: get_index_search_type(&item),
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 7b0b219..5c2adca 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -15,7 +15,7 @@
 use rustc_span::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc_target::spec::abi::Abi;
 
-use crate::clean::{self, PrimitiveType};
+use crate::clean::{self, utils::find_nearest_parent_module, PrimitiveType};
 use crate::formats::cache::cache;
 use crate::formats::item_type::ItemType;
 use crate::html::escape::Escape;
@@ -245,7 +245,7 @@
             }
 
             match pred {
-                &clean::WherePredicate::BoundPredicate { ref ty, ref bounds } => {
+                clean::WherePredicate::BoundPredicate { ty, bounds } => {
                     let bounds = bounds;
                     if f.alternate() {
                         clause.push_str(&format!(
@@ -261,7 +261,7 @@
                         ));
                     }
                 }
-                &clean::WherePredicate::RegionPredicate { ref lifetime, ref bounds } => {
+                clean::WherePredicate::RegionPredicate { lifetime, bounds } => {
                     clause.push_str(&format!(
                         "{}: {}",
                         lifetime.print(),
@@ -272,7 +272,7 @@
                             .join(" + ")
                     ));
                 }
-                &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => {
+                clean::WherePredicate::EqPredicate { lhs, rhs } => {
                     if f.alternate() {
                         clause.push_str(&format!("{:#} == {:#}", lhs.print(), rhs.print()));
                     } else {
@@ -376,8 +376,8 @@
 impl clean::GenericArgs {
     fn print(&self) -> impl fmt::Display + '_ {
         display_fn(move |f| {
-            match *self {
-                clean::GenericArgs::AngleBracketed { ref args, ref bindings } => {
+            match self {
+                clean::GenericArgs::AngleBracketed { args, bindings } => {
                     if !args.is_empty() || !bindings.is_empty() {
                         if f.alternate() {
                             f.write_str("<")?;
@@ -414,7 +414,7 @@
                         }
                     }
                 }
-                clean::GenericArgs::Parenthesized { ref inputs, ref output } => {
+                clean::GenericArgs::Parenthesized { inputs, output } => {
                     f.write_str("(")?;
                     let mut comma = false;
                     for ty in inputs {
@@ -501,7 +501,7 @@
     };
     for component in &fqp[..fqp.len() - 1] {
         url.push_str(component);
-        url.push_str("/");
+        url.push('/');
     }
     match shortty {
         ItemType::Module => {
@@ -510,7 +510,7 @@
         }
         _ => {
             url.push_str(shortty.as_str());
-            url.push_str(".");
+            url.push('.');
             url.push_str(fqp.last().unwrap());
             url.push_str(".html");
         }
@@ -870,7 +870,7 @@
             }
 
             if let Some(ref ty) = self.trait_ {
-                if self.polarity == Some(clean::ImplPolarity::Negative) {
+                if self.negative_polarity {
                     write!(f, "!")?;
                 }
 
@@ -1021,7 +1021,7 @@
                 } else {
                     if i > 0 {
                         args.push_str(" <br>");
-                        args_plain.push_str(" ");
+                        args_plain.push(' ');
                     }
                     if !input.name.is_empty() {
                         args.push_str(&format!("{}: ", input.name));
@@ -1085,32 +1085,54 @@
 }
 
 impl clean::Visibility {
-    crate fn print_with_space<'tcx>(self, tcx: TyCtxt<'tcx>) -> impl fmt::Display + 'tcx {
+    crate fn print_with_space<'tcx>(
+        self,
+        tcx: TyCtxt<'tcx>,
+        item_did: DefId,
+    ) -> impl fmt::Display + 'tcx {
         use rustc_span::symbol::kw;
 
         display_fn(move |f| match self {
             clean::Public => f.write_str("pub "),
             clean::Inherited => Ok(()),
-            clean::Visibility::Restricted(did) if did.index == CRATE_DEF_INDEX => {
-                write!(f, "pub(crate) ")
-            }
-            clean::Visibility::Restricted(did) => {
-                f.write_str("pub(")?;
-                let path = tcx.def_path(did);
-                debug!("path={:?}", path);
-                let first_name =
-                    path.data[0].data.get_opt_name().expect("modules are always named");
-                if path.data.len() != 1 || (first_name != kw::SelfLower && first_name != kw::Super)
+
+            clean::Visibility::Restricted(vis_did) => {
+                // FIXME(camelid): This may not work correctly if `item_did` is a module.
+                //                 However, rustdoc currently never displays a module's
+                //                 visibility, so it shouldn't matter.
+                let parent_module = find_nearest_parent_module(tcx, item_did);
+
+                if vis_did.index == CRATE_DEF_INDEX {
+                    write!(f, "pub(crate) ")
+                } else if parent_module == Some(vis_did) {
+                    // `pub(in foo)` where `foo` is the parent module
+                    // is the same as no visibility modifier
+                    Ok(())
+                } else if parent_module
+                    .map(|parent| find_nearest_parent_module(tcx, parent))
+                    .flatten()
+                    == Some(vis_did)
                 {
-                    f.write_str("in ")?;
+                    write!(f, "pub(super) ")
+                } else {
+                    f.write_str("pub(")?;
+                    let path = tcx.def_path(vis_did);
+                    debug!("path={:?}", path);
+                    let first_name =
+                        path.data[0].data.get_opt_name().expect("modules are always named");
+                    if path.data.len() != 1
+                        || (first_name != kw::SelfLower && first_name != kw::Super)
+                    {
+                        f.write_str("in ")?;
+                    }
+                    // modified from `resolved_path()` to work with `DefPathData`
+                    let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
+                    for seg in &path.data[..path.data.len() - 1] {
+                        write!(f, "{}::", seg.data.get_opt_name().unwrap())?;
+                    }
+                    let path = anchor(vis_did, &last_name.as_str()).to_string();
+                    write!(f, "{}) ", path)
                 }
-                // modified from `resolved_path()` to work with `DefPathData`
-                let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
-                for seg in &path.data[..path.data.len() - 1] {
-                    write!(f, "{}::", seg.data.get_opt_name().unwrap())?;
-                }
-                let path = anchor(did, &last_name.as_str()).to_string();
-                write!(f, "{}) ", path)
             }
         })
     }
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 20cf489..3363905 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -25,6 +25,7 @@
 use rustc_span::edition::Edition;
 use rustc_span::Span;
 use std::borrow::Cow;
+use std::cell::RefCell;
 use std::collections::VecDeque;
 use std::default::Default;
 use std::fmt::Write;
@@ -36,7 +37,9 @@
 use crate::html::highlight;
 use crate::html::toc::TocBuilder;
 
-use pulldown_cmark::{html, BrokenLink, CodeBlockKind, CowStr, Event, Options, Parser, Tag};
+use pulldown_cmark::{
+    html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag,
+};
 
 #[cfg(test)]
 mod tests;
@@ -326,8 +329,6 @@
     type Item = Event<'a>;
 
     fn next(&mut self) -> Option<Self::Item> {
-        use pulldown_cmark::LinkType;
-
         let mut event = self.inner.next();
 
         // Replace intra-doc links and remove disambiguators from shortcut links (`[fn@f]`).
@@ -414,11 +415,13 @@
     }
 }
 
+type SpannedEvent<'a> = (Event<'a>, Range<usize>);
+
 /// Make headings links with anchor IDs and build up TOC.
 struct HeadingLinks<'a, 'b, 'ids, I> {
     inner: I,
     toc: Option<&'b mut TocBuilder>,
-    buf: VecDeque<Event<'a>>,
+    buf: VecDeque<SpannedEvent<'a>>,
     id_map: &'ids mut IdMap,
 }
 
@@ -428,8 +431,10 @@
     }
 }
 
-impl<'a, 'b, 'ids, I: Iterator<Item = Event<'a>>> Iterator for HeadingLinks<'a, 'b, 'ids, I> {
-    type Item = Event<'a>;
+impl<'a, 'b, 'ids, I: Iterator<Item = SpannedEvent<'a>>> Iterator
+    for HeadingLinks<'a, 'b, 'ids, I>
+{
+    type Item = SpannedEvent<'a>;
 
     fn next(&mut self) -> Option<Self::Item> {
         if let Some(e) = self.buf.pop_front() {
@@ -437,31 +442,29 @@
         }
 
         let event = self.inner.next();
-        if let Some(Event::Start(Tag::Heading(level))) = event {
+        if let Some((Event::Start(Tag::Heading(level)), _)) = event {
             let mut id = String::new();
             for event in &mut self.inner {
-                match &event {
+                match &event.0 {
                     Event::End(Tag::Heading(..)) => break,
+                    Event::Start(Tag::Link(_, _, _)) | Event::End(Tag::Link(..)) => {}
                     Event::Text(text) | Event::Code(text) => {
                         id.extend(text.chars().filter_map(slugify));
+                        self.buf.push_back(event);
                     }
-                    _ => {}
-                }
-                match event {
-                    Event::Start(Tag::Link(_, _, _)) | Event::End(Tag::Link(..)) => {}
-                    event => self.buf.push_back(event),
+                    _ => self.buf.push_back(event),
                 }
             }
             let id = self.id_map.derive(id);
 
             if let Some(ref mut builder) = self.toc {
                 let mut html_header = String::new();
-                html::push_html(&mut html_header, self.buf.iter().cloned());
+                html::push_html(&mut html_header, self.buf.iter().map(|(ev, _)| ev.clone()));
                 let sec = builder.push(level as u32, html_header, id.clone());
-                self.buf.push_front(Event::Html(format!("{} ", sec).into()));
+                self.buf.push_front((Event::Html(format!("{} ", sec).into()), 0..0));
             }
 
-            self.buf.push_back(Event::Html(format!("</a></h{}>", level).into()));
+            self.buf.push_back((Event::Html(format!("</a></h{}>", level).into()), 0..0));
 
             let start_tags = format!(
                 "<h{level} id=\"{id}\" class=\"section-header\">\
@@ -469,7 +472,7 @@
                 id = id,
                 level = level
             );
-            return Some(Event::Html(start_tags.into()));
+            return Some((Event::Html(start_tags.into()), 0..0));
         }
         event
     }
@@ -489,15 +492,10 @@
 }
 
 fn check_if_allowed_tag(t: &Tag<'_>) -> bool {
-    match *t {
-        Tag::Paragraph
-        | Tag::Item
-        | Tag::Emphasis
-        | Tag::Strong
-        | Tag::Link(..)
-        | Tag::BlockQuote => true,
-        _ => false,
-    }
+    matches!(
+        t,
+        Tag::Paragraph | Tag::Item | Tag::Emphasis | Tag::Strong | Tag::Link(..) | Tag::BlockQuote
+    )
 }
 
 impl<'a, I: Iterator<Item = Event<'a>>> Iterator for SummaryLine<'a, I> {
@@ -560,23 +558,23 @@
     }
 }
 
-impl<'a, I: Iterator<Item = Event<'a>>> Iterator for Footnotes<'a, I> {
-    type Item = Event<'a>;
+impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> {
+    type Item = SpannedEvent<'a>;
 
     fn next(&mut self) -> Option<Self::Item> {
         loop {
             match self.inner.next() {
-                Some(Event::FootnoteReference(ref reference)) => {
+                Some((Event::FootnoteReference(ref reference), range)) => {
                     let entry = self.get_entry(&reference);
                     let reference = format!(
                         "<sup id=\"fnref{0}\"><a href=\"#fn{0}\">{0}</a></sup>",
                         (*entry).1
                     );
-                    return Some(Event::Html(reference.into()));
+                    return Some((Event::Html(reference.into()), range));
                 }
-                Some(Event::Start(Tag::FootnoteDefinition(def))) => {
+                Some((Event::Start(Tag::FootnoteDefinition(def)), _)) => {
                     let mut content = Vec::new();
-                    for event in &mut self.inner {
+                    for (event, _) in &mut self.inner {
                         if let Event::End(Tag::FootnoteDefinition(..)) = event {
                             break;
                         }
@@ -607,7 +605,7 @@
                             ret.push_str("</li>");
                         }
                         ret.push_str("</ol></div>");
-                        return Some(Event::Html(ret.into()));
+                        return Some((Event::Html(ret.into()), 0..0));
                     } else {
                         return None;
                     }
@@ -917,13 +915,14 @@
         };
 
         let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer));
+        let p = p.into_offset_iter();
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
         let p = HeadingLinks::new(p, None, &mut ids);
-        let p = LinkReplacer::new(p, links);
-        let p = CodeBlocks::new(p, codes, edition, playground);
         let p = Footnotes::new(p);
+        let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
+        let p = CodeBlocks::new(p, codes, edition, playground);
         html::push_html(&mut s, p);
 
         s
@@ -934,7 +933,7 @@
     crate fn into_string(self) -> String {
         let MarkdownWithToc(md, mut ids, codes, edition, playground) = self;
 
-        let p = Parser::new_ext(md, opts());
+        let p = Parser::new_ext(md, opts()).into_offset_iter();
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
@@ -942,8 +941,8 @@
 
         {
             let p = HeadingLinks::new(p, Some(&mut toc), &mut ids);
-            let p = CodeBlocks::new(p, codes, edition, playground);
             let p = Footnotes::new(p);
+            let p = CodeBlocks::new(p.map(|(ev, _)| ev), codes, edition, playground);
             html::push_html(&mut s, p);
         }
 
@@ -959,19 +958,19 @@
         if md.is_empty() {
             return String::new();
         }
-        let p = Parser::new_ext(md, opts());
+        let p = Parser::new_ext(md, opts()).into_offset_iter();
 
         // Treat inline HTML as plain text.
-        let p = p.map(|event| match event {
-            Event::Html(text) => Event::Text(text),
+        let p = p.map(|event| match event.0 {
+            Event::Html(text) => (Event::Text(text), event.1),
             _ => event,
         });
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
         let p = HeadingLinks::new(p, None, &mut ids);
-        let p = CodeBlocks::new(p, codes, edition, playground);
         let p = Footnotes::new(p);
+        let p = CodeBlocks::new(p.map(|(ev, _)| ev), codes, edition, playground);
         html::push_html(&mut s, p);
 
         s
@@ -1124,56 +1123,75 @@
     s
 }
 
-crate fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
+crate struct MarkdownLink {
+    pub kind: LinkType,
+    pub link: String,
+    pub range: Range<usize>,
+}
+
+crate fn markdown_links(md: &str) -> Vec<MarkdownLink> {
     if md.is_empty() {
         return vec![];
     }
 
-    let mut links = vec![];
-    let mut shortcut_links = vec![];
+    let links = RefCell::new(vec![]);
 
-    {
-        let locate = |s: &str| unsafe {
-            let s_start = s.as_ptr();
-            let s_end = s_start.add(s.len());
-            let md_start = md.as_ptr();
-            let md_end = md_start.add(md.len());
-            if md_start <= s_start && s_end <= md_end {
-                let start = s_start.offset_from(md_start) as usize;
-                let end = s_end.offset_from(md_start) as usize;
-                Some(start..end)
-            } else {
-                None
-            }
-        };
+    // FIXME: remove this function once pulldown_cmark can provide spans for link definitions.
+    let locate = |s: &str, fallback: Range<usize>| unsafe {
+        let s_start = s.as_ptr();
+        let s_end = s_start.add(s.len());
+        let md_start = md.as_ptr();
+        let md_end = md_start.add(md.len());
+        if md_start <= s_start && s_end <= md_end {
+            let start = s_start.offset_from(md_start) as usize;
+            let end = s_end.offset_from(md_start) as usize;
+            start..end
+        } else {
+            fallback
+        }
+    };
 
-        let mut push = |link: BrokenLink<'_>| {
-            // FIXME: use `link.span` instead of `locate`
-            // (doing it now includes the `[]` as well as the text)
-            shortcut_links.push((link.reference.to_owned(), locate(link.reference)));
-            None
-        };
-        let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut push));
+    let span_for_link = |link: &CowStr<'_>, span: Range<usize>| {
+        // For diagnostics, we want to underline the link's definition but `span` will point at
+        // where the link is used. This is a problem for reference-style links, where the definition
+        // is separate from the usage.
+        match link {
+            // `Borrowed` variant means the string (the link's destination) may come directly from
+            // the markdown text and we can locate the original link destination.
+            // NOTE: LinkReplacer also provides `Borrowed` but possibly from other sources,
+            // so `locate()` can fall back to use `span`.
+            CowStr::Borrowed(s) => locate(s, span),
 
-        // There's no need to thread an IdMap through to here because
-        // the IDs generated aren't going to be emitted anywhere.
-        let mut ids = IdMap::new();
-        let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids));
+            // For anything else, we can only use the provided range.
+            CowStr::Boxed(_) | CowStr::Inlined(_) => span,
+        }
+    };
 
-        for ev in iter {
-            if let Event::Start(Tag::Link(_, dest, _)) = ev {
-                debug!("found link: {}", dest);
-                links.push(match dest {
-                    CowStr::Borrowed(s) => (s.to_owned(), locate(s)),
-                    s @ (CowStr::Boxed(..) | CowStr::Inlined(..)) => (s.into_string(), None),
-                });
-            }
+    let mut push = |link: BrokenLink<'_>| {
+        let span = span_for_link(&CowStr::Borrowed(link.reference), link.span);
+        links.borrow_mut().push(MarkdownLink {
+            kind: LinkType::ShortcutUnknown,
+            link: link.reference.to_owned(),
+            range: span,
+        });
+        None
+    };
+    let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut push)).into_offset_iter();
+
+    // There's no need to thread an IdMap through to here because
+    // the IDs generated aren't going to be emitted anywhere.
+    let mut ids = IdMap::new();
+    let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids));
+
+    for ev in iter {
+        if let Event::Start(Tag::Link(kind, dest, _)) = ev.0 {
+            debug!("found link: {}", dest);
+            let span = span_for_link(&dest, ev.1);
+            links.borrow_mut().push(MarkdownLink { kind, link: dest.into_string(), range: span });
         }
     }
 
-    links.append(&mut shortcut_links);
-
-    links
+    links.into_inner()
 }
 
 #[derive(Debug)]
@@ -1185,6 +1203,7 @@
     crate code: Range<usize>,
     crate is_fenced: bool,
     crate syntax: Option<String>,
+    crate is_ignore: bool,
 }
 
 /// Returns a range of bytes for each code block in the markdown that is tagged as `rust` or
@@ -1200,7 +1219,7 @@
 
     while let Some((event, offset)) = p.next() {
         if let Event::Start(Tag::CodeBlock(syntax)) = event {
-            let (syntax, code_start, code_end, range, is_fenced) = match syntax {
+            let (syntax, code_start, code_end, range, is_fenced, is_ignore) = match syntax {
                 CodeBlockKind::Fenced(syntax) => {
                     let syntax = syntax.as_ref();
                     let lang_string = if syntax.is_empty() {
@@ -1211,6 +1230,7 @@
                     if !lang_string.rust {
                         continue;
                     }
+                    let is_ignore = lang_string.ignore != Ignore::None;
                     let syntax = if syntax.is_empty() { None } else { Some(syntax.to_owned()) };
                     let (code_start, mut code_end) = match p.next() {
                         Some((Event::Text(_), offset)) => (offset.start, offset.end),
@@ -1221,6 +1241,7 @@
                                 range: offset,
                                 code,
                                 syntax,
+                                is_ignore,
                             });
                             continue;
                         }
@@ -1231,6 +1252,7 @@
                                 range: offset,
                                 code,
                                 syntax,
+                                is_ignore,
                             });
                             continue;
                         }
@@ -1238,7 +1260,7 @@
                     while let Some((Event::Text(_), offset)) = p.next() {
                         code_end = offset.end;
                     }
-                    (syntax, code_start, code_end, offset, true)
+                    (syntax, code_start, code_end, offset, true, is_ignore)
                 }
                 CodeBlockKind::Indented => {
                     // The ending of the offset goes too far sometime so we reduce it by one in
@@ -1250,9 +1272,10 @@
                             offset.end,
                             Range { start: offset.start, end: offset.end - 1 },
                             false,
+                            false,
                         )
                     } else {
-                        (None, offset.start, offset.end, offset, false)
+                        (None, offset.start, offset.end, offset, false, false)
                     }
                 }
             };
@@ -1262,6 +1285,7 @@
                 range,
                 code: Range { start: code_start, end: code_end },
                 syntax,
+                is_ignore,
             });
         }
     }
@@ -1298,7 +1322,6 @@
     map.insert("trait-implementations".to_owned(), 1);
     map.insert("synthetic-implementations".to_owned(), 1);
     map.insert("blanket-implementations".to_owned(), 1);
-    map.insert("deref-methods".to_owned(), 1);
     map
 }
 
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index c408e57..497cbbb 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -78,7 +78,7 @@
                 ty: item.type_(),
                 name: item.name.unwrap().to_string(),
                 path: fqp[..fqp.len() - 1].join("::"),
-                desc: item.doc_value().map_or_else(|| String::new(), short_markdown_summary),
+                desc: item.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)),
                 parent: Some(did),
                 parent_idx: None,
                 search_type: get_index_search_type(&item),
@@ -127,7 +127,7 @@
     let crate_doc = krate
         .module
         .as_ref()
-        .map(|module| module.doc_value().map_or_else(|| String::new(), short_markdown_summary))
+        .map(|module| module.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)))
         .unwrap_or_default();
 
     #[derive(Serialize)]
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index a83a360..2db89e8 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -30,7 +30,6 @@
 #[cfg(test)]
 mod tests;
 
-use std::borrow::Cow;
 use std::cell::{Cell, RefCell};
 use std::cmp::Ordering;
 use std::collections::{BTreeMap, VecDeque};
@@ -116,6 +115,9 @@
     crate render_redirect_pages: bool,
     /// The map used to ensure all generated 'id=' attributes are unique.
     id_map: Rc<RefCell<IdMap>>,
+    /// Tracks section IDs for `Deref` targets so they match in both the main
+    /// body and the sidebar.
+    deref_id_map: Rc<RefCell<FxHashMap<DefId, String>>>,
     crate shared: Arc<SharedContext<'tcx>>,
     all: Rc<RefCell<AllTypes>>,
     /// Storage for the errors produced while generating documentation so they
@@ -198,12 +200,8 @@
 
     /// Based on whether the `collapse-docs` pass was run, return either the `doc_value` or the
     /// `collapsed_doc_value` of the given item.
-    crate fn maybe_collapsed_doc_value<'a>(&self, item: &'a clean::Item) -> Option<Cow<'a, str>> {
-        if self.collapsed {
-            item.collapsed_doc_value().map(|s| s.into())
-        } else {
-            item.doc_value().map(|s| s.into())
-        }
+    crate fn maybe_collapsed_doc_value<'a>(&self, item: &'a clean::Item) -> Option<String> {
+        if self.collapsed { item.collapsed_doc_value() } else { item.doc_value() }
     }
 }
 
@@ -377,7 +375,6 @@
         "implementors-list",
         "synthetic-implementors-list",
         "methods",
-        "deref-methods",
         "implementations",
     ]
     .iter()
@@ -511,6 +508,7 @@
             dst,
             render_redirect_pages: false,
             id_map: Rc::new(RefCell::new(id_map)),
+            deref_id_map: Rc::new(RefCell::new(FxHashMap::default())),
             shared: Arc::new(scx),
             all: Rc::new(RefCell::new(AllTypes::new())),
             errors: Rc::new(receiver),
@@ -979,7 +977,7 @@
                 .iter()
                 .map(|s| format!("\"{}\"", s.to_str().expect("invalid osstring conversion")))
                 .collect::<Vec<_>>();
-            files.sort_unstable_by(|a, b| a.cmp(b));
+            files.sort_unstable();
             let subs = subs.iter().map(|s| s.to_json_string()).collect::<Vec<_>>().join(",");
             let dirs =
                 if subs.is_empty() { String::new() } else { format!(",\"dirs\":[{}]", subs) };
@@ -1428,7 +1426,7 @@
                     .map(|opt| format!(
                         "<option value=\"{}\" {}>{}</option>",
                         opt.0,
-                        if &opt.0 == default_value { "selected" } else { "" },
+                        if opt.0 == default_value { "selected" } else { "" },
                         opt.1,
                     ))
                     .collect::<String>(),
@@ -1595,7 +1593,7 @@
             if let Some(&(ref names, ty)) = cache.paths.get(&it.def_id) {
                 for name in &names[..names.len() - 1] {
                     url.push_str(name);
-                    url.push_str("/");
+                    url.push('/');
                 }
                 url.push_str(&item_path(ty, names.last().unwrap()));
                 layout::redirect(&url)
@@ -1622,7 +1620,7 @@
             let short = short.to_string();
             map.entry(short).or_default().push((
                 myname,
-                Some(item.doc_value().map_or_else(|| String::new(), plain_text_summary)),
+                Some(item.doc_value().map_or_else(String::new, |s| plain_text_summary(&s))),
             ));
         }
 
@@ -1880,7 +1878,7 @@
         return;
     }
     if let Some(s) = item.doc_value() {
-        let mut summary_html = MarkdownSummaryLine(s, &item.links()).into_string();
+        let mut summary_html = MarkdownSummaryLine(&s, &item.links()).into_string();
 
         if s.contains('\n') {
             let link = format!(r#" <a href="{}">Read more</a>"#, naive_assoc_href(item, link));
@@ -2157,14 +2155,14 @@
                     Some(ref src) => write!(
                         w,
                         "<tr><td><code>{}extern crate {} as {};",
-                        myitem.visibility.print_with_space(cx.tcx()),
+                        myitem.visibility.print_with_space(cx.tcx(), myitem.def_id),
                         anchor(myitem.def_id, &*src.as_str()),
                         name
                     ),
                     None => write!(
                         w,
                         "<tr><td><code>{}extern crate {};",
-                        myitem.visibility.print_with_space(cx.tcx()),
+                        myitem.visibility.print_with_space(cx.tcx(), myitem.def_id),
                         anchor(myitem.def_id, &*name.as_str())
                     ),
                 }
@@ -2175,7 +2173,7 @@
                 write!(
                     w,
                     "<tr><td><code>{}{}</code></td></tr>",
-                    myitem.visibility.print_with_space(cx.tcx()),
+                    myitem.visibility.print_with_space(cx.tcx(), myitem.def_id),
                     import.print()
                 );
             }
@@ -2197,7 +2195,7 @@
                 let stab = myitem.stability_class(cx.tcx());
                 let add = if stab.is_some() { " " } else { "" };
 
-                let doc_value = myitem.doc_value().unwrap_or("");
+                let doc_value = myitem.doc_value().unwrap_or_default();
                 write!(
                     w,
                     "<tr class=\"{stab}{add}module-item\">\
@@ -2207,7 +2205,7 @@
                      </tr>",
                     name = *myitem.name.as_ref().unwrap(),
                     stab_tags = extra_info_tags(myitem, item, cx.tcx()),
-                    docs = MarkdownSummaryLine(doc_value, &myitem.links()).into_string(),
+                    docs = MarkdownSummaryLine(&doc_value, &myitem.links()).into_string(),
                     class = myitem.type_(),
                     add = add,
                     stab = stab.unwrap_or_else(String::new),
@@ -2308,7 +2306,7 @@
             let since = &since.as_str();
             if !stability::deprecation_in_effect(is_since_rustc_version, Some(since)) {
                 if *since == "TBD" {
-                    format!("Deprecating in a future Rust version")
+                    String::from("Deprecating in a future Rust version")
                 } else {
                     format!("Deprecating in {}", Escape(since))
                 }
@@ -2392,7 +2390,7 @@
     write!(
         w,
         "{vis}const {name}: {typ}",
-        vis = it.visibility.print_with_space(cx.tcx()),
+        vis = it.visibility.print_with_space(cx.tcx(), it.def_id),
         name = it.name.as_ref().unwrap(),
         typ = c.type_.print(),
     );
@@ -2426,7 +2424,7 @@
     write!(
         w,
         "{vis}static {mutability}{name}: {typ}</pre>",
-        vis = it.visibility.print_with_space(cx.tcx()),
+        vis = it.visibility.print_with_space(cx.tcx(), it.def_id),
         mutability = s.mutability.print_with_space(),
         name = it.name.as_ref().unwrap(),
         typ = s.type_.print()
@@ -2437,7 +2435,7 @@
 fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) {
     let header_len = format!(
         "{}{}{}{}{:#}fn {}{:#}",
-        it.visibility.print_with_space(cx.tcx()),
+        it.visibility.print_with_space(cx.tcx(), it.def_id),
         f.header.constness.print_with_space(),
         f.header.asyncness.print_with_space(),
         f.header.unsafety.print_with_space(),
@@ -2452,7 +2450,7 @@
         w,
         "{vis}{constness}{asyncness}{unsafety}{abi}fn \
          {name}{generics}{decl}{spotlight}{where_clause}</pre>",
-        vis = it.visibility.print_with_space(cx.tcx()),
+        vis = it.visibility.print_with_space(cx.tcx(), it.def_id),
         constness = f.header.constness.print_with_space(),
         asyncness = f.header.asyncness.print_with_space(),
         unsafety = f.header.unsafety.print_with_space(),
@@ -2578,7 +2576,7 @@
         write!(
             w,
             "{}{}{}trait {}{}{}",
-            it.visibility.print_with_space(cx.tcx()),
+            it.visibility.print_with_space(cx.tcx(), it.def_id),
             t.unsafety.print_with_space(),
             if t.is_auto { "auto " } else { "" },
             it.name.as_ref().unwrap(),
@@ -2896,7 +2894,7 @@
         w,
         "{}{}const <a href=\"{}\" class=\"constant\"><b>{}</b></a>: {}",
         extra,
-        it.visibility.print_with_space(cx.tcx()),
+        it.visibility.print_with_space(cx.tcx(), it.def_id),
         naive_assoc_href(it, link),
         it.name.as_ref().unwrap(),
         ty.print()
@@ -3015,7 +3013,7 @@
         };
         let mut header_len = format!(
             "{}{}{}{}{}{:#}fn {}{:#}",
-            meth.visibility.print_with_space(cx.tcx()),
+            meth.visibility.print_with_space(cx.tcx(), meth.def_id),
             header.constness.print_with_space(),
             header.asyncness.print_with_space(),
             header.unsafety.print_with_space(),
@@ -3037,7 +3035,7 @@
             "{}{}{}{}{}{}{}fn <a href=\"{href}\" class=\"fnname\">{name}</a>\
              {generics}{decl}{spotlight}{where_clause}",
             if parent == ItemType::Trait { "    " } else { "" },
-            meth.visibility.print_with_space(cx.tcx()),
+            meth.visibility.print_with_space(cx.tcx(), meth.def_id),
             header.constness.print_with_space(),
             header.asyncness.print_with_space(),
             header.unsafety.print_with_space(),
@@ -3189,7 +3187,7 @@
         write!(
             w,
             "{}enum {}{}{}",
-            it.visibility.print_with_space(cx.tcx()),
+            it.visibility.print_with_space(cx.tcx(), it.def_id),
             it.name.as_ref().unwrap(),
             e.generics.print(),
             WhereClause { gens: &e.generics, indent: 0, end_newline: true }
@@ -3202,9 +3200,9 @@
                 write!(w, "    ");
                 let name = v.name.as_ref().unwrap();
                 match *v.kind {
-                    clean::VariantItem(ref var) => match var.kind {
-                        clean::VariantKind::CLike => write!(w, "{}", name),
-                        clean::VariantKind::Tuple(ref tys) => {
+                    clean::VariantItem(ref var) => match var {
+                        clean::Variant::CLike => write!(w, "{}", name),
+                        clean::Variant::Tuple(ref tys) => {
                             write!(w, "{}(", name);
                             for (i, ty) in tys.iter().enumerate() {
                                 if i > 0 {
@@ -3214,7 +3212,7 @@
                             }
                             write!(w, ")");
                         }
-                        clean::VariantKind::Struct(ref s) => {
+                        clean::Variant::Struct(ref s) => {
                             render_struct(w, v, None, s.struct_type, &s.fields, "    ", false, cx);
                         }
                     },
@@ -3251,25 +3249,22 @@
                 id = id,
                 name = variant.name.as_ref().unwrap()
             );
-            if let clean::VariantItem(ref var) = *variant.kind {
-                if let clean::VariantKind::Tuple(ref tys) = var.kind {
-                    write!(w, "(");
-                    for (i, ty) in tys.iter().enumerate() {
-                        if i > 0 {
-                            write!(w, ",&nbsp;");
-                        }
-                        write!(w, "{}", ty.print());
+            if let clean::VariantItem(clean::Variant::Tuple(ref tys)) = *variant.kind {
+                write!(w, "(");
+                for (i, ty) in tys.iter().enumerate() {
+                    if i > 0 {
+                        write!(w, ",&nbsp;");
                     }
-                    write!(w, ")");
+                    write!(w, "{}", ty.print());
                 }
+                write!(w, ")");
             }
             write!(w, "</code></div>");
             document(w, cx, variant, Some(it));
             document_non_exhaustive(w, variant);
 
-            use crate::clean::{Variant, VariantKind};
-            if let clean::VariantItem(Variant { kind: VariantKind::Struct(ref s) }) = *variant.kind
-            {
+            use crate::clean::Variant;
+            if let clean::VariantItem(Variant::Struct(ref s)) = *variant.kind {
                 let variant_id = cx.derive_id(format!(
                     "{}.{}.fields",
                     ItemType::Variant,
@@ -3365,7 +3360,7 @@
     write!(
         w,
         "{}{}{}",
-        it.visibility.print_with_space(cx.tcx()),
+        it.visibility.print_with_space(cx.tcx(), it.def_id),
         if structhead { "struct " } else { "" },
         it.name.as_ref().unwrap()
     );
@@ -3385,7 +3380,7 @@
                         w,
                         "\n{}    {}{}: {},",
                         tab,
-                        field.visibility.print_with_space(cx.tcx()),
+                        field.visibility.print_with_space(cx.tcx(), field.def_id),
                         field.name.as_ref().unwrap(),
                         ty.print()
                     );
@@ -3414,7 +3409,12 @@
                 match *field.kind {
                     clean::StrippedItem(box clean::StructFieldItem(..)) => write!(w, "_"),
                     clean::StructFieldItem(ref ty) => {
-                        write!(w, "{}{}", field.visibility.print_with_space(cx.tcx()), ty.print())
+                        write!(
+                            w,
+                            "{}{}",
+                            field.visibility.print_with_space(cx.tcx(), field.def_id),
+                            ty.print()
+                        )
                     }
                     _ => unreachable!(),
                 }
@@ -3447,7 +3447,7 @@
     write!(
         w,
         "{}{}{}",
-        it.visibility.print_with_space(cx.tcx()),
+        it.visibility.print_with_space(cx.tcx(), it.def_id),
         if structhead { "union " } else { "" },
         it.name.as_ref().unwrap()
     );
@@ -3462,7 +3462,7 @@
             write!(
                 w,
                 "    {}{}: {},\n{}",
-                field.visibility.print_with_space(cx.tcx()),
+                field.visibility.print_with_space(cx.tcx(), field.def_id),
                 field.name.as_ref().unwrap(),
                 ty.print(),
                 tab
@@ -3517,14 +3517,18 @@
                 RenderMode::Normal
             }
             AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
+                let id =
+                    cx.derive_id(small_url_encode(&format!("deref-methods-{:#}", type_.print())));
+                cx.deref_id_map.borrow_mut().insert(type_.def_id().unwrap(), id.clone());
                 write!(
                     w,
-                    "<h2 id=\"deref-methods\" class=\"small-section-header\">\
-                         Methods from {}&lt;Target = {}&gt;\
-                         <a href=\"#deref-methods\" class=\"anchor\"></a>\
+                    "<h2 id=\"{id}\" class=\"small-section-header\">\
+                         Methods from {trait_}&lt;Target = {type_}&gt;\
+                         <a href=\"#{id}\" class=\"anchor\"></a>\
                      </h2>",
-                    trait_.print(),
-                    type_.print()
+                    id = id,
+                    trait_ = trait_.print(),
+                    type_ = type_.print(),
                 );
                 RenderMode::ForDeref { mut_: deref_mut_ }
             }
@@ -3548,9 +3552,6 @@
             );
         }
     }
-    if let AssocItemRender::DerefFor { .. } = what {
-        return;
-    }
     if !traits.is_empty() {
         let deref_impl =
             traits.iter().find(|t| t.inner_impl().trait_.def_id() == cache.deref_trait_did);
@@ -3560,6 +3561,12 @@
             render_deref_methods(w, cx, impl_, containing_item, has_deref_mut, cache);
         }
 
+        // If we were already one level into rendering deref methods, we don't want to render
+        // anything after recursing into any further deref methods above.
+        if let AssocItemRender::DerefFor { .. } = what {
+            return;
+        }
+
         let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) =
             traits.iter().partition(|t| t.inner_impl().synthetic);
         let (blanket_impl, concrete): (Vec<&&Impl>, _) =
@@ -3631,6 +3638,13 @@
     let what =
         AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
     if let Some(did) = target.def_id() {
+        if let Some(type_did) = impl_.inner_impl().for_.def_id() {
+            // `impl Deref<Target = S> for S`
+            if did == type_did {
+                // Avoid infinite cycles
+                return;
+            }
+        }
         render_assoc_items(w, cx, container_item, did, what, cache);
     } else {
         if let Some(prim) = target.primitive_type() {
@@ -4101,7 +4115,7 @@
     write!(
         w,
         "    {}type {};\n}}</pre>",
-        it.visibility.print_with_space(cx.tcx()),
+        it.visibility.print_with_space(cx.tcx(), it.def_id),
         it.name.as_ref().unwrap(),
     );
 
@@ -4165,14 +4179,14 @@
         );
     }
     match *it.kind {
-        clean::StructItem(ref s) => sidebar_struct(buffer, it, s),
-        clean::TraitItem(ref t) => sidebar_trait(buffer, it, t),
-        clean::PrimitiveItem(_) => sidebar_primitive(buffer, it),
-        clean::UnionItem(ref u) => sidebar_union(buffer, it, u),
-        clean::EnumItem(ref e) => sidebar_enum(buffer, it, e),
-        clean::TypedefItem(_, _) => sidebar_typedef(buffer, it),
+        clean::StructItem(ref s) => sidebar_struct(cx, buffer, it, s),
+        clean::TraitItem(ref t) => sidebar_trait(cx, buffer, it, t),
+        clean::PrimitiveItem(_) => sidebar_primitive(cx, buffer, it),
+        clean::UnionItem(ref u) => sidebar_union(cx, buffer, it, u),
+        clean::EnumItem(ref e) => sidebar_enum(cx, buffer, it, e),
+        clean::TypedefItem(_, _) => sidebar_typedef(cx, buffer, it),
         clean::ModuleItem(ref m) => sidebar_module(buffer, &m.items),
-        clean::ForeignTypeItem => sidebar_foreign_type(buffer, it),
+        clean::ForeignTypeItem => sidebar_foreign_type(cx, buffer, it),
         _ => (),
     }
 
@@ -4273,7 +4287,7 @@
         .replace("\"", "%22")
 }
 
-fn sidebar_assoc_items(it: &clean::Item) -> String {
+fn sidebar_assoc_items(cx: &Context<'_>, it: &clean::Item) -> String {
     let mut out = String::new();
     let c = cache();
     if let Some(v) = c.impls.get(&it.def_id) {
@@ -4303,69 +4317,22 @@
                 .filter(|i| i.inner_impl().trait_.is_some())
                 .find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did)
             {
-                if let Some((target, real_target)) =
-                    impl_.inner_impl().items.iter().find_map(|item| match *item.kind {
-                        clean::TypedefItem(ref t, true) => Some(match *t {
-                            clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_),
-                            _ => (&t.type_, &t.type_),
-                        }),
-                        _ => None,
-                    })
-                {
-                    let deref_mut = v
-                        .iter()
-                        .filter(|i| i.inner_impl().trait_.is_some())
-                        .any(|i| i.inner_impl().trait_.def_id() == c.deref_mut_trait_did);
-                    let inner_impl = target
-                        .def_id()
-                        .or(target
-                            .primitive_type()
-                            .and_then(|prim| c.primitive_locations.get(&prim).cloned()))
-                        .and_then(|did| c.impls.get(&did));
-                    if let Some(impls) = inner_impl {
-                        out.push_str("<a class=\"sidebar-title\" href=\"#deref-methods\">");
-                        out.push_str(&format!(
-                            "Methods from {}&lt;Target={}&gt;",
-                            Escape(&format!(
-                                "{:#}",
-                                impl_.inner_impl().trait_.as_ref().unwrap().print()
-                            )),
-                            Escape(&format!("{:#}", real_target.print()))
-                        ));
-                        out.push_str("</a>");
-                        let mut ret = impls
-                            .iter()
-                            .filter(|i| i.inner_impl().trait_.is_none())
-                            .flat_map(|i| {
-                                get_methods(i.inner_impl(), true, &mut used_links, deref_mut)
-                            })
-                            .collect::<Vec<_>>();
-                        // We want links' order to be reproducible so we don't use unstable sort.
-                        ret.sort();
-                        if !ret.is_empty() {
-                            out.push_str(&format!(
-                                "<div class=\"sidebar-links\">{}</div>",
-                                ret.join("")
-                            ));
-                        }
-                    }
-                }
+                out.push_str(&sidebar_deref_methods(cx, impl_, v));
             }
             let format_impls = |impls: Vec<&Impl>| {
                 let mut links = FxHashSet::default();
 
                 let mut ret = impls
                     .iter()
-                    .filter_map(|i| {
-                        let is_negative_impl = is_negative_impl(i.inner_impl());
-                        if let Some(ref i) = i.inner_impl().trait_ {
+                    .filter_map(|it| {
+                        if let Some(ref i) = it.inner_impl().trait_ {
                             let i_display = format!("{:#}", i.print());
                             let out = Escape(&i_display);
                             let encoded = small_url_encode(&format!("{:#}", i.print()));
                             let generated = format!(
                                 "<a href=\"#impl-{}\">{}{}</a>",
                                 encoded,
-                                if is_negative_impl { "!" } else { "" },
+                                if it.inner_impl().negative_polarity { "!" } else { "" },
                                 out
                             );
                             if links.insert(generated.clone()) { Some(generated) } else { None }
@@ -4417,7 +4384,81 @@
     out
 }
 
-fn sidebar_struct(buf: &mut Buffer, it: &clean::Item, s: &clean::Struct) {
+fn sidebar_deref_methods(cx: &Context<'_>, impl_: &Impl, v: &Vec<Impl>) -> String {
+    let mut out = String::new();
+    let c = cache();
+
+    debug!("found Deref: {:?}", impl_);
+    if let Some((target, real_target)) =
+        impl_.inner_impl().items.iter().find_map(|item| match *item.kind {
+            clean::TypedefItem(ref t, true) => Some(match *t {
+                clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_),
+                _ => (&t.type_, &t.type_),
+            }),
+            _ => None,
+        })
+    {
+        debug!("found target, real_target: {:?} {:?}", target, real_target);
+        let deref_mut = v
+            .iter()
+            .filter(|i| i.inner_impl().trait_.is_some())
+            .any(|i| i.inner_impl().trait_.def_id() == c.deref_mut_trait_did);
+        let inner_impl = target
+            .def_id()
+            .or_else(|| {
+                target.primitive_type().and_then(|prim| c.primitive_locations.get(&prim).cloned())
+            })
+            .and_then(|did| c.impls.get(&did));
+        if let Some(impls) = inner_impl {
+            debug!("found inner_impl: {:?}", impls);
+            let mut used_links = FxHashSet::default();
+            let mut ret = impls
+                .iter()
+                .filter(|i| i.inner_impl().trait_.is_none())
+                .flat_map(|i| get_methods(i.inner_impl(), true, &mut used_links, deref_mut))
+                .collect::<Vec<_>>();
+            if !ret.is_empty() {
+                let deref_id_map = cx.deref_id_map.borrow();
+                let id = deref_id_map
+                    .get(&real_target.def_id().unwrap())
+                    .expect("Deref section without derived id");
+                out.push_str(&format!(
+                    "<a class=\"sidebar-title\" href=\"#{}\">Methods from {}&lt;Target={}&gt;</a>",
+                    id,
+                    Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print())),
+                    Escape(&format!("{:#}", real_target.print())),
+                ));
+                // We want links' order to be reproducible so we don't use unstable sort.
+                ret.sort();
+                out.push_str(&format!("<div class=\"sidebar-links\">{}</div>", ret.join("")));
+            }
+        }
+
+        // Recurse into any further impls that might exist for `target`
+        if let Some(target_did) = target.def_id() {
+            if let Some(target_impls) = c.impls.get(&target_did) {
+                if let Some(target_deref_impl) = target_impls
+                    .iter()
+                    .filter(|i| i.inner_impl().trait_.is_some())
+                    .find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did)
+                {
+                    if let Some(type_did) = impl_.inner_impl().for_.def_id() {
+                        // `impl Deref<Target = S> for S`
+                        if target_did == type_did {
+                            // Avoid infinite cycles
+                            return out;
+                        }
+                    }
+                    out.push_str(&sidebar_deref_methods(cx, target_deref_impl, target_impls));
+                }
+            }
+        }
+    }
+
+    out
+}
+
+fn sidebar_struct(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, s: &clean::Struct) {
     let mut sidebar = String::new();
     let fields = get_struct_fields_name(&s.fields);
 
@@ -4431,7 +4472,7 @@
         }
     }
 
-    sidebar.push_str(&sidebar_assoc_items(it));
+    sidebar.push_str(&sidebar_assoc_items(cx, it));
 
     if !sidebar.is_empty() {
         write!(buf, "<div class=\"block items\">{}</div>", sidebar);
@@ -4458,11 +4499,7 @@
     }
 }
 
-fn is_negative_impl(i: &clean::Impl) -> bool {
-    i.polarity == Some(clean::ImplPolarity::Negative)
-}
-
-fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
+fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
     let mut sidebar = String::new();
 
     let mut types = t
@@ -4562,7 +4599,7 @@
         }
     }
 
-    sidebar.push_str(&sidebar_assoc_items(it));
+    sidebar.push_str(&sidebar_assoc_items(cx, it));
 
     sidebar.push_str("<a class=\"sidebar-title\" href=\"#implementors\">Implementors</a>");
     if t.is_auto {
@@ -4575,16 +4612,16 @@
     write!(buf, "<div class=\"block items\">{}</div>", sidebar)
 }
 
-fn sidebar_primitive(buf: &mut Buffer, it: &clean::Item) {
-    let sidebar = sidebar_assoc_items(it);
+fn sidebar_primitive(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
+    let sidebar = sidebar_assoc_items(cx, it);
 
     if !sidebar.is_empty() {
         write!(buf, "<div class=\"block items\">{}</div>", sidebar);
     }
 }
 
-fn sidebar_typedef(buf: &mut Buffer, it: &clean::Item) {
-    let sidebar = sidebar_assoc_items(it);
+fn sidebar_typedef(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
+    let sidebar = sidebar_assoc_items(cx, it);
 
     if !sidebar.is_empty() {
         write!(buf, "<div class=\"block items\">{}</div>", sidebar);
@@ -4606,7 +4643,7 @@
     fields.join("")
 }
 
-fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) {
+fn sidebar_union(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, u: &clean::Union) {
     let mut sidebar = String::new();
     let fields = get_struct_fields_name(&u.fields);
 
@@ -4618,14 +4655,14 @@
         ));
     }
 
-    sidebar.push_str(&sidebar_assoc_items(it));
+    sidebar.push_str(&sidebar_assoc_items(cx, it));
 
     if !sidebar.is_empty() {
         write!(buf, "<div class=\"block items\">{}</div>", sidebar);
     }
 }
 
-fn sidebar_enum(buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) {
+fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) {
     let mut sidebar = String::new();
 
     let mut variants = e
@@ -4645,7 +4682,7 @@
         ));
     }
 
-    sidebar.push_str(&sidebar_assoc_items(it));
+    sidebar.push_str(&sidebar_assoc_items(cx, it));
 
     if !sidebar.is_empty() {
         write!(buf, "<div class=\"block items\">{}</div>", sidebar);
@@ -4734,8 +4771,8 @@
     }
 }
 
-fn sidebar_foreign_type(buf: &mut Buffer, it: &clean::Item) {
-    let sidebar = sidebar_assoc_items(it);
+fn sidebar_foreign_type(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
+    let sidebar = sidebar_assoc_items(cx, it);
     if !sidebar.is_empty() {
         write!(buf, "<div class=\"block items\">{}</div>", sidebar);
     }
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 1de4b00..3ffb72b 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -493,11 +493,7 @@
     document.addEventListener("keypress", handleShortcut);
     document.addEventListener("keydown", handleShortcut);
 
-    function resetMouseMoved(ev) {
-        mouseMovedAfterSearch = true;
-    }
-
-    document.addEventListener("mousemove", resetMouseMoved);
+    document.addEventListener("mousemove", function() { mouseMovedAfterSearch = true; });
 
     var handleSourceHighlight = (function() {
         var prev_line_id = 0;
@@ -652,8 +648,7 @@
          */
         function execQuery(query, searchWords, filterCrates) {
             function itemTypeFromName(typename) {
-                var length = itemTypes.length;
-                for (var i = 0; i < length; ++i) {
+                for (var i = 0, len = itemTypes.length; i < len; ++i) {
                     if (itemTypes[i] === typename) {
                         return i;
                     }
@@ -667,18 +662,11 @@
                 results = {}, results_in_args = {}, results_returned = {},
                 split = valLower.split("::");
 
-            var length = split.length;
-            for (var z = 0; z < length; ++z) {
-                if (split[z] === "") {
-                    split.splice(z, 1);
-                    z -= 1;
-                }
-            }
+            split = split.filter(function(segment) { return segment !== ""; });
 
             function transformResults(results, isType) {
                 var out = [];
-                var length = results.length;
-                for (var i = 0; i < length; ++i) {
+                for (var i = 0, len = results.length; i < len; ++i) {
                     if (results[i].id > -1) {
                         var obj = searchIndex[results[i].id];
                         obj.lev = results[i].lev;
@@ -707,11 +695,11 @@
                     }
                 }
                 results = ar;
-                var i;
-                var nresults = results.length;
-                for (i = 0; i < nresults; ++i) {
-                    results[i].word = searchWords[results[i].id];
-                    results[i].item = searchIndex[results[i].id] || {};
+                var i, len, result;
+                for (i = 0, len = results.length; i < len; ++i) {
+                    result = results[i];
+                    result.word = searchWords[result.id];
+                    result.item = searchIndex[result.id] || {};
                 }
                 // if there are no results then return to default and fail
                 if (results.length === 0) {
@@ -785,8 +773,7 @@
                     return 0;
                 });
 
-                var length = results.length;
-                for (i = 0; i < length; ++i) {
+                for (i = 0, len = results.length; i < len; ++i) {
                     var result = results[i];
 
                     // this validation does not make sense when searching by types
@@ -843,11 +830,10 @@
                         var vlength = val.generics.length;
                         for (var y = 0; y < vlength; ++y) {
                             var lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1};
-                            var elength = elems.length;
                             var firstGeneric = getObjectFromId(val.generics[y]).name;
-                            for (var x = 0; x < elength; ++x) {
+                            for (var x = 0, elength = elems.length; x < elength; ++x) {
                                 var tmp_lev = levenshtein(getObjectFromId(elems[x]).name,
-                                                          firstGeneric);
+                                                                          firstGeneric);
                                 if (tmp_lev < lev.lev) {
                                     lev.lev = tmp_lev;
                                     lev.pos = x;
@@ -871,7 +857,7 @@
             // Check for type name and type generics (if any).
             function checkType(obj, val, literalSearch) {
                 var lev_distance = MAX_LEV_DISTANCE + 1;
-                var x;
+                var len, x, y, e_len, firstGeneric;
                 if (obj[NAME] === val.name) {
                     if (literalSearch === true) {
                         if (val.generics && val.generics.length !== 0) {
@@ -880,10 +866,12 @@
                                 var elems = obj[GENERICS_DATA].slice(0);
                                 var allFound = true;
 
-                                for (var y = 0; allFound === true && y < val.generics.length; ++y) {
+                                len = val.generics.length;
+                                for (y = 0; allFound === true && y < len; ++y) {
                                     allFound = false;
-                                    var firstGeneric = getObjectFromId(val.generics[y]).name;
-                                    for (x = 0; allFound === false && x < elems.length; ++x) {
+                                    firstGeneric = getObjectFromId(val.generics[y]).name;
+                                    e_len = elems.length;
+                                    for (x = 0; allFound === false && x < e_len; ++x) {
                                         allFound = getObjectFromId(elems[x]).name === firstGeneric;
                                     }
                                     if (allFound === true) {
@@ -913,12 +901,10 @@
                 // Names didn't match so let's check if one of the generic types could.
                 if (literalSearch === true) {
                      if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
-                        var length = obj[GENERICS_DATA].length;
-                        for (x = 0; x < length; ++x) {
-                            if (obj[GENERICS_DATA][x] === val.name) {
-                                return true;
-                            }
-                        }
+                        return obj[GENERICS_DATA].some(
+                            function(name) {
+                                return name === val.name;
+                            });
                     }
                     return false;
                 }
@@ -975,7 +961,7 @@
                     if (typeof ret[0] === "string") {
                         ret = [ret];
                     }
-                    for (var x = 0; x < ret.length; ++x) {
+                    for (var x = 0, len = ret.length; x < len; ++x) {
                         var tmp = ret[x];
                         if (typePassesFilter(typeFilter, tmp[1]) === false) {
                             continue;
@@ -1082,23 +1068,22 @@
                 // aliases to be before the others in the displayed results.
                 var aliases = [];
                 var crateAliases = [];
-                var i;
                 if (filterCrates !== undefined) {
                     if (ALIASES[filterCrates] && ALIASES[filterCrates][query.search]) {
-                        for (i = 0; i < ALIASES[filterCrates][query.search].length; ++i) {
-                            aliases.push(
-                                createAliasFromItem(
-                                    searchIndex[ALIASES[filterCrates][query.search][i]]));
+                        var query_aliases = ALIASES[filterCrates][query.search];
+                        var len = query_aliases.length;
+                        for (var i = 0; i < len; ++i) {
+                            aliases.push(createAliasFromItem(searchIndex[query_aliases[i]]));
                         }
                     }
                 } else {
                     Object.keys(ALIASES).forEach(function(crate) {
                         if (ALIASES[crate][query.search]) {
                             var pushTo = crate === window.currentCrate ? crateAliases : aliases;
-                            for (i = 0; i < ALIASES[crate][query.search].length; ++i) {
-                                pushTo.push(
-                                    createAliasFromItem(
-                                        searchIndex[ALIASES[crate][query.search][i]]));
+                            var query_aliases = ALIASES[crate][query.search];
+                            var len = query_aliases.length;
+                            for (var i = 0; i < len; ++i) {
+                                pushTo.push(createAliasFromItem(searchIndex[query_aliases[i]]));
                             }
                         }
                     });
@@ -1133,11 +1118,12 @@
 
             // quoted values mean literal search
             var nSearchWords = searchWords.length;
-            var i;
+            var i, it;
             var ty;
             var fullId;
             var returned;
             var in_args;
+            var len;
             if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
                 val.charAt(val.length - 1) === val.charAt(0))
             {
@@ -1185,7 +1171,7 @@
                 var input = parts[0];
                 // sort inputs so that order does not matter
                 var inputs = input.split(",").map(trimmer).sort();
-                for (i = 0; i < inputs.length; ++i) {
+                for (i = 0, len = inputs.length; i < len; ++i) {
                     inputs[i] = extractGenerics(inputs[i]);
                 }
                 var output = extractGenerics(parts[1]);
@@ -1210,7 +1196,7 @@
                             is_module = true;
                         } else {
                             var allFound = true;
-                            for (var it = 0; allFound === true && it < inputs.length; it++) {
+                            for (it = 0, len = inputs.length; allFound === true && it < len; it++) {
                                 allFound = checkType(type, inputs[it], true);
                             }
                             in_args = allFound;
@@ -1253,7 +1239,7 @@
 
                 var paths = valLower.split("::");
                 var j;
-                for (j = 0; j < paths.length; ++j) {
+                for (j = 0, len = paths.length; j < len; ++j) {
                     if (paths[j] === "") {
                         paths.splice(j, 1);
                         j -= 1;
@@ -1375,7 +1361,7 @@
          * @return {[boolean]}       [Whether the result is valid or not]
          */
         function validateResult(name, path, keys, parent) {
-            for (var i = 0; i < keys.length; ++i) {
+            for (var i = 0, len = keys.length; i < len; ++i) {
                 // each check is for validation so we negate the conditions and invalidate
                 if (!(
                     // check for an exact name match
@@ -1696,7 +1682,7 @@
             function getSmallest(arrays, positions, notDuplicates) {
                 var start = null;
 
-                for (var it = 0; it < positions.length; ++it) {
+                for (var it = 0, len = positions.length; it < len; ++it) {
                     if (arrays[it].length > positions[it] &&
                         (start === null || start > arrays[it][positions[it]].lev) &&
                         !notDuplicates[arrays[it][positions[it]].fullPath]) {
@@ -1711,7 +1697,7 @@
                 var positions = [];
                 var notDuplicates = {};
 
-                for (var x = 0; x < arrays.length; ++x) {
+                for (var x = 0, arrays_len = arrays.length; x < arrays_len; ++x) {
                     positions.push(0);
                 }
                 while (ret.length < MAX_RESULTS) {
@@ -1720,7 +1706,7 @@
                     if (smallest === null) {
                         break;
                     }
-                    for (x = 0; x < arrays.length && ret.length < MAX_RESULTS; ++x) {
+                    for (x = 0; x < arrays_len && ret.length < MAX_RESULTS; ++x) {
                         if (arrays[x].length > positions[x] &&
                                 arrays[x][positions[x]].lev === smallest &&
                                 !notDuplicates[arrays[x][positions[x]].fullPath]) {
@@ -1740,7 +1726,7 @@
                 "others": [],
             };
 
-            for (var i = 0; i < queries.length; ++i) {
+            for (var i = 0, len = queries.length; i < len; ++i) {
                 query = queries[i].trim();
                 if (query.length !== 0) {
                     var tmp = execQuery(getQuery(query), searchWords, filterCrates);
@@ -1894,7 +1880,7 @@
                             ALIASES[crate][alias_name] = [];
                         }
                         local_aliases = aliases[alias_name];
-                        for (j = 0; j < local_aliases.length; ++j) {
+                        for (j = 0, len = local_aliases.length; j < len; ++j) {
                             ALIASES[crate][alias_name].push(local_aliases[j] + currentIndex);
                         }
                     }
@@ -2062,8 +2048,7 @@
             div.appendChild(h3);
             var ul = document.createElement("ul");
 
-            var length = filtered.length;
-            for (var i = 0; i < length; ++i) {
+            for (var i = 0, len = filtered.length; i < len; ++i) {
                 var item = filtered[i];
                 var name = item[0];
                 var desc = item[1]; // can be null
@@ -2132,21 +2117,18 @@
         }
 
         var libs = Object.getOwnPropertyNames(imp);
-        var llength = libs.length;
-        for (var i = 0; i < llength; ++i) {
+        for (var i = 0, llength = libs.length; i < llength; ++i) {
             if (libs[i] === currentCrate) { continue; }
             var structs = imp[libs[i]];
 
-            var slength = structs.length;
             struct_loop:
-            for (var j = 0; j < slength; ++j) {
+            for (var j = 0, slength = structs.length; j < slength; ++j) {
                 var struct = structs[j];
 
                 var list = struct.synthetic ? synthetic_implementors : implementors;
 
                 if (struct.synthetic) {
-                    var stlength = struct.types.length;
-                    for (var k = 0; k < stlength; k++) {
+                    for (var k = 0, stlength = struct.types.length; k < stlength; k++) {
                         if (inlined_types.has(struct.types[k])) {
                             continue struct_loop;
                         }
@@ -2157,14 +2139,14 @@
                 var code = document.createElement("code");
                 code.innerHTML = struct.text;
 
-                var x = code.getElementsByTagName("a");
-                var xlength = x.length;
-                for (var it = 0; it < xlength; it++) {
-                    var href = x[it].getAttribute("href");
+                onEachLazy(code.getElementsByTagName("a"), function(elem) {
+                    var href = elem.getAttribute("href");
+
                     if (href && href.indexOf("http") !== 0) {
-                        x[it].setAttribute("href", rootPath + href);
+                        elem.setAttribute("href", rootPath + href);
                     }
-                }
+                });
+
                 var display = document.createElement("h3");
                 addClass(display, "impl");
                 display.innerHTML = "<span class=\"in-band\"><table class=\"table-display\">" +
@@ -2553,14 +2535,12 @@
             var hiddenElems = e.getElementsByClassName("hidden");
             var needToggle = false;
 
-            var hlength = hiddenElems.length;
-            for (var i = 0; i < hlength; ++i) {
-                if (hasClass(hiddenElems[i], "content") === false &&
-                    hasClass(hiddenElems[i], "docblock") === false) {
-                    needToggle = true;
-                    break;
+            var needToggle = onEachLazy(e.getElementsByClassName("hidden"), function(hiddenElem) {
+                if (hasClass(hiddenElem, "content") === false &&
+                    hasClass(hiddenElem, "docblock") === false) {
+                    return true;
                 }
-            }
+            });
             if (needToggle === true) {
                 var inner_toggle = newToggle.cloneNode(true);
                 inner_toggle.onclick = toggleClicked;
@@ -2865,7 +2845,7 @@
             return 0;
         });
         var savedCrate = getSettingValue("saved-filter-crate");
-        for (var i = 0; i < crates_text.length; ++i) {
+        for (var i = 0, len = crates_text.length; i < len; ++i) {
             var option = document.createElement("option");
             option.value = crates_text[i];
             option.innerText = crates_text[i];
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 62b08e5..8dad26d 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -1412,6 +1412,7 @@
 	.sidebar > .block.version {
 		border-bottom: none;
 		margin-top: 12px;
+		margin-bottom: 0;
 	}
 
 	nav.sub {
@@ -1582,7 +1583,10 @@
 		height: 73px;
 	}
 
-	#main {
+	/* This is to prevent the search bar from being underneath the <section>
+	 * element following it.
+	 */
+	#main, #search {
 		margin-top: 100px;
 	}
 
diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js
index 6805f2a..a9cc0ff 100644
--- a/src/librustdoc/html/static/source-script.js
+++ b/src/librustdoc/html/static/source-script.js
@@ -8,7 +8,7 @@
     var parts = window.location.pathname.split("/");
     var rootPathParts = window.rootPath.split("/");
 
-    for (var i = 0; i < rootPathParts.length; ++i) {
+    for (var i = 0, len = rootPathParts.length; i < len; ++i) {
         if (rootPathParts[i] === "..") {
             parts.pop();
         }
@@ -35,12 +35,14 @@
     };
     name.innerText = elem["name"];
 
+    var i, len;
+
     var children = document.createElement("div");
     children.className = "children";
     var folders = document.createElement("div");
     folders.className = "folders";
     if (elem.dirs) {
-        for (var i = 0; i < elem.dirs.length; ++i) {
+        for (i = 0, len = elem.dirs.length; i < len; ++i) {
             if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile,
                                hasFoundFile) === true) {
                 addClass(name, "expand");
@@ -53,7 +55,7 @@
     var files = document.createElement("div");
     files.className = "files";
     if (elem.files) {
-        for (i = 0; i < elem.files.length; ++i) {
+        for (i = 0, len = elem.files.length; i < len; ++i) {
             var file = document.createElement("a");
             file.innerText = elem.files[i];
             file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html";
diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs
index b39a4e1..c55f245 100644
--- a/src/librustdoc/html/toc.rs
+++ b/src/librustdoc/html/toc.rs
@@ -132,7 +132,7 @@
                 }
                 Some(entry) => {
                     sec_number = entry.sec_number.clone();
-                    sec_number.push_str(".");
+                    sec_number.push('.');
                     (entry.level, &entry.children)
                 }
             };
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index e347f7f..7d05cb0 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -422,7 +422,7 @@
             trait_,
             for_,
             items,
-            polarity,
+            negative_polarity,
             synthetic,
             blanket_impl,
         } = impl_;
@@ -436,7 +436,7 @@
             trait_: trait_.map(Into::into),
             for_: for_.into(),
             items: ids(items),
-            negative: polarity == Some(clean::ImplPolarity::Negative),
+            negative: negative_polarity,
             synthetic,
             blanket_impl: blanket_impl.map(Into::into),
         }
@@ -482,8 +482,8 @@
 
 impl From<clean::Variant> for Variant {
     fn from(variant: clean::Variant) -> Self {
-        use clean::VariantKind::*;
-        match variant.kind {
+        use clean::Variant::*;
+        match variant {
             CLike => Variant::Plain,
             Tuple(t) => Variant::Tuple(t.into_iter().map(Into::into).collect()),
             Struct(s) => Variant::Struct(ids(s.fields)),
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 7ed64c5..719aca6 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -15,7 +15,6 @@
 #![feature(never_type)]
 #![feature(once_cell)]
 #![feature(type_ascription)]
-#![feature(split_inclusive)]
 #![feature(str_split_once)]
 #![feature(iter_intersperse)]
 #![recursion_limit = "256"]
@@ -412,11 +411,7 @@
             )
         }),
         unstable("test-builder", |o| {
-            o.optflag(
-                "",
-                "test-builder",
-                "specified the rustc-like binary to use as the test builder",
-            )
+            o.optopt("", "test-builder", "The rustc-like binary to use as the test builder", "PATH")
         }),
         unstable("check", |o| o.optflag("", "check", "Run rustdoc checks")),
     ]
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 0a00323..05a3a15 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -235,12 +235,7 @@
                 let mut tests = Tests { found_tests: 0 };
 
                 find_testable_code(
-                    &i.attrs
-                        .doc_strings
-                        .iter()
-                        .map(|d| d.doc.as_str())
-                        .collect::<Vec<_>>()
-                        .join("\n"),
+                    &i.attrs.collapsed_doc_value().unwrap_or_default(),
                     &mut tests,
                     ErrorCodes::No,
                     false,
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index 0c76dc5..554392c 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -51,10 +51,10 @@
             let mut diag = if let Some(sp) =
                 super::source_span_for_markdown_range(self.cx, &dox, &code_block.range, &item.attrs)
             {
-                let warning_message = if buffer.has_errors {
-                    "could not parse code block as Rust code"
+                let (warning_message, suggest_using_text) = if buffer.has_errors {
+                    ("could not parse code block as Rust code", true)
                 } else {
-                    "Rust code block is empty"
+                    ("Rust code block is empty", false)
                 };
 
                 let mut diag = self.cx.sess().struct_span_warn(sp, warning_message);
@@ -67,6 +67,15 @@
                         String::from("```text"),
                         Applicability::MachineApplicable,
                     );
+                } else if suggest_using_text && code_block.is_ignore {
+                    let sp = sp.from_inner(InnerSpan::new(0, 3));
+                    diag.span_suggestion(
+                        sp,
+                        "`ignore` code blocks require valid Rust code for syntax highlighting. \
+                         Mark blocks that do not contain Rust code as text",
+                        String::from("```text,"),
+                        Applicability::MachineApplicable,
+                    );
                 }
 
                 diag
diff --git a/src/librustdoc/passes/collapse_docs.rs b/src/librustdoc/passes/collapse_docs.rs
deleted file mode 100644
index e1ba75b..0000000
--- a/src/librustdoc/passes/collapse_docs.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-use crate::clean::{self, DocFragment, DocFragmentKind, Item};
-use crate::core::DocContext;
-use crate::fold;
-use crate::fold::DocFolder;
-use crate::passes::Pass;
-
-use std::mem::take;
-
-crate const COLLAPSE_DOCS: Pass = Pass {
-    name: "collapse-docs",
-    run: collapse_docs,
-    description: "concatenates all document attributes into one document attribute",
-};
-
-crate fn collapse_docs(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate {
-    let mut krate = Collapser.fold_crate(krate);
-    krate.collapsed = true;
-    krate
-}
-
-struct Collapser;
-
-impl fold::DocFolder for Collapser {
-    fn fold_item(&mut self, mut i: Item) -> Option<Item> {
-        i.attrs.collapse_doc_comments();
-        Some(self.fold_item_recur(i))
-    }
-}
-
-fn collapse(doc_strings: &mut Vec<DocFragment>) {
-    let mut docs = vec![];
-    let mut last_frag: Option<DocFragment> = None;
-
-    for frag in take(doc_strings) {
-        if let Some(mut curr_frag) = last_frag.take() {
-            let curr_kind = &curr_frag.kind;
-            let new_kind = &frag.kind;
-
-            if matches!(*curr_kind, DocFragmentKind::Include { .. })
-                || curr_kind != new_kind
-                || curr_frag.parent_module != frag.parent_module
-            {
-                if *curr_kind == DocFragmentKind::SugaredDoc
-                    || *curr_kind == DocFragmentKind::RawDoc
-                {
-                    // add a newline for extra padding between segments
-                    curr_frag.doc.push('\n');
-                }
-                docs.push(curr_frag);
-                last_frag = Some(frag);
-            } else {
-                curr_frag.doc.push('\n');
-                curr_frag.doc.push_str(&frag.doc);
-                curr_frag.span = curr_frag.span.to(frag.span);
-                last_frag = Some(curr_frag);
-            }
-        } else {
-            last_frag = Some(frag);
-        }
-    }
-
-    if let Some(frag) = last_frag.take() {
-        docs.push(frag);
-    }
-    *doc_strings = docs;
-}
-
-impl clean::Attributes {
-    crate fn collapse_doc_comments(&mut self) {
-        collapse(&mut self.doc_strings);
-    }
-}
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 63cb02a..2809840 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -19,22 +19,24 @@
     builtin::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS},
     Lint,
 };
-use rustc_span::hygiene::MacroKind;
+use rustc_span::hygiene::{MacroKind, SyntaxContext};
 use rustc_span::symbol::Ident;
 use rustc_span::symbol::Symbol;
 use rustc_span::DUMMY_SP;
 use smallvec::{smallvec, SmallVec};
 
+use pulldown_cmark::LinkType;
+
 use std::borrow::Cow;
 use std::cell::Cell;
 use std::convert::{TryFrom, TryInto};
 use std::mem;
 use std::ops::Range;
 
-use crate::clean::{self, Crate, Item, ItemLink, PrimitiveType};
+use crate::clean::{self, utils::find_nearest_parent_module, Crate, Item, ItemLink, PrimitiveType};
 use crate::core::DocContext;
 use crate::fold::DocFolder;
-use crate::html::markdown::markdown_links;
+use crate::html::markdown::{markdown_links, MarkdownLink};
 use crate::passes::Pass;
 
 use super::span_of_attrs;
@@ -245,7 +247,7 @@
     item: &'a Item,
     dox: &'a str,
     ori_link: &'a str,
-    link_range: Option<Range<usize>>,
+    link_range: Range<usize>,
 }
 
 #[derive(Clone, Debug, Hash)]
@@ -265,8 +267,9 @@
     /// because `clean` and the disambiguator code expect them to be different.
     /// See the code for associated items on inherent impls for details.
     kind_side_channel: Cell<Option<(DefKind, DefId)>>,
-    /// Cache the resolved links so we can avoid resolving (and emitting errors for) the same link
-    visited_links: FxHashMap<ResolutionInfo, CachedLink>,
+    /// Cache the resolved links so we can avoid resolving (and emitting errors for) the same link.
+    /// The link will be `None` if it could not be resolved (i.e. the error was cached).
+    visited_links: FxHashMap<ResolutionInfo, Option<CachedLink>>,
 }
 
 impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
@@ -391,10 +394,14 @@
                         ns,
                         impl_,
                     )
-                    .map(|item| match item.kind {
-                        ty::AssocKind::Fn => "method",
-                        ty::AssocKind::Const => "associatedconstant",
-                        ty::AssocKind::Type => "associatedtype",
+                    .map(|item| {
+                        let kind = item.kind;
+                        self.kind_side_channel.set(Some((kind.as_def_kind(), item.def_id)));
+                        match kind {
+                            ty::AssocKind::Fn => "method",
+                            ty::AssocKind::Const => "associatedconstant",
+                            ty::AssocKind::Type => "associatedtype",
+                        }
                     })
                     .map(|out| {
                         (
@@ -497,15 +504,9 @@
             match res {
                 // FIXME(#76467): make this fallthrough to lookup the associated
                 // item a separate function.
-                Res::Def(DefKind::AssocFn | DefKind::AssocConst, _) => {
-                    assert_eq!(ns, ValueNS);
-                }
-                Res::Def(DefKind::AssocTy, _) => {
-                    assert_eq!(ns, TypeNS);
-                }
-                Res::Def(DefKind::Variant, _) => {
-                    return handle_variant(cx, res, extra_fragment);
-                }
+                Res::Def(DefKind::AssocFn | DefKind::AssocConst, _) => assert_eq!(ns, ValueNS),
+                Res::Def(DefKind::AssocTy, _) => assert_eq!(ns, TypeNS),
+                Res::Def(DefKind::Variant, _) => return handle_variant(cx, res, extra_fragment),
                 // Not a trait item; just return what we found.
                 Res::Primitive(ty) => {
                     if extra_fragment.is_some() {
@@ -515,12 +516,7 @@
                     }
                     return Ok((res, Some(ty.as_str().to_owned())));
                 }
-                Res::Def(DefKind::Mod, _) => {
-                    return Ok((res, extra_fragment.clone()));
-                }
-                _ => {
-                    return Ok((res, extra_fragment.clone()));
-                }
+                _ => return Ok((res, extra_fragment.clone())),
             }
         }
 
@@ -774,7 +770,12 @@
     let mut cache = cx.module_trait_cache.borrow_mut();
     let in_scope_traits = cache.entry(module).or_insert_with(|| {
         cx.enter_resolver(|resolver| {
-            resolver.traits_in_scope(module).into_iter().map(|candidate| candidate.def_id).collect()
+            let parent_scope = &ParentScope::module(resolver.get_module(module), resolver);
+            resolver
+                .traits_in_scope(None, parent_scope, SyntaxContext::root(), None)
+                .into_iter()
+                .map(|candidate| candidate.def_id)
+                .collect()
         })
     });
 
@@ -830,31 +831,9 @@
         use rustc_middle::ty::DefIdTree;
 
         let parent_node = if item.is_fake() {
-            // FIXME: is this correct?
             None
-        // If we're documenting the crate root itself, it has no parent. Use the root instead.
-        } else if item.def_id.is_top_level_module() {
-            Some(item.def_id)
         } else {
-            let mut current = item.def_id;
-            // The immediate parent might not always be a module.
-            // Find the first parent which is.
-            loop {
-                if let Some(parent) = self.cx.tcx.parent(current) {
-                    if self.cx.tcx.def_kind(parent) == DefKind::Mod {
-                        break Some(parent);
-                    }
-                    current = parent;
-                } else {
-                    debug!(
-                        "{:?} has no parent (kind={:?}, original was {:?})",
-                        current,
-                        self.cx.tcx.def_kind(current),
-                        item.def_id
-                    );
-                    break None;
-                }
-            }
+            find_nearest_parent_module(self.cx.tcx, item.def_id)
         };
 
         if parent_node.is_some() {
@@ -913,43 +892,18 @@
         // In the presence of re-exports, this is not the same as the module of the item.
         // Rather than merging all documentation into one, resolve it one attribute at a time
         // so we know which module it came from.
-        let mut attrs = item.attrs.doc_strings.iter().peekable();
-        while let Some(attr) = attrs.next() {
-            // `collapse_docs` does not have the behavior we want:
-            // we want `///` and `#[doc]` to count as the same attribute,
-            // but currently it will treat them as separate.
-            // As a workaround, combine all attributes with the same parent module into the same attribute.
-            let mut combined_docs = attr.doc.clone();
-            loop {
-                match attrs.peek() {
-                    Some(next) if next.parent_module == attr.parent_module => {
-                        combined_docs.push('\n');
-                        combined_docs.push_str(&attrs.next().unwrap().doc);
-                    }
-                    _ => break,
-                }
-            }
-            debug!("combined_docs={}", combined_docs);
+        for (parent_module, doc) in item.attrs.collapsed_doc_value_by_module_level() {
+            debug!("combined_docs={}", doc);
 
-            let (krate, parent_node) = if let Some(id) = attr.parent_module {
-                trace!("docs {:?} came from {:?}", attr.doc, id);
+            let (krate, parent_node) = if let Some(id) = parent_module {
                 (id.krate, Some(id))
             } else {
-                trace!("no parent found for {:?}", attr.doc);
                 (item.def_id.krate, parent_node)
             };
             // NOTE: if there are links that start in one crate and end in another, this will not resolve them.
             // This is a degenerate case and it's not supported by rustdoc.
-            for (ori_link, link_range) in markdown_links(&combined_docs) {
-                let link = self.resolve_link(
-                    &item,
-                    &combined_docs,
-                    &self_name,
-                    parent_node,
-                    krate,
-                    ori_link,
-                    link_range,
-                );
+            for md_link in markdown_links(&doc) {
+                let link = self.resolve_link(&item, &doc, &self_name, parent_node, krate, md_link);
                 if let Some(link) = link {
                     item.attrs.links.push(link);
                 }
@@ -981,27 +935,26 @@
         self_name: &Option<String>,
         parent_node: Option<DefId>,
         krate: CrateNum,
-        ori_link: String,
-        link_range: Option<Range<usize>>,
+        ori_link: MarkdownLink,
     ) -> Option<ItemLink> {
-        trace!("considering link '{}'", ori_link);
+        trace!("considering link '{}'", ori_link.link);
 
         // Bail early for real links.
-        if ori_link.contains('/') {
+        if ori_link.link.contains('/') {
             return None;
         }
 
         // [] is mostly likely not supposed to be a link
-        if ori_link.is_empty() {
+        if ori_link.link.is_empty() {
             return None;
         }
 
         let cx = self.cx;
-        let link = ori_link.replace("`", "");
+        let link = ori_link.link.replace("`", "");
         let parts = link.split('#').collect::<Vec<_>>();
         let (link, extra_fragment) = if parts.len() > 2 {
             // A valid link can't have multiple #'s
-            anchor_failure(cx, &item, &link, dox, link_range, AnchorFailure::MultipleAnchors);
+            anchor_failure(cx, &item, &link, dox, ori_link.range, AnchorFailure::MultipleAnchors);
             return None;
         } else if parts.len() == 2 {
             if parts[0].trim().is_empty() {
@@ -1057,7 +1010,7 @@
                 path_str,
                 disambiguator,
                 dox,
-                link_range,
+                ori_link.range,
                 smallvec![ResolutionFailure::NoParentItem],
             );
             return None;
@@ -1065,12 +1018,18 @@
 
         let resolved_self;
         // replace `Self` with suitable item's parent name
-        if path_str.starts_with("Self::") {
+        let is_lone_self = path_str == "Self";
+        let is_lone_crate = path_str == "crate";
+        if path_str.starts_with("Self::") || is_lone_self {
             if let Some(ref name) = self_name {
-                resolved_self = format!("{}::{}", name, &path_str[6..]);
-                path_str = &resolved_self;
+                if is_lone_self {
+                    path_str = name;
+                } else {
+                    resolved_self = format!("{}::{}", name, &path_str[6..]);
+                    path_str = &resolved_self;
+                }
             }
-        } else if path_str.starts_with("crate::") {
+        } else if path_str.starts_with("crate::") || is_lone_crate {
             use rustc_span::def_id::CRATE_DEF_INDEX;
 
             // HACK(jynelson): rustc_resolve thinks that `crate` is the crate currently being documented.
@@ -1079,8 +1038,12 @@
             // HACK(jynelson)(2): If we just strip `crate::` then suddenly primitives become ambiguous
             // (consider `crate::char`). Instead, change it to `self::`. This works because 'self' is now the crate root.
             // FIXME(#78696): This doesn't always work.
-            resolved_self = format!("self::{}", &path_str["crate::".len()..]);
-            path_str = &resolved_self;
+            if is_lone_crate {
+                path_str = "self";
+            } else {
+                resolved_self = format!("self::{}", &path_str["crate::".len()..]);
+                path_str = &resolved_self;
+            }
             module_id = DefId { krate, index: CRATE_DEF_INDEX };
         }
 
@@ -1097,7 +1060,7 @@
                         path_str,
                         disambiguator,
                         dox,
-                        link_range,
+                        ori_link.range,
                         smallvec![err_kind],
                     );
                     return None;
@@ -1113,15 +1076,22 @@
             return None;
         }
 
-        let key = ResolutionInfo {
-            module_id,
-            dis: disambiguator,
-            path_str: path_str.to_owned(),
-            extra_fragment,
+        let diag_info = DiagnosticInfo {
+            item,
+            dox,
+            ori_link: &ori_link.link,
+            link_range: ori_link.range.clone(),
         };
-        let diag =
-            DiagnosticInfo { item, dox, ori_link: &ori_link, link_range: link_range.clone() };
-        let (mut res, mut fragment) = self.resolve_with_disambiguator_cached(key, diag)?;
+        let (mut res, mut fragment) = self.resolve_with_disambiguator_cached(
+            ResolutionInfo {
+                module_id,
+                dis: disambiguator,
+                path_str: path_str.to_owned(),
+                extra_fragment,
+            },
+            diag_info,
+            matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut),
+        )?;
 
         // Check for a primitive which might conflict with a module
         // Report the ambiguity and require that the user specify which one they meant.
@@ -1140,7 +1110,7 @@
                             &item,
                             path_str,
                             dox,
-                            link_range,
+                            ori_link.range,
                             AnchorFailure::RustdocAnchorConflict(prim),
                         );
                         return None;
@@ -1150,7 +1120,7 @@
                 } else {
                     // `[char]` when a `char` module is in scope
                     let candidates = vec![res, prim];
-                    ambiguity_error(cx, &item, path_str, dox, link_range, candidates);
+                    ambiguity_error(cx, &item, path_str, dox, ori_link.range, candidates);
                     return None;
                 }
             }
@@ -1168,61 +1138,89 @@
                     specified.descr()
                 );
                 diag.note(&note);
-                suggest_disambiguator(resolved, diag, path_str, dox, sp, &link_range);
+                suggest_disambiguator(resolved, diag, path_str, dox, sp, &ori_link.range);
             };
-            report_diagnostic(cx, BROKEN_INTRA_DOC_LINKS, &msg, &item, dox, &link_range, callback);
+            report_diagnostic(
+                cx,
+                BROKEN_INTRA_DOC_LINKS,
+                &msg,
+                &item,
+                dox,
+                &ori_link.range,
+                callback,
+            );
         };
-        match res {
-            Res::Primitive(_) => match disambiguator {
-                Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {
-                    Some(ItemLink { link: ori_link, link_text, did: None, fragment })
-                }
-                Some(other) => {
-                    report_mismatch(other, Disambiguator::Primitive);
-                    None
-                }
-            },
-            Res::Def(kind, id) => {
-                debug!("intra-doc link to {} resolved to {:?}", path_str, res);
 
-                // Disallow e.g. linking to enums with `struct@`
-                debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator);
-                match (self.kind_side_channel.take().map(|(kind, _)| kind).unwrap_or(kind), disambiguator) {
-                    | (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, Some(Disambiguator::Kind(DefKind::Const)))
-                    // NOTE: this allows 'method' to mean both normal functions and associated functions
-                    // This can't cause ambiguity because both are in the same namespace.
-                    | (DefKind::Fn | DefKind::AssocFn, Some(Disambiguator::Kind(DefKind::Fn)))
-                    // These are namespaces; allow anything in the namespace to match
-                    | (_, Some(Disambiguator::Namespace(_)))
-                    // If no disambiguator given, allow anything
-                    | (_, None)
-                    // All of these are valid, so do nothing
-                    => {}
-                    (actual, Some(Disambiguator::Kind(expected))) if actual == expected => {}
-                    (_, Some(specified @ Disambiguator::Kind(_) | specified @ Disambiguator::Primitive)) => {
-                        report_mismatch(specified, Disambiguator::Kind(kind));
-                        return None;
-                    }
-                }
+        let verify = |kind: DefKind, id: DefId| {
+            debug!("intra-doc link to {} resolved to {:?}", path_str, res);
 
-                // item can be non-local e.g. when using #[doc(primitive = "pointer")]
-                if let Some((src_id, dst_id)) = id
-                    .as_local()
-                    .and_then(|dst_id| item.def_id.as_local().map(|src_id| (src_id, dst_id)))
+            // Disallow e.g. linking to enums with `struct@`
+            debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator);
+            match (self.kind_side_channel.take().map(|(kind, _)| kind).unwrap_or(kind), disambiguator) {
+                | (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, Some(Disambiguator::Kind(DefKind::Const)))
+                // NOTE: this allows 'method' to mean both normal functions and associated functions
+                // This can't cause ambiguity because both are in the same namespace.
+                | (DefKind::Fn | DefKind::AssocFn, Some(Disambiguator::Kind(DefKind::Fn)))
+                // These are namespaces; allow anything in the namespace to match
+                | (_, Some(Disambiguator::Namespace(_)))
+                // If no disambiguator given, allow anything
+                | (_, None)
+                // All of these are valid, so do nothing
+                => {}
+                (actual, Some(Disambiguator::Kind(expected))) if actual == expected => {}
+                (_, Some(specified @ Disambiguator::Kind(_) | specified @ Disambiguator::Primitive)) => {
+                    report_mismatch(specified, Disambiguator::Kind(kind));
+                    return None;
+                }
+            }
+
+            // item can be non-local e.g. when using #[doc(primitive = "pointer")]
+            if let Some((src_id, dst_id)) = id
+                .as_local()
+                .and_then(|dst_id| item.def_id.as_local().map(|src_id| (src_id, dst_id)))
+            {
+                use rustc_hir::def_id::LOCAL_CRATE;
+
+                let hir_src = self.cx.tcx.hir().local_def_id_to_hir_id(src_id);
+                let hir_dst = self.cx.tcx.hir().local_def_id_to_hir_id(dst_id);
+
+                if self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_src)
+                    && !self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_dst)
                 {
-                    use rustc_hir::def_id::LOCAL_CRATE;
+                    privacy_error(cx, &item, &path_str, dox, &ori_link);
+                }
+            }
 
-                    let hir_src = self.cx.tcx.hir().local_def_id_to_hir_id(src_id);
-                    let hir_dst = self.cx.tcx.hir().local_def_id_to_hir_id(dst_id);
+            Some((kind, id))
+        };
 
-                    if self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_src)
-                        && !self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_dst)
-                    {
-                        privacy_error(cx, &item, &path_str, dox, link_range);
+        match res {
+            Res::Primitive(_) => {
+                if let Some((kind, id)) = self.kind_side_channel.take() {
+                    // We're actually resolving an associated item of a primitive, so we need to
+                    // verify the disambiguator (if any) matches the type of the associated item.
+                    // This case should really follow the same flow as the `Res::Def` branch below,
+                    // but attempting to add a call to `clean::register_res` causes an ICE. @jyn514
+                    // thinks `register_res` is only needed for cross-crate re-exports, but Rust
+                    // doesn't allow statements like `use str::trim;`, making this a (hopefully)
+                    // valid omission. See https://github.com/rust-lang/rust/pull/80660#discussion_r551585677
+                    // for discussion on the matter.
+                    verify(kind, id)?;
+                } else {
+                    match disambiguator {
+                        Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {}
+                        Some(other) => {
+                            report_mismatch(other, Disambiguator::Primitive);
+                            return None;
+                        }
                     }
                 }
+                Some(ItemLink { link: ori_link.link, link_text, did: None, fragment })
+            }
+            Res::Def(kind, id) => {
+                let (kind, id) = verify(kind, id)?;
                 let id = clean::register_res(cx, rustc_hir::def::Res::Def(kind, id));
-                Some(ItemLink { link: ori_link, link_text, did: Some(id), fragment })
+                Some(ItemLink { link: ori_link.link, link_text, did: Some(id), fragment })
             }
         }
     }
@@ -1231,28 +1229,47 @@
         &mut self,
         key: ResolutionInfo,
         diag: DiagnosticInfo<'_>,
+        cache_resolution_failure: bool,
     ) -> Option<(Res, Option<String>)> {
         // Try to look up both the result and the corresponding side channel value
         if let Some(ref cached) = self.visited_links.get(&key) {
-            self.kind_side_channel.set(cached.side_channel);
-            return Some(cached.res.clone());
+            match cached {
+                Some(cached) => {
+                    self.kind_side_channel.set(cached.side_channel.clone());
+                    return Some(cached.res.clone());
+                }
+                None if cache_resolution_failure => return None,
+                None => {
+                    // Although we hit the cache and found a resolution error, this link isn't
+                    // supposed to cache those. Run link resolution again to emit the expected
+                    // resolution error.
+                }
+            }
         }
 
         let res = self.resolve_with_disambiguator(&key, diag);
 
         // Cache only if resolved successfully - don't silence duplicate errors
-        if let Some(res) = &res {
+        if let Some(res) = res {
             // Store result for the actual namespace
             self.visited_links.insert(
                 key,
-                CachedLink {
+                Some(CachedLink {
                     res: res.clone(),
                     side_channel: self.kind_side_channel.clone().into_inner(),
-                },
+                }),
             );
-        }
 
-        res
+            Some(res)
+        } else {
+            if cache_resolution_failure {
+                // For reference-style links we only want to report one resolution error
+                // so let's cache them as well.
+                self.visited_links.insert(key, None);
+            }
+
+            None
+        }
     }
 
     /// After parsing the disambiguator, resolve the main part of the link.
@@ -1298,7 +1315,7 @@
                         // This could just be a normal link or a broken link
                         // we could potentially check if something is
                         // "intra-doc-link-like" and warn in that case.
-                        return None;
+                        None
                     }
                     Err(ErrorKind::AnchorFailure(msg)) => {
                         anchor_failure(
@@ -1309,7 +1326,7 @@
                             diag.link_range,
                             msg,
                         );
-                        return None;
+                        None
                     }
                 }
             }
@@ -1405,7 +1422,7 @@
                         diag.link_range,
                         candidates.present_items().collect(),
                     );
-                    return None;
+                    None
                 }
             }
             Some(MacroNS) => {
@@ -1430,7 +1447,7 @@
                             diag.link_range,
                             smallvec![kind],
                         );
-                        return None;
+                        None
                     }
                 }
             }
@@ -1628,7 +1645,7 @@
     msg: &str,
     item: &Item,
     dox: &str,
-    link_range: &Option<Range<usize>>,
+    link_range: &Range<usize>,
     decorate: impl FnOnce(&mut DiagnosticBuilder<'_>, Option<rustc_span::Span>),
 ) {
     let hir_id = match cx.as_local_hir_id(item.def_id) {
@@ -1646,31 +1663,27 @@
     cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |lint| {
         let mut diag = lint.build(msg);
 
-        let span = link_range
-            .as_ref()
-            .and_then(|range| super::source_span_for_markdown_range(cx, dox, range, attrs));
+        let span = super::source_span_for_markdown_range(cx, dox, link_range, attrs);
 
-        if let Some(link_range) = link_range {
-            if let Some(sp) = span {
-                diag.set_span(sp);
-            } else {
-                // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
-                //                       ^     ~~~~
-                //                       |     link_range
-                //                       last_new_line_offset
-                let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
-                let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
+        if let Some(sp) = span {
+            diag.set_span(sp);
+        } else {
+            // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
+            //                       ^     ~~~~
+            //                       |     link_range
+            //                       last_new_line_offset
+            let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
+            let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
 
-                // Print the line containing the `link_range` and manually mark it with '^'s.
-                diag.note(&format!(
-                    "the link appears in this line:\n\n{line}\n\
+            // Print the line containing the `link_range` and manually mark it with '^'s.
+            diag.note(&format!(
+                "the link appears in this line:\n\n{line}\n\
                      {indicator: <before$}{indicator:^<found$}",
-                    line = line,
-                    indicator = "",
-                    before = link_range.start - last_new_line_offset,
-                    found = link_range.len(),
-                ));
-            }
+                line = line,
+                indicator = "",
+                before = link_range.start - last_new_line_offset,
+                found = link_range.len(),
+            ));
         }
 
         decorate(&mut diag, span);
@@ -1690,7 +1703,7 @@
     path_str: &str,
     disambiguator: Option<Disambiguator>,
     dox: &str,
-    link_range: Option<Range<usize>>,
+    link_range: Range<usize>,
     kinds: SmallVec<[ResolutionFailure<'_>; 3]>,
 ) {
     let tcx = collector.cx.tcx;
@@ -1914,7 +1927,7 @@
     item: &Item,
     path_str: &str,
     dox: &str,
-    link_range: Option<Range<usize>>,
+    link_range: Range<usize>,
     failure: AnchorFailure,
 ) {
     let msg = match failure {
@@ -1939,7 +1952,7 @@
     item: &Item,
     path_str: &str,
     dox: &str,
-    link_range: Option<Range<usize>>,
+    link_range: Range<usize>,
     candidates: Vec<Res>,
 ) {
     let mut msg = format!("`{}` is ", path_str);
@@ -1988,13 +2001,12 @@
     path_str: &str,
     dox: &str,
     sp: Option<rustc_span::Span>,
-    link_range: &Option<Range<usize>>,
+    link_range: &Range<usize>,
 ) {
     let suggestion = disambiguator.suggestion();
     let help = format!("to link to the {}, {}", disambiguator.descr(), suggestion.descr());
 
     if let Some(sp) = sp {
-        let link_range = link_range.as_ref().expect("must have a link range if we have a span");
         let msg = if dox.bytes().nth(link_range.start) == Some(b'`') {
             format!("`{}`", suggestion.as_help(path_str))
         } else {
@@ -2008,13 +2020,7 @@
 }
 
 /// Report a link from a public item to a private one.
-fn privacy_error(
-    cx: &DocContext<'_>,
-    item: &Item,
-    path_str: &str,
-    dox: &str,
-    link_range: Option<Range<usize>>,
-) {
+fn privacy_error(cx: &DocContext<'_>, item: &Item, path_str: &str, dox: &str, link: &MarkdownLink) {
     let sym;
     let item_name = match item.name {
         Some(name) => {
@@ -2026,7 +2032,7 @@
     let msg =
         format!("public documentation for `{}` links to private item `{}`", item_name, path_str);
 
-    report_diagnostic(cx, PRIVATE_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| {
+    report_diagnostic(cx, PRIVATE_INTRA_DOC_LINKS, &msg, item, dox, &link.range, |diag, sp| {
         if let Some(sp) = sp {
             diag.span_label(sp, "this item is private");
         }
@@ -2084,13 +2090,13 @@
         "f64" => F64,
         "char" => Char,
         "bool" | "true" | "false" => Bool,
-        "str" => Str,
+        "str" | "&str" => Str,
         // See #80181 for why these don't have symbols associated.
         "slice" => Slice,
         "array" => Array,
         "tuple" => Tuple,
         "unit" => Unit,
-        "pointer" | "*" | "*const" | "*mut" => RawPointer,
+        "pointer" | "*const" | "*mut" => RawPointer,
         "reference" | "&" | "&mut" => Reference,
         "fn" => Fn,
         "never" | "!" => Never,
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 9b0ae09..7b5e9e5 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -3,7 +3,7 @@
 use crate::core::DocContext;
 use crate::fold::DocFolder;
 
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::ty::DefIdTree;
 use rustc_span::symbol::sym;
@@ -54,39 +54,6 @@
         }
     }
 
-    let mut cleaner = BadImplStripper { prims, items: crate_items };
-
-    // scan through included items ahead of time to splice in Deref targets to the "valid" sets
-    for it in &new_items {
-        if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind {
-            if cleaner.keep_item(for_) && trait_.def_id() == cx.tcx.lang_items().deref_trait() {
-                let target = items
-                    .iter()
-                    .find_map(|item| match *item.kind {
-                        TypedefItem(ref t, true) => Some(&t.type_),
-                        _ => None,
-                    })
-                    .expect("Deref impl without Target type");
-
-                if let Some(prim) = target.primitive_type() {
-                    cleaner.prims.insert(prim);
-                } else if let Some(did) = target.def_id() {
-                    cleaner.items.insert(did);
-                }
-            }
-        }
-    }
-
-    new_items.retain(|it| {
-        if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind {
-            cleaner.keep_item(for_)
-                || trait_.as_ref().map_or(false, |t| cleaner.keep_item(t))
-                || blanket_impl.is_some()
-        } else {
-            true
-        }
-    });
-
     // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations`
     // doesn't work with it anyway, so pull them from the HIR map instead
     for &trait_did in cx.tcx.all_traits(LOCAL_CRATE).iter() {
@@ -123,6 +90,63 @@
         }
     }
 
+    let mut cleaner = BadImplStripper { prims, items: crate_items };
+
+    let mut type_did_to_deref_target: FxHashMap<DefId, &Type> = FxHashMap::default();
+    // Gather all type to `Deref` target edges.
+    for it in &new_items {
+        if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind {
+            if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
+                let target = items.iter().find_map(|item| match *item.kind {
+                    TypedefItem(ref t, true) => Some(&t.type_),
+                    _ => None,
+                });
+                if let (Some(for_did), Some(target)) = (for_.def_id(), target) {
+                    type_did_to_deref_target.insert(for_did, target);
+                }
+            }
+        }
+    }
+    // Follow all `Deref` targets of included items and recursively add them as valid
+    fn add_deref_target(
+        map: &FxHashMap<DefId, &Type>,
+        cleaner: &mut BadImplStripper,
+        type_did: &DefId,
+    ) {
+        if let Some(target) = map.get(type_did) {
+            debug!("add_deref_target: type {:?}, target {:?}", type_did, target);
+            if let Some(target_prim) = target.primitive_type() {
+                cleaner.prims.insert(target_prim);
+            } else if let Some(target_did) = target.def_id() {
+                // `impl Deref<Target = S> for S`
+                if target_did == *type_did {
+                    // Avoid infinite cycles
+                    return;
+                }
+                cleaner.items.insert(target_did);
+                add_deref_target(map, cleaner, &target_did);
+            }
+        }
+    }
+    for type_did in type_did_to_deref_target.keys() {
+        // Since only the `DefId` portion of the `Type` instances is known to be same for both the
+        // `Deref` target type and the impl for type positions, this map of types is keyed by
+        // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly.
+        if cleaner.keep_impl_with_def_id(type_did) {
+            add_deref_target(&type_did_to_deref_target, &mut cleaner, type_did);
+        }
+    }
+
+    new_items.retain(|it| {
+        if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind {
+            cleaner.keep_impl(for_)
+                || trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t))
+                || blanket_impl.is_some()
+        } else {
+            true
+        }
+    });
+
     if let Some(ref mut it) = krate.module {
         if let ModuleItem(Module { ref mut items, .. }) = *it.kind {
             items.extend(synth.impls);
@@ -192,16 +216,20 @@
 }
 
 impl BadImplStripper {
-    fn keep_item(&self, ty: &Type) -> bool {
+    fn keep_impl(&self, ty: &Type) -> bool {
         if let Generic(_) = ty {
             // keep impls made on generics
             true
         } else if let Some(prim) = ty.primitive_type() {
             self.prims.contains(&prim)
         } else if let Some(did) = ty.def_id() {
-            self.items.contains(&did)
+            self.keep_impl_with_def_id(&did)
         } else {
             false
         }
     }
+
+    fn keep_impl_with_def_id(&self, did: &DefId) -> bool {
+        self.items.contains(did)
+    }
 }
diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs
index a7a1ba1..38ec2be 100644
--- a/src/librustdoc/passes/html_tags.rs
+++ b/src/librustdoc/passes/html_tags.rs
@@ -59,7 +59,7 @@
                 continue;
             }
             let last_tag_name_low = last_tag_name.to_lowercase();
-            if ALLOWED_UNCLOSED.iter().any(|&at| at == &last_tag_name_low) {
+            if ALLOWED_UNCLOSED.iter().any(|&at| at == last_tag_name_low) {
                 continue;
             }
             // `tags` is used as a queue, meaning that everything after `pos` is included inside it.
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 51818d7..7ac42c7 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -14,9 +14,6 @@
 mod non_autolinks;
 crate use self::non_autolinks::CHECK_NON_AUTOLINKS;
 
-mod collapse_docs;
-crate use self::collapse_docs::COLLAPSE_DOCS;
-
 mod strip_hidden;
 crate use self::strip_hidden::STRIP_HIDDEN;
 
@@ -84,7 +81,6 @@
     CHECK_PRIVATE_ITEMS_DOC_TESTS,
     STRIP_HIDDEN,
     UNINDENT_COMMENTS,
-    COLLAPSE_DOCS,
     STRIP_PRIVATE,
     STRIP_PRIV_IMPORTS,
     PROPAGATE_DOC_CFG,
@@ -99,7 +95,6 @@
 /// The list of passes run by default.
 crate 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),
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index 01e3d0a..a276b7a 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -26,9 +26,7 @@
 
     // strip all impls referencing stripped items
     let mut stripper = ImplStripper { retained: &retained };
-    let krate = stripper.fold_crate(krate);
-
-    krate
+    stripper.fold_crate(krate)
 }
 
 struct Stripper<'a> {
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index a192442..162b709 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -94,7 +94,7 @@
             // implementations of traits are always public.
             clean::ImplItem(ref imp) if imp.trait_.is_some() => true,
             // Struct variant fields have inherited visibility
-            clean::VariantItem(clean::Variant { kind: clean::VariantKind::Struct(..) }) => true,
+            clean::VariantItem(clean::Variant::Struct(..)) => true,
             _ => false,
         };
 
diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs
index d0345d1..1cad480 100644
--- a/src/librustdoc/passes/unindent_comments.rs
+++ b/src/librustdoc/passes/unindent_comments.rs
@@ -68,7 +68,7 @@
     let min_indent = match docs
         .iter()
         .map(|fragment| {
-            fragment.doc.lines().fold(usize::MAX, |min_indent, line| {
+            fragment.doc.as_str().lines().fold(usize::MAX, |min_indent, line| {
                 if line.chars().all(|c| c.is_whitespace()) {
                     min_indent
                 } else {
@@ -87,7 +87,7 @@
     };
 
     for fragment in docs {
-        if fragment.doc.lines().count() == 0 {
+        if fragment.doc.as_str().lines().count() == 0 {
             continue;
         }
 
@@ -97,18 +97,6 @@
             min_indent
         };
 
-        fragment.doc = fragment
-            .doc
-            .lines()
-            .map(|line| {
-                if line.chars().all(|c| c.is_whitespace()) {
-                    line.to_string()
-                } else {
-                    assert!(line.len() >= min_indent);
-                    line[min_indent..].to_string()
-                }
-            })
-            .collect::<Vec<_>>()
-            .join("\n");
+        fragment.indent = min_indent;
     }
 }
diff --git a/src/librustdoc/passes/unindent_comments/tests.rs b/src/librustdoc/passes/unindent_comments/tests.rs
index 9dec71f..9c99248 100644
--- a/src/librustdoc/passes/unindent_comments/tests.rs
+++ b/src/librustdoc/passes/unindent_comments/tests.rs
@@ -1,21 +1,27 @@
 use super::*;
 use rustc_span::source_map::DUMMY_SP;
+use rustc_span::symbol::Symbol;
+use rustc_span::with_default_session_globals;
 
 fn create_doc_fragment(s: &str) -> Vec<DocFragment> {
     vec![DocFragment {
         line: 0,
         span: DUMMY_SP,
         parent_module: None,
-        doc: s.to_string(),
+        doc: Symbol::intern(s),
         kind: DocFragmentKind::SugaredDoc,
+        need_backline: false,
+        indent: 0,
     }]
 }
 
 #[track_caller]
 fn run_test(input: &str, expected: &str) {
-    let mut s = create_doc_fragment(input);
-    unindent_fragments(&mut s);
-    assert_eq!(s[0].doc, expected);
+    with_default_session_globals(|| {
+        let mut s = create_doc_fragment(input);
+        unindent_fragments(&mut s);
+        assert_eq!(&s.iter().collect::<String>(), expected);
+    });
 }
 
 #[test]
diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs
index 3bcf64f..24d5770 100644
--- a/src/librustdoc/theme.rs
+++ b/src/librustdoc/theme.rs
@@ -70,15 +70,15 @@
     }
 
     fn is_comment(&self) -> bool {
-        match *self {
-            Events::StartLineComment(_) | Events::StartComment(_) | Events::EndComment(_) => true,
-            _ => false,
-        }
+        matches!(
+            self,
+            Events::StartLineComment(_) | Events::StartComment(_) | Events::EndComment(_)
+        )
     }
 }
 
 fn previous_is_line_comment(events: &[Events]) -> bool {
-    if let Some(&Events::StartLineComment(_)) = events.last() { true } else { false }
+    matches!(events.last(), Some(&Events::StartLineComment(_)))
 }
 
 fn is_line_comment(pos: usize, v: &[u8], events: &[Events]) -> bool {
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 3c0aeaa..7d161ca 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -61,20 +61,60 @@
     }
 
     crate fn visit(mut self, krate: &'tcx hir::Crate<'_>) -> Module<'tcx> {
-        let mut module = self.visit_mod_contents(
+        let mut top_level_module = self.visit_mod_contents(
             krate.item.span,
             &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public },
             hir::CRATE_HIR_ID,
             &krate.item.module,
             None,
         );
-        // Attach the crate's exported macros to the top-level module:
-        module.macros.extend(krate.exported_macros.iter().map(|def| (def, None)));
-        module.is_crate = true;
-
+        top_level_module.is_crate = true;
+        // Attach the crate's exported macros to the top-level module.
+        // In the case of macros 2.0 (`pub macro`), and for built-in `derive`s or attributes as
+        // well (_e.g._, `Copy`), these are wrongly bundled in there too, so we need to fix that by
+        // moving them back to their correct locations.
+        'exported_macros: for def in krate.exported_macros {
+            // The `def` of a macro in `exported_macros` should correspond to either:
+            //  - a `#[macro_export] macro_rules!` macro,
+            //  - a built-in `derive` (or attribute) macro such as the ones in `::core`,
+            //  - a `pub macro`.
+            // Only the last two need to be fixed, thus:
+            if def.ast.macro_rules {
+                top_level_module.macros.push((def, None));
+                continue 'exported_macros;
+            }
+            let tcx = self.cx.tcx;
+            // Note: this is not the same as `.parent_module()`. Indeed, the latter looks
+            // for the closest module _ancestor_, which is not necessarily a direct parent
+            // (since a direct parent isn't necessarily a module, c.f. #77828).
+            let macro_parent_def_id = {
+                use rustc_middle::ty::DefIdTree;
+                tcx.parent(tcx.hir().local_def_id(def.hir_id).to_def_id()).unwrap()
+            };
+            let macro_parent_path = tcx.def_path(macro_parent_def_id);
+            // HACK: rustdoc has no way to lookup `doctree::Module`s by their HirId. Instead,
+            // lookup the module by its name, by looking at each path segment one at a time.
+            let mut cur_mod = &mut top_level_module;
+            for path_segment in macro_parent_path.data {
+                // Path segments may refer to a module (in which case they belong to the type
+                // namespace), which is _necessary_ for the macro to be accessible outside it
+                // (no "associated macros" as of yet). Else we bail with an outer `continue`.
+                let path_segment_ty_ns = match path_segment.data {
+                    rustc_hir::definitions::DefPathData::TypeNs(symbol) => symbol,
+                    _ => continue 'exported_macros,
+                };
+                // Descend into the child module that matches this path segment (if any).
+                match cur_mod.mods.iter_mut().find(|child| child.name == Some(path_segment_ty_ns)) {
+                    Some(child_mod) => cur_mod = &mut *child_mod,
+                    None => continue 'exported_macros,
+                }
+            }
+            let cur_mod_def_id = tcx.hir().local_def_id(cur_mod.id).to_def_id();
+            assert_eq!(cur_mod_def_id, macro_parent_def_id);
+            cur_mod.macros.push((def, None));
+        }
         self.cx.renderinfo.get_mut().exact_paths = self.exact_paths;
-
-        module
+        top_level_module
     }
 
     fn visit_mod_contents(
@@ -276,15 +316,7 @@
                     }
                 }
 
-                om.imports.push(Import {
-                    name,
-                    id: item.hir_id,
-                    vis: &item.vis,
-                    attrs: &item.attrs,
-                    path,
-                    glob: is_glob,
-                    span: item.span,
-                });
+                om.items.push((item, renamed))
             }
             hir::ItemKind::Mod(ref m) => {
                 om.mods.push(self.visit_mod_contents(
@@ -312,10 +344,10 @@
                     om.items.push((item, renamed));
                 }
             }
-            hir::ItemKind::Impl { ref of_trait, .. } => {
+            hir::ItemKind::Impl(ref impl_) => {
                 // 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 && of_trait.is_none() {
+                if !self.inlining && impl_.of_trait.is_none() {
                     om.items.push((item, None));
                 }
             }
diff --git a/src/llvm-project b/src/llvm-project
index 8d78ad1..f9a8d70 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit 8d78ad13896b955f630714f386a95ed91b237e3d
+Subproject commit f9a8d70b6e0365ac2172ca6b7f1de0341297458d
diff --git a/src/test/assembly/stack-probes.rs b/src/test/assembly/stack-probes.rs
new file mode 100644
index 0000000..9597e24
--- /dev/null
+++ b/src/test/assembly/stack-probes.rs
@@ -0,0 +1,42 @@
+// min-llvm-version: 11.0.1
+// revisions: x86_64 i686
+// assembly-output: emit-asm
+//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[i686] compile-flags: --target i686-unknown-linux-gnu
+// compile-flags: -C llvm-args=--x86-asm-syntax=intel
+
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for u8 {}
+
+// Check that inline-asm stack probes are generated correctly.
+// To avoid making this test fragile to slight asm changes,
+// we only check that the stack pointer is decremented by a page at a time,
+// instead of matching the whole probe sequence.
+
+// CHECK-LABEL: small_stack_probe:
+#[no_mangle]
+pub fn small_stack_probe(x: u8, f: fn([u8; 8192])) {
+    // CHECK-NOT: __rust_probestack
+    // x86_64: sub rsp, 4096
+    // i686: sub esp, 4096
+    let a = [x; 8192];
+    f(a);
+}
+
+// CHECK-LABEL: big_stack_probe:
+#[no_mangle]
+pub fn big_stack_probe(x: u8, f: fn([u8; 65536])) {
+    // CHECK-NOT: __rust_probestack
+    // x86_64: sub rsp, 4096
+    // i686: sub esp, 4096
+    let a = [x; 65536];
+    f(a);
+}
diff --git a/src/test/codegen/call-llvm-intrinsics.rs b/src/test/codegen/call-llvm-intrinsics.rs
index 24e3d3c..998099c 100644
--- a/src/test/codegen/call-llvm-intrinsics.rs
+++ b/src/test/codegen/call-llvm-intrinsics.rs
@@ -13,7 +13,7 @@
     }
 }
 
-extern {
+extern "C" {
     #[link_name = "llvm.sqrt.f32"]
     fn sqrt(x: f32) -> f32;
 }
diff --git a/src/test/codegen/dealloc-no-unwind.rs b/src/test/codegen/dealloc-no-unwind.rs
index ff21b4c..f047c7a 100644
--- a/src/test/codegen/dealloc-no-unwind.rs
+++ b/src/test/codegen/dealloc-no-unwind.rs
@@ -8,7 +8,7 @@
 
 impl Drop for A {
     fn drop(&mut self) {
-        extern { fn foo(); }
+        extern "C" { fn foo(); }
         unsafe { foo(); }
     }
 }
diff --git a/src/test/codegen/debug-column.rs b/src/test/codegen/debug-column.rs
index f348c48..5d3afef 100644
--- a/src/test/codegen/debug-column.rs
+++ b/src/test/codegen/debug-column.rs
@@ -18,7 +18,7 @@
     }
 }
 
-extern {
+extern "C" {
     fn giraffe();
     fn turtle();
 }
diff --git a/src/test/codegen/debug-linkage-name.rs b/src/test/codegen/debug-linkage-name.rs
index 0d7dca3..9011a7d 100644
--- a/src/test/codegen/debug-linkage-name.rs
+++ b/src/test/codegen/debug-linkage-name.rs
@@ -26,17 +26,17 @@
     // CHECK: !DISubprogram(name: "e",
     // CHECK:               linkageName:
     // CHECK-SAME:          line: 29,
-    pub extern fn e() {}
+    pub extern "C" fn e() {}
 
     // CHECK: !DISubprogram(name: "f",
     // CHECK-NOT:           linkageName:
     // CHECK-SAME:          line: 35,
     #[no_mangle]
-    pub extern fn f() {}
+    pub extern "C" fn f() {}
 
     // CHECK: !DISubprogram(name: "g",
     // CHECK-NOT:           linkageName:
     // CHECK-SAME:          line: 41,
     #[export_name = "g"]
-    pub extern fn g() {}
+    pub extern "C" fn g() {}
 }
diff --git a/src/test/codegen/export-no-mangle.rs b/src/test/codegen/export-no-mangle.rs
index 59e9760..a89d48e 100644
--- a/src/test/codegen/export-no-mangle.rs
+++ b/src/test/codegen/export-no-mangle.rs
@@ -13,19 +13,19 @@
 
     // CHECK: void @a()
     #[no_mangle]
-    pub extern fn a() {}
+    pub extern "C" fn a() {}
 
     // CHECK: void @b()
     #[export_name = "b"]
-    extern fn b() {}
+    extern "C" fn b() {}
 
     // CHECK: void @c()
     #[export_name = "c"]
     #[inline]
-    extern fn c() {}
+    extern "C" fn c() {}
 
     // CHECK: void @d()
     #[export_name = "d"]
     #[inline(always)]
-    extern fn d() {}
+    extern "C" fn d() {}
 }
diff --git a/src/test/codegen/ffi-const.rs b/src/test/codegen/ffi-const.rs
index 440d022..67baf6f 100644
--- a/src/test/codegen/ffi-const.rs
+++ b/src/test/codegen/ffi-const.rs
@@ -4,7 +4,7 @@
 
 pub fn bar() { unsafe { foo() } }
 
-extern {
+extern "C" {
     // CHECK-LABEL: declare void @foo()
     // CHECK-SAME: [[ATTRS:#[0-9]+]]
     // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}readnone{{.*}} }
diff --git a/src/test/codegen/ffi-out-of-bounds-loads.rs b/src/test/codegen/ffi-out-of-bounds-loads.rs
index 139a06a..dc16306 100644
--- a/src/test/codegen/ffi-out-of-bounds-loads.rs
+++ b/src/test/codegen/ffi-out-of-bounds-loads.rs
@@ -11,7 +11,7 @@
     f3: i32,
 }
 
-extern {
+extern "C" {
     fn foo(s: S);
 }
 
diff --git a/src/test/codegen/ffi-pure.rs b/src/test/codegen/ffi-pure.rs
index f0ebc1c..3afb085 100644
--- a/src/test/codegen/ffi-pure.rs
+++ b/src/test/codegen/ffi-pure.rs
@@ -4,7 +4,7 @@
 
 pub fn bar() { unsafe { foo() } }
 
-extern {
+extern "C" {
     // CHECK-LABEL: declare void @foo()
     // CHECK-SAME: [[ATTRS:#[0-9]+]]
     // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}readonly{{.*}} }
diff --git a/src/test/codegen/ffi-returns-twice.rs b/src/test/codegen/ffi-returns-twice.rs
index 4db328f..75301df 100644
--- a/src/test/codegen/ffi-returns-twice.rs
+++ b/src/test/codegen/ffi-returns-twice.rs
@@ -4,7 +4,7 @@
 
 pub fn bar() { unsafe { foo() } }
 
-extern {
+extern "C" {
     // CHECK-LABEL: declare void @foo()
     // CHECK-SAME: [[ATTRS:#[0-9]+]]
     // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}returns_twice{{.*}} }
diff --git a/src/test/codegen/intrinsics/move-val-init.rs b/src/test/codegen/intrinsics/move-val-init.rs
deleted file mode 100644
index 6222536..0000000
--- a/src/test/codegen/intrinsics/move-val-init.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// compile-flags: -C no-prepopulate-passes
-
-#![feature(core_intrinsics)]
-#![crate_type = "lib"]
-
-// test that `move_val_init` actually avoids big allocas
-
-use std::intrinsics::move_val_init;
-
-pub struct Big {
-    pub data: [u8; 65536]
-}
-
-// CHECK-LABEL: @test_mvi
-#[no_mangle]
-pub unsafe fn test_mvi(target: *mut Big, make_big: fn() -> Big) {
-    // CHECK: call void %make_big(%Big*{{[^%]*}} %target)
-    move_val_init(target, make_big());
-}
diff --git a/src/test/codegen/issue-47278.rs b/src/test/codegen/issue-47278.rs
index 590e8ea..9076274 100644
--- a/src/test/codegen/issue-47278.rs
+++ b/src/test/codegen/issue-47278.rs
@@ -6,4 +6,4 @@
 
 // CHECK: define {{.*}} @foo(
 #[no_mangle]
-pub extern fn foo(_: Foo) -> Foo { loop {} }
+pub extern "C" fn foo(_: Foo) -> Foo { loop {} }
diff --git a/src/test/codegen/issue-59352.rs b/src/test/codegen/issue-59352.rs
new file mode 100644
index 0000000..28bb859
--- /dev/null
+++ b/src/test/codegen/issue-59352.rs
@@ -0,0 +1,18 @@
+// This test is a mirror of mir-opt/issues/issue-59352.rs. The LLVM inliner doesn't inline
+// `char::method::is_digit()` and `char::method::to_digit()`, probably because of their size.
+//
+// Currently, the MIR optimizer isn't capable of removing the unreachable panic in this test case.
+// Once the optimizer can do that, mir-opt/issues/issue-59352.rs will need to be updated and this
+// test case should be removed as it will become redundant.
+
+// mir-opt-level=2 enables inlining and enables LLVM to optimize away the unreachable panic call.
+// compile-flags: -O -Z mir-opt-level=2
+
+#![crate_type = "rlib"]
+
+// CHECK-LABEL: @num_to_digit
+#[no_mangle]
+pub fn num_to_digit(num: char) -> u32 {
+    // CHECK-NOT: panic
+    if num.is_digit(8) { num.to_digit(8).unwrap() } else { 0 }
+}
diff --git a/src/test/codegen/repr-transparent-aggregates-1.rs b/src/test/codegen/repr-transparent-aggregates-1.rs
index 59f29e7..2b8d3c8 100644
--- a/src/test/codegen/repr-transparent-aggregates-1.rs
+++ b/src/test/codegen/repr-transparent-aggregates-1.rs
@@ -36,19 +36,19 @@
 
 // CHECK: define void @test_BigS(%BigS* [[BIGS_RET_ATTRS:.*]], %BigS* [[BIGS_ARG_ATTRS1:.*]] byval(%BigS) [[BIGS_ARG_ATTRS2:.*]])
 #[no_mangle]
-pub extern fn test_BigS(_: BigS) -> BigS { loop {} }
+pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} }
 
 // CHECK: define void @test_TsBigS(%TsBigS* [[BIGS_RET_ATTRS]], %TsBigS* [[BIGS_ARG_ATTRS1]] byval(%TsBigS) [[BIGS_ARG_ATTRS2:.*]])
 #[no_mangle]
-pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
+pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
 
 // CHECK: define void @test_TuBigS(%TuBigS* [[BIGS_RET_ATTRS]], %TuBigS* [[BIGS_ARG_ATTRS1]] byval(%TuBigS) [[BIGS_ARG_ATTRS2:.*]])
 #[no_mangle]
-pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
+pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
 
 // CHECK: define void @test_TeBigS(%"TeBigS::Variant"* [[BIGS_RET_ATTRS]], %"TeBigS::Variant"* [[BIGS_ARG_ATTRS1]] byval(%"TeBigS::Variant") [[BIGS_ARG_ATTRS2]])
 #[no_mangle]
-pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
+pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
 
 
 #[derive(Clone, Copy)]
@@ -72,16 +72,16 @@
 
 // CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS:.*]], %BigU* [[BIGU_ARG_ATTRS1:.*]] byval(%BigU) [[BIGU_ARG_ATTRS2:.*]])
 #[no_mangle]
-pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
+pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} }
 
 // CHECK: define void @test_TsBigU(%TsBigU* [[BIGU_RET_ATTRS:.*]], %TsBigU* [[BIGU_ARG_ATTRS1]] byval(%TsBigU) [[BIGU_ARG_ATTRS2]])
 #[no_mangle]
-pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
+pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
 
 // CHECK: define void @test_TuBigU(%TuBigU* [[BIGU_RET_ATTRS]], %TuBigU* [[BIGU_ARG_ATTRS1]] byval(%TuBigU) [[BIGU_ARG_ATTRS2]])
 #[no_mangle]
-pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
+pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
 
 // CHECK: define void @test_TeBigU(%"TeBigU::Variant"* [[BIGU_RET_ATTRS]], %"TeBigU::Variant"* [[BIGU_ARG_ATTRS1]] byval(%"TeBigU::Variant") [[BIGU_ARG_ATTRS2]])
 #[no_mangle]
-pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }
+pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }
diff --git a/src/test/codegen/repr-transparent.rs b/src/test/codegen/repr-transparent.rs
index 7647e01..2999731 100644
--- a/src/test/codegen/repr-transparent.rs
+++ b/src/test/codegen/repr-transparent.rs
@@ -19,21 +19,21 @@
 
 // CHECK: define float @test_F32(float %_1)
 #[no_mangle]
-pub extern fn test_F32(_: F32) -> F32 { loop {} }
+pub extern "C" fn test_F32(_: F32) -> F32 { loop {} }
 
 #[repr(transparent)]
 pub struct Ptr(*mut u8);
 
 // CHECK: define i8* @test_Ptr(i8* %_1)
 #[no_mangle]
-pub extern fn test_Ptr(_: Ptr) -> Ptr { loop {} }
+pub extern "C" fn test_Ptr(_: Ptr) -> Ptr { loop {} }
 
 #[repr(transparent)]
 pub struct WithZst(u64, Zst1);
 
 // CHECK: define i64 @test_WithZst(i64 %_1)
 #[no_mangle]
-pub extern fn test_WithZst(_: WithZst) -> WithZst { loop {} }
+pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { loop {} }
 
 #[repr(transparent)]
 pub struct WithZeroSizedArray(*const f32, [i8; 0]);
@@ -41,14 +41,14 @@
 // Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever.
 // CHECK: define i32* @test_WithZeroSizedArray(i32* %_1)
 #[no_mangle]
-pub extern fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} }
+pub extern "C" fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} }
 
 #[repr(transparent)]
 pub struct Generic<T>(T);
 
 // CHECK: define double @test_Generic(double %_1)
 #[no_mangle]
-pub extern fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} }
+pub extern "C" fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} }
 
 #[repr(transparent)]
 pub struct GenericPlusZst<T>(T, Zst2);
@@ -58,14 +58,14 @@
 
 // CHECK: define{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %_1)
 #[no_mangle]
-pub extern fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} }
+pub extern "C" fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} }
 
 #[repr(transparent)]
 pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>);
 
 // CHECK: define i16* @test_LifetimePhantom(i16* %_1)
 #[no_mangle]
-pub extern fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} }
+pub extern "C" fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} }
 
 // This works despite current alignment resrictions because PhantomData is always align(1)
 #[repr(transparent)]
@@ -75,28 +75,28 @@
 
 // CHECK: define float @test_UnitPhantom(float %_1)
 #[no_mangle]
-pub extern fn test_UnitPhantom(_: UnitPhantom<f32, Px>) -> UnitPhantom<f32, Px> { loop {} }
+pub extern "C" fn test_UnitPhantom(_: UnitPhantom<f32, Px>) -> UnitPhantom<f32, Px> { loop {} }
 
 #[repr(transparent)]
 pub struct TwoZsts(Zst1, i8, Zst2);
 
 // CHECK: define{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %_1)
 #[no_mangle]
-pub extern fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} }
+pub extern "C" fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} }
 
 #[repr(transparent)]
 pub struct Nested1(Zst2, Generic<f64>);
 
 // CHECK: define double @test_Nested1(double %_1)
 #[no_mangle]
-pub extern fn test_Nested1(_: Nested1) -> Nested1 { loop {} }
+pub extern "C" fn test_Nested1(_: Nested1) -> Nested1 { loop {} }
 
 #[repr(transparent)]
 pub struct Nested2(Nested1, Zst1);
 
 // CHECK: define double @test_Nested2(double %_1)
 #[no_mangle]
-pub extern fn test_Nested2(_: Nested2) -> Nested2 { loop {} }
+pub extern "C" fn test_Nested2(_: Nested2) -> Nested2 { loop {} }
 
 #[repr(simd)]
 struct f32x4(f32, f32, f32, f32);
@@ -106,7 +106,7 @@
 
 // CHECK: define <4 x float> @test_Vector(<4 x float> %_1)
 #[no_mangle]
-pub extern fn test_Vector(_: Vector) -> Vector { loop {} }
+pub extern "C" fn test_Vector(_: Vector) -> Vector { loop {} }
 
 trait Mirror { type It: ?Sized; }
 impl<T: ?Sized> Mirror for T { type It = Self; }
@@ -116,7 +116,7 @@
 
 // CHECK: define float @test_Projection(float %_1)
 #[no_mangle]
-pub extern fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} }
+pub extern "C" fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} }
 
 #[repr(transparent)]
 pub enum EnumF32 {
@@ -125,7 +125,7 @@
 
 // CHECK: define float @test_EnumF32(float %_1)
 #[no_mangle]
-pub extern fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} }
+pub extern "C" fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} }
 
 #[repr(transparent)]
 pub enum EnumF32WithZsts {
@@ -134,7 +134,7 @@
 
 // CHECK: define float @test_EnumF32WithZsts(float %_1)
 #[no_mangle]
-pub extern fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} }
+pub extern "C" fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} }
 
 #[repr(transparent)]
 pub union UnionF32 {
@@ -143,7 +143,7 @@
 
 // CHECK: define float @test_UnionF32(float %_1)
 #[no_mangle]
-pub extern fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }
+pub extern "C" fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }
 
 #[repr(transparent)]
 pub union UnionF32WithZsts {
@@ -154,7 +154,7 @@
 
 // CHECK: define float @test_UnionF32WithZsts(float %_1)
 #[no_mangle]
-pub extern fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} }
+pub extern "C" fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} }
 
 
 // All that remains to be tested are aggregates. They are tested in separate files called repr-
diff --git a/src/test/codegen/riscv-abi/call-llvm-intrinsics.rs b/src/test/codegen/riscv-abi/call-llvm-intrinsics.rs
index f100a23..31a88f2 100644
--- a/src/test/codegen/riscv-abi/call-llvm-intrinsics.rs
+++ b/src/test/codegen/riscv-abi/call-llvm-intrinsics.rs
@@ -13,7 +13,7 @@
     }
 }
 
-extern {
+extern "C" {
     #[link_name = "llvm.sqrt.f32"]
     fn sqrt(x: f32) -> f32;
 }
diff --git a/src/test/codegen/sanitizer-no-sanitize.rs b/src/test/codegen/sanitizer-no-sanitize.rs
index 1b2b188..fb9d249 100644
--- a/src/test/codegen/sanitizer-no-sanitize.rs
+++ b/src/test/codegen/sanitizer-no-sanitize.rs
@@ -1,4 +1,4 @@
-// Verifies that no_sanitze attribute can be used to
+// Verifies that no_sanitize attribute can be used to
 // selectively disable sanitizer instrumentation.
 //
 // needs-sanitizer-address
diff --git a/src/test/codegen/slice-as_chunks.rs b/src/test/codegen/slice-as_chunks.rs
new file mode 100644
index 0000000..48e3f73
--- /dev/null
+++ b/src/test/codegen/slice-as_chunks.rs
@@ -0,0 +1,33 @@
+// no-system-llvm
+// compile-flags: -O
+// only-64bit (because the LLVM type of i64 for usize shows up)
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+#![feature(slice_as_chunks)]
+
+// CHECK-LABEL: @chunks4
+#[no_mangle]
+pub fn chunks4(x: &[u8]) -> &[[u8; 4]] {
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: lshr i64 %x.1, 2
+    // CHECK-NOT: shl
+    // CHECK-NOT: mul
+    // CHECK-NOT: udiv
+    // CHECK-NOT: urem
+    // CHECK: ret
+    x.as_chunks().0
+}
+
+// CHECK-LABEL: @chunks4_with_remainder
+#[no_mangle]
+pub fn chunks4_with_remainder(x: &[u8]) -> (&[[u8; 4]], &[u8]) {
+    // CHECK: and i64 %x.1, -4
+    // CHECK: and i64 %x.1, 3
+    // CHECK: lshr exact
+    // CHECK-NOT: mul
+    // CHECK-NOT: udiv
+    // CHECK-NOT: urem
+    // CHECK: ret
+    x.as_chunks()
+}
diff --git a/src/test/codegen/stack-probes.rs b/src/test/codegen/stack-probes.rs
index 3e3222d..b05787d 100644
--- a/src/test/codegen/stack-probes.rs
+++ b/src/test/codegen/stack-probes.rs
@@ -13,11 +13,12 @@
 // ignore-emscripten
 // ignore-windows
 // compile-flags: -C no-prepopulate-passes
+// min-llvm-version: 11.0.1
 
 #![crate_type = "lib"]
 
 #[no_mangle]
 pub fn foo() {
 // CHECK: @foo() unnamed_addr #0
-// CHECK: attributes #0 = { {{.*}}"probe-stack"="__rust_probestack"{{.*}} }
+// CHECK: attributes #0 = { {{.*}}"probe-stack"="inline-asm"{{.*}} }
 }
diff --git a/src/test/codegen/target-cpu-on-functions.rs b/src/test/codegen/target-cpu-on-functions.rs
index 523216d..7544ac0 100644
--- a/src/test/codegen/target-cpu-on-functions.rs
+++ b/src/test/codegen/target-cpu-on-functions.rs
@@ -9,7 +9,7 @@
 
 // CHECK-LABEL: define {{.*}} @exported() {{.*}} #0
 #[no_mangle]
-pub extern fn exported() {
+pub extern "C" fn exported() {
     not_exported();
 }
 
diff --git a/src/test/codegen/unwind-extern-exports.rs b/src/test/codegen/unwind-extern-exports.rs
index e5a2936..487de20 100644
--- a/src/test/codegen/unwind-extern-exports.rs
+++ b/src/test/codegen/unwind-extern-exports.rs
@@ -11,7 +11,7 @@
 // "C" ABI
 // pub extern fn foo() {} // FIXME right now we don't abort-on-panic but add `nounwind` nevertheless
 #[unwind(allowed)]
-pub extern fn foo_allowed() {}
+pub extern "C" fn foo_allowed() {}
 
 // "Rust"
 // (`extern "Rust"` could be removed as all `fn` get it implicitly; we leave it in for clarity.)
diff --git a/src/test/codegen/unwind-extern-imports.rs b/src/test/codegen/unwind-extern-imports.rs
index 8403e1e..a2ba24a 100644
--- a/src/test/codegen/unwind-extern-imports.rs
+++ b/src/test/codegen/unwind-extern-imports.rs
@@ -4,7 +4,7 @@
 #![crate_type = "lib"]
 #![feature(unwind_attributes)]
 
-extern {
+extern "C" {
 // CHECK: Function Attrs:{{.*}}nounwind
 // CHECK-NEXT: declare void @extern_fn
     fn extern_fn();
diff --git a/src/test/codegen/vecdeque_no_panic.rs b/src/test/codegen/vecdeque_no_panic.rs
new file mode 100644
index 0000000..cbf420b
--- /dev/null
+++ b/src/test/codegen/vecdeque_no_panic.rs
@@ -0,0 +1,19 @@
+// This test checks that `VecDeque::front[_mut]()` and `VecDeque::back[_mut]()` can't panic.
+
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+use std::collections::VecDeque;
+
+// CHECK-LABEL: @dont_panic
+#[no_mangle]
+pub fn dont_panic(v: &mut VecDeque<usize>) {
+    // CHECK-NOT: expect
+    // CHECK-NOT: panic
+    v.front();
+    v.front_mut();
+    v.back();
+    v.back_mut();
+}
diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs
index 1e0e8be..43e68fe 100644
--- a/src/test/debuginfo/type-names.rs
+++ b/src/test/debuginfo/type-names.rs
@@ -23,7 +23,6 @@
 // gdbg-check:type = struct Struct2
 // gdbr-check:type = type_names::mod1::Struct2
 
-
 // ENUMS
 // gdb-command:whatis simple_enum_1
 // gdbg-check:type = union Enum1
@@ -45,7 +44,6 @@
 // gdbg-check:type = union Enum3<type_names::Struct1>
 // gdbr-check:type = type_names::mod1::mod2::Enum3<type_names::Struct1>
 
-
 // TUPLES
 // gdb-command:whatis tuple1
 // gdbg-check:type = struct (u32, type_names::Struct1, type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>)
@@ -55,7 +53,6 @@
 // gdbg-check:type = struct ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char)
 // gdbr-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char)
 
-
 // BOX
 // gdb-command:whatis box1
 // gdbg-check:type = struct (alloc::boxed::Box<f32>, i32)
@@ -65,7 +62,6 @@
 // gdbg-check:type = struct (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>>, i32)
 // gdbr-check:type = (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>>, i32)
 
-
 // REFERENCES
 // gdb-command:whatis ref1
 // gdbg-check:type = struct (&type_names::Struct1, i32)
@@ -83,7 +79,6 @@
 // gdbg-check:type = struct (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32)
 // gdbr-check:type = (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32)
 
-
 // RAW POINTERS
 // gdb-command:whatis mut_ptr1
 // gdbg-check:type = struct (*mut type_names::Struct1, isize)
@@ -109,7 +104,6 @@
 // gdbg-check:type = struct (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
 // gdbr-check:type = (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
 
-
 // VECTORS
 // gdb-command:whatis fixed_size_vec1
 // gdbg-check:type = struct ([type_names::Struct1; 3], i16)
@@ -127,7 +121,6 @@
 // gdbg-check:type = struct &[type_names::mod1::Enum2]
 // gdbr-check:type = &[type_names::mod1::Enum2]
 
-
 // TRAITS
 // gdb-command:whatis box_trait
 // gdbg-check:type = struct Box<Trait1>
@@ -153,7 +146,6 @@
 // gdbg-check:type = struct &mut Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
 // gdbr-check:type = type_names::&mut Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
 
-
 // BARE FUNCTIONS
 // gdb-command:whatis rust_fn
 // gdbg-check:type = struct (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize)
@@ -199,7 +191,6 @@
 // gdbg-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize)
 // gdbr-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize)
 
-
 // CLOSURES
 // gdb-command:whatis closure1
 // gdbg-check:type = struct (closure, usize)
@@ -219,7 +210,7 @@
 use std::ptr;
 
 pub struct Struct1;
-struct GenericStruct<T1, T2>(PhantomData<(T1,T2)>);
+struct GenericStruct<T1, T2>(PhantomData<(T1, T2)>);
 
 enum Enum1 {
     Variant1,
@@ -246,8 +237,12 @@
     }
 }
 
-trait Trait1 { fn dummy(&self) { } }
-trait Trait2<T1, T2> { fn dummy(&self, _: T1, _:T2) { } }
+trait Trait1 {
+    fn dummy(&self) {}
+}
+trait Trait2<T1, T2> {
+    fn dummy(&self, _: T1, _: T2) {}
+}
 
 impl Trait1 for isize {}
 impl<T1, T2> Trait2<T1, T2> for isize {}
@@ -257,16 +252,26 @@
 unsafe fn unsafe_fn(_: Result<char, f64>) {}
 extern "stdcall" fn extern_stdcall_fn() {}
 
-fn rust_fn_with_return_value(_: f64) -> usize { 4 }
-extern "C" fn extern_c_fn_with_return_value() -> Struct1 { Struct1 }
-unsafe fn unsafe_fn_with_return_value(_: GenericStruct<u16, u8>) -> mod1::Struct2 { mod1::Struct2 }
-extern "stdcall" fn extern_stdcall_fn_with_return_value(_: Box<isize>) -> usize { 0 }
+fn rust_fn_with_return_value(_: f64) -> usize {
+    4
+}
+extern "C" fn extern_c_fn_with_return_value() -> Struct1 {
+    Struct1
+}
+unsafe fn unsafe_fn_with_return_value(_: GenericStruct<u16, u8>) -> mod1::Struct2 {
+    mod1::Struct2
+}
+extern "stdcall" fn extern_stdcall_fn_with_return_value(_: Box<isize>) -> usize {
+    0
+}
 
-fn generic_function<T>(x: T) -> T { x }
+fn generic_function<T>(x: T) -> T {
+    x
+}
 
 #[allow(improper_ctypes)]
-extern {
-    fn printf(_:*const u8, ...) -> isize;
+extern "C" {
+    fn printf(_: *const u8, ...) -> isize;
 }
 
 // In many of the cases below, the type that is actually under test is wrapped
@@ -277,7 +282,6 @@
 // printed correctly, so the tests below just construct a tuple type that will
 // then *contain* the type name that we want to see.
 fn main() {
-
     // Structs
     let simple_struct = Struct1;
     let generic_struct1: GenericStruct<mod1::Struct2, mod1::mod2::Struct3> =
@@ -336,11 +340,11 @@
     let mut_ref_trait = (&mut mut_int1) as &mut Trait1;
 
     let generic_box_trait = (box 0_isize) as Box<Trait2<i32, mod1::Struct2>>;
-    let generic_ref_trait  = (&0_isize) as &Trait2<Struct1, Struct1>;
+    let generic_ref_trait = (&0_isize) as &Trait2<Struct1, Struct1>;
 
     let mut generic_mut_ref_trait_impl = 0_isize;
-    let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl) as
-        &mut Trait2<mod1::mod2::Struct3, GenericStruct<usize, isize>>;
+    let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl)
+        as &mut Trait2<mod1::mod2::Struct3, GenericStruct<usize, isize>>;
 
     // Bare Functions
     let rust_fn = (rust_fn, 0_usize);
@@ -364,11 +368,13 @@
     // how that maps to rustc's internal representation of these forms.
     // Once closures have reached their 1.0 form, the tests below should
     // probably be expanded.
-    let closure1 = (|x:isize| {}, 0_usize);
-    let closure2 = (|x:i8, y: f32| { (x as f32) + y }, 0_usize);
+    let closure1 = (|x: isize| {}, 0_usize);
+    let closure2 = (|x: i8, y: f32| (x as f32) + y, 0_usize);
 
     zzz(); // #break
 }
 
 #[inline(never)]
-fn zzz() { () }
+fn zzz() {
+    ()
+}
diff --git a/src/test/incremental/foreign.rs b/src/test/incremental/foreign.rs
index 498bf89..f46f92e 100644
--- a/src/test/incremental/foreign.rs
+++ b/src/test/incremental/foreign.rs
@@ -13,7 +13,7 @@
 mod mlibc {
     use libc::{c_char, c_long, c_longlong};
 
-    extern {
+    extern "C" {
         pub fn atol(x: *const c_char) -> c_long;
         pub fn atoll(x: *const c_char) -> c_longlong;
     }
@@ -31,6 +31,8 @@
 
 pub fn main() {
     assert_eq!(atol("1024".to_string()) * 10, atol("10240".to_string()));
-    assert_eq!((atoll("11111111111111111".to_string()) * 10),
-             atoll("111111111111111110".to_string()));
+    assert_eq!(
+        (atoll("11111111111111111".to_string()) * 10),
+        atoll("111111111111111110".to_string())
+    );
 }
diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs
index 59af1fc..ca8daae 100644
--- a/src/test/incremental/hashes/if_expressions.rs
+++ b/src/test/incremental/hashes/if_expressions.rs
@@ -94,7 +94,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_else_branch(x: bool) -> u32 {
     let mut ret = 1;
diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs
index fcd12ad..2e98aba 100644
--- a/src/test/incremental/hashes/inherent_impls.rs
+++ b/src/test/incremental/hashes/inherent_impls.rs
@@ -271,7 +271,7 @@
 impl Foo {
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
     #[rustc_clean(cfg="cfail3")]
-    pub extern fn make_method_extern(&self) { }
+    pub extern "C" fn make_method_extern(&self) { }
 }
 
 
diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs
index aa39ea8..4dab032 100644
--- a/src/test/incremental/hashes/trait_defs.rs
+++ b/src/test/incremental/hashes/trait_defs.rs
@@ -312,7 +312,7 @@
 trait TraitAddExternModifier {
     #[rustc_dirty(label="hir_owner", cfg="cfail2")]
     #[rustc_clean(label="hir_owner", cfg="cfail3")]
-    extern fn method();
+    extern "C" fn method();
 }
 
 
diff --git a/src/test/incremental/issue-80336-invalid-span.rs b/src/test/incremental/issue-80336-invalid-span.rs
new file mode 100644
index 0000000..7757d91
--- /dev/null
+++ b/src/test/incremental/issue-80336-invalid-span.rs
@@ -0,0 +1,10 @@
+// Regression test for issue #80336
+// Test that we properly handle encoding, decoding, and hashing
+// of spans with an invalid location and non-root `SyntaxContext`
+
+// revisions:rpass1 rpass2
+// only-x86_64
+
+pub fn main() {
+    let _ = is_x86_feature_detected!("avx2");
+}
diff --git a/src/test/mir-opt/const-promotion-extern-static.rs b/src/test/mir-opt/const-promotion-extern-static.rs
index 0f13fe1..a0d4e9b 100644
--- a/src/test/mir-opt/const-promotion-extern-static.rs
+++ b/src/test/mir-opt/const-promotion-extern-static.rs
@@ -5,11 +5,11 @@
 static Y: i32 = 42;
 
 // EMIT_MIR const_promotion_extern_static.BAR.PromoteTemps.diff
-// EMIT_MIR const_promotion_extern_static.BAR-promoted[0].ConstProp.after.mir
+// EMIT_MIR const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir
 static mut BAR: *const &i32 = [&Y].as_ptr();
 
 // EMIT_MIR const_promotion_extern_static.FOO.PromoteTemps.diff
-// EMIT_MIR const_promotion_extern_static.FOO-promoted[0].ConstProp.after.mir
+// EMIT_MIR const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir
 static mut FOO: *const &i32 = [unsafe { &X }].as_ptr();
 
 // EMIT_MIR const_promotion_extern_static.BOP.mir_map.0.mir
diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
index 8b09ead..a137d7f 100644
--- a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
+++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
@@ -24,42 +24,42 @@
 }
 
 alloc0 (static: FOO, size: 8, align: 4) {
-    ╾─alloc14─╼ 03 00 00 00                         │ ╾──╼....
+    ╾─alloc17─╼ 03 00 00 00                         │ ╾──╼....
 }
 
-alloc14 (size: 48, align: 4) {
+alloc17 (size: 48, align: 4) {
     0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc4──╼ 00 00 00 00 │ ....░░░░╾──╼....
-    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc7──╼ 02 00 00 00 │ ....░░░░╾──╼....
-    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc11─╼ 03 00 00 00 │ ....*...╾──╼....
+    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 02 00 00 00 │ ....░░░░╾──╼....
+    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc13─╼ 03 00 00 00 │ ....*...╾──╼....
 }
 
 alloc4 (size: 0, align: 4) {}
 
-alloc7 (size: 16, align: 4) {
-    ╾─alloc6──╼ 03 00 00 00 ╾─alloc8──╼ 03 00 00 00 │ ╾──╼....╾──╼....
+alloc8 (size: 16, align: 4) {
+    ╾─alloc7──╼ 03 00 00 00 ╾─alloc9──╼ 03 00 00 00 │ ╾──╼....╾──╼....
 }
 
-alloc6 (size: 3, align: 1) {
+alloc7 (size: 3, align: 1) {
     66 6f 6f                                        │ foo
 }
 
-alloc8 (size: 3, align: 1) {
+alloc9 (size: 3, align: 1) {
     62 61 72                                        │ bar
 }
 
-alloc11 (size: 24, align: 4) {
-    0x00 │ ╾─alloc10─╼ 03 00 00 00 ╾─alloc12─╼ 03 00 00 00 │ ╾──╼....╾──╼....
-    0x10 │ ╾─alloc13─╼ 04 00 00 00                         │ ╾──╼....
-}
-
-alloc10 (size: 3, align: 1) {
-    6d 65 68                                        │ meh
+alloc13 (size: 24, align: 4) {
+    0x00 │ ╾─alloc12─╼ 03 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ╾──╼....╾──╼....
+    0x10 │ ╾─alloc15─╼ 04 00 00 00                         │ ╾──╼....
 }
 
 alloc12 (size: 3, align: 1) {
+    6d 65 68                                        │ meh
+}
+
+alloc14 (size: 3, align: 1) {
     6d 6f 70                                        │ mop
 }
 
-alloc13 (size: 4, align: 1) {
+alloc15 (size: 4, align: 1) {
     6d c3 b6 70                                     │ m..p
 }
diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
index 2853a0a..ef98cf9 100644
--- a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
+++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
@@ -24,46 +24,46 @@
 }
 
 alloc0 (static: FOO, size: 16, align: 8) {
-    ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    ╾───────alloc17───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc14 (size: 72, align: 8) {
+alloc17 (size: 72, align: 8) {
     0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc4────────╼ │ ....░░░░╾──────╼
     0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
-    0x20 │ ╾───────alloc7────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc11───────╼ │ ....*...╾──────╼
+    0x20 │ ╾───────alloc8────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc13───────╼ │ ....*...╾──────╼
     0x40 │ 03 00 00 00 00 00 00 00                         │ ........
 }
 
 alloc4 (size: 0, align: 8) {}
 
-alloc7 (size: 32, align: 8) {
-    0x00 │ ╾───────alloc6────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x10 │ ╾───────alloc8────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc8 (size: 32, align: 8) {
+    0x00 │ ╾───────alloc7────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x10 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc6 (size: 3, align: 1) {
+alloc7 (size: 3, align: 1) {
     66 6f 6f                                        │ foo
 }
 
-alloc8 (size: 3, align: 1) {
+alloc9 (size: 3, align: 1) {
     62 61 72                                        │ bar
 }
 
-alloc11 (size: 48, align: 8) {
-    0x00 │ ╾───────alloc10───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x10 │ ╾───────alloc12───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x20 │ ╾───────alloc13───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
-}
-
-alloc10 (size: 3, align: 1) {
-    6d 65 68                                        │ meh
+alloc13 (size: 48, align: 8) {
+    0x00 │ ╾───────alloc12───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x10 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x20 │ ╾───────alloc15───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
 alloc12 (size: 3, align: 1) {
+    6d 65 68                                        │ meh
+}
+
+alloc14 (size: 3, align: 1) {
     6d 6f 70                                        │ mop
 }
 
-alloc13 (size: 4, align: 1) {
+alloc15 (size: 4, align: 1) {
     6d c3 b6 70                                     │ m..p
 }
diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
index 710ffee..d2e764f 100644
--- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
+++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
@@ -24,41 +24,41 @@
 }
 
 alloc0 (static: FOO, size: 8, align: 4) {
-    ╾─alloc20─╼ 03 00 00 00                         │ ╾──╼....
+    ╾─alloc27─╼ 03 00 00 00                         │ ╾──╼....
 }
 
-alloc20 (size: 48, align: 4) {
-    0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 00 00 00 00 │ ....░░░░╾──╼....
-    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc12─╼ 02 00 00 00 │ ....░░░░╾──╼....
-    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc19─╼ 03 00 00 00 │ ....*...╾──╼....
+alloc27 (size: 48, align: 4) {
+    0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc12─╼ 00 00 00 00 │ ....░░░░╾──╼....
+    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc17─╼ 02 00 00 00 │ ....░░░░╾──╼....
+    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc25─╼ 03 00 00 00 │ ....*...╾──╼....
 }
 
-alloc8 (size: 0, align: 4) {}
+alloc12 (size: 0, align: 4) {}
 
-alloc12 (size: 8, align: 4) {
-    ╾─alloc10─╼ ╾─alloc11─╼                         │ ╾──╼╾──╼
+alloc17 (size: 8, align: 4) {
+    ╾─alloc15─╼ ╾─alloc16─╼                         │ ╾──╼╾──╼
 }
 
-alloc10 (size: 1, align: 1) {
+alloc15 (size: 1, align: 1) {
     05                                              │ .
 }
 
-alloc11 (size: 1, align: 1) {
+alloc16 (size: 1, align: 1) {
     06                                              │ .
 }
 
-alloc19 (size: 12, align: 4) {
-    ╾─a15+0x3─╼ ╾─alloc16─╼ ╾─a18+0x2─╼             │ ╾──╼╾──╼╾──╼
+alloc25 (size: 12, align: 4) {
+    ╾─a21+0x3─╼ ╾─alloc22─╼ ╾─a24+0x2─╼             │ ╾──╼╾──╼╾──╼
 }
 
-alloc15 (size: 4, align: 1) {
+alloc21 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
 
-alloc16 (size: 1, align: 1) {
+alloc22 (size: 1, align: 1) {
     2a                                              │ *
 }
 
-alloc18 (size: 4, align: 1) {
+alloc24 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
index 97a7f76..00bf91f 100644
--- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
+++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
@@ -24,44 +24,44 @@
 }
 
 alloc0 (static: FOO, size: 16, align: 8) {
-    ╾───────alloc20───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    ╾───────alloc27───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc20 (size: 72, align: 8) {
-    0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc8────────╼ │ ....░░░░╾──────╼
+alloc27 (size: 72, align: 8) {
+    0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc12───────╼ │ ....░░░░╾──────╼
     0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
-    0x20 │ ╾───────alloc12───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc19───────╼ │ ....*...╾──────╼
+    0x20 │ ╾───────alloc17───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc25───────╼ │ ....*...╾──────╼
     0x40 │ 03 00 00 00 00 00 00 00                         │ ........
 }
 
-alloc8 (size: 0, align: 8) {}
+alloc12 (size: 0, align: 8) {}
 
-alloc12 (size: 16, align: 8) {
-    ╾───────alloc10───────╼ ╾───────alloc11───────╼ │ ╾──────╼╾──────╼
+alloc17 (size: 16, align: 8) {
+    ╾───────alloc15───────╼ ╾───────alloc16───────╼ │ ╾──────╼╾──────╼
 }
 
-alloc10 (size: 1, align: 1) {
+alloc15 (size: 1, align: 1) {
     05                                              │ .
 }
 
-alloc11 (size: 1, align: 1) {
+alloc16 (size: 1, align: 1) {
     06                                              │ .
 }
 
-alloc19 (size: 24, align: 8) {
-    0x00 │ ╾─────alloc15+0x3─────╼ ╾───────alloc16───────╼ │ ╾──────╼╾──────╼
-    0x10 │ ╾─────alloc18+0x2─────╼                         │ ╾──────╼
+alloc25 (size: 24, align: 8) {
+    0x00 │ ╾─────alloc21+0x3─────╼ ╾───────alloc22───────╼ │ ╾──────╼╾──────╼
+    0x10 │ ╾─────alloc24+0x2─────╼                         │ ╾──────╼
 }
 
-alloc15 (size: 4, align: 1) {
+alloc21 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
 
-alloc16 (size: 1, align: 1) {
+alloc22 (size: 1, align: 1) {
     2a                                              │ *
 }
 
-alloc18 (size: 4, align: 1) {
+alloc24 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
index 99d3a27..519002d 100644
--- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
+++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
@@ -24,30 +24,30 @@
 }
 
 alloc0 (static: FOO, size: 4, align: 4) {
-    ╾─alloc9──╼                                     │ ╾──╼
+    ╾─alloc10─╼                                     │ ╾──╼
 }
 
-alloc9 (size: 168, align: 1) {
+alloc10 (size: 168, align: 1) {
     0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................
-    0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc4──╼ │ ............╾──╼
+    0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc5──╼ │ ............╾──╼
     0x20 │ 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x50 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
-    0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc6──╼ 00 00 │ ..........╾──╼..
-    0x90 │ ╾─a7+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............
+    0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc7──╼ 00 00 │ ..........╾──╼..
+    0x90 │ ╾─a8+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............
     0xa0 │ 00 00 00 00 00 00 00 00                         │ ........
 }
 
-alloc4 (size: 4, align: 4) {
+alloc5 (size: 4, align: 4) {
     2a 00 00 00                                     │ *...
 }
 
-alloc6 (fn: main)
+alloc7 (fn: main)
 
-alloc7 (size: 100, align: 1) {
+alloc8 (size: 100, align: 1) {
     0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
index d6e4989..73c4288 100644
--- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
+++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
@@ -24,12 +24,12 @@
 }
 
 alloc0 (static: FOO, size: 8, align: 8) {
-    ╾───────alloc9────────╼                         │ ╾──────╼
+    ╾───────alloc10───────╼                         │ ╾──────╼
 }
 
-alloc9 (size: 180, align: 1) {
+alloc10 (size: 180, align: 1) {
     0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................
-    0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc4── │ ............╾───
+    0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc5── │ ............╾───
     0x20 │ ──────────╼ 01 ef cd ab 00 00 00 00 00 00 00 00 │ ───╼............
     0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
@@ -37,18 +37,18 @@
     0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x80 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ╾──── │ ..............╾─
-    0x90 │ ─────alloc6─────╼ 00 00 ╾─────alloc7+0x63─────╼ │ ─────╼..╾──────╼
+    0x90 │ ─────alloc7─────╼ 00 00 ╾─────alloc8+0x63─────╼ │ ─────╼..╾──────╼
     0xa0 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0xb0 │ 00 00 00 00                                     │ ....
 }
 
-alloc4 (size: 4, align: 4) {
+alloc5 (size: 4, align: 4) {
     2a 00 00 00                                     │ *...
 }
 
-alloc6 (fn: main)
+alloc7 (fn: main)
 
-alloc7 (size: 100, align: 1) {
+alloc8 (size: 100, align: 1) {
     0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
     0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
diff --git "a/src/test/mir-opt/const_promotion_extern_static.BAR-promoted\1330\135.ConstProp.after.mir" "b/src/test/mir-opt/const_promotion_extern_static.BAR-promoted\1330\135.SimplifyCfg-elaborate-drops.after.mir"
similarity index 91%
rename from "src/test/mir-opt/const_promotion_extern_static.BAR-promoted\1330\135.ConstProp.after.mir"
rename to "src/test/mir-opt/const_promotion_extern_static.BAR-promoted\1330\135.SimplifyCfg-elaborate-drops.after.mir"
index 5099470..2497c55 100644
--- "a/src/test/mir-opt/const_promotion_extern_static.BAR-promoted\1330\135.ConstProp.after.mir"
+++ "b/src/test/mir-opt/const_promotion_extern_static.BAR-promoted\1330\135.SimplifyCfg-elaborate-drops.after.mir"
@@ -1,4 +1,4 @@
-// MIR for `BAR::promoted[0]` after ConstProp
+// MIR for `BAR::promoted[0]` after SimplifyCfg-elaborate-drops
 
 promoted[0] in BAR: &[&i32; 1] = {
     let mut _0: &[&i32; 1];              // return place in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
@@ -14,7 +14,7 @@
                                          // mir::Constant
                                          // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34
                                          // + literal: Const { ty: &i32, val: Value(Scalar(alloc0)) }
-        _2 = _3;                         // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34
+        _2 = &(*_3);                     // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34
         _1 = [move _2];                  // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
         _0 = &_1;                        // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
         return;                          // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
diff --git "a/src/test/mir-opt/const_promotion_extern_static.FOO-promoted\1330\135.ConstProp.after.mir" "b/src/test/mir-opt/const_promotion_extern_static.FOO-promoted\1330\135.SimplifyCfg-elaborate-drops.after.mir"
similarity index 95%
rename from "src/test/mir-opt/const_promotion_extern_static.FOO-promoted\1330\135.ConstProp.after.mir"
rename to "src/test/mir-opt/const_promotion_extern_static.FOO-promoted\1330\135.SimplifyCfg-elaborate-drops.after.mir"
index 88d583b..17107ec 100644
--- "a/src/test/mir-opt/const_promotion_extern_static.FOO-promoted\1330\135.ConstProp.after.mir"
+++ "b/src/test/mir-opt/const_promotion_extern_static.FOO-promoted\1330\135.SimplifyCfg-elaborate-drops.after.mir"
@@ -1,4 +1,4 @@
-// MIR for `FOO::promoted[0]` after ConstProp
+// MIR for `FOO::promoted[0]` after SimplifyCfg-elaborate-drops
 
 promoted[0] in FOO: &[&i32; 1] = {
     let mut _0: &[&i32; 1];              // return place in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
diff --git a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
index 0d06c49..64c2703 100644
--- a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
@@ -9,18 +9,12 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21
 -         _1 = const <bool as NeedsDrop>::NEEDS; // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21
--         switchInt(_1) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/control-flow-simplification.rs:12:5: 14:6
+-         switchInt(move _1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:12:5: 14:6
 +         _1 = const false;                // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21
-+         switchInt(const false) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/control-flow-simplification.rs:12:5: 14:6
++         switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:12:5: 14:6
       }
   
       bb1: {
-          _0 = const ();                   // scope 0 at $DIR/control-flow-simplification.rs:14:6: 14:6
-          StorageDead(_1);                 // scope 0 at $DIR/control-flow-simplification.rs:15:1: 15:2
-          return;                          // scope 0 at $DIR/control-flow-simplification.rs:15:2: 15:2
-      }
-  
-      bb2: {
           StorageLive(_2);                 // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
           begin_panic::<&str>(const "explicit panic"); // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
@@ -33,5 +27,11 @@
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, size: Size { raw: 14 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) }
       }
+  
+      bb2: {
+          _0 = const ();                   // scope 0 at $DIR/control-flow-simplification.rs:14:6: 14:6
+          StorageDead(_1);                 // scope 0 at $DIR/control-flow-simplification.rs:14:5: 14:6
+          return;                          // scope 0 at $DIR/control-flow-simplification.rs:15:2: 15:2
+      }
   }
   
diff --git a/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot b/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot
index 5b6d73a..eeedbb2 100644
--- a/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot
+++ b/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot
@@ -3,8 +3,8 @@
     node [fontname="Courier, monospace"];
     edge [fontname="Courier, monospace"];
     bcb2__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb2</td></tr><tr><td align="left" balign="left">Expression(bcb0 - bcb1) at 13:10-13:10<br/>    13:10-13:10: @4[0]: Coverage::Expression(4294967295) = 1 - 2 for $DIR/coverage_graphviz.rs:13:10 - 13:11</td></tr><tr><td align="left" balign="left">bb4: Goto</td></tr></table>>];
-    bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Counter(bcb1) at 12:13-12:18<br/>    12:13-12:18: @5[0]: _0 = const ()<br/>Expression(bcb1 + 0) at 15:2-15:2<br/>    15:2-15:2: @5.Return: return</td></tr><tr><td align="left" balign="left">bb3: FalseEdge</td></tr><tr><td align="left" balign="left">bb5: Return</td></tr></table>>];
-    bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-11:17<br/>    11:12-11:17: @1.Call: _2 = bar() -&gt; [return: bb2, unwind: bb6]<br/>    11:12-11:17: @2[0]: FakeRead(ForMatchedPlace, _2)</td></tr><tr><td align="left" balign="left">bb0: FalseUnwind<br/>bb1: Call</td></tr><tr><td align="left" balign="left">bb2: SwitchInt</td></tr></table>>];
+    bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Counter(bcb1) at 12:13-12:18<br/>    12:13-12:18: @3[0]: Coverage::Expression(4294967294) = 2 + 0 for $DIR/coverage_graphviz.rs:15:1 - 15:2<br/>Expression(bcb1 + 0) at 15:2-15:2<br/>    15:2-15:2: @3.Return: return</td></tr><tr><td align="left" balign="left">bb3: Return</td></tr></table>>];
+    bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-11:17<br/>    11:12-11:17: @1.Call: _2 = bar() -&gt; [return: bb2, unwind: bb5]</td></tr><tr><td align="left" balign="left">bb0: FalseUnwind<br/>bb1: Call</td></tr><tr><td align="left" balign="left">bb2: SwitchInt</td></tr></table>>];
     bcb2__Cov_0_3 -> bcb0__Cov_0_3 [label=<>];
     bcb0__Cov_0_3 -> bcb2__Cov_0_3 [label=<false>];
     bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=<otherwise>];
diff --git a/src/test/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff b/src/test/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff
index bf99f7e..6d2dbb8 100644
--- a/src/test/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff
+++ b/src/test/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff
@@ -12,20 +12,10 @@
       bb0: {
           StorageLive(_3);                 // scope 0 at $DIR/deaggregator_test_enum_2.rs:10:8: 10:9
           _3 = _1;                         // scope 0 at $DIR/deaggregator_test_enum_2.rs:10:8: 10:9
-          switchInt(_3) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/deaggregator_test_enum_2.rs:10:5: 14:6
+          switchInt(move _3) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/deaggregator_test_enum_2.rs:10:5: 14:6
       }
   
       bb1: {
-          StorageLive(_5);                 // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:16: 13:17
-          _5 = _2;                         // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:16: 13:17
--         _0 = Foo::B(move _5);            // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:9: 13:18
-+         ((_0 as B).0: i32) = move _5;    // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:9: 13:18
-+         discriminant(_0) = 1;            // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:9: 13:18
-          StorageDead(_5);                 // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:17: 13:18
-          goto -> bb3;                     // scope 0 at $DIR/deaggregator_test_enum_2.rs:10:5: 14:6
-      }
-  
-      bb2: {
           StorageLive(_4);                 // scope 0 at $DIR/deaggregator_test_enum_2.rs:11:16: 11:17
           _4 = _2;                         // scope 0 at $DIR/deaggregator_test_enum_2.rs:11:16: 11:17
 -         _0 = Foo::A(move _4);            // scope 0 at $DIR/deaggregator_test_enum_2.rs:11:9: 11:18
@@ -35,8 +25,18 @@
           goto -> bb3;                     // scope 0 at $DIR/deaggregator_test_enum_2.rs:10:5: 14:6
       }
   
+      bb2: {
+          StorageLive(_5);                 // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:16: 13:17
+          _5 = _2;                         // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:16: 13:17
+-         _0 = Foo::B(move _5);            // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:9: 13:18
++         ((_0 as B).0: i32) = move _5;    // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:9: 13:18
++         discriminant(_0) = 1;            // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:9: 13:18
+          StorageDead(_5);                 // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:17: 13:18
+          goto -> bb3;                     // scope 0 at $DIR/deaggregator_test_enum_2.rs:10:5: 14:6
+      }
+  
       bb3: {
-          StorageDead(_3);                 // scope 0 at $DIR/deaggregator_test_enum_2.rs:15:1: 15:2
+          StorageDead(_3);                 // scope 0 at $DIR/deaggregator_test_enum_2.rs:14:5: 14:6
           return;                          // scope 0 at $DIR/deaggregator_test_enum_2.rs:15:2: 15:2
       }
   }
diff --git a/src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff
index 9c213ea..e11d24c 100644
--- a/src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff
+++ b/src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff
@@ -36,10 +36,16 @@
       }
   
       bb2: {
-          switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 1 at $DIR/branch.rs:15:13: 20:6
+          switchInt(move _3) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/branch.rs:15:13: 20:6
       }
   
       bb3: {
+-         _2 = _1;                         // scope 1 at $DIR/branch.rs:16:9: 16:10
++         nop;                             // scope 1 at $DIR/branch.rs:16:9: 16:10
+          goto -> bb6;                     // scope 1 at $DIR/branch.rs:15:13: 20:6
+      }
+  
+      bb4: {
           StorageLive(_4);                 // scope 1 at $DIR/branch.rs:18:9: 18:14
           _4 = val() -> bb5;               // scope 1 at $DIR/branch.rs:18:9: 18:14
                                            // mir::Constant
@@ -47,12 +53,6 @@
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value(Scalar(<ZST>)) }
       }
   
-      bb4: {
--         _2 = _1;                         // scope 1 at $DIR/branch.rs:16:9: 16:10
-+         nop;                             // scope 1 at $DIR/branch.rs:16:9: 16:10
-          goto -> bb6;                     // scope 1 at $DIR/branch.rs:15:13: 20:6
-      }
-  
       bb5: {
           StorageDead(_4);                 // scope 1 at $DIR/branch.rs:18:14: 18:15
 -         _2 = _1;                         // scope 1 at $DIR/branch.rs:19:9: 19:10
@@ -61,7 +61,7 @@
       }
   
       bb6: {
-          StorageDead(_3);                 // scope 1 at $DIR/branch.rs:20:6: 20:7
+          StorageDead(_3);                 // scope 1 at $DIR/branch.rs:20:5: 20:6
           _0 = const ();                   // scope 0 at $DIR/branch.rs:12:11: 21:2
 -         StorageDead(_2);                 // scope 1 at $DIR/branch.rs:21:1: 21:2
 -         StorageDead(_1);                 // scope 0 at $DIR/branch.rs:21:1: 21:2
diff --git a/src/test/mir-opt/equal_true.opt.InstCombine.diff b/src/test/mir-opt/equal_true.opt.InstCombine.diff
index a26776e..1bc4c0f 100644
--- a/src/test/mir-opt/equal_true.opt.InstCombine.diff
+++ b/src/test/mir-opt/equal_true.opt.InstCombine.diff
@@ -14,21 +14,21 @@
 -         _2 = Eq(move _3, const true);    // scope 0 at $DIR/equal_true.rs:4:8: 4:17
 +         _2 = move _3;                    // scope 0 at $DIR/equal_true.rs:4:8: 4:17
           StorageDead(_3);                 // scope 0 at $DIR/equal_true.rs:4:16: 4:17
-          switchInt(_2) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/equal_true.rs:4:5: 4:34
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/equal_true.rs:4:5: 4:34
       }
   
       bb1: {
-          _0 = const 1_i32;                // scope 0 at $DIR/equal_true.rs:4:31: 4:32
-          goto -> bb3;                     // scope 0 at $DIR/equal_true.rs:4:5: 4:34
-      }
-  
-      bb2: {
           _0 = const 0_i32;                // scope 0 at $DIR/equal_true.rs:4:20: 4:21
           goto -> bb3;                     // scope 0 at $DIR/equal_true.rs:4:5: 4:34
       }
   
+      bb2: {
+          _0 = const 1_i32;                // scope 0 at $DIR/equal_true.rs:4:31: 4:32
+          goto -> bb3;                     // scope 0 at $DIR/equal_true.rs:4:5: 4:34
+      }
+  
       bb3: {
-          StorageDead(_2);                 // scope 0 at $DIR/equal_true.rs:5:1: 5:2
+          StorageDead(_2);                 // scope 0 at $DIR/equal_true.rs:4:33: 4:34
           return;                          // scope 0 at $DIR/equal_true.rs:5:2: 5:2
       }
   }
diff --git a/src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff
index 993ff66..875e5a0 100644
--- a/src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff
@@ -9,21 +9,21 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/if-condition-int.rs:17:8: 17:9
           _2 = _1;                         // scope 0 at $DIR/if-condition-int.rs:17:8: 17:9
-          switchInt(_2) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:17:5: 17:26
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:17:5: 17:26
       }
   
       bb1: {
-          _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:17:23: 17:24
-          goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:17:5: 17:26
-      }
-  
-      bb2: {
           _0 = const 0_u32;                // scope 0 at $DIR/if-condition-int.rs:17:12: 17:13
           goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:17:5: 17:26
       }
   
+      bb2: {
+          _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:17:23: 17:24
+          goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:17:5: 17:26
+      }
+  
       bb3: {
-          StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:18:1: 18:2
+          StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:17:25: 17:26
           return;                          // scope 0 at $DIR/if-condition-int.rs:18:2: 18:2
       }
   }
diff --git a/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff
index 8ae9168..2c4952402 100644
--- a/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff
@@ -16,21 +16,21 @@
                                            // + span: $DIR/if-condition-int.rs:53:13: 53:18
                                            // + literal: Const { ty: f32, val: Value(Scalar(0xc2280000)) }
           StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:53:17: 53:18
-          switchInt(_2) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:53:5: 53:35
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:53:5: 53:35
       }
   
       bb1: {
-          _0 = const 1_i32;                // scope 0 at $DIR/if-condition-int.rs:53:32: 53:33
-          goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:53:5: 53:35
-      }
-  
-      bb2: {
           _0 = const 0_i32;                // scope 0 at $DIR/if-condition-int.rs:53:21: 53:22
           goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:53:5: 53:35
       }
   
+      bb2: {
+          _0 = const 1_i32;                // scope 0 at $DIR/if-condition-int.rs:53:32: 53:33
+          goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:53:5: 53:35
+      }
+  
       bb3: {
-          StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:54:1: 54:2
+          StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:53:34: 53:35
           return;                          // scope 0 at $DIR/if-condition-int.rs:54:2: 54:2
       }
   }
diff --git a/src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff
index ae09600..6615916 100644
--- a/src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff
@@ -13,26 +13,26 @@
           _3 = _1;                         // scope 0 at $DIR/if-condition-int.rs:21:8: 21:9
 -         _2 = Eq(move _3, const 'x');     // scope 0 at $DIR/if-condition-int.rs:21:8: 21:16
 -         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:21:15: 21:16
--         switchInt(_2) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
-+         _2 = Eq(_3, const 'x');          // scope 0 at $DIR/if-condition-int.rs:21:8: 21:16
+-         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
++         nop;                             // scope 0 at $DIR/if-condition-int.rs:21:8: 21:16
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:21:15: 21:16
-+         switchInt(move _3) -> ['x': bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
++         switchInt(move _3) -> ['x': bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
       }
   
       bb1: {
 +         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
-          _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:21:30: 21:31
-          goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
-      }
-  
-      bb2: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
           _0 = const 0_u32;                // scope 0 at $DIR/if-condition-int.rs:21:19: 21:20
           goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
       }
   
+      bb2: {
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
+          _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:21:30: 21:31
+          goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
+      }
+  
       bb3: {
-          StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:22:1: 22:2
+          StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:21:32: 21:33
           return;                          // scope 0 at $DIR/if-condition-int.rs:22:2: 22:2
       }
   }
diff --git a/src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff
index 8d59e51..7d0ed73 100644
--- a/src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff
@@ -13,26 +13,26 @@
           _3 = _1;                         // scope 0 at $DIR/if-condition-int.rs:25:8: 25:9
 -         _2 = Eq(move _3, const 42_i8);   // scope 0 at $DIR/if-condition-int.rs:25:8: 25:15
 -         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:25:14: 25:15
--         switchInt(_2) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
-+         _2 = Eq(_3, const 42_i8);        // scope 0 at $DIR/if-condition-int.rs:25:8: 25:15
+-         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
++         nop;                             // scope 0 at $DIR/if-condition-int.rs:25:8: 25:15
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:25:14: 25:15
-+         switchInt(move _3) -> [42_i8: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
++         switchInt(move _3) -> [42_i8: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
       }
   
       bb1: {
 +         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
-          _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:25:29: 25:30
-          goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
-      }
-  
-      bb2: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
           _0 = const 0_u32;                // scope 0 at $DIR/if-condition-int.rs:25:18: 25:19
           goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
       }
   
+      bb2: {
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
+          _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:25:29: 25:30
+          goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
+      }
+  
       bb3: {
-          StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:26:1: 26:2
+          StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:25:31: 25:32
           return;                          // scope 0 at $DIR/if-condition-int.rs:26:2: 26:2
       }
   }
diff --git a/src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff
index c497566..bf388a1 100644
--- a/src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff
@@ -15,40 +15,40 @@
           _3 = _1;                         // scope 0 at $DIR/if-condition-int.rs:33:8: 33:9
 -         _2 = Eq(move _3, const 42_u32);  // scope 0 at $DIR/if-condition-int.rs:33:8: 33:15
 -         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:33:14: 33:15
--         switchInt(_2) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:33:5: 39:6
-+         _2 = Eq(_3, const 42_u32);       // scope 0 at $DIR/if-condition-int.rs:33:8: 33:15
+-         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:33:5: 39:6
++         nop;                             // scope 0 at $DIR/if-condition-int.rs:33:8: 33:15
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:33:14: 33:15
-+         switchInt(move _3) -> [42_u32: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:33:5: 39:6
++         switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:33:5: 39:6
       }
   
       bb1: {
 +         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:33:5: 39:6
+          _0 = const 0_u32;                // scope 0 at $DIR/if-condition-int.rs:34:9: 34:10
+          goto -> bb6;                     // scope 0 at $DIR/if-condition-int.rs:33:5: 39:6
+      }
+  
+      bb2: {
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:33:5: 39:6
           StorageLive(_4);                 // scope 0 at $DIR/if-condition-int.rs:35:15: 35:22
           StorageLive(_5);                 // scope 0 at $DIR/if-condition-int.rs:35:15: 35:16
           _5 = _1;                         // scope 0 at $DIR/if-condition-int.rs:35:15: 35:16
 -         _4 = Ne(move _5, const 21_u32);  // scope 0 at $DIR/if-condition-int.rs:35:15: 35:22
 -         StorageDead(_5);                 // scope 0 at $DIR/if-condition-int.rs:35:21: 35:22
--         switchInt(_4) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/if-condition-int.rs:35:12: 39:6
-+         _4 = Ne(_5, const 21_u32);       // scope 0 at $DIR/if-condition-int.rs:35:15: 35:22
+-         switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/if-condition-int.rs:35:12: 39:6
++         nop;                             // scope 0 at $DIR/if-condition-int.rs:35:15: 35:22
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:35:21: 35:22
-+         switchInt(move _5) -> [21_u32: bb3, otherwise: bb4]; // scope 0 at $DIR/if-condition-int.rs:35:12: 39:6
-      }
-  
-      bb2: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:33:5: 39:6
-          _0 = const 0_u32;                // scope 0 at $DIR/if-condition-int.rs:34:9: 34:10
-          goto -> bb6;                     // scope 0 at $DIR/if-condition-int.rs:33:5: 39:6
++         switchInt(move _5) -> [21_u32: bb4, otherwise: bb3]; // scope 0 at $DIR/if-condition-int.rs:35:12: 39:6
       }
   
       bb3: {
 +         StorageDead(_5);                 // scope 0 at $DIR/if-condition-int.rs:35:12: 39:6
-          _0 = const 2_u32;                // scope 0 at $DIR/if-condition-int.rs:38:9: 38:10
+          _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:36:9: 36:10
           goto -> bb5;                     // scope 0 at $DIR/if-condition-int.rs:35:12: 39:6
       }
   
       bb4: {
 +         StorageDead(_5);                 // scope 0 at $DIR/if-condition-int.rs:35:12: 39:6
-          _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:36:9: 36:10
+          _0 = const 2_u32;                // scope 0 at $DIR/if-condition-int.rs:38:9: 38:10
           goto -> bb5;                     // scope 0 at $DIR/if-condition-int.rs:35:12: 39:6
       }
   
@@ -58,7 +58,7 @@
       }
   
       bb6: {
-          StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:40:1: 40:2
+          StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:39:5: 39:6
           return;                          // scope 0 at $DIR/if-condition-int.rs:40:2: 40:2
       }
   }
diff --git a/src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff
index d7f544e..bee2e03 100644
--- a/src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff
@@ -13,26 +13,26 @@
           _3 = _1;                         // scope 0 at $DIR/if-condition-int.rs:29:8: 29:9
 -         _2 = Eq(move _3, const -42_i32); // scope 0 at $DIR/if-condition-int.rs:29:8: 29:16
 -         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:29:15: 29:16
--         switchInt(_2) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
-+         _2 = Eq(_3, const -42_i32);      // scope 0 at $DIR/if-condition-int.rs:29:8: 29:16
+-         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
++         nop;                             // scope 0 at $DIR/if-condition-int.rs:29:8: 29:16
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:29:15: 29:16
-+         switchInt(move _3) -> [-42_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
++         switchInt(move _3) -> [-42_i32: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
       }
   
       bb1: {
 +         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
-          _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:29:30: 29:31
-          goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
-      }
-  
-      bb2: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
           _0 = const 0_u32;                // scope 0 at $DIR/if-condition-int.rs:29:19: 29:20
           goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
       }
   
+      bb2: {
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
+          _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:29:30: 29:31
+          goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
+      }
+  
       bb3: {
-          StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:30:1: 30:2
+          StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:29:32: 29:33
           return;                          // scope 0 at $DIR/if-condition-int.rs:30:2: 30:2
       }
   }
diff --git a/src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff
index 51e00e6..09a8759 100644
--- a/src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff
@@ -13,26 +13,26 @@
           _3 = _1;                         // scope 0 at $DIR/if-condition-int.rs:12:8: 12:9
 -         _2 = Eq(move _3, const 42_u32);  // scope 0 at $DIR/if-condition-int.rs:12:8: 12:15
 -         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:12:14: 12:15
--         switchInt(_2) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
-+         _2 = Eq(_3, const 42_u32);       // scope 0 at $DIR/if-condition-int.rs:12:8: 12:15
+-         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
++         nop;                             // scope 0 at $DIR/if-condition-int.rs:12:8: 12:15
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:12:14: 12:15
-+         switchInt(move _3) -> [42_u32: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
++         switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
       }
   
       bb1: {
 +         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
-          _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:12:29: 12:30
-          goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
-      }
-  
-      bb2: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
           _0 = const 0_u32;                // scope 0 at $DIR/if-condition-int.rs:12:18: 12:19
           goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
       }
   
+      bb2: {
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
+          _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:12:29: 12:30
+          goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
+      }
+  
       bb3: {
-          StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:13:1: 13:2
+          StorageDead(_2);                 // scope 0 at $DIR/if-condition-int.rs:12:31: 12:32
           return;                          // scope 0 at $DIR/if-condition-int.rs:13:2: 13:2
       }
   }
diff --git a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff
index 3dc3335..a746baa 100644
--- a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff
+++ b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff
@@ -19,10 +19,19 @@
           _3 = _1;                         // scope 0 at $DIR/inline-diverging.rs:13:8: 13:9
           _2 = Gt(move _3, const 0_i32);   // scope 0 at $DIR/inline-diverging.rs:13:8: 13:13
           StorageDead(_3);                 // scope 0 at $DIR/inline-diverging.rs:13:12: 13:13
-          switchInt(_2) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/inline-diverging.rs:13:5: 17:6
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/inline-diverging.rs:13:5: 17:6
       }
   
       bb1: {
+          StorageLive(_4);                 // scope 0 at $DIR/inline-diverging.rs:14:9: 14:10
+          _4 = _1;                         // scope 0 at $DIR/inline-diverging.rs:14:9: 14:10
+          _0 = move _4 as u32 (Misc);      // scope 0 at $DIR/inline-diverging.rs:14:9: 14:17
+          StorageDead(_4);                 // scope 0 at $DIR/inline-diverging.rs:14:16: 14:17
+          StorageDead(_2);                 // scope 0 at $DIR/inline-diverging.rs:17:5: 17:6
+          return;                          // scope 0 at $DIR/inline-diverging.rs:18:2: 18:2
+      }
+  
+      bb2: {
           StorageLive(_6);                 // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
 -         panic();                         // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
 +         StorageLive(_7);                 // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
@@ -39,14 +48,5 @@
 +                                          // + span: $DIR/inline-diverging.rs:16:9: 16:16
 +                                          // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, size: Size { raw: 14 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) }
       }
-  
-      bb2: {
-          StorageLive(_4);                 // scope 0 at $DIR/inline-diverging.rs:14:9: 14:10
-          _4 = _1;                         // scope 0 at $DIR/inline-diverging.rs:14:9: 14:10
-          _0 = move _4 as u32 (Misc);      // scope 0 at $DIR/inline-diverging.rs:14:9: 14:17
-          StorageDead(_4);                 // scope 0 at $DIR/inline-diverging.rs:14:16: 14:17
-          StorageDead(_2);                 // scope 0 at $DIR/inline-diverging.rs:18:1: 18:2
-          return;                          // scope 0 at $DIR/inline-diverging.rs:18:2: 18:2
-      }
   }
   
diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff
index 99497a6..066ac8d 100644
--- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff
+++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff
@@ -90,16 +90,16 @@
 + 
 +     bb3: {
 +         _8 = move _7;                    // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
-+         switchInt(_8) -> [false: bb4, otherwise: bb5]; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         switchInt(move _8) -> [false: bb5, otherwise: bb4]; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
 +     }
 + 
 +     bb4: {
-+         ((_1 as Yielded).0: i32) = const 13_i32; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         ((_1 as Yielded).0: i32) = const 7_i32; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
 +         goto -> bb6;                     // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
 +     }
 + 
 +     bb5: {
-+         ((_1 as Yielded).0: i32) = const 7_i32; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         ((_1 as Yielded).0: i32) = const 13_i32; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
 +         goto -> bb6;                     // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
 +     }
 + 
diff --git a/src/test/mir-opt/inst_combine_deref.do_not_miscompile.InstCombine.diff b/src/test/mir-opt/inst_combine_deref.do_not_miscompile.InstCombine.diff
index a8b523d..ee8fcdc 100644
--- a/src/test/mir-opt/inst_combine_deref.do_not_miscompile.InstCombine.diff
+++ b/src/test/mir-opt/inst_combine_deref.do_not_miscompile.InstCombine.diff
@@ -53,22 +53,10 @@
           StorageDead(_10);                // scope 4 at $DIR/inst_combine_deref.rs:60:20: 60:21
           _8 = Not(move _9);               // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23
           StorageDead(_9);                 // scope 4 at $DIR/inst_combine_deref.rs:60:22: 60:23
-          switchInt(_8) -> [false: bb1, otherwise: bb2]; // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23
+          switchInt(move _8) -> [false: bb2, otherwise: bb1]; // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23
       }
   
       bb1: {
-          _7 = const ();                   // scope 4 at $DIR/inst_combine_deref.rs:60:23: 60:23
-          StorageDead(_8);                 // scope 4 at $DIR/inst_combine_deref.rs:60:22: 60:23
-          StorageDead(_7);                 // scope 4 at $DIR/inst_combine_deref.rs:60:22: 60:23
-          _0 = const ();                   // scope 0 at $DIR/inst_combine_deref.rs:54:24: 61:2
-          StorageDead(_4);                 // scope 3 at $DIR/inst_combine_deref.rs:61:1: 61:2
-          StorageDead(_3);                 // scope 2 at $DIR/inst_combine_deref.rs:61:1: 61:2
-          StorageDead(_2);                 // scope 1 at $DIR/inst_combine_deref.rs:61:1: 61:2
-          StorageDead(_1);                 // scope 0 at $DIR/inst_combine_deref.rs:61:1: 61:2
-          return;                          // scope 0 at $DIR/inst_combine_deref.rs:61:2: 61:2
-      }
-  
-      bb2: {
           StorageLive(_11);                // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23
           core::panicking::panic(const "assertion failed: *y == 99"); // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23
                                            // mir::Constant
@@ -81,5 +69,17 @@
                                            // + span: $DIR/inst_combine_deref.rs:1:1: 1:1
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [97, 115, 115, 101, 114, 116, 105, 111, 110, 32, 102, 97, 105, 108, 101, 100, 58, 32, 42, 121, 32, 61, 61, 32, 57, 57], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [67108863], len: Size { raw: 26 } }, size: Size { raw: 26 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 26 }) }
       }
+  
+      bb2: {
+          _7 = const ();                   // scope 4 at $DIR/inst_combine_deref.rs:60:23: 60:23
+          StorageDead(_8);                 // scope 4 at $DIR/inst_combine_deref.rs:60:22: 60:23
+          StorageDead(_7);                 // scope 4 at $DIR/inst_combine_deref.rs:60:22: 60:23
+          _0 = const ();                   // scope 0 at $DIR/inst_combine_deref.rs:54:24: 61:2
+          StorageDead(_4);                 // scope 3 at $DIR/inst_combine_deref.rs:61:1: 61:2
+          StorageDead(_3);                 // scope 2 at $DIR/inst_combine_deref.rs:61:1: 61:2
+          StorageDead(_2);                 // scope 1 at $DIR/inst_combine_deref.rs:61:1: 61:2
+          StorageDead(_1);                 // scope 0 at $DIR/inst_combine_deref.rs:61:1: 61:2
+          return;                          // scope 0 at $DIR/inst_combine_deref.rs:61:2: 61:2
+      }
   }
   
diff --git a/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
index 9bd8c9c..226db95 100644
--- a/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
+++ b/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
@@ -9,42 +9,37 @@
   
       bb0: {
 +         Coverage::Counter(1) for /the/src/instrument_coverage.rs:10:1 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
-          falseUnwind -> [real: bb1, cleanup: bb6]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
+          falseUnwind -> [real: bb1, cleanup: bb5]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
       }
   
       bb1: {
           StorageLive(_2);                 // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
-          _2 = bar() -> [return: bb2, unwind: bb6]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
+          _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
                                            // mir::Constant
                                            // + span: /the/src/instrument_coverage.rs:12:12: 12:15
                                            // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
       }
   
       bb2: {
-          FakeRead(ForMatchedPlace, _2);   // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
-          switchInt(_2) -> [false: bb4, otherwise: bb3]; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10
+          switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10
       }
   
       bb3: {
-+         Coverage::Expression(4294967294) = 2 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10
-+         Coverage::Counter(2) for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10
-          falseEdge -> [real: bb5, imaginary: bb4]; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10
++         Coverage::Expression(4294967294) = 2 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
++         Coverage::Counter(2) for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
+          _0 = const ();                   // scope 0 at /the/src/instrument_coverage.rs:13:13: 13:18
+          StorageDead(_2);                 // scope 0 at /the/src/instrument_coverage.rs:14:9: 14:10
+          return;                          // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
       }
   
       bb4: {
 +         Coverage::Expression(4294967295) = 1 - 2 for /the/src/instrument_coverage.rs:14:10 - 14:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
           _1 = const ();                   // scope 0 at /the/src/instrument_coverage.rs:14:10: 14:10
-          StorageDead(_2);                 // scope 0 at /the/src/instrument_coverage.rs:15:5: 15:6
+          StorageDead(_2);                 // scope 0 at /the/src/instrument_coverage.rs:14:9: 14:10
           goto -> bb0;                     // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
       }
   
-      bb5: {
-          _0 = const ();                   // scope 0 at /the/src/instrument_coverage.rs:13:13: 13:18
-          StorageDead(_2);                 // scope 0 at /the/src/instrument_coverage.rs:15:5: 15:6
-          return;                          // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
-      }
-  
-      bb6 (cleanup): {
+      bb5 (cleanup): {
           resume;                          // scope 0 at /the/src/instrument_coverage.rs:10:1: 16:2
       }
   }
diff --git a/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
index 30036e4..e9e5a10 100644
--- a/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
@@ -19,19 +19,22 @@
     }
 
     bb1: {
-        falseUnwind -> [real: bb2, cleanup: bb6]; // scope 1 at $DIR/issue-38669.rs:6:5: 11:6
+        falseUnwind -> [real: bb2, cleanup: bb5]; // scope 1 at $DIR/issue-38669.rs:6:5: 11:6
     }
 
     bb2: {
         StorageLive(_3);                 // scope 1 at $DIR/issue-38669.rs:7:9: 9:10
         StorageLive(_4);                 // scope 1 at $DIR/issue-38669.rs:7:12: 7:24
         _4 = _1;                         // scope 1 at $DIR/issue-38669.rs:7:12: 7:24
-        FakeRead(ForMatchedPlace, _4);   // scope 1 at $DIR/issue-38669.rs:7:12: 7:24
-        switchInt(_4) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/issue-38669.rs:7:9: 9:10
+        switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/issue-38669.rs:7:9: 9:10
     }
 
     bb3: {
-        falseEdge -> [real: bb5, imaginary: bb4]; // scope 1 at $DIR/issue-38669.rs:7:9: 9:10
+        _0 = const ();                   // scope 1 at $DIR/issue-38669.rs:8:13: 8:18
+        StorageDead(_4);                 // scope 1 at $DIR/issue-38669.rs:9:9: 9:10
+        StorageDead(_3);                 // scope 1 at $DIR/issue-38669.rs:9:9: 9:10
+        StorageDead(_1);                 // scope 0 at $DIR/issue-38669.rs:12:1: 12:2
+        return;                          // scope 0 at $DIR/issue-38669.rs:12:2: 12:2
     }
 
     bb4: {
@@ -43,15 +46,7 @@
         goto -> bb1;                     // scope 1 at $DIR/issue-38669.rs:6:5: 11:6
     }
 
-    bb5: {
-        _0 = const ();                   // scope 1 at $DIR/issue-38669.rs:8:13: 8:18
-        StorageDead(_4);                 // scope 1 at $DIR/issue-38669.rs:9:9: 9:10
-        StorageDead(_3);                 // scope 1 at $DIR/issue-38669.rs:9:9: 9:10
-        StorageDead(_1);                 // scope 0 at $DIR/issue-38669.rs:12:1: 12:2
-        return;                          // scope 0 at $DIR/issue-38669.rs:12:2: 12:2
-    }
-
-    bb6 (cleanup): {
+    bb5 (cleanup): {
         resume;                          // scope 0 at $DIR/issue-38669.rs:4:1: 12:2
     }
 }
diff --git a/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir b/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir
index 5011c2a..4fc7f9d 100644
--- a/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir
+++ b/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir
@@ -33,15 +33,10 @@
     }
 
     bb1: {
-        switchInt(_2) -> [false: bb2, otherwise: bb3]; // scope 1 at $DIR/issue-41888.rs:8:5: 14:6
+        switchInt(move _2) -> [false: bb3, otherwise: bb2]; // scope 1 at $DIR/issue-41888.rs:8:5: 14:6
     }
 
     bb2: {
-        _0 = const ();                   // scope 1 at $DIR/issue-41888.rs:14:6: 14:6
-        goto -> bb7;                     // scope 1 at $DIR/issue-41888.rs:8:5: 14:6
-    }
-
-    bb3: {
         StorageLive(_3);                 // scope 1 at $DIR/issue-41888.rs:9:13: 9:20
         StorageLive(_4);                 // scope 1 at $DIR/issue-41888.rs:9:18: 9:19
         _4 = K;                          // scope 1 at $DIR/issue-41888.rs:9:18: 9:19
@@ -50,6 +45,11 @@
         goto -> bb12;                    // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
     }
 
+    bb3: {
+        _0 = const ();                   // scope 1 at $DIR/issue-41888.rs:14:6: 14:6
+        goto -> bb7;                     // scope 1 at $DIR/issue-41888.rs:8:5: 14:6
+    }
+
     bb4: {
         StorageDead(_3);                 // scope 1 at $DIR/issue-41888.rs:9:19: 9:20
         _5 = discriminant(_1);           // scope 1 at $DIR/issue-41888.rs:10:16: 10:24
@@ -71,6 +71,7 @@
     }
 
     bb7: {
+        StorageDead(_2);                 // scope 1 at $DIR/issue-41888.rs:14:5: 14:6
         goto -> bb18;                    // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
     }
 
@@ -79,7 +80,6 @@
         _8 = const false;                // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
         _9 = const false;                // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
         StorageDead(_1);                 // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
-        StorageDead(_2);                 // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
         return;                          // scope 0 at $DIR/issue-41888.rs:15:2: 15:2
     }
 
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
index 4db83c5..435b2a1 100644
--- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
@@ -99,19 +99,10 @@
           StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _9 = Not(move _10);              // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(_9) -> [false: bb1, otherwise: bb2]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          switchInt(move _9) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb1: {
-          StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _0 = const ();                   // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
-          StorageDead(_1);                 // scope 0 at $DIR/issue-73223.rs:9:1: 9:2
-          return;                          // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
-      }
-  
-      bb2: {
           _13 = const main::promoted[0];   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &[&str; 3]
@@ -143,6 +134,15 @@
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
+      bb2: {
+          StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _0 = const ();                   // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
+          StorageDead(_1);                 // scope 0 at $DIR/issue-73223.rs:9:1: 9:2
+          return;                          // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
+      }
+  
       bb3: {
           (_20.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _24) -> bb4; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
index 4db83c5..435b2a1 100644
--- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
@@ -99,19 +99,10 @@
           StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _9 = Not(move _10);              // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(_9) -> [false: bb1, otherwise: bb2]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          switchInt(move _9) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb1: {
-          StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _0 = const ();                   // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
-          StorageDead(_1);                 // scope 0 at $DIR/issue-73223.rs:9:1: 9:2
-          return;                          // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
-      }
-  
-      bb2: {
           _13 = const main::promoted[0];   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &[&str; 3]
@@ -143,6 +134,15 @@
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
+      bb2: {
+          StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _0 = const ();                   // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
+          StorageDead(_1);                 // scope 0 at $DIR/issue-73223.rs:9:1: 9:2
+          return;                          // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
+      }
+  
       bb3: {
           (_20.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _24) -> bb4; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
index 4e362f3..d87cb2a 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
@@ -151,23 +151,10 @@
           StorageDead(_17);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _15 = Not(move _16);             // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageDead(_16);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(_15) -> [false: bb3, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          switchInt(move _15) -> [false: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb3: {
-          _8 = const ();                   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_14);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_13);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_9);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _0 = const ();                   // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
-          StorageDead(_6);                 // scope 1 at $DIR/issue-73223.rs:9:1: 9:2
-          StorageDead(_1);                 // scope 0 at $DIR/issue-73223.rs:9:1: 9:2
-          return;                          // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
-      }
-  
-      bb4: {
           StorageLive(_19);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_20);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_21);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -222,6 +209,19 @@
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
+      bb4: {
+          _8 = const ();                   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_14);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_13);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_9);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _0 = const ();                   // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
+          StorageDead(_6);                 // scope 1 at $DIR/issue-73223.rs:9:1: 9:2
+          StorageDead(_1);                 // scope 0 at $DIR/issue-73223.rs:9:1: 9:2
+          return;                          // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
+      }
+  
       bb5: {
           StorageDead(_45);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_46);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
index 4e362f3..d87cb2a 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
@@ -151,23 +151,10 @@
           StorageDead(_17);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _15 = Not(move _16);             // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageDead(_16);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(_15) -> [false: bb3, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          switchInt(move _15) -> [false: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb3: {
-          _8 = const ();                   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_14);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_13);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_9);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _0 = const ();                   // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
-          StorageDead(_6);                 // scope 1 at $DIR/issue-73223.rs:9:1: 9:2
-          StorageDead(_1);                 // scope 0 at $DIR/issue-73223.rs:9:1: 9:2
-          return;                          // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
-      }
-  
-      bb4: {
           StorageLive(_19);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_20);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_21);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -222,6 +209,19 @@
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
+      bb4: {
+          _8 = const ();                   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_14);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_13);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_9);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _0 = const ();                   // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
+          StorageDead(_6);                 // scope 1 at $DIR/issue-73223.rs:9:1: 9:2
+          StorageDead(_1);                 // scope 0 at $DIR/issue-73223.rs:9:1: 9:2
+          return;                          // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
+      }
+  
       bb5: {
           StorageDead(_45);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_46);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/issues/issue-59352.rs b/src/test/mir-opt/issues/issue-59352.rs
new file mode 100644
index 0000000..9e59337
--- /dev/null
+++ b/src/test/mir-opt/issues/issue-59352.rs
@@ -0,0 +1,19 @@
+// This test is a mirror of codegen/issue-59352.rs.
+// The LLVM inliner doesn't inline `char::method::is_digit()` and so it doesn't recognize this case
+// as effectively `if x.is_some() { x.unwrap() } else { 0 }`.
+//
+// Currently, the MIR optimizer isn't capable of removing the unreachable panic in this test case.
+// Once the optimizer can do that, this test case will need to be updated and codegen/issue-59352.rs
+// removed.
+
+// EMIT_MIR issue_59352.num_to_digit.PreCodegen.after.mir
+// compile-flags: -Z mir-opt-level=2 -Z span_free_formats
+
+pub fn num_to_digit(num: char) -> u32 {
+    // CHECK-NOT: panic
+    if num.is_digit(8) { num.to_digit(8).unwrap() } else { 0 }
+}
+
+pub fn main() {
+    num_to_digit('2');
+}
diff --git a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
new file mode 100644
index 0000000..04a8c94
--- /dev/null
+++ b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
@@ -0,0 +1,102 @@
+// MIR for `num_to_digit` after PreCodegen
+
+fn num_to_digit(_1: char) -> u32 {
+    debug num => _1;                     // in scope 0 at $DIR/issue-59352.rs:12:21: 12:24
+    let mut _0: u32;                     // return place in scope 0 at $DIR/issue-59352.rs:12:35: 12:38
+    let mut _2: bool;                    // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+    let mut _3: std::option::Option<u32>; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:41
+    let mut _4: char;                    // in scope 0 at $DIR/issue-59352.rs:14:26: 14:29
+    let mut _5: u32;                     // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+    let mut _10: isize;                  // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+    scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue-59352.rs:14:8: 14:23
+        debug self => _8;                // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        debug radix => _5;               // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        let mut _6: &std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        let _7: std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        let mut _8: char;                // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        scope 2 (inlined Option::<u32>::is_some) { // at $DIR/issue-59352.rs:14:8: 14:23
+            debug self => _6;            // in scope 2 at $DIR/issue-59352.rs:14:8: 14:23
+        }
+    }
+    scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue-59352.rs:14:26: 14:50
+        debug self => _3;                // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
+        let mut _9: isize;               // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
+        scope 4 {
+            debug val => _0;             // in scope 4 at $DIR/issue-59352.rs:14:26: 14:50
+        }
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+        _8 = _1;                         // scope 0 at $DIR/issue-59352.rs:14:8: 14:11
+        StorageLive(_5);                 // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+        _5 = const 8_u32;                // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+        StorageLive(_6);                 // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        StorageLive(_7);                 // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        _7 = char::methods::<impl char>::to_digit(move _8, const 8_u32) -> bb5; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+                                         // mir::Constant
+                                         // + span: $DIR/issue-59352.rs:14:8: 14:23
+                                         // + literal: Const { ty: fn(char, u32) -> std::option::Option<u32> {std::char::methods::<impl char>::to_digit}, val: Value(Scalar(<ZST>)) }
+    }
+
+    bb1: {
+        StorageLive(_3);                 // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
+        StorageLive(_4);                 // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
+        _4 = _1;                         // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
+        _3 = char::methods::<impl char>::to_digit(move _4, const 8_u32) -> bb3; // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
+                                         // mir::Constant
+                                         // + span: $DIR/issue-59352.rs:14:30: 14:38
+                                         // + literal: Const { ty: fn(char, u32) -> std::option::Option<u32> {std::char::methods::<impl char>::to_digit}, val: Value(Scalar(<ZST>)) }
+    }
+
+    bb2: {
+        _0 = const 0_u32;                // scope 0 at $DIR/issue-59352.rs:14:60: 14:61
+        goto -> bb4;                     // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
+    }
+
+    bb3: {
+        StorageDead(_4);                 // scope 0 at $DIR/issue-59352.rs:14:40: 14:41
+        StorageLive(_9);                 // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
+        _9 = discriminant(_3);           // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
+        switchInt(move _9) -> [0_isize: bb6, 1_isize: bb8, otherwise: bb7]; // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
+    }
+
+    bb4: {
+        StorageDead(_2);                 // scope 0 at $DIR/issue-59352.rs:14:62: 14:63
+        return;                          // scope 0 at $DIR/issue-59352.rs:15:2: 15:2
+    }
+
+    bb5: {
+        _6 = &_7;                        // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        _10 = discriminant((*_6));       // scope 2 at $DIR/issue-59352.rs:14:8: 14:23
+        _2 = Eq(_10, const 1_isize);     // scope 2 at $DIR/issue-59352.rs:14:8: 14:23
+        StorageDead(_6);                 // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        StorageDead(_7);                 // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        StorageDead(_5);                 // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+        switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
+    }
+
+    bb6: {
+        core::panicking::panic(const "called `Option::unwrap()` on a `None` value"); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
+                                         // mir::Constant
+                                         // + span: $DIR/issue-59352.rs:14:26: 14:50
+                                         // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(Scalar(<ZST>)) }
+                                         // ty::Const
+                                         // + ty: &str
+                                         // + val: Value(Slice { data: Allocation { bytes: [99, 97, 108, 108, 101, 100, 32, 96, 79, 112, 116, 105, 111, 110, 58, 58, 117, 110, 119, 114, 97, 112, 40, 41, 96, 32, 111, 110, 32, 97, 32, 96, 78, 111, 110, 101, 96, 32, 118, 97, 108, 117, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [8796093022207], len: Size { raw: 43 } }, size: Size { raw: 43 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 43 })
+                                         // mir::Constant
+                                         // + span: $DIR/issue-59352.rs:14:26: 14:50
+                                         // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [99, 97, 108, 108, 101, 100, 32, 96, 79, 112, 116, 105, 111, 110, 58, 58, 117, 110, 119, 114, 97, 112, 40, 41, 96, 32, 111, 110, 32, 97, 32, 96, 78, 111, 110, 101, 96, 32, 118, 97, 108, 117, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [8796093022207], len: Size { raw: 43 } }, size: Size { raw: 43 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 43 }) }
+    }
+
+    bb7: {
+        unreachable;                     // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
+    }
+
+    bb8: {
+        _0 = move ((_3 as Some).0: u32); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
+        StorageDead(_9);                 // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
+        StorageDead(_3);                 // scope 0 at $DIR/issue-59352.rs:14:49: 14:50
+        goto -> bb4;                     // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
+    }
+}
diff --git a/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir b/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
index 56df50c..f109937 100644
--- a/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
+++ b/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
@@ -16,12 +16,14 @@
         StorageLive(_1);                 // scope 0 at $DIR/loop_test.rs:10:5: 12:6
         StorageLive(_2);                 // scope 0 at $DIR/loop_test.rs:10:8: 10:12
         _2 = const true;                 // scope 0 at $DIR/loop_test.rs:10:8: 10:12
-        FakeRead(ForMatchedPlace, _2);   // scope 0 at $DIR/loop_test.rs:10:8: 10:12
-        switchInt(_2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/loop_test.rs:10:5: 12:6
+        switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/loop_test.rs:10:5: 12:6
     }
 
     bb1: {
-        falseEdge -> [real: bb3, imaginary: bb2]; // scope 0 at $DIR/loop_test.rs:10:5: 12:6
+        _0 = const ();                   // scope 0 at $DIR/loop_test.rs:11:9: 11:15
+        StorageDead(_2);                 // scope 0 at $DIR/loop_test.rs:12:5: 12:6
+        StorageDead(_1);                 // scope 0 at $DIR/loop_test.rs:12:5: 12:6
+        return;                          // scope 0 at $DIR/loop_test.rs:17:2: 17:2
     }
 
     bb2: {
@@ -29,29 +31,22 @@
         StorageDead(_2);                 // scope 0 at $DIR/loop_test.rs:12:5: 12:6
         StorageDead(_1);                 // scope 0 at $DIR/loop_test.rs:12:5: 12:6
         StorageLive(_4);                 // scope 0 at $DIR/loop_test.rs:13:5: 16:6
-        goto -> bb4;                     // scope 0 at $DIR/loop_test.rs:13:5: 16:6
+        goto -> bb3;                     // scope 0 at $DIR/loop_test.rs:13:5: 16:6
     }
 
     bb3: {
-        _0 = const ();                   // scope 0 at $DIR/loop_test.rs:11:9: 11:15
-        StorageDead(_2);                 // scope 0 at $DIR/loop_test.rs:12:5: 12:6
-        StorageDead(_1);                 // scope 0 at $DIR/loop_test.rs:12:5: 12:6
-        return;                          // scope 0 at $DIR/loop_test.rs:17:2: 17:2
+        falseUnwind -> [real: bb4, cleanup: bb5]; // scope 0 at $DIR/loop_test.rs:13:5: 16:6
     }
 
     bb4: {
-        falseUnwind -> [real: bb5, cleanup: bb6]; // scope 0 at $DIR/loop_test.rs:13:5: 16:6
-    }
-
-    bb5: {
         StorageLive(_6);                 // scope 0 at $DIR/loop_test.rs:14:13: 14:14
         _6 = const 1_i32;                // scope 0 at $DIR/loop_test.rs:14:17: 14:18
         FakeRead(ForLet, _6);            // scope 0 at $DIR/loop_test.rs:14:13: 14:14
         StorageDead(_6);                 // scope 0 at $DIR/loop_test.rs:16:5: 16:6
-        goto -> bb4;                     // scope 0 at $DIR/loop_test.rs:1:1: 1:1
+        goto -> bb3;                     // scope 0 at $DIR/loop_test.rs:1:1: 1:1
     }
 
-    bb6 (cleanup): {
+    bb5 (cleanup): {
         resume;                          // scope 0 at $DIR/loop_test.rs:6:1: 17:2
     }
 }
diff --git a/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir b/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir
index 654dd82..740a6e0 100644
--- a/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir
+++ b/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir
@@ -3,24 +3,28 @@
 fn f_u64() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:16
     scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics.rs:35:5: 35:21
-        debug t => _2;                   // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        let _1: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        let mut _2: u64;                 // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
+        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
+        let mut _1: u64;                 // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
+        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
+        let mut _3: u64;                 // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
         scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics.rs:35:5: 35:21
         }
     }
 
     bb0: {
-        _2 = const 0_u64;                // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        StorageLive(_1);                 // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        _1 = f_non_zst::<u64>(move _2) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
+        _1 = const 0_u64;                // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
+        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
+        StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
+        _3 = move _1;                    // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
+        _2 = f_non_zst::<u64>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
                                          // mir::Constant
                                          // + span: $DIR/lower_intrinsics.rs:35:5: 35:21
                                          // + literal: Const { ty: fn(u64) {f_non_zst::<u64>}, val: Value(Scalar(<ZST>)) }
     }
 
     bb1: {
-        StorageDead(_1);                 // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
+        StorageDead(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
+        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
         _0 = const ();                   // scope 0 at $DIR/lower_intrinsics.rs:34:16: 36:2
         return;                          // scope 0 at $DIR/lower_intrinsics.rs:36:2: 36:2
     }
diff --git a/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
index 4e7cd77..95beab2 100644
--- a/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
+++ b/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
@@ -47,7 +47,7 @@
       }
   
       bb3: {
--         falseEdge -> [real: bb14, imaginary: bb5]; // scope 0 at $DIR/match-arm-scopes.rs:15:25: 15:38
+-         falseEdge -> [real: bb13, imaginary: bb5]; // scope 0 at $DIR/match-arm-scopes.rs:15:25: 15:38
 -     }
 - 
 -     bb4: {
@@ -55,7 +55,7 @@
 -     }
 - 
 -     bb5: {
--         falseEdge -> [real: bb22, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:16:9: 16:21
+-         falseEdge -> [real: bb20, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:16:9: 16:21
 -     }
 - 
 -     bb6: {
@@ -63,14 +63,14 @@
           _15 = (_2.1: bool);              // scope 0 at $DIR/match-arm-scopes.rs:16:32: 16:33
           StorageLive(_16);                // scope 0 at $DIR/match-arm-scopes.rs:16:35: 16:36
           _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:35: 16:36
--         goto -> bb21;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
+-         goto -> bb19;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
 +         goto -> bb16;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
       }
   
 -     bb7: {
 +     bb4: {
           _0 = const 1_i32;                // scope 1 at $DIR/match-arm-scopes.rs:15:77: 15:78
--         drop(_7) -> [return: bb20, unwind: bb27]; // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+-         drop(_7) -> [return: bb18, unwind: bb25]; // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
 +         drop(_7) -> [return: bb15, unwind: bb22]; // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
       }
   
@@ -85,33 +85,28 @@
           StorageLive(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
           StorageLive(_10);                // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
           _10 = _1;                        // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
--         FakeRead(ForMatchedPlace, _10);  // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
--         switchInt(_10) -> [false: bb10, otherwise: bb9]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
-+         switchInt(_10) -> [false: bb6, otherwise: bb7]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+-         switchInt(move _10) -> [false: bb10, otherwise: bb9]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
++         switchInt(move _10) -> [false: bb7, otherwise: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
       }
   
 -     bb9: {
--         falseEdge -> [real: bb11, imaginary: bb10]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
--     }
-- 
--     bb10: {
 +     bb6: {
+          _0 = const 3_i32;                // scope 0 at $DIR/match-arm-scopes.rs:15:59: 15:60
+          StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+          StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+-         goto -> bb23;                    // scope 0 at $DIR/match-arm-scopes.rs:1:1: 1:1
++         goto -> bb20;                    // scope 0 at $DIR/match-arm-scopes.rs:1:1: 1:1
+      }
+  
+-     bb10: {
++     bb7: {
           _9 = (*_6);                      // scope 0 at $DIR/match-arm-scopes.rs:15:70: 15:71
           StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
--         switchInt(move _9) -> [false: bb13, otherwise: bb12]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+-         switchInt(move _9) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
 +         switchInt(move _9) -> [false: bb9, otherwise: bb8]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
       }
   
 -     bb11: {
-+     bb7: {
-          _0 = const 3_i32;                // scope 0 at $DIR/match-arm-scopes.rs:15:59: 15:60
-          StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
-          StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
--         goto -> bb25;                    // scope 0 at $DIR/match-arm-scopes.rs:1:1: 1:1
-+         goto -> bb20;                    // scope 0 at $DIR/match-arm-scopes.rs:1:1: 1:1
-      }
-  
--     bb12: {
 +     bb8: {
           StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
 -         FakeRead(ForMatchGuard, _3);     // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
@@ -126,7 +121,7 @@
 +         goto -> bb4;                     // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
       }
   
--     bb13: {
+-     bb12: {
 +     bb9: {
           StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
@@ -135,7 +130,7 @@
 +         goto -> bb1;                     // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
       }
   
--     bb14: {
+-     bb13: {
 +     bb10: {
           StorageLive(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:26: 15:27
           _6 = &(_2.0: bool);              // scope 0 at $DIR/match-arm-scopes.rs:15:26: 15:27
@@ -146,33 +141,28 @@
           StorageLive(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
           StorageLive(_13);                // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
           _13 = _1;                        // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
--         FakeRead(ForMatchedPlace, _13);  // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
--         switchInt(_13) -> [false: bb16, otherwise: bb15]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
-+         switchInt(_13) -> [false: bb11, otherwise: bb12]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+-         switchInt(move _13) -> [false: bb15, otherwise: bb14]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
++         switchInt(move _13) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
       }
   
--     bb15: {
--         falseEdge -> [real: bb17, imaginary: bb16]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
--     }
-- 
--     bb16: {
+-     bb14: {
 +     bb11: {
-          _12 = (*_6);                     // scope 0 at $DIR/match-arm-scopes.rs:15:70: 15:71
-          StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
--         switchInt(move _12) -> [false: bb19, otherwise: bb18]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
-+         switchInt(move _12) -> [false: bb14, otherwise: bb13]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
-      }
-  
--     bb17: {
-+     bb12: {
           _0 = const 3_i32;                // scope 0 at $DIR/match-arm-scopes.rs:15:59: 15:60
           StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
           StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
--         goto -> bb25;                    // scope 0 at $DIR/match-arm-scopes.rs:1:1: 1:1
+-         goto -> bb23;                    // scope 0 at $DIR/match-arm-scopes.rs:1:1: 1:1
 +         goto -> bb20;                    // scope 0 at $DIR/match-arm-scopes.rs:1:1: 1:1
       }
   
--     bb18: {
+-     bb15: {
++     bb12: {
+          _12 = (*_6);                     // scope 0 at $DIR/match-arm-scopes.rs:15:70: 15:71
+          StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+-         switchInt(move _12) -> [false: bb17, otherwise: bb16]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
++         switchInt(move _12) -> [false: bb14, otherwise: bb13]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+      }
+  
+-     bb16: {
 +     bb13: {
           StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
 -         FakeRead(ForMatchGuard, _3);     // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
@@ -187,7 +177,7 @@
 +         goto -> bb4;                     // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
       }
   
--     bb19: {
+-     bb17: {
 +     bb14: {
           StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
@@ -196,67 +186,67 @@
 +         goto -> bb2;                     // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
       }
   
--     bb20: {
+-     bb18: {
 +     bb15: {
           StorageDead(_7);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_5);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
--         goto -> bb24;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
+-         goto -> bb22;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
 +         goto -> bb19;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
       }
   
--     bb21: {
+-     bb19: {
 +     bb16: {
           _0 = const 2_i32;                // scope 2 at $DIR/match-arm-scopes.rs:16:41: 16:42
--         drop(_16) -> [return: bb23, unwind: bb27]; // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42
+-         drop(_16) -> [return: bb21, unwind: bb25]; // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42
 +         drop(_16) -> [return: bb18, unwind: bb22]; // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42
       }
   
--     bb22: {
+-     bb20: {
 +     bb17: {
           StorageLive(_15);                // scope 0 at $DIR/match-arm-scopes.rs:16:16: 16:17
           _15 = (_2.1: bool);              // scope 0 at $DIR/match-arm-scopes.rs:16:16: 16:17
           StorageLive(_16);                // scope 0 at $DIR/match-arm-scopes.rs:16:19: 16:20
           _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:19: 16:20
--         goto -> bb21;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
+-         goto -> bb19;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
 +         goto -> bb16;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
       }
   
--     bb23: {
+-     bb21: {
 +     bb18: {
           StorageDead(_16);                // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42
           StorageDead(_15);                // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42
--         goto -> bb24;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
+-         goto -> bb22;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
 +         goto -> bb19;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
       }
   
--     bb24: {
--         drop(_2) -> [return: bb26, unwind: bb28]; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
+-     bb22: {
+-         drop(_2) -> [return: bb24, unwind: bb26]; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
 +     bb19: {
 +         goto -> bb26;                    // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
       }
   
--     bb25: {
+-     bb23: {
 +     bb20: {
           StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
--         drop(_2) -> [return: bb26, unwind: bb28]; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
+-         drop(_2) -> [return: bb24, unwind: bb26]; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
 +         drop(_2) -> [return: bb21, unwind: bb23]; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
       }
   
--     bb26: {
+-     bb24: {
 +     bb21: {
           return;                          // scope 0 at $DIR/match-arm-scopes.rs:18:2: 18:2
       }
   
--     bb27 (cleanup): {
--         drop(_2) -> bb28;                // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
+-     bb25 (cleanup): {
+-         drop(_2) -> bb26;                // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
 +     bb22 (cleanup): {
 +         goto -> bb27;                    // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
       }
   
--     bb28 (cleanup): {
+-     bb26 (cleanup): {
 +     bb23 (cleanup): {
           resume;                          // scope 0 at $DIR/match-arm-scopes.rs:13:1: 18:2
 +     }
diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff
index d0b1a96..2024034 100644
--- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff
+++ b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff
@@ -30,7 +30,7 @@
       }
   
       bb3: {
-          switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:7:5: 9:6
+          switchInt(move _2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:7:5: 9:6
       }
   
       bb4: {
@@ -39,7 +39,7 @@
       }
   
       bb5: {
-          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:10:1: 10:2
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:9:5: 9:6
           return;                          // scope 0 at $DIR/matches_reduce_branches.rs:10:2: 10:2
       }
   }
diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff
index d0b1a96..2024034 100644
--- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff
+++ b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff
@@ -30,7 +30,7 @@
       }
   
       bb3: {
-          switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:7:5: 9:6
+          switchInt(move _2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:7:5: 9:6
       }
   
       bb4: {
@@ -39,7 +39,7 @@
       }
   
       bb5: {
-          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:10:1: 10:2
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:9:5: 9:6
           return;                          // scope 0 at $DIR/matches_reduce_branches.rs:10:2: 10:2
       }
   }
diff --git a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff
index 1f46d37..1d89585 100644
--- a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff
+++ b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff
@@ -25,9 +25,9 @@
           StorageLive(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
           StorageLive(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:24: 40:28
           _6 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:24: 40:28
--         switchInt(_6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
+-         switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
 +         StorageLive(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
-+         _7 = _6;                         // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
++         _7 = move _6;                    // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
 +         _5 = Ne(_7, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:40:42: 40:47
 +         StorageDead(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
 +         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
@@ -45,41 +45,41 @@
   
       bb3: {
           StorageDead(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:47: 40:48
--         switchInt(_5) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
+-         switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
 +         StorageLive(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
-+         _8 = _5;                         // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
++         _8 = move _5;                    // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
 +         _4 = Ne(_8, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:40:62: 40:67
 +         StorageDead(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
 +         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
       }
   
       bb4: {
-          _4 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:40:62: 40:67
+          _4 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:50: 40:54
           goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
       }
   
       bb5: {
-          _4 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:50: 40:54
+          _4 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:40:62: 40:67
           goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
       }
   
       bb6: {
           StorageDead(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:67: 40:68
--         switchInt(_4) -> [false: bb7, otherwise: bb8]; // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+-         switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
 +         StorageLive(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
-+         _9 = _4;                         // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         _9 = move _4;                    // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
 +         _3 = Ne(_9, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:40:82: 40:87
 +         StorageDead(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
 +         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
       }
   
       bb7: {
-          _3 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:40:82: 40:87
+          _3 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:70: 40:74
           goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
       }
   
       bb8: {
-          _3 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:70: 40:74
+          _3 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:40:82: 40:87
           goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
       }
   
diff --git a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff
index 1f46d37..1d89585 100644
--- a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff
+++ b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff
@@ -25,9 +25,9 @@
           StorageLive(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
           StorageLive(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:24: 40:28
           _6 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:24: 40:28
--         switchInt(_6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
+-         switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
 +         StorageLive(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
-+         _7 = _6;                         // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
++         _7 = move _6;                    // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
 +         _5 = Ne(_7, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:40:42: 40:47
 +         StorageDead(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
 +         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:48
@@ -45,41 +45,41 @@
   
       bb3: {
           StorageDead(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:47: 40:48
--         switchInt(_5) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
+-         switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
 +         StorageLive(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
-+         _8 = _5;                         // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
++         _8 = move _5;                    // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
 +         _4 = Ne(_8, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:40:62: 40:67
 +         StorageDead(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
 +         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
       }
   
       bb4: {
-          _4 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:40:62: 40:67
+          _4 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:50: 40:54
           goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
       }
   
       bb5: {
-          _4 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:50: 40:54
+          _4 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:40:62: 40:67
           goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:18: 40:68
       }
   
       bb6: {
           StorageDead(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:67: 40:68
--         switchInt(_4) -> [false: bb7, otherwise: bb8]; // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
+-         switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
 +         StorageLive(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
-+         _9 = _4;                         // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
++         _9 = move _4;                    // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
 +         _3 = Ne(_9, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:40:82: 40:87
 +         StorageDead(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
 +         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
       }
   
       bb7: {
-          _3 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:40:82: 40:87
+          _3 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:70: 40:74
           goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
       }
   
       bb8: {
-          _3 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:40:70: 40:74
+          _3 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:40:82: 40:87
           goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 40:88
       }
   
diff --git a/src/test/mir-opt/multiple_return_terminators.test.MultipleReturnTerminators.diff b/src/test/mir-opt/multiple_return_terminators.test.MultipleReturnTerminators.diff
index 997c021..fb25cb9 100644
--- a/src/test/mir-opt/multiple_return_terminators.test.MultipleReturnTerminators.diff
+++ b/src/test/mir-opt/multiple_return_terminators.test.MultipleReturnTerminators.diff
@@ -9,21 +9,21 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/multiple_return_terminators.rs:5:8: 5:9
           _2 = _1;                         // scope 0 at $DIR/multiple_return_terminators.rs:5:8: 5:9
-          switchInt(_2) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/multiple_return_terminators.rs:5:5: 9:6
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/multiple_return_terminators.rs:5:5: 9:6
       }
   
       bb1: {
-          _0 = const ();                   // scope 0 at $DIR/multiple_return_terminators.rs:7:12: 9:6
-          goto -> bb3;                     // scope 0 at $DIR/multiple_return_terminators.rs:5:5: 9:6
-      }
-  
-      bb2: {
           _0 = const ();                   // scope 0 at $DIR/multiple_return_terminators.rs:5:10: 7:6
           goto -> bb3;                     // scope 0 at $DIR/multiple_return_terminators.rs:5:5: 9:6
       }
   
+      bb2: {
+          _0 = const ();                   // scope 0 at $DIR/multiple_return_terminators.rs:7:12: 9:6
+          goto -> bb3;                     // scope 0 at $DIR/multiple_return_terminators.rs:5:5: 9:6
+      }
+  
       bb3: {
-          StorageDead(_2);                 // scope 0 at $DIR/multiple_return_terminators.rs:10:1: 10:2
+          StorageDead(_2);                 // scope 0 at $DIR/multiple_return_terminators.rs:9:5: 9:6
           return;                          // scope 0 at $DIR/multiple_return_terminators.rs:10:2: 10:2
       }
   }
diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
index d8538a5..8c939d5 100644
--- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
@@ -5,19 +5,19 @@
 | '_#1r | Local | ['_#1r]
 |
 | Inferred Region Values
-| '_#0r | U0 | {bb0[0..=8], bb1[0..=8], bb2[0], bb3[0..=1], bb4[0..=3], bb5[0..=3], bb6[0..=2], bb7[0..=5], bb8[0], '_#0r, '_#1r}
-| '_#1r | U0 | {bb0[0..=8], bb1[0..=8], bb2[0], bb3[0..=1], bb4[0..=3], bb5[0..=3], bb6[0..=2], bb7[0..=5], bb8[0], '_#1r}
+| '_#0r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0], '_#0r, '_#1r}
+| '_#1r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0], '_#1r}
 | '_#2r | U0 | {}
-| '_#3r | U0 | {bb1[0..=8], bb2[0], bb4[0..=2]}
-| '_#4r | U0 | {bb1[1..=8], bb2[0], bb4[0..=2]}
-| '_#5r | U0 | {bb1[4..=8], bb2[0], bb4[0..=2]}
+| '_#3r | U0 | {bb1[0..=7], bb2[0..=2]}
+| '_#4r | U0 | {bb1[1..=7], bb2[0..=2]}
+| '_#5r | U0 | {bb1[4..=7], bb2[0..=2]}
 |
 | Inference Constraints
-| '_#0r live at {bb0[0..=8], bb1[0..=8], bb2[0], bb3[0..=1], bb4[0..=3], bb5[0..=3], bb6[0..=2], bb7[0..=5], bb8[0]}
-| '_#1r live at {bb0[0..=8], bb1[0..=8], bb2[0], bb3[0..=1], bb4[0..=3], bb5[0..=3], bb6[0..=2], bb7[0..=5], bb8[0]}
+| '_#0r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0]}
+| '_#1r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0]}
 | '_#3r live at {bb1[0]}
 | '_#4r live at {bb1[1..=3]}
-| '_#5r live at {bb1[4..=8], bb2[0], bb4[0..=2]}
+| '_#5r live at {bb1[4..=7], bb2[0..=2]}
 | '_#3r: '_#4r due to Assignment at Single(bb1[0])
 | '_#4r: '_#5r due to Assignment at Single(bb1[3])
 |
@@ -52,7 +52,7 @@
         _3 = const Const(Value(Scalar(0x00000000)): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17
         _4 = Len(_1);                    // bb0[6]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
         _5 = Lt(_3, _4);                 // bb0[7]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
-        assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb8]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
+        assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb7]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
     }
 
     bb1: {
@@ -63,55 +63,50 @@
         FakeRead(ForLet, _6);            // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
         StorageLive(_7);                 // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
         _7 = const Const(Value(Scalar(0x01)): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
-        FakeRead(ForMatchedPlace, _7);   // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
-        switchInt(_7) -> [Const(Value(Scalar(0x00)): bool): bb3, otherwise: bb2]; // bb1[8]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
+        switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb3, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
     }
 
     bb2: {
-        falseEdge -> [real: bb4, imaginary: bb3]; // bb2[0]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
+        StorageLive(_8);                 // bb2[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
+        StorageLive(_9);                 // bb2[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
+        _9 = (*_6);                      // bb2[2]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
+        _8 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb4, unwind: bb7]; // bb2[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
+                                         // mir::Constant
+                                         // + span: $DIR/region-subtyping-basic.rs:21:9: 21:14
+                                         // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
     }
 
     bb3: {
         StorageLive(_10);                // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
-        _10 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x00000016)): usize)) -> [return: bb6, unwind: bb8]; // bb3[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
+        _10 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x00000016)): usize)) -> [return: bb5, unwind: bb7]; // bb3[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
                                          // mir::Constant
                                          // + span: $DIR/region-subtyping-basic.rs:23:9: 23:14
                                          // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
     }
 
     bb4: {
-        StorageLive(_8);                 // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
-        StorageLive(_9);                 // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
-        _9 = (*_6);                      // bb4[2]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
-        _8 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb5, unwind: bb8]; // bb4[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
-                                         // mir::Constant
-                                         // + span: $DIR/region-subtyping-basic.rs:21:9: 21:14
-                                         // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
+        StorageDead(_9);                 // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:17: 21:18
+        StorageDead(_8);                 // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:18: 21:19
+        _0 = const Const(Value(Scalar(<ZST>)): ()); // bb4[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:13: 22:6
+        goto -> bb6;                     // bb4[3]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
     }
 
     bb5: {
-        StorageDead(_9);                 // bb5[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:17: 21:18
-        StorageDead(_8);                 // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:18: 21:19
-        _0 = const Const(Value(Scalar(<ZST>)): ()); // bb5[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:13: 22:6
-        goto -> bb7;                     // bb5[3]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
+        StorageDead(_10);                // bb5[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:18: 23:19
+        _0 = const Const(Value(Scalar(<ZST>)): ()); // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:22:12: 24:6
+        goto -> bb6;                     // bb5[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
     }
 
     bb6: {
-        StorageDead(_10);                // bb6[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:18: 23:19
-        _0 = const Const(Value(Scalar(<ZST>)): ()); // bb6[1]: scope 3 at $DIR/region-subtyping-basic.rs:22:12: 24:6
-        goto -> bb7;                     // bb6[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
+        StorageDead(_7);                 // bb6[0]: scope 3 at $DIR/region-subtyping-basic.rs:24:5: 24:6
+        StorageDead(_6);                 // bb6[1]: scope 2 at $DIR/region-subtyping-basic.rs:25:1: 25:2
+        StorageDead(_3);                 // bb6[2]: scope 1 at $DIR/region-subtyping-basic.rs:25:1: 25:2
+        StorageDead(_2);                 // bb6[3]: scope 1 at $DIR/region-subtyping-basic.rs:25:1: 25:2
+        StorageDead(_1);                 // bb6[4]: scope 0 at $DIR/region-subtyping-basic.rs:25:1: 25:2
+        return;                          // bb6[5]: scope 0 at $DIR/region-subtyping-basic.rs:25:2: 25:2
     }
 
-    bb7: {
-        StorageDead(_6);                 // bb7[0]: scope 2 at $DIR/region-subtyping-basic.rs:25:1: 25:2
-        StorageDead(_3);                 // bb7[1]: scope 1 at $DIR/region-subtyping-basic.rs:25:1: 25:2
-        StorageDead(_2);                 // bb7[2]: scope 1 at $DIR/region-subtyping-basic.rs:25:1: 25:2
-        StorageDead(_1);                 // bb7[3]: scope 0 at $DIR/region-subtyping-basic.rs:25:1: 25:2
-        StorageDead(_7);                 // bb7[4]: scope 0 at $DIR/region-subtyping-basic.rs:25:1: 25:2
-        return;                          // bb7[5]: scope 0 at $DIR/region-subtyping-basic.rs:25:2: 25:2
-    }
-
-    bb8 (cleanup): {
-        resume;                          // bb8[0]: scope 0 at $DIR/region-subtyping-basic.rs:16:1: 25:2
+    bb7 (cleanup): {
+        resume;                          // bb7[0]: scope 0 at $DIR/region-subtyping-basic.rs:16:1: 25:2
     }
 }
diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
index 15aba40..00704ba 100644
--- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
@@ -5,19 +5,19 @@
 | '_#1r | Local | ['_#1r]
 |
 | Inferred Region Values
-| '_#0r | U0 | {bb0[0..=8], bb1[0..=8], bb2[0], bb3[0..=1], bb4[0..=3], bb5[0..=3], bb6[0..=2], bb7[0..=5], bb8[0], '_#0r, '_#1r}
-| '_#1r | U0 | {bb0[0..=8], bb1[0..=8], bb2[0], bb3[0..=1], bb4[0..=3], bb5[0..=3], bb6[0..=2], bb7[0..=5], bb8[0], '_#1r}
+| '_#0r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0], '_#0r, '_#1r}
+| '_#1r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0], '_#1r}
 | '_#2r | U0 | {}
-| '_#3r | U0 | {bb1[0..=8], bb2[0], bb4[0..=2]}
-| '_#4r | U0 | {bb1[1..=8], bb2[0], bb4[0..=2]}
-| '_#5r | U0 | {bb1[4..=8], bb2[0], bb4[0..=2]}
+| '_#3r | U0 | {bb1[0..=7], bb2[0..=2]}
+| '_#4r | U0 | {bb1[1..=7], bb2[0..=2]}
+| '_#5r | U0 | {bb1[4..=7], bb2[0..=2]}
 |
 | Inference Constraints
-| '_#0r live at {bb0[0..=8], bb1[0..=8], bb2[0], bb3[0..=1], bb4[0..=3], bb5[0..=3], bb6[0..=2], bb7[0..=5], bb8[0]}
-| '_#1r live at {bb0[0..=8], bb1[0..=8], bb2[0], bb3[0..=1], bb4[0..=3], bb5[0..=3], bb6[0..=2], bb7[0..=5], bb8[0]}
+| '_#0r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0]}
+| '_#1r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0]}
 | '_#3r live at {bb1[0]}
 | '_#4r live at {bb1[1..=3]}
-| '_#5r live at {bb1[4..=8], bb2[0], bb4[0..=2]}
+| '_#5r live at {bb1[4..=7], bb2[0..=2]}
 | '_#3r: '_#4r due to Assignment at Single(bb1[0])
 | '_#4r: '_#5r due to Assignment at Single(bb1[3])
 |
@@ -52,7 +52,7 @@
         _3 = const Const(Value(Scalar(0x0000000000000000)): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17
         _4 = Len(_1);                    // bb0[6]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
         _5 = Lt(_3, _4);                 // bb0[7]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
-        assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb8]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
+        assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb7]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
     }
 
     bb1: {
@@ -63,55 +63,50 @@
         FakeRead(ForLet, _6);            // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
         StorageLive(_7);                 // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
         _7 = const Const(Value(Scalar(0x01)): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
-        FakeRead(ForMatchedPlace, _7);   // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
-        switchInt(_7) -> [Const(Value(Scalar(0x00)): bool): bb3, otherwise: bb2]; // bb1[8]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
+        switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb3, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
     }
 
     bb2: {
-        falseEdge -> [real: bb4, imaginary: bb3]; // bb2[0]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
+        StorageLive(_8);                 // bb2[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
+        StorageLive(_9);                 // bb2[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
+        _9 = (*_6);                      // bb2[2]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
+        _8 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb4, unwind: bb7]; // bb2[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
+                                         // mir::Constant
+                                         // + span: $DIR/region-subtyping-basic.rs:21:9: 21:14
+                                         // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
     }
 
     bb3: {
         StorageLive(_10);                // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
-        _10 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x0000000000000016)): usize)) -> [return: bb6, unwind: bb8]; // bb3[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
+        _10 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x0000000000000016)): usize)) -> [return: bb5, unwind: bb7]; // bb3[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
                                          // mir::Constant
                                          // + span: $DIR/region-subtyping-basic.rs:23:9: 23:14
                                          // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
     }
 
     bb4: {
-        StorageLive(_8);                 // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
-        StorageLive(_9);                 // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
-        _9 = (*_6);                      // bb4[2]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
-        _8 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb5, unwind: bb8]; // bb4[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
-                                         // mir::Constant
-                                         // + span: $DIR/region-subtyping-basic.rs:21:9: 21:14
-                                         // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
+        StorageDead(_9);                 // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:17: 21:18
+        StorageDead(_8);                 // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:18: 21:19
+        _0 = const Const(Value(Scalar(<ZST>)): ()); // bb4[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:13: 22:6
+        goto -> bb6;                     // bb4[3]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
     }
 
     bb5: {
-        StorageDead(_9);                 // bb5[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:17: 21:18
-        StorageDead(_8);                 // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:18: 21:19
-        _0 = const Const(Value(Scalar(<ZST>)): ()); // bb5[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:13: 22:6
-        goto -> bb7;                     // bb5[3]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
+        StorageDead(_10);                // bb5[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:18: 23:19
+        _0 = const Const(Value(Scalar(<ZST>)): ()); // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:22:12: 24:6
+        goto -> bb6;                     // bb5[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
     }
 
     bb6: {
-        StorageDead(_10);                // bb6[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:18: 23:19
-        _0 = const Const(Value(Scalar(<ZST>)): ()); // bb6[1]: scope 3 at $DIR/region-subtyping-basic.rs:22:12: 24:6
-        goto -> bb7;                     // bb6[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
+        StorageDead(_7);                 // bb6[0]: scope 3 at $DIR/region-subtyping-basic.rs:24:5: 24:6
+        StorageDead(_6);                 // bb6[1]: scope 2 at $DIR/region-subtyping-basic.rs:25:1: 25:2
+        StorageDead(_3);                 // bb6[2]: scope 1 at $DIR/region-subtyping-basic.rs:25:1: 25:2
+        StorageDead(_2);                 // bb6[3]: scope 1 at $DIR/region-subtyping-basic.rs:25:1: 25:2
+        StorageDead(_1);                 // bb6[4]: scope 0 at $DIR/region-subtyping-basic.rs:25:1: 25:2
+        return;                          // bb6[5]: scope 0 at $DIR/region-subtyping-basic.rs:25:2: 25:2
     }
 
-    bb7: {
-        StorageDead(_6);                 // bb7[0]: scope 2 at $DIR/region-subtyping-basic.rs:25:1: 25:2
-        StorageDead(_3);                 // bb7[1]: scope 1 at $DIR/region-subtyping-basic.rs:25:1: 25:2
-        StorageDead(_2);                 // bb7[2]: scope 1 at $DIR/region-subtyping-basic.rs:25:1: 25:2
-        StorageDead(_1);                 // bb7[3]: scope 0 at $DIR/region-subtyping-basic.rs:25:1: 25:2
-        StorageDead(_7);                 // bb7[4]: scope 0 at $DIR/region-subtyping-basic.rs:25:1: 25:2
-        return;                          // bb7[5]: scope 0 at $DIR/region-subtyping-basic.rs:25:2: 25:2
-    }
-
-    bb8 (cleanup): {
-        resume;                          // bb8[0]: scope 0 at $DIR/region-subtyping-basic.rs:16:1: 25:2
+    bb7 (cleanup): {
+        resume;                          // bb7[0]: scope 0 at $DIR/region-subtyping-basic.rs:16:1: 25:2
     }
 }
diff --git a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff
index 5588877..52e705f 100644
--- a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff
+++ b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff
@@ -21,31 +21,26 @@
       }
   
 -     bb2: {
--         nop;                             // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
--         switchInt(_2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
+-         switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
 +     bb1: {
-+         switchInt(_2) -> [false: bb2, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
++         switchInt(move _2) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
       }
   
 -     bb3: {
--         goto -> bb5;                     // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
--     }
-- 
--     bb4: {
 +     bb2: {
-          _1 = const ();                   // scope 0 at $DIR/simplify_cfg.rs:9:10: 9:10
-          StorageDead(_2);                 // scope 0 at $DIR/simplify_cfg.rs:10:5: 10:6
-          goto -> bb0;                     // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
+          _0 = const ();                   // scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_cfg.rs:9:9: 9:10
+          return;                          // scope 0 at $DIR/simplify_cfg.rs:11:2: 11:2
       }
   
--     bb5: {
+-     bb4: {
 +     bb3: {
-          _0 = const ();                   // scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
-          StorageDead(_2);                 // scope 0 at $DIR/simplify_cfg.rs:10:5: 10:6
-          return;                          // scope 0 at $DIR/simplify_cfg.rs:11:2: 11:2
+          _1 = const ();                   // scope 0 at $DIR/simplify_cfg.rs:9:10: 9:10
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_cfg.rs:9:9: 9:10
+          goto -> bb0;                     // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
 -     }
 - 
--     bb6 (cleanup): {
+-     bb5 (cleanup): {
 -         resume;                          // scope 0 at $DIR/simplify_cfg.rs:5:1: 11:2
       }
   }
diff --git a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
index e629352..fef3ae2 100644
--- a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
+++ b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
@@ -9,69 +9,63 @@
   
       bb0: {
 -         goto -> bb1;                     // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
-+         falseUnwind -> [real: bb1, cleanup: bb6]; // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
++         falseUnwind -> [real: bb1, cleanup: bb5]; // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
       }
   
       bb1: {
--         falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
+-         falseUnwind -> [real: bb2, cleanup: bb10]; // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
 -     }
 - 
 -     bb2: {
           StorageLive(_2);                 // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
--         _2 = bar() -> [return: bb3, unwind: bb11]; // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
-+         _2 = bar() -> [return: bb2, unwind: bb6]; // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
+-         _2 = bar() -> [return: bb3, unwind: bb10]; // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
++         _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
                                            // mir::Constant
                                            // + span: $DIR/simplify_cfg.rs:7:12: 7:15
                                            // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
       }
   
 -     bb3: {
+-         switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
 +     bb2: {
-          FakeRead(ForMatchedPlace, _2);   // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
--         switchInt(_2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
-+         switchInt(_2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
++         switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
       }
   
 -     bb4: {
--         falseEdge -> [real: bb6, imaginary: bb5]; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
 +     bb3: {
-+         falseEdge -> [real: bb5, imaginary: bb4]; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
+          _0 = const ();                   // scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
+-         goto -> bb9;                     // scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
++         StorageDead(_2);                 // scope 0 at $DIR/simplify_cfg.rs:9:9: 9:10
++         return;                          // scope 0 at $DIR/simplify_cfg.rs:11:2: 11:2
       }
   
 -     bb5: {
 +     bb4: {
           _1 = const ();                   // scope 0 at $DIR/simplify_cfg.rs:9:10: 9:10
--         goto -> bb9;                     // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
-+         StorageDead(_2);                 // scope 0 at $DIR/simplify_cfg.rs:10:5: 10:6
-+         goto -> bb0;                     // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
-      }
-  
--     bb6: {
-+     bb5: {
-          _0 = const ();                   // scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
--         goto -> bb10;                    // scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
+-         goto -> bb8;                     // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
 -     }
 - 
--     bb7: {
+-     bb6: {
 -         unreachable;                     // scope 0 at $DIR/simplify_cfg.rs:7:18: 9:10
 -     }
 - 
+-     bb7: {
+-         goto -> bb8;                     // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
+-     }
+- 
 -     bb8: {
--         goto -> bb9;                     // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
--     }
-- 
--     bb9: {
-          StorageDead(_2);                 // scope 0 at $DIR/simplify_cfg.rs:10:5: 10:6
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_cfg.rs:9:9: 9:10
 -         goto -> bb1;                     // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
--     }
-- 
--     bb10: {
--         StorageDead(_2);                 // scope 0 at $DIR/simplify_cfg.rs:10:5: 10:6
-          return;                          // scope 0 at $DIR/simplify_cfg.rs:11:2: 11:2
++         goto -> bb0;                     // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
       }
   
--     bb11 (cleanup): {
-+     bb6 (cleanup): {
+-     bb9: {
+-         StorageDead(_2);                 // scope 0 at $DIR/simplify_cfg.rs:9:9: 9:10
+-         return;                          // scope 0 at $DIR/simplify_cfg.rs:11:2: 11:2
+-     }
+- 
+-     bb10 (cleanup): {
++     bb5 (cleanup): {
           resume;                          // scope 0 at $DIR/simplify_cfg.rs:5:1: 11:2
       }
   }
diff --git a/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff b/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff
index bf3caf5..2cd57cb 100644
--- a/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff
+++ b/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff
@@ -9,16 +9,11 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/simplify_if.rs:6:8: 6:13
           _1 = const false;                // scope 0 at $DIR/simplify_if.rs:6:8: 6:13
--         switchInt(const false) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_if.rs:6:5: 8:6
-+         goto -> bb1;                     // scope 0 at $DIR/simplify_if.rs:6:5: 8:6
+-         switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:6:5: 8:6
++         goto -> bb2;                     // scope 0 at $DIR/simplify_if.rs:6:5: 8:6
       }
   
       bb1: {
-          _0 = const ();                   // scope 0 at $DIR/simplify_if.rs:8:6: 8:6
-          goto -> bb4;                     // scope 0 at $DIR/simplify_if.rs:6:5: 8:6
-      }
-  
-      bb2: {
           StorageLive(_2);                 // scope 0 at $DIR/simplify_if.rs:7:9: 7:15
           _2 = noop() -> bb3;              // scope 0 at $DIR/simplify_if.rs:7:9: 7:15
                                            // mir::Constant
@@ -26,6 +21,11 @@
                                            // + literal: Const { ty: fn() {noop}, val: Value(Scalar(<ZST>)) }
       }
   
+      bb2: {
+          _0 = const ();                   // scope 0 at $DIR/simplify_if.rs:8:6: 8:6
+          goto -> bb4;                     // scope 0 at $DIR/simplify_if.rs:6:5: 8:6
+      }
+  
       bb3: {
           StorageDead(_2);                 // scope 0 at $DIR/simplify_if.rs:7:15: 7:16
           _0 = const ();                   // scope 0 at $DIR/simplify_if.rs:6:14: 8:6
@@ -33,7 +33,7 @@
       }
   
       bb4: {
-          StorageDead(_1);                 // scope 0 at $DIR/simplify_if.rs:9:1: 9:2
+          StorageDead(_1);                 // scope 0 at $DIR/simplify_if.rs:8:5: 8:6
           return;                          // scope 0 at $DIR/simplify_if.rs:9:2: 9:2
       }
   }
diff --git a/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff
index 9f7507a..70725e5 100644
--- a/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff
@@ -47,21 +47,21 @@
           _8 = _6;                         // scope 1 at $DIR/simplify-locals-fixedpoint.rs:5:12: 5:13
           _7 = Gt(move _8, const 42_u8);   // scope 1 at $DIR/simplify-locals-fixedpoint.rs:5:12: 5:20
           StorageDead(_8);                 // scope 1 at $DIR/simplify-locals-fixedpoint.rs:5:19: 5:20
-          switchInt(_7) -> [false: bb4, otherwise: bb5]; // scope 1 at $DIR/simplify-locals-fixedpoint.rs:5:9: 7:10
+          switchInt(move _7) -> [false: bb5, otherwise: bb4]; // scope 1 at $DIR/simplify-locals-fixedpoint.rs:5:9: 7:10
       }
   
       bb4: {
-          _0 = const ();                   // scope 1 at $DIR/simplify-locals-fixedpoint.rs:7:10: 7:10
-          goto -> bb6;                     // scope 1 at $DIR/simplify-locals-fixedpoint.rs:5:9: 7:10
-      }
-  
-      bb5: {
           _0 = const ();                   // scope 1 at $DIR/simplify-locals-fixedpoint.rs:5:21: 7:10
           goto -> bb6;                     // scope 1 at $DIR/simplify-locals-fixedpoint.rs:5:9: 7:10
       }
   
+      bb5: {
+          _0 = const ();                   // scope 1 at $DIR/simplify-locals-fixedpoint.rs:7:10: 7:10
+          goto -> bb6;                     // scope 1 at $DIR/simplify-locals-fixedpoint.rs:5:9: 7:10
+      }
+  
       bb6: {
-          StorageDead(_7);                 // scope 1 at $DIR/simplify-locals-fixedpoint.rs:8:5: 8:6
+          StorageDead(_7);                 // scope 1 at $DIR/simplify-locals-fixedpoint.rs:7:9: 7:10
           StorageDead(_6);                 // scope 0 at $DIR/simplify-locals-fixedpoint.rs:8:5: 8:6
           goto -> bb7;                     // scope 0 at $DIR/simplify-locals-fixedpoint.rs:4:5: 8:6
       }
diff --git a/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
index 6f44de1..23a3fbd 100644
--- a/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
+++ b/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
@@ -44,18 +44,18 @@
 -         StorageLive(_5);                 // scope 2 at $DIR/unreachable.rs:12:9: 16:10
 -         StorageLive(_6);                 // scope 2 at $DIR/unreachable.rs:12:12: 12:16
 -         _6 = const true;                 // scope 2 at $DIR/unreachable.rs:12:12: 12:16
--         switchInt(_6) -> [false: bb4, otherwise: bb5]; // scope 2 at $DIR/unreachable.rs:12:9: 16:10
+-         switchInt(move _6) -> [false: bb5, otherwise: bb4]; // scope 2 at $DIR/unreachable.rs:12:9: 16:10
 -     }
 - 
 -     bb4: {
--         _4 = const 42_i32;               // scope 2 at $DIR/unreachable.rs:15:13: 15:20
--         _5 = const ();                   // scope 2 at $DIR/unreachable.rs:14:16: 16:10
+-         _4 = const 21_i32;               // scope 2 at $DIR/unreachable.rs:13:13: 13:20
+-         _5 = const ();                   // scope 2 at $DIR/unreachable.rs:12:17: 14:10
 -         goto -> bb6;                     // scope 2 at $DIR/unreachable.rs:12:9: 16:10
 -     }
 - 
 -     bb5: {
--         _4 = const 21_i32;               // scope 2 at $DIR/unreachable.rs:13:13: 13:20
--         _5 = const ();                   // scope 2 at $DIR/unreachable.rs:12:17: 14:10
+-         _4 = const 42_i32;               // scope 2 at $DIR/unreachable.rs:15:13: 15:20
+-         _5 = const ();                   // scope 2 at $DIR/unreachable.rs:14:16: 16:10
 -         goto -> bb6;                     // scope 2 at $DIR/unreachable.rs:12:9: 16:10
 -     }
 - 
diff --git a/src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff
index 9bca06a..3eda183 100644
--- a/src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff
+++ b/src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff
@@ -46,18 +46,18 @@
           StorageLive(_5);                 // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10
           StorageLive(_6);                 // scope 2 at $DIR/unreachable_asm.rs:14:12: 14:16
           _6 = const true;                 // scope 2 at $DIR/unreachable_asm.rs:14:12: 14:16
-          switchInt(_6) -> [false: bb4, otherwise: bb5]; // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10
+          switchInt(move _6) -> [false: bb5, otherwise: bb4]; // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10
       }
   
       bb4: {
-          _4 = const 42_i32;               // scope 2 at $DIR/unreachable_asm.rs:17:13: 17:20
-          _5 = const ();                   // scope 2 at $DIR/unreachable_asm.rs:16:16: 18:10
+          _4 = const 21_i32;               // scope 2 at $DIR/unreachable_asm.rs:15:13: 15:20
+          _5 = const ();                   // scope 2 at $DIR/unreachable_asm.rs:14:17: 16:10
           goto -> bb6;                     // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10
       }
   
       bb5: {
-          _4 = const 21_i32;               // scope 2 at $DIR/unreachable_asm.rs:15:13: 15:20
-          _5 = const ();                   // scope 2 at $DIR/unreachable_asm.rs:14:17: 16:10
+          _4 = const 42_i32;               // scope 2 at $DIR/unreachable_asm.rs:17:13: 17:20
+          _5 = const ();                   // scope 2 at $DIR/unreachable_asm.rs:16:16: 18:10
           goto -> bb6;                     // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10
       }
   
diff --git a/src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff
index cbc24ea..d0d52e8 100644
--- a/src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff
+++ b/src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff
@@ -49,21 +49,10 @@
           StorageLive(_5);                 // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
           StorageLive(_6);                 // scope 2 at $DIR/unreachable_asm_2.rs:14:12: 14:16
           _6 = const true;                 // scope 2 at $DIR/unreachable_asm_2.rs:14:12: 14:16
-          switchInt(_6) -> [false: bb4, otherwise: bb5]; // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
+          switchInt(move _6) -> [false: bb5, otherwise: bb4]; // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
       }
   
       bb4: {
-          StorageLive(_8);                 // scope 2 at $DIR/unreachable_asm_2.rs:20:13: 20:41
-          llvm_asm!(LlvmInlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []); // scope 4 at $DIR/unreachable_asm_2.rs:20:22: 20:39
-          _8 = const ();                   // scope 4 at $DIR/unreachable_asm_2.rs:20:13: 20:41
-          StorageDead(_8);                 // scope 2 at $DIR/unreachable_asm_2.rs:20:40: 20:41
-          _4 = const 42_i32;               // scope 2 at $DIR/unreachable_asm_2.rs:21:13: 21:20
-          _5 = const ();                   // scope 2 at $DIR/unreachable_asm_2.rs:18:16: 22:10
--         goto -> bb6;                     // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
-+         unreachable;                     // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
-      }
-  
-      bb5: {
           StorageLive(_7);                 // scope 2 at $DIR/unreachable_asm_2.rs:16:13: 16:41
           llvm_asm!(LlvmInlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []); // scope 3 at $DIR/unreachable_asm_2.rs:16:22: 16:39
           _7 = const ();                   // scope 3 at $DIR/unreachable_asm_2.rs:16:13: 16:41
@@ -71,6 +60,17 @@
           _4 = const 21_i32;               // scope 2 at $DIR/unreachable_asm_2.rs:17:13: 17:20
           _5 = const ();                   // scope 2 at $DIR/unreachable_asm_2.rs:14:17: 18:10
 -         goto -> bb6;                     // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
++         unreachable;                     // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
+      }
+  
+      bb5: {
+          StorageLive(_8);                 // scope 2 at $DIR/unreachable_asm_2.rs:20:13: 20:41
+          llvm_asm!(LlvmInlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []); // scope 4 at $DIR/unreachable_asm_2.rs:20:22: 20:39
+          _8 = const ();                   // scope 4 at $DIR/unreachable_asm_2.rs:20:13: 20:41
+          StorageDead(_8);                 // scope 2 at $DIR/unreachable_asm_2.rs:20:40: 20:41
+          _4 = const 42_i32;               // scope 2 at $DIR/unreachable_asm_2.rs:21:13: 21:20
+          _5 = const ();                   // scope 2 at $DIR/unreachable_asm_2.rs:18:16: 22:10
+-         goto -> bb6;                     // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
 -     }
 - 
 -     bb6: {
diff --git a/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
index fd8286f..2c0cc04 100644
--- a/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
+++ b/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
@@ -45,16 +45,11 @@
           StorageLive(_5);                 // scope 2 at $DIR/unreachable_diverging.rs:15:9: 17:10
           StorageLive(_6);                 // scope 2 at $DIR/unreachable_diverging.rs:15:12: 15:13
           _6 = _1;                         // scope 2 at $DIR/unreachable_diverging.rs:15:12: 15:13
--         switchInt(_6) -> [false: bb4, otherwise: bb5]; // scope 2 at $DIR/unreachable_diverging.rs:15:9: 17:10
+-         switchInt(move _6) -> [false: bb5, otherwise: bb4]; // scope 2 at $DIR/unreachable_diverging.rs:15:9: 17:10
 +         goto -> bb4;                     // scope 2 at $DIR/unreachable_diverging.rs:15:9: 17:10
       }
   
       bb4: {
--         _5 = const ();                   // scope 2 at $DIR/unreachable_diverging.rs:17:10: 17:10
--         goto -> bb6;                     // scope 2 at $DIR/unreachable_diverging.rs:15:9: 17:10
--     }
-- 
--     bb5: {
 -         _5 = loop_forever() -> bb6;      // scope 2 at $DIR/unreachable_diverging.rs:16:13: 16:27
 +         _5 = loop_forever() -> bb5;      // scope 2 at $DIR/unreachable_diverging.rs:16:13: 16:27
                                            // mir::Constant
@@ -62,8 +57,12 @@
                                            // + literal: Const { ty: fn() {loop_forever}, val: Value(Scalar(<ZST>)) }
       }
   
+      bb5: {
+-         _5 = const ();                   // scope 2 at $DIR/unreachable_diverging.rs:17:10: 17:10
+-         goto -> bb6;                     // scope 2 at $DIR/unreachable_diverging.rs:15:9: 17:10
+-     }
+- 
 -     bb6: {
-+     bb5: {
           StorageDead(_6);                 // scope 2 at $DIR/unreachable_diverging.rs:17:9: 17:10
           StorageDead(_5);                 // scope 2 at $DIR/unreachable_diverging.rs:17:9: 17:10
           StorageLive(_7);                 // scope 2 at $DIR/unreachable_diverging.rs:18:9: 18:22
diff --git a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
index c27c68d..0c03489 100644
--- a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
+++ b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
@@ -40,19 +40,19 @@
 
     bb4: {
         StorageDead(_5);                 // scope 0 at $DIR/while-storage.rs:11:22: 11:23
-        switchInt(_4) -> [false: bb5, otherwise: bb6]; // scope 0 at $DIR/while-storage.rs:11:9: 13:10
+        switchInt(move _4) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/while-storage.rs:11:9: 13:10
     }
 
     bb5: {
-        StorageDead(_4);                 // scope 0 at $DIR/while-storage.rs:14:5: 14:6
-        StorageDead(_2);                 // scope 0 at $DIR/while-storage.rs:14:5: 14:6
-        goto -> bb0;                     // scope 0 at $DIR/while-storage.rs:10:5: 14:6
+        _0 = const ();                   // scope 0 at $DIR/while-storage.rs:12:13: 12:18
+        StorageDead(_4);                 // scope 0 at $DIR/while-storage.rs:13:9: 13:10
+        goto -> bb7;                     // scope 0 at $DIR/while-storage.rs:1:1: 1:1
     }
 
     bb6: {
-        _0 = const ();                   // scope 0 at $DIR/while-storage.rs:12:13: 12:18
-        StorageDead(_4);                 // scope 0 at $DIR/while-storage.rs:14:5: 14:6
-        goto -> bb7;                     // scope 0 at $DIR/while-storage.rs:1:1: 1:1
+        StorageDead(_4);                 // scope 0 at $DIR/while-storage.rs:13:9: 13:10
+        StorageDead(_2);                 // scope 0 at $DIR/while-storage.rs:14:5: 14:6
+        goto -> bb0;                     // scope 0 at $DIR/while-storage.rs:10:5: 14:6
     }
 
     bb7: {
diff --git a/src/test/pretty/expanded-and-path-remap-80832.pp b/src/test/pretty/expanded-and-path-remap-80832.pp
new file mode 100644
index 0000000..6dbc19e
--- /dev/null
+++ b/src/test/pretty/expanded-and-path-remap-80832.pp
@@ -0,0 +1,13 @@
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use ::std::prelude::v1::*;
+#[macro_use]
+extern crate std;
+// Test for issue 80832
+//
+// pretty-mode:expanded
+// pp-exact:expanded-and-path-remap-80832.pp
+// compile-flags: --remap-path-prefix {{src-base}}=the/src
+
+fn main() { }
diff --git a/src/test/pretty/expanded-and-path-remap-80832.rs b/src/test/pretty/expanded-and-path-remap-80832.rs
new file mode 100644
index 0000000..f48441f
--- /dev/null
+++ b/src/test/pretty/expanded-and-path-remap-80832.rs
@@ -0,0 +1,7 @@
+// Test for issue 80832
+//
+// pretty-mode:expanded
+// pp-exact:expanded-and-path-remap-80832.pp
+// compile-flags: --remap-path-prefix {{src-base}}=the/src
+
+fn main() {}
diff --git a/src/test/run-make-fulldeps/archive-duplicate-names/foo.rs b/src/test/run-make-fulldeps/archive-duplicate-names/foo.rs
index 5f5ed42..0bf13c4 100644
--- a/src/test/run-make-fulldeps/archive-duplicate-names/foo.rs
+++ b/src/test/run-make-fulldeps/archive-duplicate-names/foo.rs
@@ -1,7 +1,7 @@
 #![crate_type = "rlib"]
 
 #[link(name = "foo", kind = "static")]
-extern {
+extern "C" {
     fn foo();
     fn bar();
 }
diff --git a/src/test/run-make-fulldeps/c-dynamic-dylib/foo.rs b/src/test/run-make-fulldeps/c-dynamic-dylib/foo.rs
index 14f6701..9f7a9e2 100644
--- a/src/test/run-make-fulldeps/c-dynamic-dylib/foo.rs
+++ b/src/test/run-make-fulldeps/c-dynamic-dylib/foo.rs
@@ -1,7 +1,7 @@
 #![crate_type = "dylib"]
 
 #[link(name = "cfoo")]
-extern {
+extern "C" {
     fn foo();
 }
 
diff --git a/src/test/run-make-fulldeps/c-dynamic-rlib/foo.rs b/src/test/run-make-fulldeps/c-dynamic-rlib/foo.rs
index 9bf3689..3dd376f 100644
--- a/src/test/run-make-fulldeps/c-dynamic-rlib/foo.rs
+++ b/src/test/run-make-fulldeps/c-dynamic-rlib/foo.rs
@@ -1,7 +1,7 @@
 #![crate_type = "rlib"]
 
 #[link(name = "cfoo")]
-extern {
+extern "C" {
     fn foo();
 }
 
diff --git a/src/test/run-make-fulldeps/c-static-dylib/foo.rs b/src/test/run-make-fulldeps/c-static-dylib/foo.rs
index 25e1ed2..1e8af4d 100644
--- a/src/test/run-make-fulldeps/c-static-dylib/foo.rs
+++ b/src/test/run-make-fulldeps/c-static-dylib/foo.rs
@@ -1,7 +1,7 @@
 #![crate_type = "dylib"]
 
 #[link(name = "cfoo", kind = "static")]
-extern {
+extern "C" {
     fn foo();
 }
 
diff --git a/src/test/run-make-fulldeps/c-static-rlib/foo.rs b/src/test/run-make-fulldeps/c-static-rlib/foo.rs
index d434ecf..9c6d208 100644
--- a/src/test/run-make-fulldeps/c-static-rlib/foo.rs
+++ b/src/test/run-make-fulldeps/c-static-rlib/foo.rs
@@ -1,7 +1,7 @@
 #![crate_type = "rlib"]
 
 #[link(name = "cfoo", kind = "static")]
-extern {
+extern "C" {
     fn foo();
 }
 
diff --git a/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs b/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs
index c2cc3af..c406949 100644
--- a/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs
+++ b/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs
@@ -3,11 +3,11 @@
 extern crate bar;
 
 #[no_mangle]
-pub extern fn foo() {
+pub extern "C" fn foo() {
     bar::bar();
 }
 
 #[no_mangle]
-pub extern fn bar(a: u32, b: u32) -> u32 {
+pub extern "C" fn bar(a: u32, b: u32) -> u32 {
     a + b
 }
diff --git a/src/test/run-make-fulldeps/cdylib-fewer-symbols/foo.rs b/src/test/run-make-fulldeps/cdylib-fewer-symbols/foo.rs
index 5a6f7c4..af37bc8 100644
--- a/src/test/run-make-fulldeps/cdylib-fewer-symbols/foo.rs
+++ b/src/test/run-make-fulldeps/cdylib-fewer-symbols/foo.rs
@@ -1,6 +1,6 @@
 #![crate_type = "cdylib"]
 
 #[no_mangle]
-pub extern fn foo() -> u32 {
+pub extern "C" fn foo() -> u32 {
     3
 }
diff --git a/src/test/run-make-fulldeps/cdylib/foo.rs b/src/test/run-make-fulldeps/cdylib/foo.rs
index c2cc3af..c406949 100644
--- a/src/test/run-make-fulldeps/cdylib/foo.rs
+++ b/src/test/run-make-fulldeps/cdylib/foo.rs
@@ -3,11 +3,11 @@
 extern crate bar;
 
 #[no_mangle]
-pub extern fn foo() {
+pub extern "C" fn foo() {
     bar::bar();
 }
 
 #[no_mangle]
-pub extern fn bar(a: u32, b: u32) -> u32 {
+pub extern "C" fn bar(a: u32, b: u32) -> u32 {
     a + b
 }
diff --git a/src/test/run-make-fulldeps/compiler-lookup-paths/d.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/d.rs
index ca2676c..6cd9916 100644
--- a/src/test/run-make-fulldeps/compiler-lookup-paths/d.rs
+++ b/src/test/run-make-fulldeps/compiler-lookup-paths/d.rs
@@ -1,4 +1,4 @@
 #![crate_type = "rlib"]
 
 #[link(name = "native", kind = "static")]
-extern {}
+extern "C" {}
diff --git a/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.rs b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.rs
index 7b5c740..7fdb815 100644
--- a/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.rs
+++ b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.rs
@@ -1,6 +1,10 @@
-extern { fn foo(); }
+extern "C" {
+    fn foo();
+}
 
 pub fn main() {
-    unsafe { foo(); }
+    unsafe {
+        foo();
+    }
     assert_eq!(7f32.powi(3), 343f32);
 }
diff --git a/src/test/run-make-fulldeps/coverage-reports/Makefile b/src/test/run-make-fulldeps/coverage-reports/Makefile
index c4700b3..f98245b 100644
--- a/src/test/run-make-fulldeps/coverage-reports/Makefile
+++ b/src/test/run-make-fulldeps/coverage-reports/Makefile
@@ -172,7 +172,7 @@
 	# files are redundant, so there is no need to generate `expected_*.json` files or
 	# compare actual JSON results.)
 
-	$(DIFF) --ignore-matching-lines='::<.*>.*:$$' \
+	$(DIFF) --ignore-matching-lines='^  | .*::<.*>.*:$$' --ignore-matching-lines='^  | <.*>::.*:$$' \
 		expected_show_coverage.$@.txt "$(TMPDIR)"/actual_show_coverage.$@.txt || \
 		( grep -q '^\/\/ ignore-llvm-cov-show-diffs' $(SOURCEDIR)/$@.rs && \
 			>&2 echo 'diff failed, but suppressed with `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs' \
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt
index e1731c7..8f67170 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt
@@ -21,50 +21,86 @@
    20|       |//!
    21|       |//! doctest returning a result:
    22|      1|//! ```
-   23|      1|//! #[derive(Debug)]
-   24|      1|//! struct SomeError;
-   25|      1|//! let mut res = Err(SomeError);
-   26|      1|//! if res.is_ok() {
-   27|      0|//!   res?;
-   28|      1|//! } else {
-   29|      1|//!   res = Ok(0);
-   30|      1|//! }
-   31|       |//! // need to be explicit because rustdoc cant infer the return type
-   32|      1|//! Ok::<(), SomeError>(())
-   33|      1|//! ```
-   34|       |//!
-   35|       |//! doctest with custom main:
-   36|       |//! ```
-   37|       |//! #[derive(Debug)]
-   38|       |//! struct SomeError;
-   39|       |//!
-   40|       |//! extern crate doctest_crate;
-   41|       |//!
-   42|      1|//! fn doctest_main() -> Result<(), SomeError> {
-   43|      1|//!     doctest_crate::fn_run_in_doctests(2);
-   44|      1|//!     Ok(())
-   45|      1|//! }
-   46|       |//!
-   47|       |//! // this `main` is not shown as covered, as it clashes with all the other
-   48|       |//! // `main` functions that were automatically generated for doctests
-   49|       |//! fn main() -> Result<(), SomeError> {
-   50|       |//!     doctest_main()
-   51|       |//! }
-   52|       |//! ```
-   53|       |
-   54|       |/// doctest attached to fn testing external code:
-   55|       |/// ```
-   56|      1|/// extern crate doctest_crate;
-   57|      1|/// doctest_crate::fn_run_in_doctests(3);
-   58|      1|/// ```
-   59|       |///
-   60|      1|fn main() {
-   61|      1|    if true {
-   62|      1|        assert_eq!(1, 1);
-   63|       |    } else {
-   64|       |        assert_eq!(1, 2);
-   65|       |    }
-   66|      1|}
+   23|      2|//! #[derive(Debug, PartialEq)]
+                       ^1
+   24|      1|//! struct SomeError {
+   25|      1|//!     msg: String,
+   26|      1|//! }
+   27|      1|//! let mut res = Err(SomeError { msg: String::from("a message") });
+   28|      1|//! if res.is_ok() {
+   29|      0|//!     res?;
+   30|       |//! } else {
+   31|      1|//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+   32|      1|//!         println!("{:?}", res);
+   33|      1|//!     }
+                   ^0
+   34|      1|//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+   35|      1|//!         res = Ok(1);
+   36|      1|//!     }
+                   ^0
+   37|      1|//!     res = Ok(0);
+   38|       |//! }
+   39|       |//! // need to be explicit because rustdoc cant infer the return type
+   40|      1|//! Ok::<(), SomeError>(())
+   41|      1|//! ```
+   42|       |//!
+   43|       |//! doctest with custom main:
+   44|       |//! ```
+   45|      1|//! fn some_func() {
+   46|      1|//!     println!("called some_func()");
+   47|      1|//! }
+   48|       |//!
+   49|       |//! #[derive(Debug)]
+   50|       |//! struct SomeError;
+   51|       |//!
+   52|       |//! extern crate doctest_crate;
+   53|       |//!
+   54|      1|//! fn doctest_main() -> Result<(), SomeError> {
+   55|      1|//!     some_func();
+   56|      1|//!     doctest_crate::fn_run_in_doctests(2);
+   57|      1|//!     Ok(())
+   58|      1|//! }
+   59|       |//!
+   60|       |//! // this `main` is not shown as covered, as it clashes with all the other
+   61|       |//! // `main` functions that were automatically generated for doctests
+   62|       |//! fn main() -> Result<(), SomeError> {
+   63|       |//!     doctest_main()
+   64|       |//! }
+   65|       |//! ```
+   66|       |
+   67|       |/// doctest attached to fn testing external code:
+   68|       |/// ```
+   69|      1|/// extern crate doctest_crate;
+   70|      1|/// doctest_crate::fn_run_in_doctests(3);
+   71|      1|/// ```
+   72|       |///
+   73|      1|fn main() {
+   74|      1|    if true {
+   75|      1|        assert_eq!(1, 1);
+   76|       |    } else {
+   77|       |        assert_eq!(1, 2);
+   78|       |    }
+   79|      1|}
+   80|       |
+   81|       |// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
+   82|       |// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
+   83|       |// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
+   84|       |//
+   85|       |// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
+   86|       |// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
+   87|       |// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
+   88|       |// one character past, the `if` block's closing brace. In both cases, these are most likely off
+   89|       |// by the number of characters stripped from the beginning of each doc comment line: indent
+   90|       |// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
+   91|       |// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
+   92|       |// more pronounced, and show up in more places, with background color used to show some distinct
+   93|       |// code regions with different coverage counts.
+   94|       |//
+   95|       |// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
+   96|       |// character stripped from the beginning of doc comment lines with a space. This will give coverage
+   97|       |// results the correct column offsets, and I think it should compile correctly, but I don't know
+   98|       |// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
+   99|       |// if the indentation changed. I don't know if there is a more viable solution.
 
 ../coverage/lib/doctest_crate.rs:
     1|       |/// A function run only from within doctests
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.main.-------.InstrumentCoverage.0.html
index 9834124..176587a 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.main.-------.InstrumentCoverage.0.html
@@ -77,27 +77,24 @@
 16:11-16:24: @2[3]: _4 = Gt(move _5, const 0_i32)
 16:11-16:24: @2[5]: FakeRead(ForMatchedPlace, _4)"><span class="annotation">@1,2⦊</span>countdown &gt; 0<span class="annotation">⦉@1,2</span></span></span><span class="code" style="--layer: 0"> {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code even" style="--layer: 1" title="17:12-17:21: @5[3]: _8 = _1
-17:12-17:25: @5[4]: _7 = Lt(move _8, const 5_i32)
-17:12-17:25: @5[6]: FakeRead(ForMatchedPlace, _7)"><span class="annotation">@3,5⦊</span>countdown &lt; 5<span class="annotation">⦉@3,5</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="18:13-18:31: @8.Call: _9 = might_abort(const false) -&gt; [return: bb9, unwind: bb22]
-17:26-19:10: @9[1]: _6 = const ()"><span class="annotation">@6,8,9⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="18:13-18:31: @8.Call: _9 = might_abort(const false) -&gt; [return: bb9, unwind: bb22]
-17:26-19:10: @9[1]: _6 = const ()">            might_abort(false);</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="18:13-18:31: @8.Call: _9 = might_abort(const false) -&gt; [return: bb9, unwind: bb22]
-17:26-19:10: @9[1]: _6 = const ()">        }<span class="annotation">⦉@6,8,9</span></span></span><span><span class="code even" style="--layer: 1" title="19:10-19:10: @7[0]: _6 = const ()"><span class="annotation">@7⦊</span>‸<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"></span></span>
+17:12-17:25: @5[4]: _7 = Lt(move _8, const 5_i32)"><span class="annotation">@3,5⦊</span>countdown &lt; 5<span class="annotation">⦉@3,5</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="18:13-18:31: @6.Call: _9 = might_abort(const false) -&gt; [return: bb8, unwind: bb19]
+17:26-19:10: @8[1]: _6 = const ()"><span class="annotation">@6,8⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="18:13-18:31: @6.Call: _9 = might_abort(const false) -&gt; [return: bb8, unwind: bb19]
+17:26-19:10: @8[1]: _6 = const ()">            might_abort(false);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="18:13-18:31: @6.Call: _9 = might_abort(const false) -&gt; [return: bb8, unwind: bb19]
+17:26-19:10: @8[1]: _6 = const ()">        }<span class="annotation">⦉@6,8</span></span></span><span><span class="code even" style="--layer: 1" title="19:10-19:10: @7[0]: _6 = const ()"><span class="annotation">@7⦊</span>‸<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        // See discussion (below the `Notes` section) on coverage results for the closing brace.</span></span>
-<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code odd" style="--layer: 1" title="21:12-21:21: @10[5]: _12 = _1
-21:12-21:25: @10[6]: _11 = Lt(move _12, const 5_i32)
-21:12-21:25: @10[8]: FakeRead(ForMatchedPlace, _11)"><span class="annotation">@10⦊</span>countdown &lt; 5<span class="annotation">⦉@10</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="21:28-21:46: @13.Call: _13 = might_abort(const false) -&gt; [return: bb14, unwind: bb22]
-21:26-21:49: @14[1]: _10 = const ()"><span class="annotation">@11,13,14⦊</span>{ might_abort(false); }<span class="annotation">⦉@11,13,14</span></span></span><span><span class="code odd" style="--layer: 1" title="21:49-21:49: @12[0]: _10 = const ()"><span class="annotation">@12⦊</span>‸<span class="annotation">⦉@12</span></span></span><span class="code" style="--layer: 0"> // Counts for different regions on one line.</span></span>
+<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code odd" style="--layer: 1" title="21:12-21:21: @9[5]: _12 = _1
+21:12-21:25: @9[6]: _11 = Lt(move _12, const 5_i32)"><span class="annotation">@9⦊</span>countdown &lt; 5<span class="annotation">⦉@9</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="21:28-21:46: @10.Call: _13 = might_abort(const false) -&gt; [return: bb12, unwind: bb19]
+21:26-21:49: @12[1]: _10 = const ()"><span class="annotation">@10,12⦊</span>{ might_abort(false); }<span class="annotation">⦉@10,12</span></span></span><span><span class="code odd" style="--layer: 1" title="21:49-21:49: @11[0]: _10 = const ()"><span class="annotation">@11⦊</span>‸<span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"> // Counts for different regions on one line.</span></span>
 <span class="line"><span class="code" style="--layer: 0">        // For the following example, the closing brace is the last character on the line.</span></span>
 <span class="line"><span class="code" style="--layer: 0">        // This shows the character after the closing brace is highlighted, even if that next</span></span>
 <span class="line"><span class="code" style="--layer: 0">        // character is a newline.</span></span>
-<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code even" style="--layer: 1" title="25:12-25:21: @15[5]: _16 = _1
-25:12-25:25: @15[6]: _15 = Lt(move _16, const 5_i32)
-25:12-25:25: @15[8]: FakeRead(ForMatchedPlace, _15)"><span class="annotation">@15⦊</span>countdown &lt; 5<span class="annotation">⦉@15</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="25:28-25:46: @18.Call: _17 = might_abort(const false) -&gt; [return: bb19, unwind: bb22]
-25:26-25:49: @19[1]: _14 = const ()"><span class="annotation">@16,18,19⦊</span>{ might_abort(false); }<span class="annotation">⦉@16,18,19</span></span></span><span><span class="code even" style="--layer: 1" title="25:49-25:49: @17[0]: _14 = const ()"><span class="annotation">@17⦊</span>‸<span class="annotation">⦉@17</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="26:9-26:23: @20[2]: _18 = CheckedSub(_1, const 1_i32)
-26:9-26:23: @21[0]: _1 = move (_18.0: i32)"><span class="annotation">@20,21⦊</span>countdown -= 1<span class="annotation">⦉@20,21</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code even" style="--layer: 1" title="25:12-25:21: @13[5]: _16 = _1
+25:12-25:25: @13[6]: _15 = Lt(move _16, const 5_i32)"><span class="annotation">@13⦊</span>countdown &lt; 5<span class="annotation">⦉@13</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="25:28-25:46: @14.Call: _17 = might_abort(const false) -&gt; [return: bb16, unwind: bb19]
+25:26-25:49: @16[1]: _14 = const ()"><span class="annotation">@14,16⦊</span>{ might_abort(false); }<span class="annotation">⦉@14,16</span></span></span><span><span class="code even" style="--layer: 1" title="25:49-25:49: @15[0]: _14 = const ()"><span class="annotation">@15⦊</span>‸<span class="annotation">⦉@15</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="26:9-26:23: @17[2]: _18 = CheckedSub(_1, const 1_i32)
+26:9-26:23: @18[0]: _1 = move (_18.0: i32)"><span class="annotation">@17,18⦊</span>countdown -= 1<span class="annotation">⦉@17,18</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
 <span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="28:8-28:10: @4[4]: _20 = ()
 28:5-28:11: @4[5]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _20)
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.might_abort.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.might_abort.-------.InstrumentCoverage.0.html
index ab7108a..b058dce 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.might_abort.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.might_abort.-------.InstrumentCoverage.0.html
@@ -70,36 +70,35 @@
 </head>
 <body>
 <div class="code" style="counter-reset: line 4"><span class="line"><span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>fn might_abort(should_abort: bool) <span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">{</span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="6:8-6:20: @0[1]: _2 = _1
-6:8-6:20: @0[2]: FakeRead(ForMatchedPlace, _2)"><span class="annotation">@0⦊</span>should_abort<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="7:18-7:31: @3[6]: _33 = const might_abort::promoted[3]
-7:18-7:31: @3[7]: _9 = &amp;(*_33)
-7:18-7:31: @3[8]: _8 = &amp;(*_9)
-7:18-7:31: @3[9]: _7 = move _8 as &amp;[&amp;str] (Pointer(Unsize))
-7:9-7:33: @3[15]: _15 = ()
-7:9-7:33: @3[16]: FakeRead(ForMatchedPlace, _15)
-7:9-7:33: @3[17]: _32 = const might_abort::promoted[2]
-7:9-7:33: @3[18]: _13 = &amp;(*_32)
-7:9-7:33: @3[19]: _12 = &amp;(*_13)
-7:9-7:33: @3[20]: _11 = move _12 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-7:9-7:33: @3.Call: _6 = Arguments::new_v1(move _7, move _11) -&gt; [return: bb4, unwind: bb8]
-7:9-7:33: @4.Call: _5 = _print(move _6) -&gt; [return: bb5, unwind: bb8]
-7:9-7:33: @5[5]: _4 = const ()
-8:9-8:37: @5.Call: begin_panic::&lt;&amp;str&gt;(const &quot;panics and aborts&quot;) -&gt; bb8"><span class="annotation">@1,3,4,5⦊</span>println!("aborting...");</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="7:18-7:31: @3[6]: _33 = const might_abort::promoted[3]
-7:18-7:31: @3[7]: _9 = &amp;(*_33)
-7:18-7:31: @3[8]: _8 = &amp;(*_9)
-7:18-7:31: @3[9]: _7 = move _8 as &amp;[&amp;str] (Pointer(Unsize))
-7:9-7:33: @3[15]: _15 = ()
-7:9-7:33: @3[16]: FakeRead(ForMatchedPlace, _15)
-7:9-7:33: @3[17]: _32 = const might_abort::promoted[2]
-7:9-7:33: @3[18]: _13 = &amp;(*_32)
-7:9-7:33: @3[19]: _12 = &amp;(*_13)
-7:9-7:33: @3[20]: _11 = move _12 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-7:9-7:33: @3.Call: _6 = Arguments::new_v1(move _7, move _11) -&gt; [return: bb4, unwind: bb8]
-7:9-7:33: @4.Call: _5 = _print(move _6) -&gt; [return: bb5, unwind: bb8]
-7:9-7:33: @5[5]: _4 = const ()
-8:9-8:37: @5.Call: begin_panic::&lt;&amp;str&gt;(const &quot;panics and aborts&quot;) -&gt; bb8">        panic!("panics and aborts");<span class="annotation">⦉@1,3,4,5</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="6:8-6:20: @0[1]: _2 = _1"><span class="annotation">@0⦊</span>should_abort<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="7:18-7:31: @1[6]: _33 = const might_abort::promoted[3]
+7:18-7:31: @1[7]: _9 = &amp;(*_33)
+7:18-7:31: @1[8]: _8 = &amp;(*_9)
+7:18-7:31: @1[9]: _7 = move _8 as &amp;[&amp;str] (Pointer(Unsize))
+7:9-7:33: @1[15]: _15 = ()
+7:9-7:33: @1[16]: FakeRead(ForMatchedPlace, _15)
+7:9-7:33: @1[17]: _32 = const might_abort::promoted[2]
+7:9-7:33: @1[18]: _13 = &amp;(*_32)
+7:9-7:33: @1[19]: _12 = &amp;(*_13)
+7:9-7:33: @1[20]: _11 = move _12 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+7:9-7:33: @1.Call: _6 = Arguments::new_v1(move _7, move _11) -&gt; [return: bb3, unwind: bb7]
+7:9-7:33: @3.Call: _5 = _print(move _6) -&gt; [return: bb4, unwind: bb7]
+7:9-7:33: @4[5]: _4 = const ()
+8:9-8:37: @4.Call: begin_panic::&lt;&amp;str&gt;(const &quot;panics and aborts&quot;) -&gt; bb7"><span class="annotation">@1,3,4⦊</span>println!("aborting...");</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="7:18-7:31: @1[6]: _33 = const might_abort::promoted[3]
+7:18-7:31: @1[7]: _9 = &amp;(*_33)
+7:18-7:31: @1[8]: _8 = &amp;(*_9)
+7:18-7:31: @1[9]: _7 = move _8 as &amp;[&amp;str] (Pointer(Unsize))
+7:9-7:33: @1[15]: _15 = ()
+7:9-7:33: @1[16]: FakeRead(ForMatchedPlace, _15)
+7:9-7:33: @1[17]: _32 = const might_abort::promoted[2]
+7:9-7:33: @1[18]: _13 = &amp;(*_32)
+7:9-7:33: @1[19]: _12 = &amp;(*_13)
+7:9-7:33: @1[20]: _11 = move _12 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+7:9-7:33: @1.Call: _6 = Arguments::new_v1(move _7, move _11) -&gt; [return: bb3, unwind: bb7]
+7:9-7:33: @3.Call: _5 = _print(move _6) -&gt; [return: bb4, unwind: bb7]
+7:9-7:33: @4[5]: _4 = const ()
+8:9-8:37: @4.Call: begin_panic::&lt;&amp;str&gt;(const &quot;panics and aborts&quot;) -&gt; bb7">        panic!("panics and aborts");<span class="annotation">⦉@1,3,4</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    } else </span><span><span class="code even" style="--layer: 1" title="10:18-10:31: @2[6]: _31 = const might_abort::promoted[1]
 10:18-10:31: @2[7]: _23 = &amp;(*_31)
 10:18-10:31: @2[8]: _22 = &amp;(*_23)
@@ -110,11 +109,11 @@
 10:9-10:33: @2[18]: _27 = &amp;(*_30)
 10:9-10:33: @2[19]: _26 = &amp;(*_27)
 10:9-10:33: @2[20]: _25 = move _26 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-10:9-10:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb6, unwind: bb8]
-10:9-10:33: @6.Call: _19 = _print(move _20) -&gt; [return: bb7, unwind: bb8]
-10:9-10:33: @7[5]: _18 = const ()
-9:12-11:6: @7[7]: _0 = const ()
-12:2-12:2: @7.Return: return"><span class="annotation">@2,6,7⦊</span>{</span></span>
+10:9-10:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb5, unwind: bb7]
+10:9-10:33: @5.Call: _19 = _print(move _20) -&gt; [return: bb6, unwind: bb7]
+10:9-10:33: @6[5]: _18 = const ()
+9:12-11:6: @6[7]: _0 = const ()
+12:2-12:2: @6.Return: return"><span class="annotation">@2,5,6⦊</span>{</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="10:18-10:31: @2[6]: _31 = const might_abort::promoted[1]
 10:18-10:31: @2[7]: _23 = &amp;(*_31)
 10:18-10:31: @2[8]: _22 = &amp;(*_23)
@@ -125,11 +124,11 @@
 10:9-10:33: @2[18]: _27 = &amp;(*_30)
 10:9-10:33: @2[19]: _26 = &amp;(*_27)
 10:9-10:33: @2[20]: _25 = move _26 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-10:9-10:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb6, unwind: bb8]
-10:9-10:33: @6.Call: _19 = _print(move _20) -&gt; [return: bb7, unwind: bb8]
-10:9-10:33: @7[5]: _18 = const ()
-9:12-11:6: @7[7]: _0 = const ()
-12:2-12:2: @7.Return: return">        println!("Don't Panic");</span></span>
+10:9-10:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb5, unwind: bb7]
+10:9-10:33: @5.Call: _19 = _print(move _20) -&gt; [return: bb6, unwind: bb7]
+10:9-10:33: @6[5]: _18 = const ()
+9:12-11:6: @6[7]: _0 = const ()
+12:2-12:2: @6.Return: return">        println!("Don't Panic");</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="10:18-10:31: @2[6]: _31 = const might_abort::promoted[1]
 10:18-10:31: @2[7]: _23 = &amp;(*_31)
 10:18-10:31: @2[8]: _22 = &amp;(*_23)
@@ -140,11 +139,11 @@
 10:9-10:33: @2[18]: _27 = &amp;(*_30)
 10:9-10:33: @2[19]: _26 = &amp;(*_27)
 10:9-10:33: @2[20]: _25 = move _26 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-10:9-10:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb6, unwind: bb8]
-10:9-10:33: @6.Call: _19 = _print(move _20) -&gt; [return: bb7, unwind: bb8]
-10:9-10:33: @7[5]: _18 = const ()
-9:12-11:6: @7[7]: _0 = const ()
-12:2-12:2: @7.Return: return">    }</span></span>
+10:9-10:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb5, unwind: bb7]
+10:9-10:33: @5.Call: _19 = _print(move _20) -&gt; [return: bb6, unwind: bb7]
+10:9-10:33: @6[5]: _18 = const ()
+9:12-11:6: @6[7]: _0 = const ()
+12:2-12:2: @6.Return: return">    }</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="10:18-10:31: @2[6]: _31 = const might_abort::promoted[1]
 10:18-10:31: @2[7]: _23 = &amp;(*_31)
 10:18-10:31: @2[8]: _22 = &amp;(*_23)
@@ -155,10 +154,10 @@
 10:9-10:33: @2[18]: _27 = &amp;(*_30)
 10:9-10:33: @2[19]: _26 = &amp;(*_27)
 10:9-10:33: @2[20]: _25 = move _26 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-10:9-10:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb6, unwind: bb8]
-10:9-10:33: @6.Call: _19 = _print(move _20) -&gt; [return: bb7, unwind: bb8]
-10:9-10:33: @7[5]: _18 = const ()
-9:12-11:6: @7[7]: _0 = const ()
-12:2-12:2: @7.Return: return">}<span class="annotation">⦉@2,6,7</span></span></span></span></div>
+10:9-10:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb5, unwind: bb7]
+10:9-10:33: @5.Call: _19 = _print(move _20) -&gt; [return: bb6, unwind: bb7]
+10:9-10:33: @6[5]: _18 = const ()
+9:12-11:6: @6[7]: _0 = const ()
+12:2-12:2: @6.Return: return">}<span class="annotation">⦉@2,5,6</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.main.-------.InstrumentCoverage.0.html
index f24de8e..365e94c 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.main.-------.InstrumentCoverage.0.html
@@ -77,22 +77,20 @@
 11:11-11:24: @2[3]: _4 = Gt(move _5, const 0_i32)
 11:11-11:24: @2[5]: FakeRead(ForMatchedPlace, _4)"><span class="annotation">@1,2⦊</span>countdown &gt; 0<span class="annotation">⦉@1,2</span></span></span><span class="code" style="--layer: 0"> {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code even" style="--layer: 1" title="12:12-12:21: @5[3]: _8 = _1
-12:12-12:26: @5[4]: _7 = Eq(move _8, const 1_i32)
-12:12-12:26: @5[6]: FakeRead(ForMatchedPlace, _7)"><span class="annotation">@3,5⦊</span>countdown == 1<span class="annotation">⦉@3,5</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="13:13-13:33: @8.Call: _9 = might_fail_assert(const 3_u32) -&gt; [return: bb9, unwind: bb17]
-12:27-14:10: @9[1]: _6 = const ()"><span class="annotation">@6,8,9⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="13:13-13:33: @8.Call: _9 = might_fail_assert(const 3_u32) -&gt; [return: bb9, unwind: bb17]
-12:27-14:10: @9[1]: _6 = const ()">            might_fail_assert(3);</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="13:13-13:33: @8.Call: _9 = might_fail_assert(const 3_u32) -&gt; [return: bb9, unwind: bb17]
-12:27-14:10: @9[1]: _6 = const ()">        }<span class="annotation">⦉@6,8,9</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code even" style="--layer: 1" title="14:19-14:28: @7[2]: _11 = _1
-14:19-14:32: @7[3]: _10 = Lt(move _11, const 5_i32)
-14:19-14:32: @7[5]: FakeRead(ForMatchedPlace, _10)"><span class="annotation">@7⦊</span>countdown &lt; 5<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="15:13-15:33: @12.Call: _12 = might_fail_assert(const 2_u32) -&gt; [return: bb13, unwind: bb17]
-14:33-16:10: @13[1]: _6 = const ()"><span class="annotation">@10,12,13⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="15:13-15:33: @12.Call: _12 = might_fail_assert(const 2_u32) -&gt; [return: bb13, unwind: bb17]
-14:33-16:10: @13[1]: _6 = const ()">            might_fail_assert(2);</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="15:13-15:33: @12.Call: _12 = might_fail_assert(const 2_u32) -&gt; [return: bb13, unwind: bb17]
-14:33-16:10: @13[1]: _6 = const ()">        }<span class="annotation">⦉@10,12,13</span></span></span><span><span class="code even" style="--layer: 1" title="16:10-16:10: @11[0]: _6 = const ()"><span class="annotation">@11⦊</span>‸<span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="17:9-17:23: @15[2]: _13 = CheckedSub(_1, const 1_i32)
-17:9-17:23: @16[0]: _1 = move (_13.0: i32)"><span class="annotation">@15,16⦊</span>countdown -= 1<span class="annotation">⦉@15,16</span></span></span><span class="code" style="--layer: 0">;</span></span>
+12:12-12:26: @5[4]: _7 = Eq(move _8, const 1_i32)"><span class="annotation">@3,5⦊</span>countdown == 1<span class="annotation">⦉@3,5</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="13:13-13:33: @6.Call: _9 = might_fail_assert(const 3_u32) -&gt; [return: bb8, unwind: bb15]
+12:27-14:10: @8[1]: _6 = const ()"><span class="annotation">@6,8⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="13:13-13:33: @6.Call: _9 = might_fail_assert(const 3_u32) -&gt; [return: bb8, unwind: bb15]
+12:27-14:10: @8[1]: _6 = const ()">            might_fail_assert(3);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="13:13-13:33: @6.Call: _9 = might_fail_assert(const 3_u32) -&gt; [return: bb8, unwind: bb15]
+12:27-14:10: @8[1]: _6 = const ()">        }<span class="annotation">⦉@6,8</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code even" style="--layer: 1" title="14:19-14:28: @7[2]: _11 = _1
+14:19-14:32: @7[3]: _10 = Lt(move _11, const 5_i32)"><span class="annotation">@7⦊</span>countdown &lt; 5<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="15:13-15:33: @9.Call: _12 = might_fail_assert(const 2_u32) -&gt; [return: bb11, unwind: bb15]
+14:33-16:10: @11[1]: _6 = const ()"><span class="annotation">@9,11⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="15:13-15:33: @9.Call: _12 = might_fail_assert(const 2_u32) -&gt; [return: bb11, unwind: bb15]
+14:33-16:10: @11[1]: _6 = const ()">            might_fail_assert(2);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="15:13-15:33: @9.Call: _12 = might_fail_assert(const 2_u32) -&gt; [return: bb11, unwind: bb15]
+14:33-16:10: @11[1]: _6 = const ()">        }<span class="annotation">⦉@9,11</span></span></span><span><span class="code even" style="--layer: 1" title="16:10-16:10: @10[0]: _6 = const ()"><span class="annotation">@10⦊</span>‸<span class="annotation">⦉@10</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="17:9-17:23: @13[2]: _13 = CheckedSub(_1, const 1_i32)
+17:9-17:23: @14[0]: _1 = move (_13.0: i32)"><span class="annotation">@13,14⦊</span>countdown -= 1<span class="annotation">⦉@13,14</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
 <span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="19:8-19:10: @4[4]: _15 = ()
 19:5-19:11: @4[5]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _15)
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.might_fail_assert.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.might_fail_assert.-------.InstrumentCoverage.0.html
index 13cfebf..823bb0c 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.might_fail_assert.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.might_fail_assert.-------.InstrumentCoverage.0.html
@@ -80,18 +80,18 @@
 5:5-5:48: @0[22]: _15 = (_13.0: &amp;u32)
 5:5-5:48: @0[25]: _17 = &amp;(*_15)
 5:5-5:48: @0[27]: _18 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-5:5-5:48: @0.Call: _16 = ArgumentV1::new::&lt;u32&gt;(move _17, move _18) -&gt; [return: bb1, unwind: bb13]
+5:5-5:48: @0.Call: _16 = ArgumentV1::new::&lt;u32&gt;(move _17, move _18) -&gt; [return: bb1, unwind: bb12]
 5:5-5:48: @1[2]: _12 = [move _16]
 5:5-5:48: @1[5]: _11 = &amp;_12
 5:5-5:48: @1[6]: _10 = &amp;(*_11)
 5:5-5:48: @1[7]: _9 = move _10 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-5:5-5:48: @1.Call: _4 = Arguments::new_v1(move _5, move _9) -&gt; [return: bb2, unwind: bb13]
-5:5-5:48: @2.Call: _3 = _print(move _4) -&gt; [return: bb3, unwind: bb13]
+5:5-5:48: @1.Call: _4 = Arguments::new_v1(move _5, move _9) -&gt; [return: bb2, unwind: bb12]
+5:5-5:48: @2.Call: _3 = _print(move _4) -&gt; [return: bb3, unwind: bb12]
 5:5-5:48: @3[6]: _2 = const ()"><span class="annotation">@0,1,2,3,4⦊</span>println!("does 1 + 1 = {}?", one_plus_one);<span class="annotation">⦉@0,1,2,3,4</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    assert_eq!(</span><span><span class="code even" style="--layer: 1" title="6:16-6:21: @3[11]: _23 = CheckedAdd(const 1_u32, const 1_u32)"><span class="annotation">@0,1,2,3,4⦊</span>1 + 1<span class="annotation">⦉@0,1,2,3,4</span></span></span><span class="code" style="--layer: 0">, one_plus_one, </span><span><span class="code odd" style="--layer: 1" title="6:37-6:61: @7[28]: _70 = const might_fail_assert::promoted[1]
-6:37-6:61: @7[29]: _50 = &amp;(*_70)
-6:37-6:61: @7[30]: _49 = &amp;(*_50)
-6:37-6:61: @7[31]: _48 = move _49 as &amp;[&amp;str] (Pointer(Unsize))"><span class="annotation">@5,7,8,9,10,11,12⦊</span>"the argument was wrong"<span class="annotation">⦉@5,7,8,9,10,11,12</span></span></span><span class="code" style="--layer: 0">);</span></span>
+<span class="line"><span class="code" style="--layer: 0">    assert_eq!(</span><span><span class="code even" style="--layer: 1" title="6:16-6:21: @3[11]: _23 = CheckedAdd(const 1_u32, const 1_u32)"><span class="annotation">@0,1,2,3,4⦊</span>1 + 1<span class="annotation">⦉@0,1,2,3,4</span></span></span><span class="code" style="--layer: 0">, one_plus_one, </span><span><span class="code odd" style="--layer: 1" title="6:37-6:61: @5[28]: _70 = const might_fail_assert::promoted[1]
+6:37-6:61: @5[29]: _50 = &amp;(*_70)
+6:37-6:61: @5[30]: _49 = &amp;(*_50)
+6:37-6:61: @5[31]: _48 = move _49 as &amp;[&amp;str] (Pointer(Unsize))"><span class="annotation">@5,7,8,9,10,11⦊</span>"the argument was wrong"<span class="annotation">⦉@5,7,8,9,10,11</span></span></span><span class="code" style="--layer: 0">);</span></span>
 <span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code even" style="--layer: 1" title="7:2-7:2: @6.Return: return"><span class="annotation">@6⦊</span>‸<span class="annotation">⦉@6</span></span></span></span></div>
 </body>
 </html>
diff --git "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.c-\173closure\0430\175.-------.InstrumentCoverage.0.html" "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.c-\173closure\0430\175.-------.InstrumentCoverage.0.html"
index 82a22cc..21bfce7 100644
--- "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.c-\173closure\0430\175.-------.InstrumentCoverage.0.html"
+++ "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.c-\173closure\0430\175.-------.InstrumentCoverage.0.html"
@@ -70,15 +70,13 @@
 </head>
 <body>
 <div class="code" style="counter-reset: line 4"><span class="line">                        <span><span class="code even" style="--layer: 1" title="6:8-6:9: @0[5]: _5 = _3
-6:8-6:14: @0[6]: _4 = Eq(move _5, const 8_u8)
-6:8-6:14: @0[8]: FakeRead(ForMatchedPlace, _4)"><span class="annotation">@0⦊</span>{</span></span>
+6:8-6:14: @0[6]: _4 = Eq(move _5, const 8_u8)"><span class="annotation">@0⦊</span>{</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="6:8-6:9: @0[5]: _5 = _3
-6:8-6:14: @0[6]: _4 = Eq(move _5, const 8_u8)
-6:8-6:14: @0[8]: FakeRead(ForMatchedPlace, _4)">    if x == 8<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="7:9-7:10: @3[0]: _0 = const 1_u8"><span class="annotation">@1,3⦊</span>1<span class="annotation">⦉@1,3</span></span></span><span class="code" style="--layer: 0"></span></span>
+6:8-6:14: @0[6]: _4 = Eq(move _5, const 8_u8)">    if x == 8<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="7:9-7:10: @1[0]: _0 = const 1_u8"><span class="annotation">@1⦊</span>1<span class="annotation">⦉@1</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    } else {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="9:9-9:10: @2[0]: _0 = const 0_u8"><span class="annotation">@2⦊</span>0<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="11:2-11:2: @4.Return: return"><span class="annotation">@4⦊</span>‸<span class="annotation">⦉@4</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="11:2-11:2: @3.Return: return"><span class="annotation">@3⦊</span>‸<span class="annotation">⦉@3</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-c.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-c.-------.InstrumentCoverage.0.html
index a8e2d7e..e6384b7 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-c.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-c.-------.InstrumentCoverage.0.html
@@ -70,12 +70,10 @@
 </head>
 <body>
 <div class="code" style="counter-reset: line 50"><span class="line">    <span><span class="code even" style="--layer: 1" title="52:12-52:13: @0[2]: _3 = _1
-52:12-52:18: @0[3]: _2 = Eq(move _3, const 8_u8)
-52:12-52:18: @0[5]: FakeRead(ForMatchedPlace, _2)"><span class="annotation">@0⦊</span>fn c(x: u8) -&gt; u8 {</span></span>
+52:12-52:18: @0[3]: _2 = Eq(move _3, const 8_u8)"><span class="annotation">@0⦊</span>fn c(x: u8) -&gt; u8 {</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="52:12-52:13: @0[2]: _3 = _1
-52:12-52:18: @0[3]: _2 = Eq(move _3, const 8_u8)
-52:12-52:18: @0[5]: FakeRead(ForMatchedPlace, _2)">        if x == 8<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="53:13-53:14: @3[0]: _0 = const 1_u8"><span class="annotation">@1,3⦊</span>1<span class="annotation">⦉@1,3</span></span></span><span class="code" style="--layer: 0"> // This line appears covered, but the 1-character expression span covering the `1`</span></span>
+52:12-52:18: @0[3]: _2 = Eq(move _3, const 8_u8)">        if x == 8<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="53:13-53:14: @1[0]: _0 = const 1_u8"><span class="annotation">@1⦊</span>1<span class="annotation">⦉@1</span></span></span><span class="code" style="--layer: 0"> // This line appears covered, but the 1-character expression span covering the `1`</span></span>
 <span class="line"><span class="code" style="--layer: 0">              // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because</span></span>
 <span class="line"><span class="code" style="--layer: 0">              // `fn j()` executes the open brace for the funciton body, followed by the function's</span></span>
 <span class="line"><span class="code" style="--layer: 0">              // first executable statement, `match x`. Inner function declarations are not</span></span>
@@ -87,6 +85,6 @@
 <span class="line"><span class="code" style="--layer: 0">        } else {</span></span>
 <span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="63:13-63:14: @2[0]: _0 = const 0_u8"><span class="annotation">@2⦊</span>0<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        }</span></span>
-<span class="line"><span class="code" style="--layer: 0">    }</span><span><span class="code odd" style="--layer: 1" title="65:6-65:6: @4.Return: return"><span class="annotation">@4⦊</span>‸<span class="annotation">⦉@4</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">    }</span><span><span class="code odd" style="--layer: 1" title="65:6-65:6: @3.Return: return"><span class="annotation">@3⦊</span>‸<span class="annotation">⦉@3</span></span></span></span></div>
 </body>
 </html>
diff --git "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0430\175.-------.InstrumentCoverage.0.html" "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0430\175.-------.InstrumentCoverage.0.html"
index 523e839..b4b171d 100644
--- "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0430\175.-------.InstrumentCoverage.0.html"
+++ "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0430\175.-------.InstrumentCoverage.0.html"
@@ -72,28 +72,25 @@
 <div class="code" style="counter-reset: line 32"><span class="line">        <span class="code" style="--layer: 0">||</span></span>
 <span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="35:29-35:30: @0[1]: _2 = const 0_i32
 35:13-35:26: @0[2]: FakeRead(ForLet, _2)
-36:12-36:20: @0[5]: _4 = (*((*_1).0: &amp;bool))
-36:12-36:20: @0[6]: FakeRead(ForMatchedPlace, _4)"><span class="annotation">@0⦊</span>{</span></span>
+36:12-36:20: @0[5]: _4 = (*((*_1).0: &amp;bool))"><span class="annotation">@0⦊</span>{</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="35:29-35:30: @0[1]: _2 = const 0_i32
 35:13-35:26: @0[2]: FakeRead(ForLet, _2)
-36:12-36:20: @0[5]: _4 = (*((*_1).0: &amp;bool))
-36:12-36:20: @0[6]: FakeRead(ForMatchedPlace, _4)">        let mut countdown = 0;</span></span>
+36:12-36:20: @0[5]: _4 = (*((*_1).0: &amp;bool))">        let mut countdown = 0;</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="35:29-35:30: @0[1]: _2 = const 0_i32
 35:13-35:26: @0[2]: FakeRead(ForLet, _2)
-36:12-36:20: @0[5]: _4 = (*((*_1).0: &amp;bool))
-36:12-36:20: @0[6]: FakeRead(ForMatchedPlace, _4)">        if is_false<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="37:13-37:27: @3[0]: _2 = const 10_i32
-36:21-38:10: @3[1]: _3 = const ()"><span class="annotation">@1,3⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="37:13-37:27: @3[0]: _2 = const 10_i32
-36:21-38:10: @3[1]: _3 = const ()">            countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="37:13-37:27: @3[0]: _2 = const 10_i32
-36:21-38:10: @3[1]: _3 = const ()">        }<span class="annotation">⦉@1,3</span></span></span><span><span class="code even" style="--layer: 1" title="38:10-38:10: @2[0]: _3 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="39:9-39:23: @4[4]: _6 = const &quot;alt string 2&quot;
-39:9-39:23: @4[5]: _5 = &amp;(*_6)
-39:9-39:34: @4.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb5, unwind: bb6]
-40:6-40:6: @5.Return: return"><span class="annotation">@4,5⦊</span>"alt string 2".to_owned()</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="39:9-39:23: @4[4]: _6 = const &quot;alt string 2&quot;
-39:9-39:23: @4[5]: _5 = &amp;(*_6)
-39:9-39:34: @4.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb5, unwind: bb6]
-40:6-40:6: @5.Return: return">    }<span class="annotation">⦉@4,5</span></span></span></span></div>
+36:12-36:20: @0[5]: _4 = (*((*_1).0: &amp;bool))">        if is_false<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="37:13-37:27: @1[0]: _2 = const 10_i32
+36:21-38:10: @1[1]: _3 = const ()"><span class="annotation">@1⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="37:13-37:27: @1[0]: _2 = const 10_i32
+36:21-38:10: @1[1]: _3 = const ()">            countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="37:13-37:27: @1[0]: _2 = const 10_i32
+36:21-38:10: @1[1]: _3 = const ()">        }<span class="annotation">⦉@1</span></span></span><span><span class="code even" style="--layer: 1" title="38:10-38:10: @2[0]: _3 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="39:9-39:23: @3[4]: _6 = const &quot;alt string 2&quot;
+39:9-39:23: @3[5]: _5 = &amp;(*_6)
+39:9-39:34: @3.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb4, unwind: bb5]
+40:6-40:6: @4.Return: return"><span class="annotation">@3,4⦊</span>"alt string 2".to_owned()</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="39:9-39:23: @3[4]: _6 = const &quot;alt string 2&quot;
+39:9-39:23: @3[5]: _5 = &amp;(*_6)
+39:9-39:34: @3.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb4, unwind: bb5]
+40:6-40:6: @4.Return: return">    }<span class="annotation">⦉@3,4</span></span></span></span></div>
 </body>
 </html>
diff --git "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\04310\175.-------.InstrumentCoverage.0.html" "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\04310\175.-------.InstrumentCoverage.0.html"
index fdae1a0..c1edc3e 100644
--- "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\04310\175.-------.InstrumentCoverage.0.html"
+++ "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\04310\175.-------.InstrumentCoverage.0.html"
@@ -72,28 +72,25 @@
 <div class="code" style="counter-reset: line 17"><span class="line">            <span class="code" style="--layer: 0">||</span></span>
 <span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="20:37-20:38: @0[1]: _2 = const 0_i32
 20:21-20:34: @0[2]: FakeRead(ForLet, _2)
-21:20-21:28: @0[5]: _4 = (*(_1.0: &amp;bool))
-21:20-21:28: @0[6]: FakeRead(ForMatchedPlace, _4)"><span class="annotation">@0⦊</span>{</span></span>
+21:20-21:28: @0[5]: _4 = (*(_1.0: &amp;bool))"><span class="annotation">@0⦊</span>{</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="20:37-20:38: @0[1]: _2 = const 0_i32
 20:21-20:34: @0[2]: FakeRead(ForLet, _2)
-21:20-21:28: @0[5]: _4 = (*(_1.0: &amp;bool))
-21:20-21:28: @0[6]: FakeRead(ForMatchedPlace, _4)">                let mut countdown = 0;</span></span>
+21:20-21:28: @0[5]: _4 = (*(_1.0: &amp;bool))">                let mut countdown = 0;</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="20:37-20:38: @0[1]: _2 = const 0_i32
 20:21-20:34: @0[2]: FakeRead(ForLet, _2)
-21:20-21:28: @0[5]: _4 = (*(_1.0: &amp;bool))
-21:20-21:28: @0[6]: FakeRead(ForMatchedPlace, _4)">                if is_false<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="22:21-22:35: @3[0]: _2 = const 10_i32
-21:29-23:18: @3[1]: _3 = const ()"><span class="annotation">@1,3⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="22:21-22:35: @3[0]: _2 = const 10_i32
-21:29-23:18: @3[1]: _3 = const ()">                    countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="22:21-22:35: @3[0]: _2 = const 10_i32
-21:29-23:18: @3[1]: _3 = const ()">                }<span class="annotation">⦉@1,3</span></span></span><span><span class="code even" style="--layer: 1" title="23:18-23:18: @2[0]: _3 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">                </span><span><span class="code odd" style="--layer: 1" title="24:17-24:31: @4[4]: _6 = const &quot;alt string 1&quot;
-24:17-24:31: @4[5]: _5 = &amp;(*_6)
-24:17-24:42: @4.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb5, unwind: bb6]
-25:14-25:14: @5.Return: return"><span class="annotation">@4,5⦊</span>"alt string 1".to_owned()</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="24:17-24:31: @4[4]: _6 = const &quot;alt string 1&quot;
-24:17-24:31: @4[5]: _5 = &amp;(*_6)
-24:17-24:42: @4.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb5, unwind: bb6]
-25:14-25:14: @5.Return: return">            }<span class="annotation">⦉@4,5</span></span></span></span></div>
+21:20-21:28: @0[5]: _4 = (*(_1.0: &amp;bool))">                if is_false<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="22:21-22:35: @1[0]: _2 = const 10_i32
+21:29-23:18: @1[1]: _3 = const ()"><span class="annotation">@1⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="22:21-22:35: @1[0]: _2 = const 10_i32
+21:29-23:18: @1[1]: _3 = const ()">                    countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="22:21-22:35: @1[0]: _2 = const 10_i32
+21:29-23:18: @1[1]: _3 = const ()">                }<span class="annotation">⦉@1</span></span></span><span><span class="code even" style="--layer: 1" title="23:18-23:18: @2[0]: _3 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">                </span><span><span class="code odd" style="--layer: 1" title="24:17-24:31: @3[4]: _6 = const &quot;alt string 1&quot;
+24:17-24:31: @3[5]: _5 = &amp;(*_6)
+24:17-24:42: @3.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb4, unwind: bb5]
+25:14-25:14: @4.Return: return"><span class="annotation">@3,4⦊</span>"alt string 1".to_owned()</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="24:17-24:31: @3[4]: _6 = const &quot;alt string 1&quot;
+24:17-24:31: @3[5]: _5 = &amp;(*_6)
+24:17-24:42: @3.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb4, unwind: bb5]
+25:14-25:14: @4.Return: return">            }<span class="annotation">⦉@3,4</span></span></span></span></div>
 </body>
 </html>
diff --git "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\04311\175.-------.InstrumentCoverage.0.html" "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\04311\175.-------.InstrumentCoverage.0.html"
index 48f3944..24c1cad 100644
--- "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\04311\175.-------.InstrumentCoverage.0.html"
+++ "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\04311\175.-------.InstrumentCoverage.0.html"
@@ -72,28 +72,25 @@
 <div class="code" style="counter-reset: line 59"><span class="line">            <span class="code" style="--layer: 0">||</span></span>
 <span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="62:37-62:38: @0[1]: _2 = const 0_i32
 62:21-62:34: @0[2]: FakeRead(ForLet, _2)
-63:20-63:28: @0[5]: _4 = (*(_1.0: &amp;bool))
-63:20-63:28: @0[6]: FakeRead(ForMatchedPlace, _4)"><span class="annotation">@0⦊</span>{</span></span>
+63:20-63:28: @0[5]: _4 = (*(_1.0: &amp;bool))"><span class="annotation">@0⦊</span>{</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="62:37-62:38: @0[1]: _2 = const 0_i32
 62:21-62:34: @0[2]: FakeRead(ForLet, _2)
-63:20-63:28: @0[5]: _4 = (*(_1.0: &amp;bool))
-63:20-63:28: @0[6]: FakeRead(ForMatchedPlace, _4)">                let mut countdown = 0;</span></span>
+63:20-63:28: @0[5]: _4 = (*(_1.0: &amp;bool))">                let mut countdown = 0;</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="62:37-62:38: @0[1]: _2 = const 0_i32
 62:21-62:34: @0[2]: FakeRead(ForLet, _2)
-63:20-63:28: @0[5]: _4 = (*(_1.0: &amp;bool))
-63:20-63:28: @0[6]: FakeRead(ForMatchedPlace, _4)">                if is_false<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="64:21-64:35: @3[0]: _2 = const 10_i32
-63:29-65:18: @3[1]: _3 = const ()"><span class="annotation">@1,3⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="64:21-64:35: @3[0]: _2 = const 10_i32
-63:29-65:18: @3[1]: _3 = const ()">                    countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="64:21-64:35: @3[0]: _2 = const 10_i32
-63:29-65:18: @3[1]: _3 = const ()">                }<span class="annotation">⦉@1,3</span></span></span><span><span class="code even" style="--layer: 1" title="65:18-65:18: @2[0]: _3 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">                </span><span><span class="code odd" style="--layer: 1" title="66:17-66:31: @4[4]: _6 = const &quot;alt string 3&quot;
-66:17-66:31: @4[5]: _5 = &amp;(*_6)
-66:17-66:42: @4.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb5, unwind: bb6]
-67:14-67:14: @5.Return: return"><span class="annotation">@4,5⦊</span>"alt string 3".to_owned()</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="66:17-66:31: @4[4]: _6 = const &quot;alt string 3&quot;
-66:17-66:31: @4[5]: _5 = &amp;(*_6)
-66:17-66:42: @4.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb5, unwind: bb6]
-67:14-67:14: @5.Return: return">            }<span class="annotation">⦉@4,5</span></span></span></span></div>
+63:20-63:28: @0[5]: _4 = (*(_1.0: &amp;bool))">                if is_false<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="64:21-64:35: @1[0]: _2 = const 10_i32
+63:29-65:18: @1[1]: _3 = const ()"><span class="annotation">@1⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="64:21-64:35: @1[0]: _2 = const 10_i32
+63:29-65:18: @1[1]: _3 = const ()">                    countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="64:21-64:35: @1[0]: _2 = const 10_i32
+63:29-65:18: @1[1]: _3 = const ()">                }<span class="annotation">⦉@1</span></span></span><span><span class="code even" style="--layer: 1" title="65:18-65:18: @2[0]: _3 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">                </span><span><span class="code odd" style="--layer: 1" title="66:17-66:31: @3[4]: _6 = const &quot;alt string 3&quot;
+66:17-66:31: @3[5]: _5 = &amp;(*_6)
+66:17-66:42: @3.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb4, unwind: bb5]
+67:14-67:14: @4.Return: return"><span class="annotation">@3,4⦊</span>"alt string 3".to_owned()</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="66:17-66:31: @3[4]: _6 = const &quot;alt string 3&quot;
+66:17-66:31: @3[5]: _5 = &amp;(*_6)
+66:17-66:42: @3.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb4, unwind: bb5]
+67:14-67:14: @4.Return: return">            }<span class="annotation">⦉@3,4</span></span></span></span></div>
 </body>
 </html>
diff --git "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0431\175.-------.InstrumentCoverage.0.html" "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0431\175.-------.InstrumentCoverage.0.html"
index 233ebf1..7a3921c 100644
--- "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0431\175.-------.InstrumentCoverage.0.html"
+++ "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0431\175.-------.InstrumentCoverage.0.html"
@@ -72,28 +72,25 @@
 <div class="code" style="counter-reset: line 74"><span class="line">        <span class="code" style="--layer: 0">||</span></span>
 <span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="77:29-77:30: @0[1]: _2 = const 0_i32
 77:13-77:26: @0[2]: FakeRead(ForLet, _2)
-78:12-78:20: @0[5]: _4 = (*((*_1).0: &amp;bool))
-78:12-78:20: @0[6]: FakeRead(ForMatchedPlace, _4)"><span class="annotation">@0⦊</span>{</span></span>
+78:12-78:20: @0[5]: _4 = (*((*_1).0: &amp;bool))"><span class="annotation">@0⦊</span>{</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="77:29-77:30: @0[1]: _2 = const 0_i32
 77:13-77:26: @0[2]: FakeRead(ForLet, _2)
-78:12-78:20: @0[5]: _4 = (*((*_1).0: &amp;bool))
-78:12-78:20: @0[6]: FakeRead(ForMatchedPlace, _4)">        let mut countdown = 0;</span></span>
+78:12-78:20: @0[5]: _4 = (*((*_1).0: &amp;bool))">        let mut countdown = 0;</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="77:29-77:30: @0[1]: _2 = const 0_i32
 77:13-77:26: @0[2]: FakeRead(ForLet, _2)
-78:12-78:20: @0[5]: _4 = (*((*_1).0: &amp;bool))
-78:12-78:20: @0[6]: FakeRead(ForMatchedPlace, _4)">        if is_false<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="79:13-79:27: @3[0]: _2 = const 10_i32
-78:21-80:10: @3[1]: _3 = const ()"><span class="annotation">@1,3⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="79:13-79:27: @3[0]: _2 = const 10_i32
-78:21-80:10: @3[1]: _3 = const ()">            countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="79:13-79:27: @3[0]: _2 = const 10_i32
-78:21-80:10: @3[1]: _3 = const ()">        }<span class="annotation">⦉@1,3</span></span></span><span><span class="code even" style="--layer: 1" title="80:10-80:10: @2[0]: _3 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="81:9-81:23: @4[4]: _6 = const &quot;alt string 4&quot;
-81:9-81:23: @4[5]: _5 = &amp;(*_6)
-81:9-81:34: @4.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb5, unwind: bb6]
-82:6-82:6: @5.Return: return"><span class="annotation">@4,5⦊</span>"alt string 4".to_owned()</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="81:9-81:23: @4[4]: _6 = const &quot;alt string 4&quot;
-81:9-81:23: @4[5]: _5 = &amp;(*_6)
-81:9-81:34: @4.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb5, unwind: bb6]
-82:6-82:6: @5.Return: return">    }<span class="annotation">⦉@4,5</span></span></span></span></div>
+78:12-78:20: @0[5]: _4 = (*((*_1).0: &amp;bool))">        if is_false<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="79:13-79:27: @1[0]: _2 = const 10_i32
+78:21-80:10: @1[1]: _3 = const ()"><span class="annotation">@1⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="79:13-79:27: @1[0]: _2 = const 10_i32
+78:21-80:10: @1[1]: _3 = const ()">            countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="79:13-79:27: @1[0]: _2 = const 10_i32
+78:21-80:10: @1[1]: _3 = const ()">        }<span class="annotation">⦉@1</span></span></span><span><span class="code even" style="--layer: 1" title="80:10-80:10: @2[0]: _3 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="81:9-81:23: @3[4]: _6 = const &quot;alt string 4&quot;
+81:9-81:23: @3[5]: _5 = &amp;(*_6)
+81:9-81:34: @3.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb4, unwind: bb5]
+82:6-82:6: @4.Return: return"><span class="annotation">@3,4⦊</span>"alt string 4".to_owned()</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="81:9-81:23: @3[4]: _6 = const &quot;alt string 4&quot;
+81:9-81:23: @3[5]: _5 = &amp;(*_6)
+81:9-81:34: @3.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb4, unwind: bb5]
+82:6-82:6: @4.Return: return">    }<span class="annotation">⦉@3,4</span></span></span></span></div>
 </body>
 </html>
diff --git "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0432\175.-------.InstrumentCoverage.0.html" "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0432\175.-------.InstrumentCoverage.0.html"
index 1cdca25..06b817e 100644
--- "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0432\175.-------.InstrumentCoverage.0.html"
+++ "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0432\175.-------.InstrumentCoverage.0.html"
@@ -72,60 +72,57 @@
 <div class="code" style="counter-reset: line 96"><span class="line">        <span class="code" style="--layer: 0">|val|</span></span>
 <span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="99:29-99:30: @0[1]: _3 = const 0_i32
 99:13-99:26: @0[2]: FakeRead(ForLet, _3)
-100:12-100:20: @0[5]: _5 = (*((*_1).0: &amp;bool))
-100:12-100:20: @0[6]: FakeRead(ForMatchedPlace, _5)"><span class="annotation">@0⦊</span>{</span></span>
+100:12-100:20: @0[5]: _5 = (*((*_1).0: &amp;bool))"><span class="annotation">@0⦊</span>{</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="99:29-99:30: @0[1]: _3 = const 0_i32
 99:13-99:26: @0[2]: FakeRead(ForLet, _3)
-100:12-100:20: @0[5]: _5 = (*((*_1).0: &amp;bool))
-100:12-100:20: @0[6]: FakeRead(ForMatchedPlace, _5)">        let mut countdown = 0;</span></span>
+100:12-100:20: @0[5]: _5 = (*((*_1).0: &amp;bool))">        let mut countdown = 0;</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="99:29-99:30: @0[1]: _3 = const 0_i32
 99:13-99:26: @0[2]: FakeRead(ForLet, _3)
-100:12-100:20: @0[5]: _5 = (*((*_1).0: &amp;bool))
-100:12-100:20: @0[6]: FakeRead(ForMatchedPlace, _5)">        if is_false<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="101:13-101:27: @3[0]: _3 = const 10_i32
-100:21-102:10: @3[1]: _4 = const ()"><span class="annotation">@1,3⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="101:13-101:27: @3[0]: _3 = const 10_i32
-100:21-102:10: @3[1]: _4 = const ()">            countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="101:13-101:27: @3[0]: _3 = const 10_i32
-100:21-102:10: @3[1]: _4 = const ()">        }<span class="annotation">⦉@1,3</span></span></span><span><span class="code even" style="--layer: 1" title="102:10-102:10: @2[0]: _4 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="103:17-103:23: @4[7]: _22 = const main::{closure#2}::promoted[0]
-103:17-103:23: @4[8]: _10 = &amp;(*_22)
-103:17-103:23: @4[9]: _9 = &amp;(*_10)
-103:17-103:23: @4[10]: _8 = move _9 as &amp;[&amp;str] (Pointer(Unsize))
-103:25-103:28: @4[18]: _17 = &amp;_2
-103:9-103:29: @4[19]: _16 = (move _17,)
-103:9-103:29: @4[21]: FakeRead(ForMatchedPlace, _16)
-103:9-103:29: @4[23]: _18 = (_16.0: &amp;&amp;str)
-103:9-103:29: @4[26]: _20 = &amp;(*_18)
-103:9-103:29: @4[28]: _21 = &lt;&amp;str as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;str, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-103:9-103:29: @4.Call: _19 = ArgumentV1::new::&lt;&amp;str&gt;(move _20, move _21) -&gt; [return: bb5, unwind: bb10]
-103:9-103:29: @5[2]: _15 = [move _19]
-103:9-103:29: @5[5]: _14 = &amp;_15
-103:9-103:29: @5[6]: _13 = &amp;(*_14)
-103:9-103:29: @5[7]: _12 = move _13 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-103:9-103:29: @5.Call: _7 = Arguments::new_v1(move _8, move _12) -&gt; [return: bb6, unwind: bb10]
-103:9-103:29: @6.Call: _6 = format(move _7) -&gt; [return: bb7, unwind: bb10]
-103:9-103:29: @7[1]: FakeRead(ForLet, _6)
-103:9-103:29: @7[6]: _0 = move _6
-104:6-104:6: @8.Return: return"><span class="annotation">@4,5,6,7,8⦊</span>format!("'{}'", val)</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="103:17-103:23: @4[7]: _22 = const main::{closure#2}::promoted[0]
-103:17-103:23: @4[8]: _10 = &amp;(*_22)
-103:17-103:23: @4[9]: _9 = &amp;(*_10)
-103:17-103:23: @4[10]: _8 = move _9 as &amp;[&amp;str] (Pointer(Unsize))
-103:25-103:28: @4[18]: _17 = &amp;_2
-103:9-103:29: @4[19]: _16 = (move _17,)
-103:9-103:29: @4[21]: FakeRead(ForMatchedPlace, _16)
-103:9-103:29: @4[23]: _18 = (_16.0: &amp;&amp;str)
-103:9-103:29: @4[26]: _20 = &amp;(*_18)
-103:9-103:29: @4[28]: _21 = &lt;&amp;str as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;str, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-103:9-103:29: @4.Call: _19 = ArgumentV1::new::&lt;&amp;str&gt;(move _20, move _21) -&gt; [return: bb5, unwind: bb10]
-103:9-103:29: @5[2]: _15 = [move _19]
-103:9-103:29: @5[5]: _14 = &amp;_15
-103:9-103:29: @5[6]: _13 = &amp;(*_14)
-103:9-103:29: @5[7]: _12 = move _13 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-103:9-103:29: @5.Call: _7 = Arguments::new_v1(move _8, move _12) -&gt; [return: bb6, unwind: bb10]
-103:9-103:29: @6.Call: _6 = format(move _7) -&gt; [return: bb7, unwind: bb10]
-103:9-103:29: @7[1]: FakeRead(ForLet, _6)
-103:9-103:29: @7[6]: _0 = move _6
-104:6-104:6: @8.Return: return">    }<span class="annotation">⦉@4,5,6,7,8</span></span></span></span></div>
+100:12-100:20: @0[5]: _5 = (*((*_1).0: &amp;bool))">        if is_false<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="101:13-101:27: @1[0]: _3 = const 10_i32
+100:21-102:10: @1[1]: _4 = const ()"><span class="annotation">@1⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="101:13-101:27: @1[0]: _3 = const 10_i32
+100:21-102:10: @1[1]: _4 = const ()">            countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="101:13-101:27: @1[0]: _3 = const 10_i32
+100:21-102:10: @1[1]: _4 = const ()">        }<span class="annotation">⦉@1</span></span></span><span><span class="code even" style="--layer: 1" title="102:10-102:10: @2[0]: _4 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="103:17-103:23: @3[7]: _22 = const main::{closure#2}::promoted[0]
+103:17-103:23: @3[8]: _10 = &amp;(*_22)
+103:17-103:23: @3[9]: _9 = &amp;(*_10)
+103:17-103:23: @3[10]: _8 = move _9 as &amp;[&amp;str] (Pointer(Unsize))
+103:25-103:28: @3[18]: _17 = &amp;_2
+103:9-103:29: @3[19]: _16 = (move _17,)
+103:9-103:29: @3[21]: FakeRead(ForMatchedPlace, _16)
+103:9-103:29: @3[23]: _18 = (_16.0: &amp;&amp;str)
+103:9-103:29: @3[26]: _20 = &amp;(*_18)
+103:9-103:29: @3[28]: _21 = &lt;&amp;str as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;str, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+103:9-103:29: @3.Call: _19 = ArgumentV1::new::&lt;&amp;str&gt;(move _20, move _21) -&gt; [return: bb4, unwind: bb9]
+103:9-103:29: @4[2]: _15 = [move _19]
+103:9-103:29: @4[5]: _14 = &amp;_15
+103:9-103:29: @4[6]: _13 = &amp;(*_14)
+103:9-103:29: @4[7]: _12 = move _13 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+103:9-103:29: @4.Call: _7 = Arguments::new_v1(move _8, move _12) -&gt; [return: bb5, unwind: bb9]
+103:9-103:29: @5.Call: _6 = format(move _7) -&gt; [return: bb6, unwind: bb9]
+103:9-103:29: @6[1]: FakeRead(ForLet, _6)
+103:9-103:29: @6[6]: _0 = move _6
+104:6-104:6: @7.Return: return"><span class="annotation">@3,4,5,6,7⦊</span>format!("'{}'", val)</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="103:17-103:23: @3[7]: _22 = const main::{closure#2}::promoted[0]
+103:17-103:23: @3[8]: _10 = &amp;(*_22)
+103:17-103:23: @3[9]: _9 = &amp;(*_10)
+103:17-103:23: @3[10]: _8 = move _9 as &amp;[&amp;str] (Pointer(Unsize))
+103:25-103:28: @3[18]: _17 = &amp;_2
+103:9-103:29: @3[19]: _16 = (move _17,)
+103:9-103:29: @3[21]: FakeRead(ForMatchedPlace, _16)
+103:9-103:29: @3[23]: _18 = (_16.0: &amp;&amp;str)
+103:9-103:29: @3[26]: _20 = &amp;(*_18)
+103:9-103:29: @3[28]: _21 = &lt;&amp;str as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;str, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+103:9-103:29: @3.Call: _19 = ArgumentV1::new::&lt;&amp;str&gt;(move _20, move _21) -&gt; [return: bb4, unwind: bb9]
+103:9-103:29: @4[2]: _15 = [move _19]
+103:9-103:29: @4[5]: _14 = &amp;_15
+103:9-103:29: @4[6]: _13 = &amp;(*_14)
+103:9-103:29: @4[7]: _12 = move _13 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+103:9-103:29: @4.Call: _7 = Arguments::new_v1(move _8, move _12) -&gt; [return: bb5, unwind: bb9]
+103:9-103:29: @5.Call: _6 = format(move _7) -&gt; [return: bb6, unwind: bb9]
+103:9-103:29: @6[1]: FakeRead(ForLet, _6)
+103:9-103:29: @6[6]: _0 = move _6
+104:6-104:6: @7.Return: return">    }<span class="annotation">⦉@3,4,5,6,7</span></span></span></span></div>
 </body>
 </html>
diff --git "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0433\175.-------.InstrumentCoverage.0.html" "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0433\175.-------.InstrumentCoverage.0.html"
index 032a6a7..0940775 100644
--- "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0433\175.-------.InstrumentCoverage.0.html"
+++ "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-\173closure\0433\175.-------.InstrumentCoverage.0.html"
@@ -72,22 +72,20 @@
 <div class="code" style="counter-reset: line 119"><span class="line">        <span class="code" style="--layer: 0">|</span></span>
 <span class="line"><span class="code" style="--layer: 0">            mut countdown</span></span>
 <span class="line"><span class="code" style="--layer: 0">        |</span></span>
-<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="124:12-124:20: @0[2]: _4 = (*((*_1).0: &amp;bool))
-124:12-124:20: @0[3]: FakeRead(ForMatchedPlace, _4)"><span class="annotation">@0⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="124:12-124:20: @0[2]: _4 = (*((*_1).0: &amp;bool))
-124:12-124:20: @0[3]: FakeRead(ForMatchedPlace, _4)">        if is_false<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="125:13-125:27: @3[0]: _2 = const 10_i32
-124:21-126:10: @3[1]: _3 = const ()"><span class="annotation">@1,3⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="125:13-125:27: @3[0]: _2 = const 10_i32
-124:21-126:10: @3[1]: _3 = const ()">            countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="125:13-125:27: @3[0]: _2 = const 10_i32
-124:21-126:10: @3[1]: _3 = const ()">        }<span class="annotation">⦉@1,3</span></span></span><span><span class="code even" style="--layer: 1" title="126:10-126:10: @2[0]: _3 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="127:9-127:35: @4[4]: _6 = const &quot;closure should be unused&quot;
-127:9-127:35: @4[5]: _5 = &amp;(*_6)
-127:9-127:46: @4.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb5, unwind: bb6]
-128:6-128:6: @5.Return: return"><span class="annotation">@4,5⦊</span>"closure should be unused".to_owned()</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="127:9-127:35: @4[4]: _6 = const &quot;closure should be unused&quot;
-127:9-127:35: @4[5]: _5 = &amp;(*_6)
-127:9-127:46: @4.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb5, unwind: bb6]
-128:6-128:6: @5.Return: return">    }<span class="annotation">⦉@4,5</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="124:12-124:20: @0[2]: _4 = (*((*_1).0: &amp;bool))"><span class="annotation">@0⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="124:12-124:20: @0[2]: _4 = (*((*_1).0: &amp;bool))">        if is_false<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="125:13-125:27: @1[0]: _2 = const 10_i32
+124:21-126:10: @1[1]: _3 = const ()"><span class="annotation">@1⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="125:13-125:27: @1[0]: _2 = const 10_i32
+124:21-126:10: @1[1]: _3 = const ()">            countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="125:13-125:27: @1[0]: _2 = const 10_i32
+124:21-126:10: @1[1]: _3 = const ()">        }<span class="annotation">⦉@1</span></span></span><span><span class="code even" style="--layer: 1" title="126:10-126:10: @2[0]: _3 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="127:9-127:35: @3[4]: _6 = const &quot;closure should be unused&quot;
+127:9-127:35: @3[5]: _5 = &amp;(*_6)
+127:9-127:46: @3.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb4, unwind: bb5]
+128:6-128:6: @4.Return: return"><span class="annotation">@3,4⦊</span>"closure should be unused".to_owned()</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="127:9-127:35: @3[4]: _6 = const &quot;closure should be unused&quot;
+127:9-127:35: @3[5]: _5 = &amp;(*_6)
+127:9-127:46: @3.Call: _0 = &lt;str as ToOwned&gt;::to_owned(move _5) -&gt; [return: bb4, unwind: bb5]
+128:6-128:6: @4.Return: return">    }<span class="annotation">⦉@3,4</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.conditions/conditions.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.conditions/conditions.main.-------.InstrumentCoverage.0.html
index e16b366..184dba6 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.conditions/conditions.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.conditions/conditions.main.-------.InstrumentCoverage.0.html
@@ -72,255 +72,236 @@
 <div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>fn main() <span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">{</span></span>
 <span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="4:25-4:26: @0[1]: _1 = const 0_u32
 4:9-4:22: @0[2]: FakeRead(ForLet, _1)
-5:8-5:12: @0[5]: _3 = const true
-5:8-5:12: @0[6]: FakeRead(ForMatchedPlace, _3)"><span class="annotation">@0⦊</span>mut countdown = 0;</span></span>
+5:8-5:12: @0[5]: _3 = const true"><span class="annotation">@0⦊</span>mut countdown = 0;</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="4:25-4:26: @0[1]: _1 = const 0_u32
 4:9-4:22: @0[2]: FakeRead(ForLet, _1)
-5:8-5:12: @0[5]: _3 = const true
-5:8-5:12: @0[6]: FakeRead(ForMatchedPlace, _3)">    if true<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="6:9-6:23: @3[0]: _1 = const 10_u32
-5:13-7:6: @3[1]: _2 = const ()"><span class="annotation">@1,3⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="6:9-6:23: @3[0]: _1 = const 10_u32
-5:13-7:6: @3[1]: _2 = const ()">        countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="6:9-6:23: @3[0]: _1 = const 10_u32
-5:13-7:6: @3[1]: _2 = const ()">    }<span class="annotation">⦉@1,3</span></span></span><span><span class="code even" style="--layer: 1" title="7:6-7:6: @2[0]: _2 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
+5:8-5:12: @0[5]: _3 = const true">    if true<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="6:9-6:23: @1[0]: _1 = const 10_u32
+5:13-7:6: @1[1]: _2 = const ()"><span class="annotation">@1⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="6:9-6:23: @1[0]: _1 = const 10_u32
+5:13-7:6: @1[1]: _2 = const ()">        countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="6:9-6:23: @1[0]: _1 = const 10_u32
+5:13-7:6: @1[1]: _2 = const ()">    }<span class="annotation">⦉@1</span></span></span><span><span class="code even" style="--layer: 1" title="7:6-7:6: @2[0]: _2 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    const B: u32 = 100;</span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code odd" style="--layer: 1" title="10:9-10:10: @25[0]: FakeRead(ForLet, _4)"><span class="annotation">@25⦊</span>x<span class="annotation">⦉@25</span></span></span><span class="code" style="--layer: 0"> = if </span><span><span class="code even" style="--layer: 1" title="10:16-10:25: @4[5]: _6 = _1
-10:16-10:29: @4[6]: _5 = Gt(move _6, const 7_u32)
-10:16-10:29: @4[8]: FakeRead(ForMatchedPlace, _5)"><span class="annotation">@4⦊</span>countdown &gt; 7<span class="annotation">⦉@4</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="11:9-11:23: @7[0]: _7 = CheckedSub(_1, const 4_u32)
-11:9-11:23: @8[0]: _1 = move (_7.0: u32)
-12:9-12:10: @8[1]: _4 = const B"><span class="annotation">@5,7,8⦊</span>countdown -= 4;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:23: @7[0]: _7 = CheckedSub(_1, const 4_u32)
-11:9-11:23: @8[0]: _1 = move (_7.0: u32)
-12:9-12:10: @8[1]: _4 = const B">        B<span class="annotation">⦉@5,7,8</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    } else if </span><span><span class="code even" style="--layer: 1" title="13:15-13:24: @6[2]: _9 = _1
-13:15-13:28: @6[3]: _8 = Gt(move _9, const 2_u32)
-13:15-13:28: @6[5]: FakeRead(ForMatchedPlace, _8)"><span class="annotation">@6⦊</span>countdown &gt; 2<span class="annotation">⦉@6</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code odd" style="--layer: 1" title="14:12-14:21: @11[5]: _14 = _1
-14:12-14:25: @11[6]: _13 = Lt(move _14, const 1_u32)"><span class="annotation">@9,11⦊</span>countdown &lt; 1<span class="annotation">⦉@9,11</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="14:29-14:38: @18[2]: _16 = _1
-14:29-14:42: @18[3]: _15 = Gt(move _16, const 5_u32)"><span class="annotation">@18⦊</span>countdown &gt; 5<span class="annotation">⦉@18</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="14:46-14:55: @14[2]: _18 = _1
-14:46-14:60: @14[3]: _17 = Ne(move _18, const 9_u32)"><span class="annotation">@14⦊</span>countdown != 9<span class="annotation">⦉@14</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="15:13-15:26: @22[0]: _1 = const 0_u32
-14:61-16:10: @22[1]: _10 = const ()"><span class="annotation">@20,22⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="15:13-15:26: @22[0]: _1 = const 0_u32
-14:61-16:10: @22[1]: _10 = const ()">            countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="15:13-15:26: @22[0]: _1 = const 0_u32
-14:61-16:10: @22[1]: _10 = const ()">        }<span class="annotation">⦉@20,22</span></span></span><span><span class="code odd" style="--layer: 1" title="16:10-16:10: @21[0]: _10 = const ()"><span class="annotation">@21⦊</span>‸<span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="17:9-17:23: @23[2]: _19 = CheckedSub(_1, const 5_u32)
-17:9-17:23: @24[0]: _1 = move (_19.0: u32)
-18:9-18:18: @24[1]: _4 = _1"><span class="annotation">@23,24⦊</span>countdown -= 5;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="17:9-17:23: @23[2]: _19 = CheckedSub(_1, const 5_u32)
-17:9-17:23: @24[0]: _1 = move (_19.0: u32)
-18:9-18:18: @24[1]: _4 = _1">        countdown<span class="annotation">⦉@23,24</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code odd" style="--layer: 1" title="10:9-10:10: @21[1]: FakeRead(ForLet, _4)"><span class="annotation">@21⦊</span>x<span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0"> = if </span><span><span class="code even" style="--layer: 1" title="10:16-10:25: @3[5]: _6 = _1
+10:16-10:29: @3[6]: _5 = Gt(move _6, const 7_u32)"><span class="annotation">@3⦊</span>countdown &gt; 7<span class="annotation">⦉@3</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="11:9-11:23: @4[0]: _7 = CheckedSub(_1, const 4_u32)
+11:9-11:23: @6[0]: _1 = move (_7.0: u32)
+12:9-12:10: @6[1]: _4 = const B"><span class="annotation">@4,6⦊</span>countdown -= 4;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:23: @4[0]: _7 = CheckedSub(_1, const 4_u32)
+11:9-11:23: @6[0]: _1 = move (_7.0: u32)
+12:9-12:10: @6[1]: _4 = const B">        B<span class="annotation">⦉@4,6</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    } else if </span><span><span class="code even" style="--layer: 1" title="13:15-13:24: @5[2]: _9 = _1
+13:15-13:28: @5[3]: _8 = Gt(move _9, const 2_u32)"><span class="annotation">@5⦊</span>countdown &gt; 2<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code odd" style="--layer: 1" title="14:12-14:21: @7[5]: _14 = _1
+14:12-14:25: @7[6]: _13 = Lt(move _14, const 1_u32)"><span class="annotation">@7⦊</span>countdown &lt; 1<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="14:29-14:38: @15[2]: _16 = _1
+14:29-14:42: @15[3]: _15 = Gt(move _16, const 5_u32)"><span class="annotation">@15⦊</span>countdown &gt; 5<span class="annotation">⦉@15</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="14:46-14:55: @11[2]: _18 = _1
+14:46-14:60: @11[3]: _17 = Ne(move _18, const 9_u32)"><span class="annotation">@11⦊</span>countdown != 9<span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="15:13-15:26: @17[0]: _1 = const 0_u32
+14:61-16:10: @17[1]: _10 = const ()"><span class="annotation">@17⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="15:13-15:26: @17[0]: _1 = const 0_u32
+14:61-16:10: @17[1]: _10 = const ()">            countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="15:13-15:26: @17[0]: _1 = const 0_u32
+14:61-16:10: @17[1]: _10 = const ()">        }<span class="annotation">⦉@17</span></span></span><span><span class="code odd" style="--layer: 1" title="16:10-16:10: @18[0]: _10 = const ()"><span class="annotation">@18⦊</span>‸<span class="annotation">⦉@18</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="17:9-17:23: @19[2]: _19 = CheckedSub(_1, const 5_u32)
+17:9-17:23: @20[0]: _1 = move (_19.0: u32)
+18:9-18:18: @20[1]: _4 = _1"><span class="annotation">@19,20⦊</span>countdown -= 5;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="17:9-17:23: @19[2]: _19 = CheckedSub(_1, const 5_u32)
+17:9-17:23: @20[0]: _1 = move (_19.0: u32)
+18:9-18:18: @20[1]: _4 = _1">        countdown<span class="annotation">⦉@19,20</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    } else {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="20:9-20:15: @10[0]: _0 = const ()"><span class="annotation">@10⦊</span>return<span class="annotation">⦉@10</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="20:9-20:15: @8[0]: _0 = const ()"><span class="annotation">@8⦊</span>return<span class="annotation">⦉@8</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    };</span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="23:25-23:26: @25[3]: _21 = const 0_i32
-23:9-23:22: @25[4]: FakeRead(ForLet, _21)
-24:8-24:12: @25[7]: _23 = const true
-24:8-24:12: @25[8]: FakeRead(ForMatchedPlace, _23)"><span class="annotation">@25⦊</span>mut countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="23:25-23:26: @25[3]: _21 = const 0_i32
-23:9-23:22: @25[4]: FakeRead(ForLet, _21)
-24:8-24:12: @25[7]: _23 = const true
-24:8-24:12: @25[8]: FakeRead(ForMatchedPlace, _23)">    if true<span class="annotation">⦉@25</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="25:9-25:23: @28[0]: _21 = const 10_i32
-24:13-26:6: @28[1]: _22 = const ()"><span class="annotation">@26,28⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="25:9-25:23: @28[0]: _21 = const 10_i32
-24:13-26:6: @28[1]: _22 = const ()">        countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="25:9-25:23: @28[0]: _21 = const 10_i32
-24:13-26:6: @28[1]: _22 = const ()">    }<span class="annotation">⦉@26,28</span></span></span><span><span class="code even" style="--layer: 1" title="26:6-26:6: @27[0]: _22 = const ()"><span class="annotation">@27⦊</span>‸<span class="annotation">⦉@27</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="23:25-23:26: @21[3]: _21 = const 0_i32
+23:9-23:22: @21[4]: FakeRead(ForLet, _21)
+24:8-24:12: @21[7]: _23 = const true"><span class="annotation">@21⦊</span>mut countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="23:25-23:26: @21[3]: _21 = const 0_i32
+23:9-23:22: @21[4]: FakeRead(ForLet, _21)
+24:8-24:12: @21[7]: _23 = const true">    if true<span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="25:9-25:23: @22[0]: _21 = const 10_i32
+24:13-26:6: @22[1]: _22 = const ()"><span class="annotation">@22⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="25:9-25:23: @22[0]: _21 = const 10_i32
+24:13-26:6: @22[1]: _22 = const ()">        countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="25:9-25:23: @22[0]: _21 = const 10_i32
+24:13-26:6: @22[1]: _22 = const ()">    }<span class="annotation">⦉@22</span></span></span><span><span class="code even" style="--layer: 1" title="26:6-26:6: @23[0]: _22 = const ()"><span class="annotation">@23⦊</span>‸<span class="annotation">⦉@23</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code odd" style="--layer: 1" title="28:8-28:17: @29[5]: _26 = _21
-28:8-28:21: @29[6]: _25 = Gt(move _26, const 7_i32)
-28:8-28:21: @29[8]: FakeRead(ForMatchedPlace, _25)"><span class="annotation">@29⦊</span>countdown &gt; 7<span class="annotation">⦉@29</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="29:9-29:23: @32[0]: _27 = CheckedSub(_21, const 4_i32)
-29:9-29:23: @33[0]: _21 = move (_27.0: i32)
-28:22-30:6: @33[1]: _24 = const ()"><span class="annotation">@30,32,33⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="29:9-29:23: @32[0]: _27 = CheckedSub(_21, const 4_i32)
-29:9-29:23: @33[0]: _21 = move (_27.0: i32)
-28:22-30:6: @33[1]: _24 = const ()">        countdown -= 4;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="29:9-29:23: @32[0]: _27 = CheckedSub(_21, const 4_i32)
-29:9-29:23: @33[0]: _21 = move (_27.0: i32)
-28:22-30:6: @33[1]: _24 = const ()">    }<span class="annotation">⦉@30,32,33</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code odd" style="--layer: 1" title="30:15-30:24: @31[2]: _29 = _21
-30:15-30:28: @31[3]: _28 = Gt(move _29, const 2_i32)
-30:15-30:28: @31[5]: FakeRead(ForMatchedPlace, _28)"><span class="annotation">@31⦊</span>countdown &gt; 2<span class="annotation">⦉@31</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code even" style="--layer: 1" title="31:12-31:21: @36[5]: _34 = _21
-31:12-31:25: @36[6]: _33 = Lt(move _34, const 1_i32)"><span class="annotation">@34,36⦊</span>countdown &lt; 1<span class="annotation">⦉@34,36</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="31:29-31:38: @43[2]: _36 = _21
-31:29-31:42: @43[3]: _35 = Gt(move _36, const 5_i32)"><span class="annotation">@43⦊</span>countdown &gt; 5<span class="annotation">⦉@43</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="31:46-31:55: @39[2]: _38 = _21
-31:46-31:60: @39[3]: _37 = Ne(move _38, const 9_i32)"><span class="annotation">@39⦊</span>countdown != 9<span class="annotation">⦉@39</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="32:13-32:26: @47[0]: _21 = const 0_i32
-31:61-33:10: @47[1]: _30 = const ()"><span class="annotation">@45,47⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="32:13-32:26: @47[0]: _21 = const 0_i32
-31:61-33:10: @47[1]: _30 = const ()">            countdown = 0;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="32:13-32:26: @47[0]: _21 = const 0_i32
-31:61-33:10: @47[1]: _30 = const ()">        }<span class="annotation">⦉@45,47</span></span></span><span><span class="code even" style="--layer: 1" title="33:10-33:10: @46[0]: _30 = const ()"><span class="annotation">@46⦊</span>‸<span class="annotation">⦉@46</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="34:9-34:23: @48[2]: _39 = CheckedSub(_21, const 5_i32)
-34:9-34:23: @49[0]: _21 = move (_39.0: i32)"><span class="annotation">@48,49⦊</span>countdown -= 5<span class="annotation">⦉@48,49</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code odd" style="--layer: 1" title="28:8-28:17: @24[5]: _26 = _21
+28:8-28:21: @24[6]: _25 = Gt(move _26, const 7_i32)"><span class="annotation">@24⦊</span>countdown &gt; 7<span class="annotation">⦉@24</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="29:9-29:23: @25[0]: _27 = CheckedSub(_21, const 4_i32)
+29:9-29:23: @27[0]: _21 = move (_27.0: i32)
+28:22-30:6: @27[1]: _24 = const ()"><span class="annotation">@25,27⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="29:9-29:23: @25[0]: _27 = CheckedSub(_21, const 4_i32)
+29:9-29:23: @27[0]: _21 = move (_27.0: i32)
+28:22-30:6: @27[1]: _24 = const ()">        countdown -= 4;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="29:9-29:23: @25[0]: _27 = CheckedSub(_21, const 4_i32)
+29:9-29:23: @27[0]: _21 = move (_27.0: i32)
+28:22-30:6: @27[1]: _24 = const ()">    }<span class="annotation">⦉@25,27</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code odd" style="--layer: 1" title="30:15-30:24: @26[2]: _29 = _21
+30:15-30:28: @26[3]: _28 = Gt(move _29, const 2_i32)"><span class="annotation">@26⦊</span>countdown &gt; 2<span class="annotation">⦉@26</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code even" style="--layer: 1" title="31:12-31:21: @28[5]: _34 = _21
+31:12-31:25: @28[6]: _33 = Lt(move _34, const 1_i32)"><span class="annotation">@28⦊</span>countdown &lt; 1<span class="annotation">⦉@28</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="31:29-31:38: @36[2]: _36 = _21
+31:29-31:42: @36[3]: _35 = Gt(move _36, const 5_i32)"><span class="annotation">@36⦊</span>countdown &gt; 5<span class="annotation">⦉@36</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="31:46-31:55: @32[2]: _38 = _21
+31:46-31:60: @32[3]: _37 = Ne(move _38, const 9_i32)"><span class="annotation">@32⦊</span>countdown != 9<span class="annotation">⦉@32</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="32:13-32:26: @38[0]: _21 = const 0_i32
+31:61-33:10: @38[1]: _30 = const ()"><span class="annotation">@38⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="32:13-32:26: @38[0]: _21 = const 0_i32
+31:61-33:10: @38[1]: _30 = const ()">            countdown = 0;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="32:13-32:26: @38[0]: _21 = const 0_i32
+31:61-33:10: @38[1]: _30 = const ()">        }<span class="annotation">⦉@38</span></span></span><span><span class="code even" style="--layer: 1" title="33:10-33:10: @39[0]: _30 = const ()"><span class="annotation">@39⦊</span>‸<span class="annotation">⦉@39</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="34:9-34:23: @40[2]: _39 = CheckedSub(_21, const 5_i32)
+34:9-34:23: @41[0]: _21 = move (_39.0: i32)"><span class="annotation">@40,41⦊</span>countdown -= 5<span class="annotation">⦉@40,41</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    } else {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="36:9-36:15: @35[0]: _0 = const ()"><span class="annotation">@35⦊</span>return<span class="annotation">⦉@35</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="36:9-36:15: @29[0]: _0 = const ()"><span class="annotation">@29⦊</span>return<span class="annotation">⦉@29</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code odd" style="--layer: 1" title="39:8-39:12: @50[4]: _42 = const true
-39:8-39:12: @50[5]: FakeRead(ForMatchedPlace, _42)"><span class="annotation">@50⦊</span>true<span class="annotation">⦉@50</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        let </span><span><span class="code even" style="--layer: 1" title="40:29-40:30: @53[1]: _43 = const 0_i32
-40:13-40:26: @53[2]: FakeRead(ForLet, _43)
-41:12-41:16: @53[5]: _45 = const true
-41:12-41:16: @53[6]: FakeRead(ForMatchedPlace, _45)"><span class="annotation">@51,53⦊</span>mut countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="40:29-40:30: @53[1]: _43 = const 0_i32
-40:13-40:26: @53[2]: FakeRead(ForLet, _43)
-41:12-41:16: @53[5]: _45 = const true
-41:12-41:16: @53[6]: FakeRead(ForMatchedPlace, _45)">        if true<span class="annotation">⦉@51,53</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="42:13-42:27: @56[0]: _43 = const 10_i32
-41:17-43:10: @56[1]: _44 = const ()"><span class="annotation">@54,56⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="42:13-42:27: @56[0]: _43 = const 10_i32
-41:17-43:10: @56[1]: _44 = const ()">            countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="42:13-42:27: @56[0]: _43 = const 10_i32
-41:17-43:10: @56[1]: _44 = const ()">        }<span class="annotation">⦉@54,56</span></span></span><span><span class="code even" style="--layer: 1" title="43:10-43:10: @55[0]: _44 = const ()"><span class="annotation">@55⦊</span>‸<span class="annotation">⦉@55</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code odd" style="--layer: 1" title="39:8-39:12: @42[4]: _42 = const true"><span class="annotation">@42⦊</span>true<span class="annotation">⦉@42</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        let </span><span><span class="code even" style="--layer: 1" title="40:29-40:30: @43[1]: _43 = const 0_i32
+40:13-40:26: @43[2]: FakeRead(ForLet, _43)
+41:12-41:16: @43[5]: _45 = const true"><span class="annotation">@43⦊</span>mut countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="40:29-40:30: @43[1]: _43 = const 0_i32
+40:13-40:26: @43[2]: FakeRead(ForLet, _43)
+41:12-41:16: @43[5]: _45 = const true">        if true<span class="annotation">⦉@43</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="42:13-42:27: @45[0]: _43 = const 10_i32
+41:17-43:10: @45[1]: _44 = const ()"><span class="annotation">@45⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="42:13-42:27: @45[0]: _43 = const 10_i32
+41:17-43:10: @45[1]: _44 = const ()">            countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="42:13-42:27: @45[0]: _43 = const 10_i32
+41:17-43:10: @45[1]: _44 = const ()">        }<span class="annotation">⦉@45</span></span></span><span><span class="code even" style="--layer: 1" title="43:10-43:10: @46[0]: _44 = const ()"><span class="annotation">@46⦊</span>‸<span class="annotation">⦉@46</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code odd" style="--layer: 1" title="45:12-45:21: @57[4]: _47 = _43
-45:12-45:25: @57[5]: _46 = Gt(move _47, const 7_i32)
-45:12-45:25: @57[7]: FakeRead(ForMatchedPlace, _46)"><span class="annotation">@57⦊</span>countdown &gt; 7<span class="annotation">⦉@57</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="46:13-46:27: @60[0]: _48 = CheckedSub(_43, const 4_i32)
-46:13-46:27: @61[0]: _43 = move (_48.0: i32)
-45:26-47:10: @61[1]: _41 = const ()"><span class="annotation">@58,60,61⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="46:13-46:27: @60[0]: _48 = CheckedSub(_43, const 4_i32)
-46:13-46:27: @61[0]: _43 = move (_48.0: i32)
-45:26-47:10: @61[1]: _41 = const ()">            countdown -= 4;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="46:13-46:27: @60[0]: _48 = CheckedSub(_43, const 4_i32)
-46:13-46:27: @61[0]: _43 = move (_48.0: i32)
-45:26-47:10: @61[1]: _41 = const ()">        }<span class="annotation">⦉@58,60,61</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        else if </span><span><span class="code odd" style="--layer: 1" title="48:17-48:26: @59[2]: _50 = _43
-48:17-48:30: @59[3]: _49 = Gt(move _50, const 2_i32)
-48:17-48:30: @59[5]: FakeRead(ForMatchedPlace, _49)"><span class="annotation">@59⦊</span>countdown &gt; 2<span class="annotation">⦉@59</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">            if </span><span><span class="code even" style="--layer: 1" title="49:16-49:25: @64[5]: _55 = _43
-49:16-49:29: @64[6]: _54 = Lt(move _55, const 1_i32)"><span class="annotation">@62,64⦊</span>countdown &lt; 1<span class="annotation">⦉@62,64</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="49:33-49:42: @71[2]: _57 = _43
-49:33-49:46: @71[3]: _56 = Gt(move _57, const 5_i32)"><span class="annotation">@71⦊</span>countdown &gt; 5<span class="annotation">⦉@71</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="49:50-49:59: @67[2]: _59 = _43
-49:50-49:64: @67[3]: _58 = Ne(move _59, const 9_i32)"><span class="annotation">@67⦊</span>countdown != 9<span class="annotation">⦉@67</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="50:17-50:30: @75[0]: _43 = const 0_i32
-49:65-51:14: @75[1]: _51 = const ()"><span class="annotation">@73,75⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="50:17-50:30: @75[0]: _43 = const 0_i32
-49:65-51:14: @75[1]: _51 = const ()">                countdown = 0;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="50:17-50:30: @75[0]: _43 = const 0_i32
-49:65-51:14: @75[1]: _51 = const ()">            }<span class="annotation">⦉@73,75</span></span></span><span><span class="code even" style="--layer: 1" title="51:14-51:14: @74[0]: _51 = const ()"><span class="annotation">@74⦊</span>‸<span class="annotation">⦉@74</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="52:13-52:27: @76[2]: _60 = CheckedSub(_43, const 5_i32)
-52:13-52:27: @77[0]: _43 = move (_60.0: i32)"><span class="annotation">@76,77⦊</span>countdown -= 5<span class="annotation">⦉@76,77</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code odd" style="--layer: 1" title="45:12-45:21: @47[4]: _47 = _43
+45:12-45:25: @47[5]: _46 = Gt(move _47, const 7_i32)"><span class="annotation">@47⦊</span>countdown &gt; 7<span class="annotation">⦉@47</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="46:13-46:27: @48[0]: _48 = CheckedSub(_43, const 4_i32)
+46:13-46:27: @50[0]: _43 = move (_48.0: i32)
+45:26-47:10: @50[1]: _41 = const ()"><span class="annotation">@48,50⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="46:13-46:27: @48[0]: _48 = CheckedSub(_43, const 4_i32)
+46:13-46:27: @50[0]: _43 = move (_48.0: i32)
+45:26-47:10: @50[1]: _41 = const ()">            countdown -= 4;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="46:13-46:27: @48[0]: _48 = CheckedSub(_43, const 4_i32)
+46:13-46:27: @50[0]: _43 = move (_48.0: i32)
+45:26-47:10: @50[1]: _41 = const ()">        }<span class="annotation">⦉@48,50</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        else if </span><span><span class="code odd" style="--layer: 1" title="48:17-48:26: @49[2]: _50 = _43
+48:17-48:30: @49[3]: _49 = Gt(move _50, const 2_i32)"><span class="annotation">@49⦊</span>countdown &gt; 2<span class="annotation">⦉@49</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">            if </span><span><span class="code even" style="--layer: 1" title="49:16-49:25: @51[5]: _55 = _43
+49:16-49:29: @51[6]: _54 = Lt(move _55, const 1_i32)"><span class="annotation">@51⦊</span>countdown &lt; 1<span class="annotation">⦉@51</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="49:33-49:42: @59[2]: _57 = _43
+49:33-49:46: @59[3]: _56 = Gt(move _57, const 5_i32)"><span class="annotation">@59⦊</span>countdown &gt; 5<span class="annotation">⦉@59</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="49:50-49:59: @55[2]: _59 = _43
+49:50-49:64: @55[3]: _58 = Ne(move _59, const 9_i32)"><span class="annotation">@55⦊</span>countdown != 9<span class="annotation">⦉@55</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="50:17-50:30: @61[0]: _43 = const 0_i32
+49:65-51:14: @61[1]: _51 = const ()"><span class="annotation">@61⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="50:17-50:30: @61[0]: _43 = const 0_i32
+49:65-51:14: @61[1]: _51 = const ()">                countdown = 0;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="50:17-50:30: @61[0]: _43 = const 0_i32
+49:65-51:14: @61[1]: _51 = const ()">            }<span class="annotation">⦉@61</span></span></span><span><span class="code even" style="--layer: 1" title="51:14-51:14: @62[0]: _51 = const ()"><span class="annotation">@62⦊</span>‸<span class="annotation">⦉@62</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="52:13-52:27: @63[2]: _60 = CheckedSub(_43, const 5_i32)
+52:13-52:27: @64[0]: _43 = move (_60.0: i32)"><span class="annotation">@63,64⦊</span>countdown -= 5<span class="annotation">⦉@63,64</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">        } else {</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="54:13-54:19: @63[0]: _0 = const ()"><span class="annotation">@63⦊</span>return<span class="annotation">⦉@63</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="54:13-54:19: @52[0]: _0 = const ()"><span class="annotation">@52⦊</span>return<span class="annotation">⦉@52</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">        }</span></span>
-<span class="line"><span class="code" style="--layer: 0">    }</span><span><span class="code odd" style="--layer: 1" title="56:6-56:6: @52[0]: _41 = const ()"><span class="annotation">@52⦊</span>‸<span class="annotation">⦉@52</span></span></span><span class="code" style="--layer: 0"> // Note: closing brace shows uncovered (vs. `0` for implicit else) because condition literal</span></span>
+<span class="line"><span class="code" style="--layer: 0">    }</span><span><span class="code odd" style="--layer: 1" title="56:6-56:6: @44[0]: _41 = const ()"><span class="annotation">@44⦊</span>‸<span class="annotation">⦉@44</span></span></span><span class="code" style="--layer: 0"> // Note: closing brace shows uncovered (vs. `0` for implicit else) because condition literal</span></span>
 <span class="line"><span class="code" style="--layer: 0">      // `true` was const-evaluated. The compiler knows the `if` block will be executed.</span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="59:25-59:26: @79[3]: _62 = const 0_i32
-59:9-59:22: @79[4]: FakeRead(ForLet, _62)
-60:8-60:12: @79[7]: _64 = const true
-60:8-60:12: @79[8]: FakeRead(ForMatchedPlace, _64)"><span class="annotation">@79⦊</span>mut countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="59:25-59:26: @79[3]: _62 = const 0_i32
-59:9-59:22: @79[4]: FakeRead(ForLet, _62)
-60:8-60:12: @79[7]: _64 = const true
-60:8-60:12: @79[8]: FakeRead(ForMatchedPlace, _64)">    if true<span class="annotation">⦉@79</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="61:9-61:22: @82[0]: _62 = const 1_i32
-60:13-62:6: @82[1]: _63 = const ()"><span class="annotation">@80,82⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="61:9-61:22: @82[0]: _62 = const 1_i32
-60:13-62:6: @82[1]: _63 = const ()">        countdown = 1;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="61:9-61:22: @82[0]: _62 = const 1_i32
-60:13-62:6: @82[1]: _63 = const ()">    }<span class="annotation">⦉@80,82</span></span></span><span><span class="code even" style="--layer: 1" title="62:6-62:6: @81[0]: _63 = const ()"><span class="annotation">@81⦊</span>‸<span class="annotation">⦉@81</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="59:25-59:26: @66[3]: _62 = const 0_i32
+59:9-59:22: @66[4]: FakeRead(ForLet, _62)
+60:8-60:12: @66[7]: _64 = const true"><span class="annotation">@66⦊</span>mut countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="59:25-59:26: @66[3]: _62 = const 0_i32
+59:9-59:22: @66[4]: FakeRead(ForLet, _62)
+60:8-60:12: @66[7]: _64 = const true">    if true<span class="annotation">⦉@66</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="61:9-61:22: @67[0]: _62 = const 1_i32
+60:13-62:6: @67[1]: _63 = const ()"><span class="annotation">@67⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="61:9-61:22: @67[0]: _62 = const 1_i32
+60:13-62:6: @67[1]: _63 = const ()">        countdown = 1;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="61:9-61:22: @67[0]: _62 = const 1_i32
+60:13-62:6: @67[1]: _63 = const ()">    }<span class="annotation">⦉@67</span></span></span><span><span class="code even" style="--layer: 1" title="62:6-62:6: @68[0]: _63 = const ()"><span class="annotation">@68⦊</span>‸<span class="annotation">⦉@68</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code odd" style="--layer: 1" title="64:9-64:10: @106[0]: FakeRead(ForLet, _65)"><span class="annotation">@106⦊</span>z<span class="annotation">⦉@106</span></span></span><span class="code" style="--layer: 0"> = if </span><span><span class="code even" style="--layer: 1" title="64:16-64:25: @83[5]: _67 = _62
-64:16-64:29: @83[6]: _66 = Gt(move _67, const 7_i32)
-64:16-64:29: @83[8]: FakeRead(ForMatchedPlace, _66)"><span class="annotation">@83⦊</span>countdown &gt; 7<span class="annotation">⦉@83</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="65:9-65:23: @86[0]: _68 = CheckedSub(_62, const 4_i32)
-65:9-65:23: @87[0]: _62 = move (_68.0: i32)
-64:30-66:6: @87[1]: _65 = const ()"><span class="annotation">@84,86,87⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="65:9-65:23: @86[0]: _68 = CheckedSub(_62, const 4_i32)
-65:9-65:23: @87[0]: _62 = move (_68.0: i32)
-64:30-66:6: @87[1]: _65 = const ()">        countdown -= 4;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="65:9-65:23: @86[0]: _68 = CheckedSub(_62, const 4_i32)
-65:9-65:23: @87[0]: _62 = move (_68.0: i32)
-64:30-66:6: @87[1]: _65 = const ()">    }<span class="annotation">⦉@84,86,87</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code even" style="--layer: 1" title="66:15-66:24: @85[2]: _70 = _62
-66:15-66:28: @85[3]: _69 = Gt(move _70, const 2_i32)
-66:15-66:28: @85[5]: FakeRead(ForMatchedPlace, _69)"><span class="annotation">@85⦊</span>countdown &gt; 2<span class="annotation">⦉@85</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code odd" style="--layer: 1" title="67:12-67:21: @90[5]: _75 = _62
-67:12-67:25: @90[6]: _74 = Lt(move _75, const 1_i32)"><span class="annotation">@88,90⦊</span>countdown &lt; 1<span class="annotation">⦉@88,90</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="67:29-67:38: @97[2]: _77 = _62
-67:29-67:42: @97[3]: _76 = Gt(move _77, const 5_i32)"><span class="annotation">@97⦊</span>countdown &gt; 5<span class="annotation">⦉@97</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="67:46-67:55: @93[2]: _79 = _62
-67:46-67:60: @93[3]: _78 = Ne(move _79, const 9_i32)"><span class="annotation">@93⦊</span>countdown != 9<span class="annotation">⦉@93</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="68:13-68:26: @101[0]: _62 = const 0_i32
-67:61-69:10: @101[1]: _71 = const ()"><span class="annotation">@99,101⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="68:13-68:26: @101[0]: _62 = const 0_i32
-67:61-69:10: @101[1]: _71 = const ()">            countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="68:13-68:26: @101[0]: _62 = const 0_i32
-67:61-69:10: @101[1]: _71 = const ()">        }<span class="annotation">⦉@99,101</span></span></span><span><span class="code odd" style="--layer: 1" title="69:10-69:10: @100[0]: _71 = const ()"><span class="annotation">@100⦊</span>‸<span class="annotation">⦉@100</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="70:9-70:23: @102[2]: _80 = CheckedSub(_62, const 5_i32)
-70:9-70:23: @103[0]: _62 = move (_80.0: i32)"><span class="annotation">@102,103⦊</span>countdown -= 5<span class="annotation">⦉@102,103</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code odd" style="--layer: 1" title="64:9-64:10: @89[1]: FakeRead(ForLet, _65)"><span class="annotation">@89⦊</span>z<span class="annotation">⦉@89</span></span></span><span class="code" style="--layer: 0"> = if </span><span><span class="code even" style="--layer: 1" title="64:16-64:25: @69[5]: _67 = _62
+64:16-64:29: @69[6]: _66 = Gt(move _67, const 7_i32)"><span class="annotation">@69⦊</span>countdown &gt; 7<span class="annotation">⦉@69</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="65:9-65:23: @70[0]: _68 = CheckedSub(_62, const 4_i32)
+65:9-65:23: @72[0]: _62 = move (_68.0: i32)
+64:30-66:6: @72[1]: _65 = const ()"><span class="annotation">@70,72⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="65:9-65:23: @70[0]: _68 = CheckedSub(_62, const 4_i32)
+65:9-65:23: @72[0]: _62 = move (_68.0: i32)
+64:30-66:6: @72[1]: _65 = const ()">        countdown -= 4;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="65:9-65:23: @70[0]: _68 = CheckedSub(_62, const 4_i32)
+65:9-65:23: @72[0]: _62 = move (_68.0: i32)
+64:30-66:6: @72[1]: _65 = const ()">    }<span class="annotation">⦉@70,72</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code even" style="--layer: 1" title="66:15-66:24: @71[2]: _70 = _62
+66:15-66:28: @71[3]: _69 = Gt(move _70, const 2_i32)"><span class="annotation">@71⦊</span>countdown &gt; 2<span class="annotation">⦉@71</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code odd" style="--layer: 1" title="67:12-67:21: @73[5]: _75 = _62
+67:12-67:25: @73[6]: _74 = Lt(move _75, const 1_i32)"><span class="annotation">@73⦊</span>countdown &lt; 1<span class="annotation">⦉@73</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="67:29-67:38: @81[2]: _77 = _62
+67:29-67:42: @81[3]: _76 = Gt(move _77, const 5_i32)"><span class="annotation">@81⦊</span>countdown &gt; 5<span class="annotation">⦉@81</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="67:46-67:55: @77[2]: _79 = _62
+67:46-67:60: @77[3]: _78 = Ne(move _79, const 9_i32)"><span class="annotation">@77⦊</span>countdown != 9<span class="annotation">⦉@77</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="68:13-68:26: @83[0]: _62 = const 0_i32
+67:61-69:10: @83[1]: _71 = const ()"><span class="annotation">@83⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="68:13-68:26: @83[0]: _62 = const 0_i32
+67:61-69:10: @83[1]: _71 = const ()">            countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="68:13-68:26: @83[0]: _62 = const 0_i32
+67:61-69:10: @83[1]: _71 = const ()">        }<span class="annotation">⦉@83</span></span></span><span><span class="code odd" style="--layer: 1" title="69:10-69:10: @84[0]: _71 = const ()"><span class="annotation">@84⦊</span>‸<span class="annotation">⦉@84</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="70:9-70:23: @85[2]: _80 = CheckedSub(_62, const 5_i32)
+70:9-70:23: @86[0]: _62 = move (_80.0: i32)"><span class="annotation">@85,86⦊</span>countdown -= 5<span class="annotation">⦉@85,86</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    } else {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        let </span><span><span class="code odd" style="--layer: 1" title="72:35-72:44: @89[1]: _82 = _62
-72:13-72:32: @89[2]: FakeRead(ForLet, _82)
-73:18-73:27: @89[9]: _113 = const main::promoted[1]
-73:18-73:27: @89[10]: _88 = &amp;(*_113)
-73:18-73:27: @89[11]: _87 = &amp;(*_88)
-73:18-73:27: @89[12]: _86 = move _87 as &amp;[&amp;str] (Pointer(Unsize))
-73:9-73:29: @89[18]: _94 = ()
-73:9-73:29: @89[19]: FakeRead(ForMatchedPlace, _94)
-73:9-73:29: @89[20]: _112 = const main::promoted[0]
-73:9-73:29: @89[21]: _92 = &amp;(*_112)
-73:9-73:29: @89[22]: _91 = &amp;(*_92)
-73:9-73:29: @89[23]: _90 = move _91 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-73:9-73:29: @89.Call: _85 = Arguments::new_v1(move _86, move _90) -&gt; [return: bb104, unwind: bb132]
-73:9-73:29: @104.Call: _84 = _print(move _85) -&gt; [return: bb105, unwind: bb132]
-73:9-73:29: @105[5]: _83 = const ()
-74:9-74:15: @105[7]: _0 = const ()"><span class="annotation">@89,104,105⦊</span>should_be_reachable = countdown;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="72:35-72:44: @89[1]: _82 = _62
-72:13-72:32: @89[2]: FakeRead(ForLet, _82)
-73:18-73:27: @89[9]: _113 = const main::promoted[1]
-73:18-73:27: @89[10]: _88 = &amp;(*_113)
-73:18-73:27: @89[11]: _87 = &amp;(*_88)
-73:18-73:27: @89[12]: _86 = move _87 as &amp;[&amp;str] (Pointer(Unsize))
-73:9-73:29: @89[18]: _94 = ()
-73:9-73:29: @89[19]: FakeRead(ForMatchedPlace, _94)
-73:9-73:29: @89[20]: _112 = const main::promoted[0]
-73:9-73:29: @89[21]: _92 = &amp;(*_112)
-73:9-73:29: @89[22]: _91 = &amp;(*_92)
-73:9-73:29: @89[23]: _90 = move _91 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-73:9-73:29: @89.Call: _85 = Arguments::new_v1(move _86, move _90) -&gt; [return: bb104, unwind: bb132]
-73:9-73:29: @104.Call: _84 = _print(move _85) -&gt; [return: bb105, unwind: bb132]
-73:9-73:29: @105[5]: _83 = const ()
-74:9-74:15: @105[7]: _0 = const ()">        println!("reached");</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="72:35-72:44: @89[1]: _82 = _62
-72:13-72:32: @89[2]: FakeRead(ForLet, _82)
-73:18-73:27: @89[9]: _113 = const main::promoted[1]
-73:18-73:27: @89[10]: _88 = &amp;(*_113)
-73:18-73:27: @89[11]: _87 = &amp;(*_88)
-73:18-73:27: @89[12]: _86 = move _87 as &amp;[&amp;str] (Pointer(Unsize))
-73:9-73:29: @89[18]: _94 = ()
-73:9-73:29: @89[19]: FakeRead(ForMatchedPlace, _94)
-73:9-73:29: @89[20]: _112 = const main::promoted[0]
-73:9-73:29: @89[21]: _92 = &amp;(*_112)
-73:9-73:29: @89[22]: _91 = &amp;(*_92)
-73:9-73:29: @89[23]: _90 = move _91 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-73:9-73:29: @89.Call: _85 = Arguments::new_v1(move _86, move _90) -&gt; [return: bb104, unwind: bb132]
-73:9-73:29: @104.Call: _84 = _print(move _85) -&gt; [return: bb105, unwind: bb132]
-73:9-73:29: @105[5]: _83 = const ()
-74:9-74:15: @105[7]: _0 = const ()">        return<span class="annotation">⦉@89,104,105</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">        let </span><span><span class="code odd" style="--layer: 1" title="72:35-72:44: @74[1]: _82 = _62
+72:13-72:32: @74[2]: FakeRead(ForLet, _82)
+73:18-73:27: @74[9]: _113 = const main::promoted[1]
+73:18-73:27: @74[10]: _88 = &amp;(*_113)
+73:18-73:27: @74[11]: _87 = &amp;(*_88)
+73:18-73:27: @74[12]: _86 = move _87 as &amp;[&amp;str] (Pointer(Unsize))
+73:9-73:29: @74[18]: _94 = ()
+73:9-73:29: @74[19]: FakeRead(ForMatchedPlace, _94)
+73:9-73:29: @74[20]: _112 = const main::promoted[0]
+73:9-73:29: @74[21]: _92 = &amp;(*_112)
+73:9-73:29: @74[22]: _91 = &amp;(*_92)
+73:9-73:29: @74[23]: _90 = move _91 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+73:9-73:29: @74.Call: _85 = Arguments::new_v1(move _86, move _90) -&gt; [return: bb87, unwind: bb112]
+73:9-73:29: @87.Call: _84 = _print(move _85) -&gt; [return: bb88, unwind: bb112]
+73:9-73:29: @88[5]: _83 = const ()
+74:9-74:15: @88[7]: _0 = const ()"><span class="annotation">@74,87,88⦊</span>should_be_reachable = countdown;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="72:35-72:44: @74[1]: _82 = _62
+72:13-72:32: @74[2]: FakeRead(ForLet, _82)
+73:18-73:27: @74[9]: _113 = const main::promoted[1]
+73:18-73:27: @74[10]: _88 = &amp;(*_113)
+73:18-73:27: @74[11]: _87 = &amp;(*_88)
+73:18-73:27: @74[12]: _86 = move _87 as &amp;[&amp;str] (Pointer(Unsize))
+73:9-73:29: @74[18]: _94 = ()
+73:9-73:29: @74[19]: FakeRead(ForMatchedPlace, _94)
+73:9-73:29: @74[20]: _112 = const main::promoted[0]
+73:9-73:29: @74[21]: _92 = &amp;(*_112)
+73:9-73:29: @74[22]: _91 = &amp;(*_92)
+73:9-73:29: @74[23]: _90 = move _91 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+73:9-73:29: @74.Call: _85 = Arguments::new_v1(move _86, move _90) -&gt; [return: bb87, unwind: bb112]
+73:9-73:29: @87.Call: _84 = _print(move _85) -&gt; [return: bb88, unwind: bb112]
+73:9-73:29: @88[5]: _83 = const ()
+74:9-74:15: @88[7]: _0 = const ()">        println!("reached");</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="72:35-72:44: @74[1]: _82 = _62
+72:13-72:32: @74[2]: FakeRead(ForLet, _82)
+73:18-73:27: @74[9]: _113 = const main::promoted[1]
+73:18-73:27: @74[10]: _88 = &amp;(*_113)
+73:18-73:27: @74[11]: _87 = &amp;(*_88)
+73:18-73:27: @74[12]: _86 = move _87 as &amp;[&amp;str] (Pointer(Unsize))
+73:9-73:29: @74[18]: _94 = ()
+73:9-73:29: @74[19]: FakeRead(ForMatchedPlace, _94)
+73:9-73:29: @74[20]: _112 = const main::promoted[0]
+73:9-73:29: @74[21]: _92 = &amp;(*_112)
+73:9-73:29: @74[22]: _91 = &amp;(*_92)
+73:9-73:29: @74[23]: _90 = move _91 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+73:9-73:29: @74.Call: _85 = Arguments::new_v1(move _86, move _90) -&gt; [return: bb87, unwind: bb112]
+73:9-73:29: @87.Call: _84 = _print(move _85) -&gt; [return: bb88, unwind: bb112]
+73:9-73:29: @88[5]: _83 = const ()
+74:9-74:15: @88[7]: _0 = const ()">        return<span class="annotation">⦉@74,87,88</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    };</span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="77:9-77:10: @127[0]: FakeRead(ForLet, _95)"><span class="annotation">@127⦊</span>w<span class="annotation">⦉@127</span></span></span><span class="code" style="--layer: 0"> = if </span><span><span class="code odd" style="--layer: 1" title="77:16-77:25: @106[5]: _97 = _62
-77:16-77:29: @106[6]: _96 = Gt(move _97, const 7_i32)
-77:16-77:29: @106[8]: FakeRead(ForMatchedPlace, _96)"><span class="annotation">@106⦊</span>countdown &gt; 7<span class="annotation">⦉@106</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="78:9-78:23: @109[0]: _98 = CheckedSub(_62, const 4_i32)
-78:9-78:23: @110[0]: _62 = move (_98.0: i32)
-77:30-79:6: @110[1]: _95 = const ()"><span class="annotation">@107,109,110⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="78:9-78:23: @109[0]: _98 = CheckedSub(_62, const 4_i32)
-78:9-78:23: @110[0]: _62 = move (_98.0: i32)
-77:30-79:6: @110[1]: _95 = const ()">        countdown -= 4;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="78:9-78:23: @109[0]: _98 = CheckedSub(_62, const 4_i32)
-78:9-78:23: @110[0]: _62 = move (_98.0: i32)
-77:30-79:6: @110[1]: _95 = const ()">    }<span class="annotation">⦉@107,109,110</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code odd" style="--layer: 1" title="79:15-79:24: @108[2]: _100 = _62
-79:15-79:28: @108[3]: _99 = Gt(move _100, const 2_i32)
-79:15-79:28: @108[5]: FakeRead(ForMatchedPlace, _99)"><span class="annotation">@108⦊</span>countdown &gt; 2<span class="annotation">⦉@108</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code even" style="--layer: 1" title="80:12-80:21: @113[5]: _105 = _62
-80:12-80:25: @113[6]: _104 = Lt(move _105, const 1_i32)"><span class="annotation">@111,113⦊</span>countdown &lt; 1<span class="annotation">⦉@111,113</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="80:29-80:38: @120[2]: _107 = _62
-80:29-80:42: @120[3]: _106 = Gt(move _107, const 5_i32)"><span class="annotation">@120⦊</span>countdown &gt; 5<span class="annotation">⦉@120</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="80:46-80:55: @116[2]: _109 = _62
-80:46-80:60: @116[3]: _108 = Ne(move _109, const 9_i32)"><span class="annotation">@116⦊</span>countdown != 9<span class="annotation">⦉@116</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="81:13-81:26: @124[0]: _62 = const 0_i32
-80:61-82:10: @124[1]: _101 = const ()"><span class="annotation">@122,124⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="81:13-81:26: @124[0]: _62 = const 0_i32
-80:61-82:10: @124[1]: _101 = const ()">            countdown = 0;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="81:13-81:26: @124[0]: _62 = const 0_i32
-80:61-82:10: @124[1]: _101 = const ()">        }<span class="annotation">⦉@122,124</span></span></span><span><span class="code even" style="--layer: 1" title="82:10-82:10: @123[0]: _101 = const ()"><span class="annotation">@123⦊</span>‸<span class="annotation">⦉@123</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="83:9-83:23: @125[2]: _110 = CheckedSub(_62, const 5_i32)
-83:9-83:23: @126[0]: _62 = move (_110.0: i32)"><span class="annotation">@125,126⦊</span>countdown -= 5<span class="annotation">⦉@125,126</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="77:9-77:10: @107[1]: FakeRead(ForLet, _95)"><span class="annotation">@107⦊</span>w<span class="annotation">⦉@107</span></span></span><span class="code" style="--layer: 0"> = if </span><span><span class="code odd" style="--layer: 1" title="77:16-77:25: @89[5]: _97 = _62
+77:16-77:29: @89[6]: _96 = Gt(move _97, const 7_i32)"><span class="annotation">@89⦊</span>countdown &gt; 7<span class="annotation">⦉@89</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="78:9-78:23: @90[0]: _98 = CheckedSub(_62, const 4_i32)
+78:9-78:23: @92[0]: _62 = move (_98.0: i32)
+77:30-79:6: @92[1]: _95 = const ()"><span class="annotation">@90,92⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="78:9-78:23: @90[0]: _98 = CheckedSub(_62, const 4_i32)
+78:9-78:23: @92[0]: _62 = move (_98.0: i32)
+77:30-79:6: @92[1]: _95 = const ()">        countdown -= 4;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="78:9-78:23: @90[0]: _98 = CheckedSub(_62, const 4_i32)
+78:9-78:23: @92[0]: _62 = move (_98.0: i32)
+77:30-79:6: @92[1]: _95 = const ()">    }<span class="annotation">⦉@90,92</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code odd" style="--layer: 1" title="79:15-79:24: @91[2]: _100 = _62
+79:15-79:28: @91[3]: _99 = Gt(move _100, const 2_i32)"><span class="annotation">@91⦊</span>countdown &gt; 2<span class="annotation">⦉@91</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code even" style="--layer: 1" title="80:12-80:21: @93[5]: _105 = _62
+80:12-80:25: @93[6]: _104 = Lt(move _105, const 1_i32)"><span class="annotation">@93⦊</span>countdown &lt; 1<span class="annotation">⦉@93</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="80:29-80:38: @101[2]: _107 = _62
+80:29-80:42: @101[3]: _106 = Gt(move _107, const 5_i32)"><span class="annotation">@101⦊</span>countdown &gt; 5<span class="annotation">⦉@101</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="80:46-80:55: @97[2]: _109 = _62
+80:46-80:60: @97[3]: _108 = Ne(move _109, const 9_i32)"><span class="annotation">@97⦊</span>countdown != 9<span class="annotation">⦉@97</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="81:13-81:26: @103[0]: _62 = const 0_i32
+80:61-82:10: @103[1]: _101 = const ()"><span class="annotation">@103⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="81:13-81:26: @103[0]: _62 = const 0_i32
+80:61-82:10: @103[1]: _101 = const ()">            countdown = 0;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="81:13-81:26: @103[0]: _62 = const 0_i32
+80:61-82:10: @103[1]: _101 = const ()">        }<span class="annotation">⦉@103</span></span></span><span><span class="code even" style="--layer: 1" title="82:10-82:10: @104[0]: _101 = const ()"><span class="annotation">@104⦊</span>‸<span class="annotation">⦉@104</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="83:9-83:23: @105[2]: _110 = CheckedSub(_62, const 5_i32)
+83:9-83:23: @106[0]: _62 = move (_110.0: i32)"><span class="annotation">@105,106⦊</span>countdown -= 5<span class="annotation">⦉@105,106</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    } else {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="85:9-85:15: @112[0]: _0 = const ()"><span class="annotation">@112⦊</span>return<span class="annotation">⦉@112</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="85:9-85:15: @94[0]: _0 = const ()"><span class="annotation">@94⦊</span>return<span class="annotation">⦉@94</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    };</span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="87:2-87:2: @131.Return: return"><span class="annotation">@131⦊</span>‸<span class="annotation">⦉@131</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="87:2-87:2: @111.Return: return"><span class="annotation">@111⦊</span>‸<span class="annotation">⦉@111</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.main.-------.InstrumentCoverage.0.html
index 59d0060..421fe27 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.main.-------.InstrumentCoverage.0.html
@@ -69,83 +69,75 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 26"><span class="line"><span><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+<div class="code" style="counter-reset: line 26"><span class="line"><span><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 31:19-31:35: @1[0]: _3 = &amp;_4
-31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 31:19-31:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 31:9-31:16: @2[3]: FakeRead(ForLet, _1)
 33:25-33:26: @3[2]: _5 = const 0_i32
 33:9-33:22: @3[3]: FakeRead(ForLet, _5)
-34:8-34:15: @3[5]: _6 = _1
-34:8-34:15: @3[6]: FakeRead(ForMatchedPlace, _6)"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+34:8-34:15: @3[5]: _6 = _1"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 31:19-31:35: @1[0]: _3 = &amp;_4
-31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 31:19-31:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 31:9-31:16: @2[3]: FakeRead(ForLet, _1)
 33:25-33:26: @3[2]: _5 = const 0_i32
 33:9-33:22: @3[3]: FakeRead(ForLet, _5)
-34:8-34:15: @3[5]: _6 = _1
-34:8-34:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+34:8-34:15: @3[5]: _6 = _1">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 31:19-31:35: @1[0]: _3 = &amp;_4
-31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 31:19-31:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 31:9-31:16: @2[3]: FakeRead(ForLet, _1)
 33:25-33:26: @3[2]: _5 = const 0_i32
 33:9-33:22: @3[3]: FakeRead(ForLet, _5)
-34:8-34:15: @3[5]: _6 = _1
-34:8-34:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+34:8-34:15: @3[5]: _6 = _1">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 31:19-31:35: @1[0]: _3 = &amp;_4
-31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 31:19-31:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 31:9-31:16: @2[3]: FakeRead(ForLet, _1)
 33:25-33:26: @3[2]: _5 = const 0_i32
 33:9-33:22: @3[3]: FakeRead(ForLet, _5)
-34:8-34:15: @3[5]: _6 = _1
-34:8-34:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    // dependent conditions.</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+34:8-34:15: @3[5]: _6 = _1">    // dependent conditions.</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 31:19-31:35: @1[0]: _3 = &amp;_4
-31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 31:19-31:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 31:9-31:16: @2[3]: FakeRead(ForLet, _1)
 33:25-33:26: @3[2]: _5 = const 0_i32
 33:9-33:22: @3[3]: FakeRead(ForLet, _5)
-34:8-34:15: @3[5]: _6 = _1
-34:8-34:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    let is_true = std::env::args().len() == 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+34:8-34:15: @3[5]: _6 = _1">    let is_true = std::env::args().len() == 1;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 31:19-31:35: @1[0]: _3 = &amp;_4
-31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 31:19-31:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 31:9-31:16: @2[3]: FakeRead(ForLet, _1)
 33:25-33:26: @3[2]: _5 = const 0_i32
 33:9-33:22: @3[3]: FakeRead(ForLet, _5)
-34:8-34:15: @3[5]: _6 = _1
-34:8-34:15: @3[6]: FakeRead(ForMatchedPlace, _6)"></span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+34:8-34:15: @3[5]: _6 = _1"></span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 31:19-31:35: @1[0]: _3 = &amp;_4
-31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 31:19-31:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 31:9-31:16: @2[3]: FakeRead(ForLet, _1)
 33:25-33:26: @3[2]: _5 = const 0_i32
 33:9-33:22: @3[3]: FakeRead(ForLet, _5)
-34:8-34:15: @3[5]: _6 = _1
-34:8-34:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    let mut countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+34:8-34:15: @3[5]: _6 = _1">    let mut countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:19-31:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 31:19-31:35: @1[0]: _3 = &amp;_4
-31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+31:19-31:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 31:19-31:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 31:9-31:16: @2[3]: FakeRead(ForLet, _1)
 33:25-33:26: @3[2]: _5 = const 0_i32
 33:9-33:22: @3[3]: FakeRead(ForLet, _5)
-34:8-34:15: @3[5]: _6 = _1
-34:8-34:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="35:9-35:23: @6[0]: _5 = const 10_i32
-34:16-36:6: @6[1]: _0 = const ()"><span class="annotation">@4,6⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="35:9-35:23: @6[0]: _5 = const 10_i32
-34:16-36:6: @6[1]: _0 = const ()">        countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="35:9-35:23: @6[0]: _5 = const 10_i32
-34:16-36:6: @6[1]: _0 = const ()">    }<span class="annotation">⦉@4,6</span></span></span><span><span class="code even" style="--layer: 1" title="36:6-36:6: @5[0]: _0 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="37:2-37:2: @7.Return: return"><span class="annotation">@7⦊</span>‸<span class="annotation">⦉@7</span></span></span></span></div>
+34:8-34:15: @3[5]: _6 = _1">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="35:9-35:23: @4[0]: _5 = const 10_i32
+34:16-36:6: @4[1]: _0 = const ()"><span class="annotation">@4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="35:9-35:23: @4[0]: _5 = const 10_i32
+34:16-36:6: @4[1]: _0 = const ()">        countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="35:9-35:23: @4[0]: _5 = const 10_i32
+34:16-36:6: @4[1]: _0 = const ()">    }<span class="annotation">⦉@4</span></span></span><span><span class="code even" style="--layer: 1" title="36:6-36:6: @5[0]: _0 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="37:2-37:2: @6.Return: return"><span class="annotation">@6⦊</span>‸<span class="annotation">⦉@6</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_fn.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_fn.-------.InstrumentCoverage.0.html
index 1a535b9..ff3493c 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_fn.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_fn.-------.InstrumentCoverage.0.html
@@ -69,83 +69,75 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 14"><span class="line"><span><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+<div class="code" style="counter-reset: line 14"><span class="line"><span><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 19:19-19:35: @1[0]: _3 = &amp;_4
-19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 19:19-19:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 19:9-19:16: @2[3]: FakeRead(ForLet, _1)
 21:25-21:26: @3[2]: _5 = const 0_i32
 21:9-21:22: @3[3]: FakeRead(ForLet, _5)
-22:8-22:15: @3[5]: _6 = _1
-22:8-22:15: @3[6]: FakeRead(ForMatchedPlace, _6)"><span class="annotation">@0,1,2,3⦊</span>fn unused_fn() {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+22:8-22:15: @3[5]: _6 = _1"><span class="annotation">@0,1,2,3⦊</span>fn unused_fn() {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 19:19-19:35: @1[0]: _3 = &amp;_4
-19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 19:19-19:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 19:9-19:16: @2[3]: FakeRead(ForLet, _1)
 21:25-21:26: @3[2]: _5 = const 0_i32
 21:9-21:22: @3[3]: FakeRead(ForLet, _5)
-22:8-22:15: @3[5]: _6 = _1
-22:8-22:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+22:8-22:15: @3[5]: _6 = _1">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 19:19-19:35: @1[0]: _3 = &amp;_4
-19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 19:19-19:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 19:9-19:16: @2[3]: FakeRead(ForLet, _1)
 21:25-21:26: @3[2]: _5 = const 0_i32
 21:9-21:22: @3[3]: FakeRead(ForLet, _5)
-22:8-22:15: @3[5]: _6 = _1
-22:8-22:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+22:8-22:15: @3[5]: _6 = _1">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 19:19-19:35: @1[0]: _3 = &amp;_4
-19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 19:19-19:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 19:9-19:16: @2[3]: FakeRead(ForLet, _1)
 21:25-21:26: @3[2]: _5 = const 0_i32
 21:9-21:22: @3[3]: FakeRead(ForLet, _5)
-22:8-22:15: @3[5]: _6 = _1
-22:8-22:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    // dependent conditions.</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+22:8-22:15: @3[5]: _6 = _1">    // dependent conditions.</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 19:19-19:35: @1[0]: _3 = &amp;_4
-19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 19:19-19:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 19:9-19:16: @2[3]: FakeRead(ForLet, _1)
 21:25-21:26: @3[2]: _5 = const 0_i32
 21:9-21:22: @3[3]: FakeRead(ForLet, _5)
-22:8-22:15: @3[5]: _6 = _1
-22:8-22:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    let is_true = std::env::args().len() == 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+22:8-22:15: @3[5]: _6 = _1">    let is_true = std::env::args().len() == 1;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 19:19-19:35: @1[0]: _3 = &amp;_4
-19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 19:19-19:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 19:9-19:16: @2[3]: FakeRead(ForLet, _1)
 21:25-21:26: @3[2]: _5 = const 0_i32
 21:9-21:22: @3[3]: FakeRead(ForLet, _5)
-22:8-22:15: @3[5]: _6 = _1
-22:8-22:15: @3[6]: FakeRead(ForMatchedPlace, _6)"></span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+22:8-22:15: @3[5]: _6 = _1"></span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 19:19-19:35: @1[0]: _3 = &amp;_4
-19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 19:19-19:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 19:9-19:16: @2[3]: FakeRead(ForLet, _1)
 21:25-21:26: @3[2]: _5 = const 0_i32
 21:9-21:22: @3[3]: FakeRead(ForLet, _5)
-22:8-22:15: @3[5]: _6 = _1
-22:8-22:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    let mut countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+22:8-22:15: @3[5]: _6 = _1">    let mut countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="19:19-19:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 19:19-19:35: @1[0]: _3 = &amp;_4
-19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+19:19-19:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 19:19-19:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 19:9-19:16: @2[3]: FakeRead(ForLet, _1)
 21:25-21:26: @3[2]: _5 = const 0_i32
 21:9-21:22: @3[3]: FakeRead(ForLet, _5)
-22:8-22:15: @3[5]: _6 = _1
-22:8-22:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="23:9-23:23: @6[0]: _5 = const 10_i32
-22:16-24:6: @6[1]: _0 = const ()"><span class="annotation">@4,6⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="23:9-23:23: @6[0]: _5 = const 10_i32
-22:16-24:6: @6[1]: _0 = const ()">        countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="23:9-23:23: @6[0]: _5 = const 10_i32
-22:16-24:6: @6[1]: _0 = const ()">    }<span class="annotation">⦉@4,6</span></span></span><span><span class="code even" style="--layer: 1" title="24:6-24:6: @5[0]: _0 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="25:2-25:2: @7.Return: return"><span class="annotation">@7⦊</span>‸<span class="annotation">⦉@7</span></span></span></span></div>
+22:8-22:15: @3[5]: _6 = _1">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="23:9-23:23: @4[0]: _5 = const 10_i32
+22:16-24:6: @4[1]: _0 = const ()"><span class="annotation">@4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="23:9-23:23: @4[0]: _5 = const 10_i32
+22:16-24:6: @4[1]: _0 = const ()">        countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="23:9-23:23: @4[0]: _5 = const 10_i32
+22:16-24:6: @4[1]: _0 = const ()">    }<span class="annotation">⦉@4</span></span></span><span><span class="code even" style="--layer: 1" title="24:6-24:6: @5[0]: _0 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="25:2-25:2: @6.Return: return"><span class="annotation">@6⦊</span>‸<span class="annotation">⦉@6</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_pub_fn_not_in_library.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_pub_fn_not_in_library.-------.InstrumentCoverage.0.html
index 6eff51a..829113e 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_pub_fn_not_in_library.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_pub_fn_not_in_library.-------.InstrumentCoverage.0.html
@@ -69,83 +69,75 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[5]: _6 = _1
-10:8-10:15: @3[6]: FakeRead(ForMatchedPlace, _6)"><span class="annotation">@0,1,2,3⦊</span>pub fn unused_pub_fn_not_in_library() {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+10:8-10:15: @3[5]: _6 = _1"><span class="annotation">@0,1,2,3⦊</span>pub fn unused_pub_fn_not_in_library() {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[5]: _6 = _1
-10:8-10:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+10:8-10:15: @3[5]: _6 = _1">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[5]: _6 = _1
-10:8-10:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+10:8-10:15: @3[5]: _6 = _1">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[5]: _6 = _1
-10:8-10:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    // dependent conditions.</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+10:8-10:15: @3[5]: _6 = _1">    // dependent conditions.</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[5]: _6 = _1
-10:8-10:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    let is_true = std::env::args().len() == 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+10:8-10:15: @3[5]: _6 = _1">    let is_true = std::env::args().len() == 1;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[5]: _6 = _1
-10:8-10:15: @3[6]: FakeRead(ForMatchedPlace, _6)"></span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+10:8-10:15: @3[5]: _6 = _1"></span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[5]: _6 = _1
-10:8-10:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    let mut countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+10:8-10:15: @3[5]: _6 = _1">    let mut countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[5]: _6 = _1
-10:8-10:15: @3[6]: FakeRead(ForMatchedPlace, _6)">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="11:9-11:23: @6[0]: _5 = const 10_i32
-10:16-12:6: @6[1]: _0 = const ()"><span class="annotation">@4,6⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:23: @6[0]: _5 = const 10_i32
-10:16-12:6: @6[1]: _0 = const ()">        countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:23: @6[0]: _5 = const 10_i32
-10:16-12:6: @6[1]: _0 = const ()">    }<span class="annotation">⦉@4,6</span></span></span><span><span class="code even" style="--layer: 1" title="12:6-12:6: @5[0]: _0 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="13:2-13:2: @7.Return: return"><span class="annotation">@7⦊</span>‸<span class="annotation">⦉@7</span></span></span></span></div>
+10:8-10:15: @3[5]: _6 = _1">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="11:9-11:23: @4[0]: _5 = const 10_i32
+10:16-12:6: @4[1]: _0 = const ()"><span class="annotation">@4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:23: @4[0]: _5 = const 10_i32
+10:16-12:6: @4[1]: _0 = const ()">        countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:23: @4[0]: _5 = const 10_i32
+10:16-12:6: @4[1]: _0 = const ()">    }<span class="annotation">⦉@4</span></span></span><span><span class="code even" style="--layer: 1" title="12:6-12:6: @5[0]: _0 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="13:2-13:2: @6.Return: return"><span class="annotation">@6⦊</span>‸<span class="annotation">⦉@6</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html
index 8d07455..3566912 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html
@@ -69,59 +69,58 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 59"><span class="line"><span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>fn main() <span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">{</span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="61:8-61:12: @0[1]: _1 = const true
-61:8-61:12: @0[2]: FakeRead(ForMatchedPlace, _1)"><span class="annotation">@0⦊</span>true<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="62:9-62:26: @5[0]: _2 = const ()"><span class="annotation">@5⦊</span></span></span><span class="code even" style="--layer: 2" title="62:9-62:26: @6[5]: _75 = const main::promoted[3]
-62:9-62:26: @6[6]: _18 = &amp;(*_75)
-62:9-62:26: @6[7]: _17 = &amp;(*_18)
-62:9-62:26: @6[8]: _16 = move _17 as &amp;[&amp;str] (Pointer(Unsize))
-62:9-62:26: @6[17]: _26 = &amp;(*_8)
-62:9-62:26: @6[18]: _25 = &amp;_26
-62:9-62:26: @6[21]: _28 = &amp;(*_9)
-62:9-62:26: @6[22]: _27 = &amp;_28
-62:9-62:26: @6[23]: _24 = (move _25, move _27)
-62:9-62:26: @6[26]: FakeRead(ForMatchedPlace, _24)
-62:9-62:26: @6[28]: _29 = (_24.0: &amp;&amp;i32)
-62:9-62:26: @6[30]: _30 = (_24.1: &amp;&amp;i32)
-62:9-62:26: @6[33]: _32 = &amp;(*_29)
-62:9-62:26: @6[35]: _33 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-62:9-62:26: @6.Call: _31 = ArgumentV1::new::&lt;&amp;i32&gt;(move _32, move _33) -&gt; [return: bb7, unwind: bb17]
-62:9-62:26: @7[4]: _35 = &amp;(*_30)
-62:9-62:26: @7[6]: _36 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-62:9-62:26: @7.Call: _34 = ArgumentV1::new::&lt;&amp;i32&gt;(move _35, move _36) -&gt; [return: bb8, unwind: bb17]
-62:9-62:26: @8[2]: _23 = [move _31, move _34]
-62:9-62:26: @8[7]: _22 = &amp;_23
-62:9-62:26: @8[8]: _21 = &amp;(*_22)
-62:9-62:26: @8[9]: _20 = move _21 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-62:9-62:26: @8.Call: _15 = Arguments::new_v1(move _16, move _20) -&gt; [return: bb9, unwind: bb17]
-62:9-62:26: @9.Call: core::panicking::panic_fmt(move _15) -&gt; bb17"><span class="annotation">@4,6,7,8,9⦊</span>assert_eq!(1, 1);<span class="annotation">⦉@4,6,7,8,9</span></span><span><span class="code odd" style="--layer: 1" title="62:9-62:26: @5[0]: _2 = const ()"><span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+<div class="code" style="counter-reset: line 72"><span class="line"><span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>fn main() <span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">{</span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="74:8-74:12: @0[1]: _1 = const true"><span class="annotation">@0⦊</span>true<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="75:9-75:26: @4[0]: _2 = const ()"><span class="annotation">@4⦊</span></span></span><span class="code even" style="--layer: 2" title="75:9-75:26: @3[5]: _75 = const main::promoted[3]
+75:9-75:26: @3[6]: _18 = &amp;(*_75)
+75:9-75:26: @3[7]: _17 = &amp;(*_18)
+75:9-75:26: @3[8]: _16 = move _17 as &amp;[&amp;str] (Pointer(Unsize))
+75:9-75:26: @3[17]: _26 = &amp;(*_8)
+75:9-75:26: @3[18]: _25 = &amp;_26
+75:9-75:26: @3[21]: _28 = &amp;(*_9)
+75:9-75:26: @3[22]: _27 = &amp;_28
+75:9-75:26: @3[23]: _24 = (move _25, move _27)
+75:9-75:26: @3[26]: FakeRead(ForMatchedPlace, _24)
+75:9-75:26: @3[28]: _29 = (_24.0: &amp;&amp;i32)
+75:9-75:26: @3[30]: _30 = (_24.1: &amp;&amp;i32)
+75:9-75:26: @3[33]: _32 = &amp;(*_29)
+75:9-75:26: @3[35]: _33 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+75:9-75:26: @3.Call: _31 = ArgumentV1::new::&lt;&amp;i32&gt;(move _32, move _33) -&gt; [return: bb5, unwind: bb14]
+75:9-75:26: @5[4]: _35 = &amp;(*_30)
+75:9-75:26: @5[6]: _36 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+75:9-75:26: @5.Call: _34 = ArgumentV1::new::&lt;&amp;i32&gt;(move _35, move _36) -&gt; [return: bb6, unwind: bb14]
+75:9-75:26: @6[2]: _23 = [move _31, move _34]
+75:9-75:26: @6[7]: _22 = &amp;_23
+75:9-75:26: @6[8]: _21 = &amp;(*_22)
+75:9-75:26: @6[9]: _20 = move _21 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+75:9-75:26: @6.Call: _15 = Arguments::new_v1(move _16, move _20) -&gt; [return: bb7, unwind: bb14]
+75:9-75:26: @7.Call: core::panicking::panic_fmt(move _15) -&gt; bb14"><span class="annotation">@3,5,6,7⦊</span>assert_eq!(1, 1);<span class="annotation">⦉@3,5,6,7</span></span><span><span class="code odd" style="--layer: 1" title="75:9-75:26: @4[0]: _2 = const ()"><span class="annotation">⦉@4</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    } else {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="64:9-64:26: @11[0]: _37 = const ()"><span class="annotation">@11⦊</span></span></span><span class="code even" style="--layer: 2" title="64:9-64:26: @12[5]: _72 = const main::promoted[0]
-64:9-64:26: @12[6]: _53 = &amp;(*_72)
-64:9-64:26: @12[7]: _52 = &amp;(*_53)
-64:9-64:26: @12[8]: _51 = move _52 as &amp;[&amp;str] (Pointer(Unsize))
-64:9-64:26: @12[17]: _61 = &amp;(*_43)
-64:9-64:26: @12[18]: _60 = &amp;_61
-64:9-64:26: @12[21]: _63 = &amp;(*_44)
-64:9-64:26: @12[22]: _62 = &amp;_63
-64:9-64:26: @12[23]: _59 = (move _60, move _62)
-64:9-64:26: @12[26]: FakeRead(ForMatchedPlace, _59)
-64:9-64:26: @12[28]: _64 = (_59.0: &amp;&amp;i32)
-64:9-64:26: @12[30]: _65 = (_59.1: &amp;&amp;i32)
-64:9-64:26: @12[33]: _67 = &amp;(*_64)
-64:9-64:26: @12[35]: _68 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-64:9-64:26: @12.Call: _66 = ArgumentV1::new::&lt;&amp;i32&gt;(move _67, move _68) -&gt; [return: bb13, unwind: bb17]
-64:9-64:26: @13[4]: _70 = &amp;(*_65)
-64:9-64:26: @13[6]: _71 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-64:9-64:26: @13.Call: _69 = ArgumentV1::new::&lt;&amp;i32&gt;(move _70, move _71) -&gt; [return: bb14, unwind: bb17]
-64:9-64:26: @14[2]: _58 = [move _66, move _69]
-64:9-64:26: @14[7]: _57 = &amp;_58
-64:9-64:26: @14[8]: _56 = &amp;(*_57)
-64:9-64:26: @14[9]: _55 = move _56 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-64:9-64:26: @14.Call: _50 = Arguments::new_v1(move _51, move _55) -&gt; [return: bb15, unwind: bb17]
-64:9-64:26: @15.Call: core::panicking::panic_fmt(move _50) -&gt; bb17"><span class="annotation">@10,12,13,14,15⦊</span>assert_eq!(1, 2);<span class="annotation">⦉@10,12,13,14,15</span></span><span><span class="code even" style="--layer: 1" title="64:9-64:26: @11[0]: _37 = const ()"><span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="77:9-77:26: @9[0]: _37 = const ()"><span class="annotation">@9⦊</span></span></span><span class="code even" style="--layer: 2" title="77:9-77:26: @8[5]: _72 = const main::promoted[0]
+77:9-77:26: @8[6]: _53 = &amp;(*_72)
+77:9-77:26: @8[7]: _52 = &amp;(*_53)
+77:9-77:26: @8[8]: _51 = move _52 as &amp;[&amp;str] (Pointer(Unsize))
+77:9-77:26: @8[17]: _61 = &amp;(*_43)
+77:9-77:26: @8[18]: _60 = &amp;_61
+77:9-77:26: @8[21]: _63 = &amp;(*_44)
+77:9-77:26: @8[22]: _62 = &amp;_63
+77:9-77:26: @8[23]: _59 = (move _60, move _62)
+77:9-77:26: @8[26]: FakeRead(ForMatchedPlace, _59)
+77:9-77:26: @8[28]: _64 = (_59.0: &amp;&amp;i32)
+77:9-77:26: @8[30]: _65 = (_59.1: &amp;&amp;i32)
+77:9-77:26: @8[33]: _67 = &amp;(*_64)
+77:9-77:26: @8[35]: _68 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+77:9-77:26: @8.Call: _66 = ArgumentV1::new::&lt;&amp;i32&gt;(move _67, move _68) -&gt; [return: bb10, unwind: bb14]
+77:9-77:26: @10[4]: _70 = &amp;(*_65)
+77:9-77:26: @10[6]: _71 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+77:9-77:26: @10.Call: _69 = ArgumentV1::new::&lt;&amp;i32&gt;(move _70, move _71) -&gt; [return: bb11, unwind: bb14]
+77:9-77:26: @11[2]: _58 = [move _66, move _69]
+77:9-77:26: @11[7]: _57 = &amp;_58
+77:9-77:26: @11[8]: _56 = &amp;(*_57)
+77:9-77:26: @11[9]: _55 = move _56 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+77:9-77:26: @11.Call: _50 = Arguments::new_v1(move _51, move _55) -&gt; [return: bb12, unwind: bb14]
+77:9-77:26: @12.Call: core::panicking::panic_fmt(move _50) -&gt; bb14"><span class="annotation">@8,10,11,12⦊</span>assert_eq!(1, 2);<span class="annotation">⦉@8,10,11,12</span></span><span><span class="code even" style="--layer: 1" title="77:9-77:26: @9[0]: _37 = const ()"><span class="annotation">⦉@9</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="66:2-66:2: @16.Return: return"><span class="annotation">@16⦊</span>‸<span class="annotation">⦉@16</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="79:2-79:2: @13.Return: return"><span class="annotation">@13⦊</span>‸<span class="annotation">⦉@13</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html
index ae119d9..02c25cc 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html
@@ -71,103 +71,103 @@
 <body>
 <div class="code" style="counter-reset: line 1"><span class="line"><span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>pub fn fn_run_in_doctests(conditional: usize) <span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">{</span></span>
 <span class="line"><span class="code" style="--layer: 0">    match </span><span><span class="code even" style="--layer: 1" title="3:11-3:22: @0[0]: FakeRead(ForMatchedPlace, _1)"><span class="annotation">@0⦊</span>conditional<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        1 =&gt; </span><span><span class="code odd" style="--layer: 1" title="4:14-4:30: @7[0]: _0 = const ()"><span class="annotation">@7⦊</span></span></span><span class="code even" style="--layer: 2" title="4:14-4:30: @8[5]: _138 = const fn_run_in_doctests::promoted[0]
-4:14-4:30: @8[6]: _17 = &amp;(*_138)
-4:14-4:30: @8[7]: _16 = &amp;(*_17)
-4:14-4:30: @8[8]: _15 = move _16 as &amp;[&amp;str] (Pointer(Unsize))
-4:14-4:30: @8[17]: _25 = &amp;(*_7)
-4:14-4:30: @8[18]: _24 = &amp;_25
-4:14-4:30: @8[21]: _27 = &amp;(*_8)
-4:14-4:30: @8[22]: _26 = &amp;_27
-4:14-4:30: @8[23]: _23 = (move _24, move _26)
-4:14-4:30: @8[26]: FakeRead(ForMatchedPlace, _23)
-4:14-4:30: @8[28]: _28 = (_23.0: &amp;&amp;i32)
-4:14-4:30: @8[30]: _29 = (_23.1: &amp;&amp;i32)
-4:14-4:30: @8[33]: _31 = &amp;(*_28)
-4:14-4:30: @8[35]: _32 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-4:14-4:30: @8.Call: _30 = ArgumentV1::new::&lt;&amp;i32&gt;(move _31, move _32) -&gt; [return: bb9, unwind: bb33]
-4:14-4:30: @9[4]: _34 = &amp;(*_29)
-4:14-4:30: @9[6]: _35 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-4:14-4:30: @9.Call: _33 = ArgumentV1::new::&lt;&amp;i32&gt;(move _34, move _35) -&gt; [return: bb10, unwind: bb33]
-4:14-4:30: @10[2]: _22 = [move _30, move _33]
-4:14-4:30: @10[7]: _21 = &amp;_22
-4:14-4:30: @10[8]: _20 = &amp;(*_21)
-4:14-4:30: @10[9]: _19 = move _20 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-4:14-4:30: @10.Call: _14 = Arguments::new_v1(move _15, move _19) -&gt; [return: bb11, unwind: bb33]
-4:14-4:30: @11.Call: core::panicking::panic_fmt(move _14) -&gt; bb33"><span class="annotation">@6,8,9,10,11⦊</span>assert_eq!(1, 1)<span class="annotation">⦉@6,8,9,10,11</span></span><span><span class="code odd" style="--layer: 1" title="4:14-4:30: @7[0]: _0 = const ()"><span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0">, // this is run,</span></span>
-<span class="line"><span class="code" style="--layer: 0">        2 =&gt; </span><span><span class="code even" style="--layer: 1" title="5:14-5:30: @14[0]: _0 = const ()"><span class="annotation">@14⦊</span></span></span><span class="code even" style="--layer: 2" title="5:14-5:30: @15[5]: _141 = const fn_run_in_doctests::promoted[3]
-5:14-5:30: @15[6]: _51 = &amp;(*_141)
-5:14-5:30: @15[7]: _50 = &amp;(*_51)
-5:14-5:30: @15[8]: _49 = move _50 as &amp;[&amp;str] (Pointer(Unsize))
-5:14-5:30: @15[17]: _59 = &amp;(*_41)
-5:14-5:30: @15[18]: _58 = &amp;_59
-5:14-5:30: @15[21]: _61 = &amp;(*_42)
-5:14-5:30: @15[22]: _60 = &amp;_61
-5:14-5:30: @15[23]: _57 = (move _58, move _60)
-5:14-5:30: @15[26]: FakeRead(ForMatchedPlace, _57)
-5:14-5:30: @15[28]: _62 = (_57.0: &amp;&amp;i32)
-5:14-5:30: @15[30]: _63 = (_57.1: &amp;&amp;i32)
-5:14-5:30: @15[33]: _65 = &amp;(*_62)
-5:14-5:30: @15[35]: _66 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-5:14-5:30: @15.Call: _64 = ArgumentV1::new::&lt;&amp;i32&gt;(move _65, move _66) -&gt; [return: bb16, unwind: bb33]
-5:14-5:30: @16[4]: _68 = &amp;(*_63)
-5:14-5:30: @16[6]: _69 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-5:14-5:30: @16.Call: _67 = ArgumentV1::new::&lt;&amp;i32&gt;(move _68, move _69) -&gt; [return: bb17, unwind: bb33]
-5:14-5:30: @17[2]: _56 = [move _64, move _67]
-5:14-5:30: @17[7]: _55 = &amp;_56
-5:14-5:30: @17[8]: _54 = &amp;(*_55)
-5:14-5:30: @17[9]: _53 = move _54 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-5:14-5:30: @17.Call: _48 = Arguments::new_v1(move _49, move _53) -&gt; [return: bb18, unwind: bb33]
-5:14-5:30: @18.Call: core::panicking::panic_fmt(move _48) -&gt; bb33"><span class="annotation">@13,15,16,17,18⦊</span>assert_eq!(1, 1)<span class="annotation">⦉@13,15,16,17,18</span></span><span><span class="code even" style="--layer: 1" title="5:14-5:30: @14[0]: _0 = const ()"><span class="annotation">⦉@14</span></span></span><span class="code" style="--layer: 0">, // this,</span></span>
-<span class="line"><span class="code" style="--layer: 0">        3 =&gt; </span><span><span class="code odd" style="--layer: 1" title="6:14-6:30: @21[0]: _0 = const ()"><span class="annotation">@21⦊</span></span></span><span class="code even" style="--layer: 2" title="6:14-6:30: @22[5]: _144 = const fn_run_in_doctests::promoted[6]
-6:14-6:30: @22[6]: _85 = &amp;(*_144)
-6:14-6:30: @22[7]: _84 = &amp;(*_85)
-6:14-6:30: @22[8]: _83 = move _84 as &amp;[&amp;str] (Pointer(Unsize))
-6:14-6:30: @22[17]: _93 = &amp;(*_75)
-6:14-6:30: @22[18]: _92 = &amp;_93
-6:14-6:30: @22[21]: _95 = &amp;(*_76)
-6:14-6:30: @22[22]: _94 = &amp;_95
-6:14-6:30: @22[23]: _91 = (move _92, move _94)
-6:14-6:30: @22[26]: FakeRead(ForMatchedPlace, _91)
-6:14-6:30: @22[28]: _96 = (_91.0: &amp;&amp;i32)
-6:14-6:30: @22[30]: _97 = (_91.1: &amp;&amp;i32)
-6:14-6:30: @22[33]: _99 = &amp;(*_96)
-6:14-6:30: @22[35]: _100 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-6:14-6:30: @22.Call: _98 = ArgumentV1::new::&lt;&amp;i32&gt;(move _99, move _100) -&gt; [return: bb23, unwind: bb33]
-6:14-6:30: @23[4]: _102 = &amp;(*_97)
-6:14-6:30: @23[6]: _103 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-6:14-6:30: @23.Call: _101 = ArgumentV1::new::&lt;&amp;i32&gt;(move _102, move _103) -&gt; [return: bb24, unwind: bb33]
-6:14-6:30: @24[2]: _90 = [move _98, move _101]
-6:14-6:30: @24[7]: _89 = &amp;_90
-6:14-6:30: @24[8]: _88 = &amp;(*_89)
-6:14-6:30: @24[9]: _87 = move _88 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-6:14-6:30: @24.Call: _82 = Arguments::new_v1(move _83, move _87) -&gt; [return: bb25, unwind: bb33]
-6:14-6:30: @25.Call: core::panicking::panic_fmt(move _82) -&gt; bb33"><span class="annotation">@20,22,23,24,25⦊</span>assert_eq!(1, 1)<span class="annotation">⦉@20,22,23,24,25</span></span><span><span class="code odd" style="--layer: 1" title="6:14-6:30: @21[0]: _0 = const ()"><span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0">, // and this too</span></span>
-<span class="line"><span class="code" style="--layer: 0">        _ =&gt; </span><span><span class="code even" style="--layer: 1" title="7:14-7:30: @27[0]: _0 = const ()"><span class="annotation">@27⦊</span></span></span><span class="code even" style="--layer: 2" title="7:14-7:30: @28[5]: _147 = const fn_run_in_doctests::promoted[9]
-7:14-7:30: @28[6]: _119 = &amp;(*_147)
-7:14-7:30: @28[7]: _118 = &amp;(*_119)
-7:14-7:30: @28[8]: _117 = move _118 as &amp;[&amp;str] (Pointer(Unsize))
-7:14-7:30: @28[17]: _127 = &amp;(*_109)
-7:14-7:30: @28[18]: _126 = &amp;_127
-7:14-7:30: @28[21]: _129 = &amp;(*_110)
-7:14-7:30: @28[22]: _128 = &amp;_129
-7:14-7:30: @28[23]: _125 = (move _126, move _128)
-7:14-7:30: @28[26]: FakeRead(ForMatchedPlace, _125)
-7:14-7:30: @28[28]: _130 = (_125.0: &amp;&amp;i32)
-7:14-7:30: @28[30]: _131 = (_125.1: &amp;&amp;i32)
-7:14-7:30: @28[33]: _133 = &amp;(*_130)
-7:14-7:30: @28[35]: _134 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-7:14-7:30: @28.Call: _132 = ArgumentV1::new::&lt;&amp;i32&gt;(move _133, move _134) -&gt; [return: bb29, unwind: bb33]
-7:14-7:30: @29[4]: _136 = &amp;(*_131)
-7:14-7:30: @29[6]: _137 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-7:14-7:30: @29.Call: _135 = ArgumentV1::new::&lt;&amp;i32&gt;(move _136, move _137) -&gt; [return: bb30, unwind: bb33]
-7:14-7:30: @30[2]: _124 = [move _132, move _135]
-7:14-7:30: @30[7]: _123 = &amp;_124
-7:14-7:30: @30[8]: _122 = &amp;(*_123)
-7:14-7:30: @30[9]: _121 = move _122 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-7:14-7:30: @30.Call: _116 = Arguments::new_v1(move _117, move _121) -&gt; [return: bb31, unwind: bb33]
-7:14-7:30: @31.Call: core::panicking::panic_fmt(move _116) -&gt; bb33"><span class="annotation">@26,28,29,30,31⦊</span>assert_eq!(1, 2)<span class="annotation">⦉@26,28,29,30,31</span></span><span><span class="code even" style="--layer: 1" title="7:14-7:30: @27[0]: _0 = const ()"><span class="annotation">⦉@27</span></span></span><span class="code" style="--layer: 0">, // however this is not</span></span>
+<span class="line"><span class="code" style="--layer: 0">        1 =&gt; </span><span><span class="code odd" style="--layer: 1" title="4:14-4:30: @7[0]: _0 = const ()"><span class="annotation">@7⦊</span></span></span><span class="code even" style="--layer: 2" title="4:14-4:30: @6[5]: _138 = const fn_run_in_doctests::promoted[0]
+4:14-4:30: @6[6]: _17 = &amp;(*_138)
+4:14-4:30: @6[7]: _16 = &amp;(*_17)
+4:14-4:30: @6[8]: _15 = move _16 as &amp;[&amp;str] (Pointer(Unsize))
+4:14-4:30: @6[17]: _25 = &amp;(*_7)
+4:14-4:30: @6[18]: _24 = &amp;_25
+4:14-4:30: @6[21]: _27 = &amp;(*_8)
+4:14-4:30: @6[22]: _26 = &amp;_27
+4:14-4:30: @6[23]: _23 = (move _24, move _26)
+4:14-4:30: @6[26]: FakeRead(ForMatchedPlace, _23)
+4:14-4:30: @6[28]: _28 = (_23.0: &amp;&amp;i32)
+4:14-4:30: @6[30]: _29 = (_23.1: &amp;&amp;i32)
+4:14-4:30: @6[33]: _31 = &amp;(*_28)
+4:14-4:30: @6[35]: _32 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+4:14-4:30: @6.Call: _30 = ArgumentV1::new::&lt;&amp;i32&gt;(move _31, move _32) -&gt; [return: bb8, unwind: bb29]
+4:14-4:30: @8[4]: _34 = &amp;(*_29)
+4:14-4:30: @8[6]: _35 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+4:14-4:30: @8.Call: _33 = ArgumentV1::new::&lt;&amp;i32&gt;(move _34, move _35) -&gt; [return: bb9, unwind: bb29]
+4:14-4:30: @9[2]: _22 = [move _30, move _33]
+4:14-4:30: @9[7]: _21 = &amp;_22
+4:14-4:30: @9[8]: _20 = &amp;(*_21)
+4:14-4:30: @9[9]: _19 = move _20 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+4:14-4:30: @9.Call: _14 = Arguments::new_v1(move _15, move _19) -&gt; [return: bb10, unwind: bb29]
+4:14-4:30: @10.Call: core::panicking::panic_fmt(move _14) -&gt; bb29"><span class="annotation">@6,8,9,10⦊</span>assert_eq!(1, 1)<span class="annotation">⦉@6,8,9,10</span></span><span><span class="code odd" style="--layer: 1" title="4:14-4:30: @7[0]: _0 = const ()"><span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0">, // this is run,</span></span>
+<span class="line"><span class="code" style="--layer: 0">        2 =&gt; </span><span><span class="code even" style="--layer: 1" title="5:14-5:30: @13[0]: _0 = const ()"><span class="annotation">@13⦊</span></span></span><span class="code even" style="--layer: 2" title="5:14-5:30: @12[5]: _141 = const fn_run_in_doctests::promoted[3]
+5:14-5:30: @12[6]: _51 = &amp;(*_141)
+5:14-5:30: @12[7]: _50 = &amp;(*_51)
+5:14-5:30: @12[8]: _49 = move _50 as &amp;[&amp;str] (Pointer(Unsize))
+5:14-5:30: @12[17]: _59 = &amp;(*_41)
+5:14-5:30: @12[18]: _58 = &amp;_59
+5:14-5:30: @12[21]: _61 = &amp;(*_42)
+5:14-5:30: @12[22]: _60 = &amp;_61
+5:14-5:30: @12[23]: _57 = (move _58, move _60)
+5:14-5:30: @12[26]: FakeRead(ForMatchedPlace, _57)
+5:14-5:30: @12[28]: _62 = (_57.0: &amp;&amp;i32)
+5:14-5:30: @12[30]: _63 = (_57.1: &amp;&amp;i32)
+5:14-5:30: @12[33]: _65 = &amp;(*_62)
+5:14-5:30: @12[35]: _66 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+5:14-5:30: @12.Call: _64 = ArgumentV1::new::&lt;&amp;i32&gt;(move _65, move _66) -&gt; [return: bb14, unwind: bb29]
+5:14-5:30: @14[4]: _68 = &amp;(*_63)
+5:14-5:30: @14[6]: _69 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+5:14-5:30: @14.Call: _67 = ArgumentV1::new::&lt;&amp;i32&gt;(move _68, move _69) -&gt; [return: bb15, unwind: bb29]
+5:14-5:30: @15[2]: _56 = [move _64, move _67]
+5:14-5:30: @15[7]: _55 = &amp;_56
+5:14-5:30: @15[8]: _54 = &amp;(*_55)
+5:14-5:30: @15[9]: _53 = move _54 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+5:14-5:30: @15.Call: _48 = Arguments::new_v1(move _49, move _53) -&gt; [return: bb16, unwind: bb29]
+5:14-5:30: @16.Call: core::panicking::panic_fmt(move _48) -&gt; bb29"><span class="annotation">@12,14,15,16⦊</span>assert_eq!(1, 1)<span class="annotation">⦉@12,14,15,16</span></span><span><span class="code even" style="--layer: 1" title="5:14-5:30: @13[0]: _0 = const ()"><span class="annotation">⦉@13</span></span></span><span class="code" style="--layer: 0">, // this,</span></span>
+<span class="line"><span class="code" style="--layer: 0">        3 =&gt; </span><span><span class="code odd" style="--layer: 1" title="6:14-6:30: @19[0]: _0 = const ()"><span class="annotation">@19⦊</span></span></span><span class="code even" style="--layer: 2" title="6:14-6:30: @18[5]: _144 = const fn_run_in_doctests::promoted[6]
+6:14-6:30: @18[6]: _85 = &amp;(*_144)
+6:14-6:30: @18[7]: _84 = &amp;(*_85)
+6:14-6:30: @18[8]: _83 = move _84 as &amp;[&amp;str] (Pointer(Unsize))
+6:14-6:30: @18[17]: _93 = &amp;(*_75)
+6:14-6:30: @18[18]: _92 = &amp;_93
+6:14-6:30: @18[21]: _95 = &amp;(*_76)
+6:14-6:30: @18[22]: _94 = &amp;_95
+6:14-6:30: @18[23]: _91 = (move _92, move _94)
+6:14-6:30: @18[26]: FakeRead(ForMatchedPlace, _91)
+6:14-6:30: @18[28]: _96 = (_91.0: &amp;&amp;i32)
+6:14-6:30: @18[30]: _97 = (_91.1: &amp;&amp;i32)
+6:14-6:30: @18[33]: _99 = &amp;(*_96)
+6:14-6:30: @18[35]: _100 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+6:14-6:30: @18.Call: _98 = ArgumentV1::new::&lt;&amp;i32&gt;(move _99, move _100) -&gt; [return: bb20, unwind: bb29]
+6:14-6:30: @20[4]: _102 = &amp;(*_97)
+6:14-6:30: @20[6]: _103 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+6:14-6:30: @20.Call: _101 = ArgumentV1::new::&lt;&amp;i32&gt;(move _102, move _103) -&gt; [return: bb21, unwind: bb29]
+6:14-6:30: @21[2]: _90 = [move _98, move _101]
+6:14-6:30: @21[7]: _89 = &amp;_90
+6:14-6:30: @21[8]: _88 = &amp;(*_89)
+6:14-6:30: @21[9]: _87 = move _88 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+6:14-6:30: @21.Call: _82 = Arguments::new_v1(move _83, move _87) -&gt; [return: bb22, unwind: bb29]
+6:14-6:30: @22.Call: core::panicking::panic_fmt(move _82) -&gt; bb29"><span class="annotation">@18,20,21,22⦊</span>assert_eq!(1, 1)<span class="annotation">⦉@18,20,21,22</span></span><span><span class="code odd" style="--layer: 1" title="6:14-6:30: @19[0]: _0 = const ()"><span class="annotation">⦉@19</span></span></span><span class="code" style="--layer: 0">, // and this too</span></span>
+<span class="line"><span class="code" style="--layer: 0">        _ =&gt; </span><span><span class="code even" style="--layer: 1" title="7:14-7:30: @24[0]: _0 = const ()"><span class="annotation">@24⦊</span></span></span><span class="code even" style="--layer: 2" title="7:14-7:30: @23[5]: _147 = const fn_run_in_doctests::promoted[9]
+7:14-7:30: @23[6]: _119 = &amp;(*_147)
+7:14-7:30: @23[7]: _118 = &amp;(*_119)
+7:14-7:30: @23[8]: _117 = move _118 as &amp;[&amp;str] (Pointer(Unsize))
+7:14-7:30: @23[17]: _127 = &amp;(*_109)
+7:14-7:30: @23[18]: _126 = &amp;_127
+7:14-7:30: @23[21]: _129 = &amp;(*_110)
+7:14-7:30: @23[22]: _128 = &amp;_129
+7:14-7:30: @23[23]: _125 = (move _126, move _128)
+7:14-7:30: @23[26]: FakeRead(ForMatchedPlace, _125)
+7:14-7:30: @23[28]: _130 = (_125.0: &amp;&amp;i32)
+7:14-7:30: @23[30]: _131 = (_125.1: &amp;&amp;i32)
+7:14-7:30: @23[33]: _133 = &amp;(*_130)
+7:14-7:30: @23[35]: _134 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+7:14-7:30: @23.Call: _132 = ArgumentV1::new::&lt;&amp;i32&gt;(move _133, move _134) -&gt; [return: bb25, unwind: bb29]
+7:14-7:30: @25[4]: _136 = &amp;(*_131)
+7:14-7:30: @25[6]: _137 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+7:14-7:30: @25.Call: _135 = ArgumentV1::new::&lt;&amp;i32&gt;(move _136, move _137) -&gt; [return: bb26, unwind: bb29]
+7:14-7:30: @26[2]: _124 = [move _132, move _135]
+7:14-7:30: @26[7]: _123 = &amp;_124
+7:14-7:30: @26[8]: _122 = &amp;(*_123)
+7:14-7:30: @26[9]: _121 = move _122 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+7:14-7:30: @26.Call: _116 = Arguments::new_v1(move _117, move _121) -&gt; [return: bb27, unwind: bb29]
+7:14-7:30: @27.Call: core::panicking::panic_fmt(move _116) -&gt; bb29"><span class="annotation">@23,25,26,27⦊</span>assert_eq!(1, 2)<span class="annotation">⦉@23,25,26,27</span></span><span><span class="code even" style="--layer: 1" title="7:14-7:30: @24[0]: _0 = const ()"><span class="annotation">⦉@24</span></span></span><span class="code" style="--layer: 0">, // however this is not</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="9:2-9:2: @32.Return: return"><span class="annotation">@32⦊</span>‸<span class="annotation">⦉@32</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="9:2-9:2: @28.Return: return"><span class="annotation">@28⦊</span>‸<span class="annotation">⦉@28</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html
index fa3c4b3..3b5d1e2 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html
@@ -73,86 +73,80 @@
 15:9-15:21: @0[2]: FakeRead(ForLet, _1)
 17:16-17:42: @0[4]: _2 = Firework { strength: const 100_i32 }
 17:9-17:13: @0[5]: FakeRead(ForLet, _2)
-19:8-19:12: @0[8]: _4 = const true
-19:8-19:12: @0[9]: FakeRead(ForMatchedPlace, _4)"><span class="annotation">@0⦊</span>fn main() -&gt; Result&lt;(),u8&gt; {</span></span>
+19:8-19:12: @0[8]: _4 = const true"><span class="annotation">@0⦊</span>fn main() -&gt; Result&lt;(),u8&gt; {</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="15:24-15:48: @0[1]: _1 = Firework { strength: const 1_i32 }
 15:9-15:21: @0[2]: FakeRead(ForLet, _1)
 17:16-17:42: @0[4]: _2 = Firework { strength: const 100_i32 }
 17:9-17:13: @0[5]: FakeRead(ForLet, _2)
-19:8-19:12: @0[8]: _4 = const true
-19:8-19:12: @0[9]: FakeRead(ForMatchedPlace, _4)">    let _firecracker = Firework { strength: 1 };</span></span>
+19:8-19:12: @0[8]: _4 = const true">    let _firecracker = Firework { strength: 1 };</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="15:24-15:48: @0[1]: _1 = Firework { strength: const 1_i32 }
 15:9-15:21: @0[2]: FakeRead(ForLet, _1)
 17:16-17:42: @0[4]: _2 = Firework { strength: const 100_i32 }
 17:9-17:13: @0[5]: FakeRead(ForLet, _2)
-19:8-19:12: @0[8]: _4 = const true
-19:8-19:12: @0[9]: FakeRead(ForMatchedPlace, _4)"></span></span>
+19:8-19:12: @0[8]: _4 = const true"></span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="15:24-15:48: @0[1]: _1 = Firework { strength: const 1_i32 }
 15:9-15:21: @0[2]: FakeRead(ForLet, _1)
 17:16-17:42: @0[4]: _2 = Firework { strength: const 100_i32 }
 17:9-17:13: @0[5]: FakeRead(ForLet, _2)
-19:8-19:12: @0[8]: _4 = const true
-19:8-19:12: @0[9]: FakeRead(ForMatchedPlace, _4)">    let _tnt = Firework { strength: 100 };</span></span>
+19:8-19:12: @0[8]: _4 = const true">    let _tnt = Firework { strength: 100 };</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="15:24-15:48: @0[1]: _1 = Firework { strength: const 1_i32 }
 15:9-15:21: @0[2]: FakeRead(ForLet, _1)
 17:16-17:42: @0[4]: _2 = Firework { strength: const 100_i32 }
 17:9-17:13: @0[5]: FakeRead(ForLet, _2)
-19:8-19:12: @0[8]: _4 = const true
-19:8-19:12: @0[9]: FakeRead(ForMatchedPlace, _4)"></span></span>
+19:8-19:12: @0[8]: _4 = const true"></span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="15:24-15:48: @0[1]: _1 = Firework { strength: const 1_i32 }
 15:9-15:21: @0[2]: FakeRead(ForLet, _1)
 17:16-17:42: @0[4]: _2 = Firework { strength: const 100_i32 }
 17:9-17:13: @0[5]: FakeRead(ForLet, _2)
-19:8-19:12: @0[8]: _4 = const true
-19:8-19:12: @0[9]: FakeRead(ForMatchedPlace, _4)">    if true<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="20:18-20:41: @3[6]: _21 = const main::promoted[1]
-20:18-20:41: @3[7]: _11 = &amp;(*_21)
-20:18-20:41: @3[8]: _10 = &amp;(*_11)
-20:18-20:41: @3[9]: _9 = move _10 as &amp;[&amp;str] (Pointer(Unsize))
-20:9-20:43: @3[15]: _17 = ()
-20:9-20:43: @3[16]: FakeRead(ForMatchedPlace, _17)
-20:9-20:43: @3[17]: _20 = const main::promoted[0]
-20:9-20:43: @3[18]: _15 = &amp;(*_20)
-20:9-20:43: @3[19]: _14 = &amp;(*_15)
-20:9-20:43: @3[20]: _13 = move _14 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-20:9-20:43: @3.Call: _8 = Arguments::new_v1(move _9, move _13) -&gt; [return: bb4, unwind: bb12]
-20:9-20:43: @4.Call: _7 = _print(move _8) -&gt; [return: bb5, unwind: bb12]
-20:9-20:43: @5[5]: _6 = const ()
-21:16-21:22: @5[7]: _0 = std::result::Result::&lt;(), u8&gt;::Err(const 1_u8)"><span class="annotation">@1,3,4,5,9,10⦊</span>println!("Exiting with error...");</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="20:18-20:41: @3[6]: _21 = const main::promoted[1]
-20:18-20:41: @3[7]: _11 = &amp;(*_21)
-20:18-20:41: @3[8]: _10 = &amp;(*_11)
-20:18-20:41: @3[9]: _9 = move _10 as &amp;[&amp;str] (Pointer(Unsize))
-20:9-20:43: @3[15]: _17 = ()
-20:9-20:43: @3[16]: FakeRead(ForMatchedPlace, _17)
-20:9-20:43: @3[17]: _20 = const main::promoted[0]
-20:9-20:43: @3[18]: _15 = &amp;(*_20)
-20:9-20:43: @3[19]: _14 = &amp;(*_15)
-20:9-20:43: @3[20]: _13 = move _14 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-20:9-20:43: @3.Call: _8 = Arguments::new_v1(move _9, move _13) -&gt; [return: bb4, unwind: bb12]
-20:9-20:43: @4.Call: _7 = _print(move _8) -&gt; [return: bb5, unwind: bb12]
-20:9-20:43: @5[5]: _6 = const ()
-21:16-21:22: @5[7]: _0 = std::result::Result::&lt;(), u8&gt;::Err(const 1_u8)">        return Err(1)<span class="annotation">⦉@1,3,4,5,9,10</span></span></span><span class="code" style="--layer: 0">;</span></span>
+19:8-19:12: @0[8]: _4 = const true">    if true<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="20:18-20:41: @1[6]: _21 = const main::promoted[1]
+20:18-20:41: @1[7]: _11 = &amp;(*_21)
+20:18-20:41: @1[8]: _10 = &amp;(*_11)
+20:18-20:41: @1[9]: _9 = move _10 as &amp;[&amp;str] (Pointer(Unsize))
+20:9-20:43: @1[15]: _17 = ()
+20:9-20:43: @1[16]: FakeRead(ForMatchedPlace, _17)
+20:9-20:43: @1[17]: _20 = const main::promoted[0]
+20:9-20:43: @1[18]: _15 = &amp;(*_20)
+20:9-20:43: @1[19]: _14 = &amp;(*_15)
+20:9-20:43: @1[20]: _13 = move _14 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+20:9-20:43: @1.Call: _8 = Arguments::new_v1(move _9, move _13) -&gt; [return: bb3, unwind: bb11]
+20:9-20:43: @3.Call: _7 = _print(move _8) -&gt; [return: bb4, unwind: bb11]
+20:9-20:43: @4[5]: _6 = const ()
+21:16-21:22: @4[7]: _0 = std::result::Result::&lt;(), u8&gt;::Err(const 1_u8)"><span class="annotation">@1,3,4,8,9⦊</span>println!("Exiting with error...");</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="20:18-20:41: @1[6]: _21 = const main::promoted[1]
+20:18-20:41: @1[7]: _11 = &amp;(*_21)
+20:18-20:41: @1[8]: _10 = &amp;(*_11)
+20:18-20:41: @1[9]: _9 = move _10 as &amp;[&amp;str] (Pointer(Unsize))
+20:9-20:43: @1[15]: _17 = ()
+20:9-20:43: @1[16]: FakeRead(ForMatchedPlace, _17)
+20:9-20:43: @1[17]: _20 = const main::promoted[0]
+20:9-20:43: @1[18]: _15 = &amp;(*_20)
+20:9-20:43: @1[19]: _14 = &amp;(*_15)
+20:9-20:43: @1[20]: _13 = move _14 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+20:9-20:43: @1.Call: _8 = Arguments::new_v1(move _9, move _13) -&gt; [return: bb3, unwind: bb11]
+20:9-20:43: @3.Call: _7 = _print(move _8) -&gt; [return: bb4, unwind: bb11]
+20:9-20:43: @4[5]: _6 = const ()
+21:16-21:22: @4[7]: _0 = std::result::Result::&lt;(), u8&gt;::Err(const 1_u8)">        return Err(1)<span class="annotation">⦉@1,3,4,8,9</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span><span><span class="code even" style="--layer: 1" title="22:6-22:6: @2[0]: _3 = const ()
 24:13-24:40: @2[4]: _18 = Firework { strength: const 1000_i32 }
-26:8-26:10: @6[2]: _19 = ()
-26:5-26:11: @6[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _19)"><span class="annotation">@2,6,7,8⦊</span></span></span>
+26:8-26:10: @5[2]: _19 = ()
+26:5-26:11: @5[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _19)"><span class="annotation">@2,5,6,7⦊</span></span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="22:6-22:6: @2[0]: _3 = const ()
 24:13-24:40: @2[4]: _18 = Firework { strength: const 1000_i32 }
-26:8-26:10: @6[2]: _19 = ()
-26:5-26:11: @6[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _19)"></span></span>
+26:8-26:10: @5[2]: _19 = ()
+26:5-26:11: @5[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _19)"></span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="22:6-22:6: @2[0]: _3 = const ()
 24:13-24:40: @2[4]: _18 = Firework { strength: const 1000_i32 }
-26:8-26:10: @6[2]: _19 = ()
-26:5-26:11: @6[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _19)">    let _ = Firework { strength: 1000 };</span></span>
+26:8-26:10: @5[2]: _19 = ()
+26:5-26:11: @5[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _19)">    let _ = Firework { strength: 1000 };</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="22:6-22:6: @2[0]: _3 = const ()
 24:13-24:40: @2[4]: _18 = Firework { strength: const 1000_i32 }
-26:8-26:10: @6[2]: _19 = ()
-26:5-26:11: @6[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _19)"></span></span>
+26:8-26:10: @5[2]: _19 = ()
+26:5-26:11: @5[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _19)"></span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="22:6-22:6: @2[0]: _3 = const ()
 24:13-24:40: @2[4]: _18 = Firework { strength: const 1000_i32 }
-26:8-26:10: @6[2]: _19 = ()
-26:5-26:11: @6[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _19)">    Ok(())<span class="annotation">⦉@2,6,7,8</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="27:2-27:2: @11.Return: return"><span class="annotation">@11⦊</span>‸<span class="annotation">⦉@11</span></span></span></span></div>
+26:8-26:10: @5[2]: _19 = ()
+26:5-26:11: @5[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _19)">    Ok(())<span class="annotation">⦉@2,5,6,7</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="27:2-27:2: @10.Return: return"><span class="annotation">@10⦊</span>‸<span class="annotation">⦉@10</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html
index 52c5d4f..0373b38 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html
@@ -72,175 +72,166 @@
 <div class="code" style="counter-reset: line 21"><span class="line"><span><span class="code even" style="--layer: 1" title="23:27-23:51: @0[1]: _1 = Firework::&lt;i32&gt; { strength: const 1_i32 }
 23:9-23:24: @0[2]: FakeRead(ForLet, _1)
 24:5-24:16: @0[5]: _3 = &amp;mut _1
-24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb16]
+24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb15]
 26:19-26:47: @1[3]: _4 = Firework::&lt;f64&gt; { strength: const 100.09999999999999f64 }
 26:9-26:16: @1[4]: FakeRead(ForLet, _4)
 27:5-27:8: @1[7]: _6 = &amp;mut _4
-27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb15]
+27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb14]
 28:5-28:8: @2[4]: _8 = &amp;mut _4
-28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb15]
-30:8-30:12: @3[4]: _10 = const true
-30:8-30:12: @3[5]: FakeRead(ForMatchedPlace, _10)"><span class="annotation">@0,1,2,3⦊</span>fn main() -&gt; Result&lt;(),u8&gt; {</span></span>
+28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb14]
+30:8-30:12: @3[4]: _10 = const true"><span class="annotation">@0,1,2,3⦊</span>fn main() -&gt; Result&lt;(),u8&gt; {</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="23:27-23:51: @0[1]: _1 = Firework::&lt;i32&gt; { strength: const 1_i32 }
 23:9-23:24: @0[2]: FakeRead(ForLet, _1)
 24:5-24:16: @0[5]: _3 = &amp;mut _1
-24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb16]
+24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb15]
 26:19-26:47: @1[3]: _4 = Firework::&lt;f64&gt; { strength: const 100.09999999999999f64 }
 26:9-26:16: @1[4]: FakeRead(ForLet, _4)
 27:5-27:8: @1[7]: _6 = &amp;mut _4
-27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb15]
+27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb14]
 28:5-28:8: @2[4]: _8 = &amp;mut _4
-28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb15]
-30:8-30:12: @3[4]: _10 = const true
-30:8-30:12: @3[5]: FakeRead(ForMatchedPlace, _10)">    let mut firecracker = Firework { strength: 1 };</span></span>
+28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb14]
+30:8-30:12: @3[4]: _10 = const true">    let mut firecracker = Firework { strength: 1 };</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="23:27-23:51: @0[1]: _1 = Firework::&lt;i32&gt; { strength: const 1_i32 }
 23:9-23:24: @0[2]: FakeRead(ForLet, _1)
 24:5-24:16: @0[5]: _3 = &amp;mut _1
-24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb16]
+24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb15]
 26:19-26:47: @1[3]: _4 = Firework::&lt;f64&gt; { strength: const 100.09999999999999f64 }
 26:9-26:16: @1[4]: FakeRead(ForLet, _4)
 27:5-27:8: @1[7]: _6 = &amp;mut _4
-27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb15]
+27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb14]
 28:5-28:8: @2[4]: _8 = &amp;mut _4
-28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb15]
-30:8-30:12: @3[4]: _10 = const true
-30:8-30:12: @3[5]: FakeRead(ForMatchedPlace, _10)">    firecracker.set_strength(2);</span></span>
+28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb14]
+30:8-30:12: @3[4]: _10 = const true">    firecracker.set_strength(2);</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="23:27-23:51: @0[1]: _1 = Firework::&lt;i32&gt; { strength: const 1_i32 }
 23:9-23:24: @0[2]: FakeRead(ForLet, _1)
 24:5-24:16: @0[5]: _3 = &amp;mut _1
-24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb16]
+24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb15]
 26:19-26:47: @1[3]: _4 = Firework::&lt;f64&gt; { strength: const 100.09999999999999f64 }
 26:9-26:16: @1[4]: FakeRead(ForLet, _4)
 27:5-27:8: @1[7]: _6 = &amp;mut _4
-27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb15]
+27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb14]
 28:5-28:8: @2[4]: _8 = &amp;mut _4
-28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb15]
-30:8-30:12: @3[4]: _10 = const true
-30:8-30:12: @3[5]: FakeRead(ForMatchedPlace, _10)"></span></span>
+28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb14]
+30:8-30:12: @3[4]: _10 = const true"></span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="23:27-23:51: @0[1]: _1 = Firework::&lt;i32&gt; { strength: const 1_i32 }
 23:9-23:24: @0[2]: FakeRead(ForLet, _1)
 24:5-24:16: @0[5]: _3 = &amp;mut _1
-24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb16]
+24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb15]
 26:19-26:47: @1[3]: _4 = Firework::&lt;f64&gt; { strength: const 100.09999999999999f64 }
 26:9-26:16: @1[4]: FakeRead(ForLet, _4)
 27:5-27:8: @1[7]: _6 = &amp;mut _4
-27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb15]
+27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb14]
 28:5-28:8: @2[4]: _8 = &amp;mut _4
-28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb15]
-30:8-30:12: @3[4]: _10 = const true
-30:8-30:12: @3[5]: FakeRead(ForMatchedPlace, _10)">    let mut tnt = Firework { strength: 100.1 };</span></span>
+28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb14]
+30:8-30:12: @3[4]: _10 = const true">    let mut tnt = Firework { strength: 100.1 };</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="23:27-23:51: @0[1]: _1 = Firework::&lt;i32&gt; { strength: const 1_i32 }
 23:9-23:24: @0[2]: FakeRead(ForLet, _1)
 24:5-24:16: @0[5]: _3 = &amp;mut _1
-24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb16]
+24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb15]
 26:19-26:47: @1[3]: _4 = Firework::&lt;f64&gt; { strength: const 100.09999999999999f64 }
 26:9-26:16: @1[4]: FakeRead(ForLet, _4)
 27:5-27:8: @1[7]: _6 = &amp;mut _4
-27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb15]
+27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb14]
 28:5-28:8: @2[4]: _8 = &amp;mut _4
-28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb15]
-30:8-30:12: @3[4]: _10 = const true
-30:8-30:12: @3[5]: FakeRead(ForMatchedPlace, _10)">    tnt.set_strength(200.1);</span></span>
+28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb14]
+30:8-30:12: @3[4]: _10 = const true">    tnt.set_strength(200.1);</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="23:27-23:51: @0[1]: _1 = Firework::&lt;i32&gt; { strength: const 1_i32 }
 23:9-23:24: @0[2]: FakeRead(ForLet, _1)
 24:5-24:16: @0[5]: _3 = &amp;mut _1
-24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb16]
+24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb15]
 26:19-26:47: @1[3]: _4 = Firework::&lt;f64&gt; { strength: const 100.09999999999999f64 }
 26:9-26:16: @1[4]: FakeRead(ForLet, _4)
 27:5-27:8: @1[7]: _6 = &amp;mut _4
-27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb15]
+27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb14]
 28:5-28:8: @2[4]: _8 = &amp;mut _4
-28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb15]
-30:8-30:12: @3[4]: _10 = const true
-30:8-30:12: @3[5]: FakeRead(ForMatchedPlace, _10)">    tnt.set_strength(300.3);</span></span>
+28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb14]
+30:8-30:12: @3[4]: _10 = const true">    tnt.set_strength(300.3);</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="23:27-23:51: @0[1]: _1 = Firework::&lt;i32&gt; { strength: const 1_i32 }
 23:9-23:24: @0[2]: FakeRead(ForLet, _1)
 24:5-24:16: @0[5]: _3 = &amp;mut _1
-24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb16]
+24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb15]
 26:19-26:47: @1[3]: _4 = Firework::&lt;f64&gt; { strength: const 100.09999999999999f64 }
 26:9-26:16: @1[4]: FakeRead(ForLet, _4)
 27:5-27:8: @1[7]: _6 = &amp;mut _4
-27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb15]
+27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb14]
 28:5-28:8: @2[4]: _8 = &amp;mut _4
-28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb15]
-30:8-30:12: @3[4]: _10 = const true
-30:8-30:12: @3[5]: FakeRead(ForMatchedPlace, _10)"></span></span>
+28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb14]
+30:8-30:12: @3[4]: _10 = const true"></span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="23:27-23:51: @0[1]: _1 = Firework::&lt;i32&gt; { strength: const 1_i32 }
 23:9-23:24: @0[2]: FakeRead(ForLet, _1)
 24:5-24:16: @0[5]: _3 = &amp;mut _1
-24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb16]
+24:5-24:32: @0.Call: _2 = Firework::&lt;i32&gt;::set_strength(move _3, const 2_i32) -&gt; [return: bb1, unwind: bb15]
 26:19-26:47: @1[3]: _4 = Firework::&lt;f64&gt; { strength: const 100.09999999999999f64 }
 26:9-26:16: @1[4]: FakeRead(ForLet, _4)
 27:5-27:8: @1[7]: _6 = &amp;mut _4
-27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb15]
+27:5-27:28: @1.Call: _5 = Firework::&lt;f64&gt;::set_strength(move _6, const 200.09999999999999f64) -&gt; [return: bb2, unwind: bb14]
 28:5-28:8: @2[4]: _8 = &amp;mut _4
-28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb15]
-30:8-30:12: @3[4]: _10 = const true
-30:8-30:12: @3[5]: FakeRead(ForMatchedPlace, _10)">    if true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="31:18-31:41: @6[6]: _27 = const main::promoted[1]
-31:18-31:41: @6[7]: _17 = &amp;(*_27)
-31:18-31:41: @6[8]: _16 = &amp;(*_17)
-31:18-31:41: @6[9]: _15 = move _16 as &amp;[&amp;str] (Pointer(Unsize))
-31:9-31:43: @6[15]: _23 = ()
-31:9-31:43: @6[16]: FakeRead(ForMatchedPlace, _23)
-31:9-31:43: @6[17]: _26 = const main::promoted[0]
-31:9-31:43: @6[18]: _21 = &amp;(*_26)
-31:9-31:43: @6[19]: _20 = &amp;(*_21)
-31:9-31:43: @6[20]: _19 = move _20 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-31:9-31:43: @6.Call: _14 = Arguments::new_v1(move _15, move _19) -&gt; [return: bb7, unwind: bb15]
-31:9-31:43: @7.Call: _13 = _print(move _14) -&gt; [return: bb8, unwind: bb15]
-31:9-31:43: @8[5]: _12 = const ()
-32:16-32:22: @8[7]: _0 = std::result::Result::&lt;(), u8&gt;::Err(const 1_u8)"><span class="annotation">@4,6,7,8,12,13⦊</span>println!("Exiting with error...");</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="31:18-31:41: @6[6]: _27 = const main::promoted[1]
-31:18-31:41: @6[7]: _17 = &amp;(*_27)
-31:18-31:41: @6[8]: _16 = &amp;(*_17)
-31:18-31:41: @6[9]: _15 = move _16 as &amp;[&amp;str] (Pointer(Unsize))
-31:9-31:43: @6[15]: _23 = ()
-31:9-31:43: @6[16]: FakeRead(ForMatchedPlace, _23)
-31:9-31:43: @6[17]: _26 = const main::promoted[0]
-31:9-31:43: @6[18]: _21 = &amp;(*_26)
-31:9-31:43: @6[19]: _20 = &amp;(*_21)
-31:9-31:43: @6[20]: _19 = move _20 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-31:9-31:43: @6.Call: _14 = Arguments::new_v1(move _15, move _19) -&gt; [return: bb7, unwind: bb15]
-31:9-31:43: @7.Call: _13 = _print(move _14) -&gt; [return: bb8, unwind: bb15]
-31:9-31:43: @8[5]: _12 = const ()
-32:16-32:22: @8[7]: _0 = std::result::Result::&lt;(), u8&gt;::Err(const 1_u8)">        return Err(1)<span class="annotation">⦉@4,6,7,8,12,13</span></span></span><span class="code" style="--layer: 0">;</span></span>
+28:5-28:28: @2.Call: _7 = Firework::&lt;f64&gt;::set_strength(move _8, const 300.30000000000001f64) -&gt; [return: bb3, unwind: bb14]
+30:8-30:12: @3[4]: _10 = const true">    if true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="31:18-31:41: @4[6]: _27 = const main::promoted[1]
+31:18-31:41: @4[7]: _17 = &amp;(*_27)
+31:18-31:41: @4[8]: _16 = &amp;(*_17)
+31:18-31:41: @4[9]: _15 = move _16 as &amp;[&amp;str] (Pointer(Unsize))
+31:9-31:43: @4[15]: _23 = ()
+31:9-31:43: @4[16]: FakeRead(ForMatchedPlace, _23)
+31:9-31:43: @4[17]: _26 = const main::promoted[0]
+31:9-31:43: @4[18]: _21 = &amp;(*_26)
+31:9-31:43: @4[19]: _20 = &amp;(*_21)
+31:9-31:43: @4[20]: _19 = move _20 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+31:9-31:43: @4.Call: _14 = Arguments::new_v1(move _15, move _19) -&gt; [return: bb6, unwind: bb14]
+31:9-31:43: @6.Call: _13 = _print(move _14) -&gt; [return: bb7, unwind: bb14]
+31:9-31:43: @7[5]: _12 = const ()
+32:16-32:22: @7[7]: _0 = std::result::Result::&lt;(), u8&gt;::Err(const 1_u8)"><span class="annotation">@4,6,7,11,12⦊</span>println!("Exiting with error...");</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="31:18-31:41: @4[6]: _27 = const main::promoted[1]
+31:18-31:41: @4[7]: _17 = &amp;(*_27)
+31:18-31:41: @4[8]: _16 = &amp;(*_17)
+31:18-31:41: @4[9]: _15 = move _16 as &amp;[&amp;str] (Pointer(Unsize))
+31:9-31:43: @4[15]: _23 = ()
+31:9-31:43: @4[16]: FakeRead(ForMatchedPlace, _23)
+31:9-31:43: @4[17]: _26 = const main::promoted[0]
+31:9-31:43: @4[18]: _21 = &amp;(*_26)
+31:9-31:43: @4[19]: _20 = &amp;(*_21)
+31:9-31:43: @4[20]: _19 = move _20 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+31:9-31:43: @4.Call: _14 = Arguments::new_v1(move _15, move _19) -&gt; [return: bb6, unwind: bb14]
+31:9-31:43: @6.Call: _13 = _print(move _14) -&gt; [return: bb7, unwind: bb14]
+31:9-31:43: @7[5]: _12 = const ()
+32:16-32:22: @7[7]: _0 = std::result::Result::&lt;(), u8&gt;::Err(const 1_u8)">        return Err(1)<span class="annotation">⦉@4,6,7,11,12</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span><span><span class="code even" style="--layer: 1" title="33:6-33:6: @5[0]: _9 = const ()
 39:13-39:40: @5[4]: _24 = Firework::&lt;i32&gt; { strength: const 1000_i32 }
-41:8-41:10: @9[2]: _25 = ()
-41:5-41:11: @9[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)"><span class="annotation">@5,9,10,11⦊</span> // The remaining lines below have no coverage because `if true` (with the constant literal</span></span>
+41:8-41:10: @8[2]: _25 = ()
+41:5-41:11: @8[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)"><span class="annotation">@5,8,9,10⦊</span> // The remaining lines below have no coverage because `if true` (with the constant literal</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="33:6-33:6: @5[0]: _9 = const ()
 39:13-39:40: @5[4]: _24 = Firework::&lt;i32&gt; { strength: const 1000_i32 }
-41:8-41:10: @9[2]: _25 = ()
-41:5-41:11: @9[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)">      // `true`) is guaranteed to execute the `then` block, which is also guaranteed to `return`.</span></span>
+41:8-41:10: @8[2]: _25 = ()
+41:5-41:11: @8[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)">      // `true`) is guaranteed to execute the `then` block, which is also guaranteed to `return`.</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="33:6-33:6: @5[0]: _9 = const ()
 39:13-39:40: @5[4]: _24 = Firework::&lt;i32&gt; { strength: const 1000_i32 }
-41:8-41:10: @9[2]: _25 = ()
-41:5-41:11: @9[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)">      // Thankfully, in the normal case, conditions are not guaranteed ahead of time, and as shown</span></span>
+41:8-41:10: @8[2]: _25 = ()
+41:5-41:11: @8[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)">      // Thankfully, in the normal case, conditions are not guaranteed ahead of time, and as shown</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="33:6-33:6: @5[0]: _9 = const ()
 39:13-39:40: @5[4]: _24 = Firework::&lt;i32&gt; { strength: const 1000_i32 }
-41:8-41:10: @9[2]: _25 = ()
-41:5-41:11: @9[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)">      // in other tests, the lines below would have coverage (which would show they had `0`</span></span>
+41:8-41:10: @8[2]: _25 = ()
+41:5-41:11: @8[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)">      // in other tests, the lines below would have coverage (which would show they had `0`</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="33:6-33:6: @5[0]: _9 = const ()
 39:13-39:40: @5[4]: _24 = Firework::&lt;i32&gt; { strength: const 1000_i32 }
-41:8-41:10: @9[2]: _25 = ()
-41:5-41:11: @9[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)">      // executions, assuming the condition still evaluated to `true`).</span></span>
+41:8-41:10: @8[2]: _25 = ()
+41:5-41:11: @8[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)">      // executions, assuming the condition still evaluated to `true`).</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="33:6-33:6: @5[0]: _9 = const ()
 39:13-39:40: @5[4]: _24 = Firework::&lt;i32&gt; { strength: const 1000_i32 }
-41:8-41:10: @9[2]: _25 = ()
-41:5-41:11: @9[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)"></span></span>
+41:8-41:10: @8[2]: _25 = ()
+41:5-41:11: @8[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)"></span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="33:6-33:6: @5[0]: _9 = const ()
 39:13-39:40: @5[4]: _24 = Firework::&lt;i32&gt; { strength: const 1000_i32 }
-41:8-41:10: @9[2]: _25 = ()
-41:5-41:11: @9[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)">    let _ = Firework { strength: 1000 };</span></span>
+41:8-41:10: @8[2]: _25 = ()
+41:5-41:11: @8[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)">    let _ = Firework { strength: 1000 };</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="33:6-33:6: @5[0]: _9 = const ()
 39:13-39:40: @5[4]: _24 = Firework::&lt;i32&gt; { strength: const 1000_i32 }
-41:8-41:10: @9[2]: _25 = ()
-41:5-41:11: @9[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)"></span></span>
+41:8-41:10: @8[2]: _25 = ()
+41:5-41:11: @8[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)"></span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="33:6-33:6: @5[0]: _9 = const ()
 39:13-39:40: @5[4]: _24 = Firework::&lt;i32&gt; { strength: const 1000_i32 }
-41:8-41:10: @9[2]: _25 = ()
-41:5-41:11: @9[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)">    Ok(())<span class="annotation">⦉@5,9,10,11</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="42:2-42:2: @14.Return: return"><span class="annotation">@14⦊</span>‸<span class="annotation">⦉@14</span></span></span></span></div>
+41:8-41:10: @8[2]: _25 = ()
+41:5-41:11: @8[3]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _25)">    Ok(())<span class="annotation">⦉@5,8,9,10</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="42:2-42:2: @13.Return: return"><span class="annotation">@13⦊</span>‸<span class="annotation">⦉@13</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if/if.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if/if.main.-------.InstrumentCoverage.0.html
index 8eb6c1d..dd9ba4a 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if/if.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if/if.main.-------.InstrumentCoverage.0.html
@@ -69,189 +69,170 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">    // dependent conditions.</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">    // dependent conditions.</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">    let</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">    let</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">    is_true</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">    is_true</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">    =</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">    =</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">        std::env::args().len()</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">        std::env::args().len()</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">    ==</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">    ==</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">        1</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">        1</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">    ;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">    ;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">    let</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">    let</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">        mut</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">        mut</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">    countdown</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">    countdown</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">    =</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">    =</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">        0</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">        0</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">    ;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">    ;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">    if</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+21:9-21:16: @3[5]: _6 = _1">    if</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:9-10:25: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 10:9-10:25: @1[0]: _3 = &amp;_4
-10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+10:9-10:31: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 10:9-12:10: @2[1]: _1 = Eq(move _2, const 1_usize)
 8:5-8:12: @2[3]: FakeRead(ForLet, _1)
 18:9-18:10: @3[2]: _5 = const 0_i32
 15:9-16:14: @3[3]: FakeRead(ForLet, _5)
-21:9-21:16: @3[5]: _6 = _1
-21:9-21:16: @3[6]: FakeRead(ForMatchedPlace, _6)">        is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="23:9-25:15: @6[0]: _5 = const 10_i32
-22:5-27:6: @6[1]: _0 = const ()"><span class="annotation">@4,6⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="23:9-25:15: @6[0]: _5 = const 10_i32
-22:5-27:6: @6[1]: _0 = const ()">        countdown</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="23:9-25:15: @6[0]: _5 = const 10_i32
-22:5-27:6: @6[1]: _0 = const ()">        =</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="23:9-25:15: @6[0]: _5 = const 10_i32
-22:5-27:6: @6[1]: _0 = const ()">            10</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="23:9-25:15: @6[0]: _5 = const 10_i32
-22:5-27:6: @6[1]: _0 = const ()">        ;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="23:9-25:15: @6[0]: _5 = const 10_i32
-22:5-27:6: @6[1]: _0 = const ()">    }<span class="annotation">⦉@4,6</span></span></span><span><span class="code even" style="--layer: 1" title="27:6-27:6: @5[0]: _0 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="28:2-28:2: @7.Return: return"><span class="annotation">@7⦊</span>‸<span class="annotation">⦉@7</span></span></span></span></div>
+21:9-21:16: @3[5]: _6 = _1">        is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="23:9-25:15: @4[0]: _5 = const 10_i32
+22:5-27:6: @4[1]: _0 = const ()"><span class="annotation">@4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="23:9-25:15: @4[0]: _5 = const 10_i32
+22:5-27:6: @4[1]: _0 = const ()">        countdown</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="23:9-25:15: @4[0]: _5 = const 10_i32
+22:5-27:6: @4[1]: _0 = const ()">        =</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="23:9-25:15: @4[0]: _5 = const 10_i32
+22:5-27:6: @4[1]: _0 = const ()">            10</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="23:9-25:15: @4[0]: _5 = const 10_i32
+22:5-27:6: @4[1]: _0 = const ()">        ;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="23:9-25:15: @4[0]: _5 = const 10_i32
+22:5-27:6: @4[1]: _0 = const ()">    }<span class="annotation">⦉@4</span></span></span><span><span class="code even" style="--layer: 1" title="27:6-27:6: @5[0]: _0 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="28:2-28:2: @6.Return: return"><span class="annotation">@6⦊</span>‸<span class="annotation">⦉@6</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html
index 5b2cce4..b642be3 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html
@@ -69,99 +69,90 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
+<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb11]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb10]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-11:9-11:16: @3[6]: _7 = _1
-11:9-11:16: @3[7]: FakeRead(ForMatchedPlace, _7)"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
+11:9-11:16: @3[6]: _7 = _1"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb11]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb10]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-11:9-11:16: @3[6]: _7 = _1
-11:9-11:16: @3[7]: FakeRead(ForMatchedPlace, _7)">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
+11:9-11:16: @3[6]: _7 = _1">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb11]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb10]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-11:9-11:16: @3[6]: _7 = _1
-11:9-11:16: @3[7]: FakeRead(ForMatchedPlace, _7)">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
+11:9-11:16: @3[6]: _7 = _1">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb11]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb10]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-11:9-11:16: @3[6]: _7 = _1
-11:9-11:16: @3[7]: FakeRead(ForMatchedPlace, _7)">    // dependent conditions.</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
+11:9-11:16: @3[6]: _7 = _1">    // dependent conditions.</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb11]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb10]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-11:9-11:16: @3[6]: _7 = _1
-11:9-11:16: @3[7]: FakeRead(ForMatchedPlace, _7)">    let is_true = std::env::args().len() == 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
+11:9-11:16: @3[6]: _7 = _1">    let is_true = std::env::args().len() == 1;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb11]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb10]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-11:9-11:16: @3[6]: _7 = _1
-11:9-11:16: @3[7]: FakeRead(ForMatchedPlace, _7)"></span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
+11:9-11:16: @3[6]: _7 = _1"></span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb11]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb10]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-11:9-11:16: @3[6]: _7 = _1
-11:9-11:16: @3[7]: FakeRead(ForMatchedPlace, _7)">    let mut countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
+11:9-11:16: @3[6]: _7 = _1">    let mut countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb11]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb10]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-11:9-11:16: @3[6]: _7 = _1
-11:9-11:16: @3[7]: FakeRead(ForMatchedPlace, _7)">    if</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
+11:9-11:16: @3[6]: _7 = _1">    if</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb11]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb10]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-11:9-11:16: @3[6]: _7 = _1
-11:9-11:16: @3[7]: FakeRead(ForMatchedPlace, _7)">        is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="13:9-15:15: @6[0]: _5 = const 10_i32
-12:5-17:6: @6[1]: _6 = const ()"><span class="annotation">@4,6⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="13:9-15:15: @6[0]: _5 = const 10_i32
-12:5-17:6: @6[1]: _6 = const ()">        countdown</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="13:9-15:15: @6[0]: _5 = const 10_i32
-12:5-17:6: @6[1]: _6 = const ()">        =</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="13:9-15:15: @6[0]: _5 = const 10_i32
-12:5-17:6: @6[1]: _6 = const ()">            10</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="13:9-15:15: @6[0]: _5 = const 10_i32
-12:5-17:6: @6[1]: _6 = const ()">        ;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="13:9-15:15: @6[0]: _5 = const 10_i32
-12:5-17:6: @6[1]: _6 = const ()">    }<span class="annotation">⦉@4,6</span></span></span><span class="code" style="--layer: 0"></span></span>
+11:9-11:16: @3[6]: _7 = _1">        is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="13:9-15:15: @4[0]: _5 = const 10_i32
+12:5-17:6: @4[1]: _6 = const ()"><span class="annotation">@4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="13:9-15:15: @4[0]: _5 = const 10_i32
+12:5-17:6: @4[1]: _6 = const ()">        countdown</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="13:9-15:15: @4[0]: _5 = const 10_i32
+12:5-17:6: @4[1]: _6 = const ()">        =</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="13:9-15:15: @4[0]: _5 = const 10_i32
+12:5-17:6: @4[1]: _6 = const ()">            10</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="13:9-15:15: @4[0]: _5 = const 10_i32
+12:5-17:6: @4[1]: _6 = const ()">        ;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="13:9-15:15: @4[0]: _5 = const 10_i32
+12:5-17:6: @4[1]: _6 = const ()">    }<span class="annotation">⦉@4</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    else // Note coverage region difference without semicolon</span></span>
 <span class="line"><span class="code" style="--layer: 0">    {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="20:9-22:16: @5[0]: _5 = const 100_i32
@@ -173,33 +164,32 @@
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    if</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="26:9-26:16: @7[3]: _8 = _1
-26:9-26:16: @7[4]: FakeRead(ForMatchedPlace, _8)"><span class="annotation">@7⦊</span>is_true<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="28:9-30:15: @10[0]: _5 = const 10_i32
-27:5-32:6: @10[1]: _0 = const ()"><span class="annotation">@8,10⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="28:9-30:15: @10[0]: _5 = const 10_i32
-27:5-32:6: @10[1]: _0 = const ()">        countdown</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="28:9-30:15: @10[0]: _5 = const 10_i32
-27:5-32:6: @10[1]: _0 = const ()">        =</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="28:9-30:15: @10[0]: _5 = const 10_i32
-27:5-32:6: @10[1]: _0 = const ()">            10</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="28:9-30:15: @10[0]: _5 = const 10_i32
-27:5-32:6: @10[1]: _0 = const ()">        ;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="28:9-30:15: @10[0]: _5 = const 10_i32
-27:5-32:6: @10[1]: _0 = const ()">    }<span class="annotation">⦉@8,10</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="26:9-26:16: @6[3]: _8 = _1"><span class="annotation">@6⦊</span>is_true<span class="annotation">⦉@6</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="28:9-30:15: @7[0]: _5 = const 10_i32
+27:5-32:6: @7[1]: _0 = const ()"><span class="annotation">@7⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="28:9-30:15: @7[0]: _5 = const 10_i32
+27:5-32:6: @7[1]: _0 = const ()">        countdown</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="28:9-30:15: @7[0]: _5 = const 10_i32
+27:5-32:6: @7[1]: _0 = const ()">        =</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="28:9-30:15: @7[0]: _5 = const 10_i32
+27:5-32:6: @7[1]: _0 = const ()">            10</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="28:9-30:15: @7[0]: _5 = const 10_i32
+27:5-32:6: @7[1]: _0 = const ()">        ;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="28:9-30:15: @7[0]: _5 = const 10_i32
+27:5-32:6: @7[1]: _0 = const ()">    }<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    else</span></span>
-<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="35:9-37:16: @9[0]: _5 = const 100_i32
-34:5-39:6: @9[1]: _0 = const ()"><span class="annotation">@9⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="35:9-37:16: @9[0]: _5 = const 100_i32
-34:5-39:6: @9[1]: _0 = const ()">        countdown</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="35:9-37:16: @9[0]: _5 = const 100_i32
-34:5-39:6: @9[1]: _0 = const ()">        =</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="35:9-37:16: @9[0]: _5 = const 100_i32
-34:5-39:6: @9[1]: _0 = const ()">            100</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="35:9-37:16: @9[0]: _5 = const 100_i32
-34:5-39:6: @9[1]: _0 = const ()">        ;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="35:9-37:16: @9[0]: _5 = const 100_i32
-34:5-39:6: @9[1]: _0 = const ()">    }<span class="annotation">⦉@9</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code even" style="--layer: 1" title="40:2-40:2: @11.Return: return"><span class="annotation">@11⦊</span>‸<span class="annotation">⦉@11</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="35:9-37:16: @8[0]: _5 = const 100_i32
+34:5-39:6: @8[1]: _0 = const ()"><span class="annotation">@8⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="35:9-37:16: @8[0]: _5 = const 100_i32
+34:5-39:6: @8[1]: _0 = const ()">        countdown</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="35:9-37:16: @8[0]: _5 = const 100_i32
+34:5-39:6: @8[1]: _0 = const ()">        =</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="35:9-37:16: @8[0]: _5 = const 100_i32
+34:5-39:6: @8[1]: _0 = const ()">            100</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="35:9-37:16: @8[0]: _5 = const 100_i32
+34:5-39:6: @8[1]: _0 = const ()">        ;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="35:9-37:16: @8[0]: _5 = const 100_i32
+34:5-39:6: @8[1]: _0 = const ()">    }<span class="annotation">⦉@8</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code even" style="--layer: 1" title="40:2-40:2: @9.Return: return"><span class="annotation">@9⦊</span>‸<span class="annotation">⦉@9</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main.-------.InstrumentCoverage.0.html
index 693b15f..d21710b 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main.-------.InstrumentCoverage.0.html
@@ -73,47 +73,43 @@
 <span class="line"><span class="code" style="--layer: 0">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
 <span class="line"><span class="code" style="--layer: 0">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
 <span class="line"><span class="code" style="--layer: 0">    // dependent conditions.</span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb15]
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb14]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_u32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[6]: _7 = _1
-10:8-10:15: @3[7]: FakeRead(ForMatchedPlace, _7)"><span class="annotation">@0,1,2,3⦊</span>is_true = std::env::args().len() == 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb15]
+10:8-10:15: @3[6]: _7 = _1"><span class="annotation">@0,1,2,3⦊</span>is_true = std::env::args().len() == 1;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb14]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_u32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[6]: _7 = _1
-10:8-10:15: @3[7]: FakeRead(ForMatchedPlace, _7)"></span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb15]
+10:8-10:15: @3[6]: _7 = _1"></span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb14]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_u32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[6]: _7 = _1
-10:8-10:15: @3[7]: FakeRead(ForMatchedPlace, _7)">    let mut countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb15]
+10:8-10:15: @3[6]: _7 = _1">    let mut countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb14]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_u32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[6]: _7 = _1
-10:8-10:15: @3[7]: FakeRead(ForMatchedPlace, _7)">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="11:9-11:23: @6[0]: _5 = const 10_u32
-10:16-12:6: @6[1]: _6 = const ()"><span class="annotation">@4,6⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:23: @6[0]: _5 = const 10_u32
-10:16-12:6: @6[1]: _6 = const ()">        countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:23: @6[0]: _5 = const 10_u32
-10:16-12:6: @6[1]: _6 = const ()">    }<span class="annotation">⦉@4,6</span></span></span><span><span class="code even" style="--layer: 1" title="12:6-12:6: @5[0]: _6 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+10:8-10:15: @3[6]: _7 = _1">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="11:9-11:23: @4[0]: _5 = const 10_u32
+10:16-12:6: @4[1]: _6 = const ()"><span class="annotation">@4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:23: @4[0]: _5 = const 10_u32
+10:16-12:6: @4[1]: _6 = const ()">        countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:23: @4[0]: _5 = const 10_u32
+10:16-12:6: @4[1]: _6 = const ()">    }<span class="annotation">⦉@4</span></span></span><span><span class="code even" style="--layer: 1" title="12:6-12:6: @5[0]: _6 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    mod in_mod {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        const IN_MOD_CONST: u32 = 1000;</span></span>
@@ -149,46 +145,45 @@
 <span class="line"><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    type InType = String;</span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code odd" style="--layer: 1" title="48:8-48:15: @7[4]: _9 = _1
-48:8-48:15: @7[5]: FakeRead(ForMatchedPlace, _9)"><span class="annotation">@7⦊</span>is_true<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="49:17-49:26: @10[2]: _11 = _5
-49:9-49:27: @10.Call: _10 = in_func(move _11) -&gt; [return: bb11, unwind: bb15]
-48:16-50:6: @11[2]: _8 = const ()"><span class="annotation">@8,10,11⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="49:17-49:26: @10[2]: _11 = _5
-49:9-49:27: @10.Call: _10 = in_func(move _11) -&gt; [return: bb11, unwind: bb15]
-48:16-50:6: @11[2]: _8 = const ()">        in_func(countdown);</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="49:17-49:26: @10[2]: _11 = _5
-49:9-49:27: @10.Call: _10 = in_func(move _11) -&gt; [return: bb11, unwind: bb15]
-48:16-50:6: @11[2]: _8 = const ()">    }<span class="annotation">⦉@8,10,11</span></span></span><span><span class="code odd" style="--layer: 1" title="50:6-50:6: @9[0]: _8 = const ()"><span class="annotation">@9⦊</span>‸<span class="annotation">⦉@9</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code odd" style="--layer: 1" title="48:8-48:15: @6[4]: _9 = _1"><span class="annotation">@6⦊</span>is_true<span class="annotation">⦉@6</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="49:17-49:26: @7[2]: _11 = _5
+49:9-49:27: @7.Call: _10 = in_func(move _11) -&gt; [return: bb9, unwind: bb13]
+48:16-50:6: @9[2]: _8 = const ()"><span class="annotation">@7,9⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="49:17-49:26: @7[2]: _11 = _5
+49:9-49:27: @7.Call: _10 = in_func(move _11) -&gt; [return: bb9, unwind: bb13]
+48:16-50:6: @9[2]: _8 = const ()">        in_func(countdown);</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="49:17-49:26: @7[2]: _11 = _5
+49:9-49:27: @7.Call: _10 = in_func(move _11) -&gt; [return: bb9, unwind: bb13]
+48:16-50:6: @9[2]: _8 = const ()">    }<span class="annotation">⦉@7,9</span></span></span><span><span class="code odd" style="--layer: 1" title="50:6-50:6: @8[0]: _8 = const ()"><span class="annotation">@8⦊</span>‸<span class="annotation">⦉@8</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="52:19-54:6: @12[3]: _12 = InStruct { in_struct_field: const 101_u32 }
-52:9-52:16: @12[4]: FakeRead(ForLet, _12)
-56:5-56:8: @12[7]: _14 = &amp;mut _12
-56:5-56:29: @12.Call: _13 = &lt;InStruct as InTrait&gt;::default_trait_func(move _14) -&gt; [return: bb13, unwind: bb15]
-57:2-57:2: @13.Return: return"><span class="annotation">@12,13⦊</span>mut val = InStruct {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="52:19-54:6: @12[3]: _12 = InStruct { in_struct_field: const 101_u32 }
-52:9-52:16: @12[4]: FakeRead(ForLet, _12)
-56:5-56:8: @12[7]: _14 = &amp;mut _12
-56:5-56:29: @12.Call: _13 = &lt;InStruct as InTrait&gt;::default_trait_func(move _14) -&gt; [return: bb13, unwind: bb15]
-57:2-57:2: @13.Return: return">        in_struct_field: 101,</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="52:19-54:6: @12[3]: _12 = InStruct { in_struct_field: const 101_u32 }
-52:9-52:16: @12[4]: FakeRead(ForLet, _12)
-56:5-56:8: @12[7]: _14 = &amp;mut _12
-56:5-56:29: @12.Call: _13 = &lt;InStruct as InTrait&gt;::default_trait_func(move _14) -&gt; [return: bb13, unwind: bb15]
-57:2-57:2: @13.Return: return">    };</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="52:19-54:6: @12[3]: _12 = InStruct { in_struct_field: const 101_u32 }
-52:9-52:16: @12[4]: FakeRead(ForLet, _12)
-56:5-56:8: @12[7]: _14 = &amp;mut _12
-56:5-56:29: @12.Call: _13 = &lt;InStruct as InTrait&gt;::default_trait_func(move _14) -&gt; [return: bb13, unwind: bb15]
-57:2-57:2: @13.Return: return"></span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="52:19-54:6: @12[3]: _12 = InStruct { in_struct_field: const 101_u32 }
-52:9-52:16: @12[4]: FakeRead(ForLet, _12)
-56:5-56:8: @12[7]: _14 = &amp;mut _12
-56:5-56:29: @12.Call: _13 = &lt;InStruct as InTrait&gt;::default_trait_func(move _14) -&gt; [return: bb13, unwind: bb15]
-57:2-57:2: @13.Return: return">    val.default_trait_func();</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="52:19-54:6: @12[3]: _12 = InStruct { in_struct_field: const 101_u32 }
-52:9-52:16: @12[4]: FakeRead(ForLet, _12)
-56:5-56:8: @12[7]: _14 = &amp;mut _12
-56:5-56:29: @12.Call: _13 = &lt;InStruct as InTrait&gt;::default_trait_func(move _14) -&gt; [return: bb13, unwind: bb15]
-57:2-57:2: @13.Return: return">}<span class="annotation">⦉@12,13</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="52:19-54:6: @10[3]: _12 = InStruct { in_struct_field: const 101_u32 }
+52:9-52:16: @10[4]: FakeRead(ForLet, _12)
+56:5-56:8: @10[7]: _14 = &amp;mut _12
+56:5-56:29: @10.Call: _13 = &lt;InStruct as InTrait&gt;::default_trait_func(move _14) -&gt; [return: bb11, unwind: bb13]
+57:2-57:2: @11.Return: return"><span class="annotation">@10,11⦊</span>mut val = InStruct {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="52:19-54:6: @10[3]: _12 = InStruct { in_struct_field: const 101_u32 }
+52:9-52:16: @10[4]: FakeRead(ForLet, _12)
+56:5-56:8: @10[7]: _14 = &amp;mut _12
+56:5-56:29: @10.Call: _13 = &lt;InStruct as InTrait&gt;::default_trait_func(move _14) -&gt; [return: bb11, unwind: bb13]
+57:2-57:2: @11.Return: return">        in_struct_field: 101,</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="52:19-54:6: @10[3]: _12 = InStruct { in_struct_field: const 101_u32 }
+52:9-52:16: @10[4]: FakeRead(ForLet, _12)
+56:5-56:8: @10[7]: _14 = &amp;mut _12
+56:5-56:29: @10.Call: _13 = &lt;InStruct as InTrait&gt;::default_trait_func(move _14) -&gt; [return: bb11, unwind: bb13]
+57:2-57:2: @11.Return: return">    };</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="52:19-54:6: @10[3]: _12 = InStruct { in_struct_field: const 101_u32 }
+52:9-52:16: @10[4]: FakeRead(ForLet, _12)
+56:5-56:8: @10[7]: _14 = &amp;mut _12
+56:5-56:29: @10.Call: _13 = &lt;InStruct as InTrait&gt;::default_trait_func(move _14) -&gt; [return: bb11, unwind: bb13]
+57:2-57:2: @11.Return: return"></span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="52:19-54:6: @10[3]: _12 = InStruct { in_struct_field: const 101_u32 }
+52:9-52:16: @10[4]: FakeRead(ForLet, _12)
+56:5-56:8: @10[7]: _14 = &amp;mut _12
+56:5-56:29: @10.Call: _13 = &lt;InStruct as InTrait&gt;::default_trait_func(move _14) -&gt; [return: bb11, unwind: bb13]
+57:2-57:2: @11.Return: return">    val.default_trait_func();</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="52:19-54:6: @10[3]: _12 = InStruct { in_struct_field: const 101_u32 }
+52:9-52:16: @10[4]: FakeRead(ForLet, _12)
+56:5-56:8: @10[7]: _14 = &amp;mut _12
+56:5-56:29: @10.Call: _13 = &lt;InStruct as InTrait&gt;::default_trait_func(move _14) -&gt; [return: bb11, unwind: bb13]
+57:2-57:2: @11.Return: return">}<span class="annotation">⦉@10,11</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html
index f30f0ed..0cfe211 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html
@@ -69,204 +69,191 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb36]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
 9:10-9:15: @3[4]: _5 = (_8.0: i32)
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
-10:8-10:15: @3[12]: _10 = _1
-10:8-10:15: @3[13]: FakeRead(ForMatchedPlace, _10)"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+10:8-10:15: @3[12]: _10 = _1"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb36]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
 9:10-9:15: @3[4]: _5 = (_8.0: i32)
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
-10:8-10:15: @3[12]: _10 = _1
-10:8-10:15: @3[13]: FakeRead(ForMatchedPlace, _10)">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+10:8-10:15: @3[12]: _10 = _1">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb36]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
 9:10-9:15: @3[4]: _5 = (_8.0: i32)
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
-10:8-10:15: @3[12]: _10 = _1
-10:8-10:15: @3[13]: FakeRead(ForMatchedPlace, _10)">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+10:8-10:15: @3[12]: _10 = _1">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb36]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
 9:10-9:15: @3[4]: _5 = (_8.0: i32)
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
-10:8-10:15: @3[12]: _10 = _1
-10:8-10:15: @3[13]: FakeRead(ForMatchedPlace, _10)">    // dependent conditions.</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+10:8-10:15: @3[12]: _10 = _1">    // dependent conditions.</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb36]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
 9:10-9:15: @3[4]: _5 = (_8.0: i32)
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
-10:8-10:15: @3[12]: _10 = _1
-10:8-10:15: @3[13]: FakeRead(ForMatchedPlace, _10)">    let is_true = std::env::args().len() == 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+10:8-10:15: @3[12]: _10 = _1">    let is_true = std::env::args().len() == 1;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb36]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
 9:10-9:15: @3[4]: _5 = (_8.0: i32)
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
-10:8-10:15: @3[12]: _10 = _1
-10:8-10:15: @3[13]: FakeRead(ForMatchedPlace, _10)"></span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+10:8-10:15: @3[12]: _10 = _1"></span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb36]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
 9:10-9:15: @3[4]: _5 = (_8.0: i32)
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
-10:8-10:15: @3[12]: _10 = _1
-10:8-10:15: @3[13]: FakeRead(ForMatchedPlace, _10)">    let (mut a, mut b, mut c) = (0, 0, 0);</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+10:8-10:15: @3[12]: _10 = _1">    let (mut a, mut b, mut c) = (0, 0, 0);</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb36]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
 9:10-9:15: @3[4]: _5 = (_8.0: i32)
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
-10:8-10:15: @3[12]: _10 = _1
-10:8-10:15: @3[13]: FakeRead(ForMatchedPlace, _10)">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="11:9-11:14: @6[0]: _5 = const 1_i32
-12:9-12:15: @6[1]: _6 = const 10_i32
-13:9-13:16: @6[2]: _7 = const 100_i32
-10:16-14:6: @6[3]: _9 = const ()"><span class="annotation">@4,6⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:14: @6[0]: _5 = const 1_i32
-12:9-12:15: @6[1]: _6 = const 10_i32
-13:9-13:16: @6[2]: _7 = const 100_i32
-10:16-14:6: @6[3]: _9 = const ()">        a = 1;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:14: @6[0]: _5 = const 1_i32
-12:9-12:15: @6[1]: _6 = const 10_i32
-13:9-13:16: @6[2]: _7 = const 100_i32
-10:16-14:6: @6[3]: _9 = const ()">        b = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:14: @6[0]: _5 = const 1_i32
-12:9-12:15: @6[1]: _6 = const 10_i32
-13:9-13:16: @6[2]: _7 = const 100_i32
-10:16-14:6: @6[3]: _9 = const ()">        c = 100;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:14: @6[0]: _5 = const 1_i32
-12:9-12:15: @6[1]: _6 = const 10_i32
-13:9-13:16: @6[2]: _7 = const 100_i32
-10:16-14:6: @6[3]: _9 = const ()">    }<span class="annotation">⦉@4,6</span></span></span><span><span class="code even" style="--layer: 1" title="14:6-14:6: @5[0]: _9 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+10:8-10:15: @3[12]: _10 = _1">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="11:9-11:14: @4[0]: _5 = const 1_i32
+12:9-12:15: @4[1]: _6 = const 10_i32
+13:9-13:16: @4[2]: _7 = const 100_i32
+10:16-14:6: @4[3]: _9 = const ()"><span class="annotation">@4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:14: @4[0]: _5 = const 1_i32
+12:9-12:15: @4[1]: _6 = const 10_i32
+13:9-13:16: @4[2]: _7 = const 100_i32
+10:16-14:6: @4[3]: _9 = const ()">        a = 1;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:14: @4[0]: _5 = const 1_i32
+12:9-12:15: @4[1]: _6 = const 10_i32
+13:9-13:16: @4[2]: _7 = const 100_i32
+10:16-14:6: @4[3]: _9 = const ()">        b = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:14: @4[0]: _5 = const 1_i32
+12:9-12:15: @4[1]: _6 = const 10_i32
+13:9-13:16: @4[2]: _7 = const 100_i32
+10:16-14:6: @4[3]: _9 = const ()">        c = 100;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:14: @4[0]: _5 = const 1_i32
+12:9-12:15: @4[1]: _6 = const 10_i32
+13:9-13:16: @4[2]: _7 = const 100_i32
+10:16-14:6: @4[3]: _9 = const ()">    }<span class="annotation">⦉@4</span></span></span><span><span class="code even" style="--layer: 1" title="14:6-14:6: @5[0]: _9 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    let</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="16:9-16:17: @11[2]: FakeRead(ForLet, _11)"><span class="annotation">@11⦊</span>somebool<span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="16:9-16:17: @10[2]: FakeRead(ForLet, _11)"><span class="annotation">@10⦊</span>somebool<span class="annotation">⦉@10</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        =</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="18:13-18:14: @7[5]: _13 = _5
-18:17-18:18: @7[7]: _14 = _6
-18:13-18:18: @7[8]: _12 = Lt(move _13, move _14)"><span class="annotation">@7⦊</span>a &lt; b<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="18:13-18:14: @6[5]: _13 = _5
+18:17-18:18: @6[7]: _14 = _6
+18:13-18:18: @6[8]: _12 = Lt(move _13, move _14)"><span class="annotation">@6⦊</span>a &lt; b<span class="annotation">⦉@6</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        ||</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="20:13-20:14: @10[2]: _16 = _6
-20:17-20:18: @10[4]: _17 = _7
-20:13-20:18: @10[5]: _15 = Lt(move _16, move _17)"><span class="annotation">@10⦊</span>b &lt; c<span class="annotation">⦉@10</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="20:13-20:14: @9[2]: _16 = _6
+20:17-20:18: @9[4]: _17 = _7
+20:13-20:18: @9[5]: _15 = Lt(move _16, move _17)"><span class="annotation">@9⦊</span>b &lt; c<span class="annotation">⦉@9</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    ;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    let</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="23:9-23:17: @15[2]: FakeRead(ForLet, _18)"><span class="annotation">@15⦊</span>somebool<span class="annotation">⦉@15</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="23:9-23:17: @14[2]: FakeRead(ForLet, _18)"><span class="annotation">@14⦊</span>somebool<span class="annotation">⦉@14</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        =</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="25:13-25:14: @11[6]: _20 = _6
-25:17-25:18: @11[8]: _21 = _5
-25:13-25:18: @11[9]: _19 = Lt(move _20, move _21)"><span class="annotation">@11⦊</span>b &lt; a<span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="25:13-25:14: @10[6]: _20 = _6
+25:17-25:18: @10[8]: _21 = _5
+25:13-25:18: @10[9]: _19 = Lt(move _20, move _21)"><span class="annotation">@10⦊</span>b &lt; a<span class="annotation">⦉@10</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        ||</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="27:13-27:14: @14[2]: _23 = _6
-27:17-27:18: @14[4]: _24 = _7
-27:13-27:18: @14[5]: _22 = Lt(move _23, move _24)"><span class="annotation">@14⦊</span>b &lt; c<span class="annotation">⦉@14</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="27:13-27:14: @13[2]: _23 = _6
+27:17-27:18: @13[4]: _24 = _7
+27:13-27:18: @13[5]: _22 = Lt(move _23, move _24)"><span class="annotation">@13⦊</span>b &lt; c<span class="annotation">⦉@13</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    ;</span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code odd" style="--layer: 1" title="29:9-29:17: @19[2]: FakeRead(ForLet, _25)"><span class="annotation">@19⦊</span>somebool<span class="annotation">⦉@19</span></span></span><span class="code" style="--layer: 0"> = </span><span><span class="code even" style="--layer: 1" title="29:20-29:21: @15[6]: _27 = _5
-29:24-29:25: @15[8]: _28 = _6
-29:20-29:25: @15[9]: _26 = Lt(move _27, move _28)"><span class="annotation">@15⦊</span>a &lt; b<span class="annotation">⦉@15</span></span></span><span class="code" style="--layer: 0"> &amp;&amp; </span><span><span class="code odd" style="--layer: 1" title="29:29-29:30: @18[2]: _30 = _6
-29:33-29:34: @18[4]: _31 = _7
-29:29-29:34: @18[5]: _29 = Lt(move _30, move _31)"><span class="annotation">@18⦊</span>b &lt; c<span class="annotation">⦉@18</span></span></span><span class="code" style="--layer: 0">;</span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="30:9-30:17: @23[2]: FakeRead(ForLet, _32)"><span class="annotation">@23⦊</span>somebool<span class="annotation">⦉@23</span></span></span><span class="code" style="--layer: 0"> = </span><span><span class="code odd" style="--layer: 1" title="30:20-30:21: @19[6]: _34 = _6
-30:24-30:25: @19[8]: _35 = _5
-30:20-30:25: @19[9]: _33 = Lt(move _34, move _35)"><span class="annotation">@19⦊</span>b &lt; a<span class="annotation">⦉@19</span></span></span><span class="code" style="--layer: 0"> &amp;&amp; </span><span><span class="code even" style="--layer: 1" title="30:29-30:30: @22[2]: _37 = _6
-30:33-30:34: @22[4]: _38 = _7
-30:29-30:34: @22[5]: _36 = Lt(move _37, move _38)"><span class="annotation">@22⦊</span>b &lt; c<span class="annotation">⦉@22</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code odd" style="--layer: 1" title="29:9-29:17: @18[2]: FakeRead(ForLet, _25)"><span class="annotation">@18⦊</span>somebool<span class="annotation">⦉@18</span></span></span><span class="code" style="--layer: 0"> = </span><span><span class="code even" style="--layer: 1" title="29:20-29:21: @14[6]: _27 = _5
+29:24-29:25: @14[8]: _28 = _6
+29:20-29:25: @14[9]: _26 = Lt(move _27, move _28)"><span class="annotation">@14⦊</span>a &lt; b<span class="annotation">⦉@14</span></span></span><span class="code" style="--layer: 0"> &amp;&amp; </span><span><span class="code odd" style="--layer: 1" title="29:29-29:30: @17[2]: _30 = _6
+29:33-29:34: @17[4]: _31 = _7
+29:29-29:34: @17[5]: _29 = Lt(move _30, move _31)"><span class="annotation">@17⦊</span>b &lt; c<span class="annotation">⦉@17</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="30:9-30:17: @22[2]: FakeRead(ForLet, _32)"><span class="annotation">@22⦊</span>somebool<span class="annotation">⦉@22</span></span></span><span class="code" style="--layer: 0"> = </span><span><span class="code odd" style="--layer: 1" title="30:20-30:21: @18[6]: _34 = _6
+30:24-30:25: @18[8]: _35 = _5
+30:20-30:25: @18[9]: _33 = Lt(move _34, move _35)"><span class="annotation">@18⦊</span>b &lt; a<span class="annotation">⦉@18</span></span></span><span class="code" style="--layer: 0"> &amp;&amp; </span><span><span class="code even" style="--layer: 1" title="30:29-30:30: @21[2]: _37 = _6
+30:33-30:34: @21[4]: _38 = _7
+30:29-30:34: @21[5]: _36 = Lt(move _37, move _38)"><span class="annotation">@21⦊</span>b &lt; c<span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    if</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="34:9-34:16: @23[6]: _41 = _1
-33:9-34:16: @23[7]: _40 = Not(move _41)
-33:9-34:16: @23[9]: FakeRead(ForMatchedPlace, _40)"><span class="annotation">@23⦊</span>!</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="34:9-34:16: @23[6]: _41 = _1
-33:9-34:16: @23[7]: _40 = Not(move _41)
-33:9-34:16: @23[9]: FakeRead(ForMatchedPlace, _40)">        is_true<span class="annotation">⦉@23</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="36:9-36:14: @26[0]: _5 = const 2_i32
-35:5-38:6: @26[1]: _39 = const ()"><span class="annotation">@24,26⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="36:9-36:14: @26[0]: _5 = const 2_i32
-35:5-38:6: @26[1]: _39 = const ()">        a = 2</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="36:9-36:14: @26[0]: _5 = const 2_i32
-35:5-38:6: @26[1]: _39 = const ()">        ;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="36:9-36:14: @26[0]: _5 = const 2_i32
-35:5-38:6: @26[1]: _39 = const ()">    }<span class="annotation">⦉@24,26</span></span></span><span><span class="code odd" style="--layer: 1" title="38:6-38:6: @25[0]: _39 = const ()"><span class="annotation">@25⦊</span>‸<span class="annotation">⦉@25</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="34:9-34:16: @22[6]: _41 = _1
+33:9-34:16: @22[7]: _40 = Not(move _41)"><span class="annotation">@22⦊</span>!</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="34:9-34:16: @22[6]: _41 = _1
+33:9-34:16: @22[7]: _40 = Not(move _41)">        is_true<span class="annotation">⦉@22</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="36:9-36:14: @23[0]: _5 = const 2_i32
+35:5-38:6: @23[1]: _39 = const ()"><span class="annotation">@23⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="36:9-36:14: @23[0]: _5 = const 2_i32
+35:5-38:6: @23[1]: _39 = const ()">        a = 2</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="36:9-36:14: @23[0]: _5 = const 2_i32
+35:5-38:6: @23[1]: _39 = const ()">        ;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="36:9-36:14: @23[0]: _5 = const 2_i32
+35:5-38:6: @23[1]: _39 = const ()">    }<span class="annotation">⦉@23</span></span></span><span><span class="code odd" style="--layer: 1" title="38:6-38:6: @24[0]: _39 = const ()"><span class="annotation">@24⦊</span>‸<span class="annotation">⦉@24</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    if</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="41:9-41:16: @27[4]: _43 = _1
-41:9-41:16: @27[5]: FakeRead(ForMatchedPlace, _43)"><span class="annotation">@27⦊</span>is_true<span class="annotation">⦉@27</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="43:9-43:15: @30[0]: _6 = const 30_i32
-42:5-45:6: @30[1]: _42 = const ()"><span class="annotation">@28,30⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="43:9-43:15: @30[0]: _6 = const 30_i32
-42:5-45:6: @30[1]: _42 = const ()">        b = 30</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="43:9-43:15: @30[0]: _6 = const 30_i32
-42:5-45:6: @30[1]: _42 = const ()">        ;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="43:9-43:15: @30[0]: _6 = const 30_i32
-42:5-45:6: @30[1]: _42 = const ()">    }<span class="annotation">⦉@28,30</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="41:9-41:16: @25[4]: _43 = _1"><span class="annotation">@25⦊</span>is_true<span class="annotation">⦉@25</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="43:9-43:15: @26[0]: _6 = const 30_i32
+42:5-45:6: @26[1]: _42 = const ()"><span class="annotation">@26⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="43:9-43:15: @26[0]: _6 = const 30_i32
+42:5-45:6: @26[1]: _42 = const ()">        b = 30</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="43:9-43:15: @26[0]: _6 = const 30_i32
+42:5-45:6: @26[1]: _42 = const ()">        ;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="43:9-43:15: @26[0]: _6 = const 30_i32
+42:5-45:6: @26[1]: _42 = const ()">    }<span class="annotation">⦉@26</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    else</span></span>
-<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="48:9-48:16: @29[0]: _7 = const 400_i32
-47:5-50:6: @29[1]: _42 = const ()"><span class="annotation">@29⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="48:9-48:16: @29[0]: _7 = const 400_i32
-47:5-50:6: @29[1]: _42 = const ()">        c = 400</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="48:9-48:16: @29[0]: _7 = const 400_i32
-47:5-50:6: @29[1]: _42 = const ()">        ;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="48:9-48:16: @29[0]: _7 = const 400_i32
-47:5-50:6: @29[1]: _42 = const ()">    }<span class="annotation">⦉@29</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="48:9-48:16: @27[0]: _7 = const 400_i32
+47:5-50:6: @27[1]: _42 = const ()"><span class="annotation">@27⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="48:9-48:16: @27[0]: _7 = const 400_i32
+47:5-50:6: @27[1]: _42 = const ()">        c = 400</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="48:9-48:16: @27[0]: _7 = const 400_i32
+47:5-50:6: @27[1]: _42 = const ()">        ;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="48:9-48:16: @27[0]: _7 = const 400_i32
+47:5-50:6: @27[1]: _42 = const ()">    }<span class="annotation">⦉@27</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code odd" style="--layer: 1" title="52:9-52:16: @31[5]: _46 = _1
-52:8-52:16: @31[6]: _45 = Not(move _46)
-52:8-52:16: @31[8]: FakeRead(ForMatchedPlace, _45)"><span class="annotation">@31⦊</span>!is_true<span class="annotation">⦉@31</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="53:9-53:14: @34[0]: _5 = const 2_i32
-52:17-54:6: @34[1]: _44 = const ()"><span class="annotation">@32,34⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="53:9-53:14: @34[0]: _5 = const 2_i32
-52:17-54:6: @34[1]: _44 = const ()">        a = 2;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="53:9-53:14: @34[0]: _5 = const 2_i32
-52:17-54:6: @34[1]: _44 = const ()">    }<span class="annotation">⦉@32,34</span></span></span><span><span class="code odd" style="--layer: 1" title="54:6-54:6: @33[0]: _44 = const ()"><span class="annotation">@33⦊</span>‸<span class="annotation">⦉@33</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code odd" style="--layer: 1" title="52:9-52:16: @28[5]: _46 = _1
+52:8-52:16: @28[6]: _45 = Not(move _46)"><span class="annotation">@28⦊</span>!is_true<span class="annotation">⦉@28</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="53:9-53:14: @29[0]: _5 = const 2_i32
+52:17-54:6: @29[1]: _44 = const ()"><span class="annotation">@29⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="53:9-53:14: @29[0]: _5 = const 2_i32
+52:17-54:6: @29[1]: _44 = const ()">        a = 2;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="53:9-53:14: @29[0]: _5 = const 2_i32
+52:17-54:6: @29[1]: _44 = const ()">    }<span class="annotation">⦉@29</span></span></span><span><span class="code odd" style="--layer: 1" title="54:6-54:6: @30[0]: _44 = const ()"><span class="annotation">@30⦊</span>‸<span class="annotation">⦉@30</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="56:8-56:15: @35[3]: _47 = _1
-56:8-56:15: @35[4]: FakeRead(ForMatchedPlace, _47)"><span class="annotation">@35⦊</span>is_true<span class="annotation">⦉@35</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="57:9-57:15: @38[0]: _6 = const 30_i32
-56:16-58:6: @38[1]: _0 = const ()"><span class="annotation">@36,38⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="57:9-57:15: @38[0]: _6 = const 30_i32
-56:16-58:6: @38[1]: _0 = const ()">        b = 30;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="57:9-57:15: @38[0]: _6 = const 30_i32
-56:16-58:6: @38[1]: _0 = const ()">    }<span class="annotation">⦉@36,38</span></span></span><span class="code" style="--layer: 0"> else </span><span><span class="code even" style="--layer: 1" title="59:9-59:16: @37[0]: _7 = const 400_i32
-58:12-60:6: @37[1]: _0 = const ()"><span class="annotation">@37⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="59:9-59:16: @37[0]: _7 = const 400_i32
-58:12-60:6: @37[1]: _0 = const ()">        c = 400;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="59:9-59:16: @37[0]: _7 = const 400_i32
-58:12-60:6: @37[1]: _0 = const ()">    }<span class="annotation">⦉@37</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="61:2-61:2: @39.Return: return"><span class="annotation">@39⦊</span>‸<span class="annotation">⦉@39</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="56:8-56:15: @31[3]: _47 = _1"><span class="annotation">@31⦊</span>is_true<span class="annotation">⦉@31</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="57:9-57:15: @32[0]: _6 = const 30_i32
+56:16-58:6: @32[1]: _0 = const ()"><span class="annotation">@32⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="57:9-57:15: @32[0]: _6 = const 30_i32
+56:16-58:6: @32[1]: _0 = const ()">        b = 30;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="57:9-57:15: @32[0]: _6 = const 30_i32
+56:16-58:6: @32[1]: _0 = const ()">    }<span class="annotation">⦉@32</span></span></span><span class="code" style="--layer: 0"> else </span><span><span class="code even" style="--layer: 1" title="59:9-59:16: @33[0]: _7 = const 400_i32
+58:12-60:6: @33[1]: _0 = const ()"><span class="annotation">@33⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="59:9-59:16: @33[0]: _7 = const 400_i32
+58:12-60:6: @33[1]: _0 = const ()">        c = 400;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="59:9-59:16: @33[0]: _7 = const 400_i32
+58:12-60:6: @33[1]: _0 = const ()">    }<span class="annotation">⦉@33</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="61:2-61:2: @34.Return: return"><span class="annotation">@34⦊</span>‸<span class="annotation">⦉@34</span></span></span></span></div>
 </body>
 </html>
diff --git "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loops_branches/loops_branches.\173impl\0430\175-fmt.-------.InstrumentCoverage.0.html" "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loops_branches/loops_branches.\173impl\0430\175-fmt.-------.InstrumentCoverage.0.html"
index 312d2ee..b3f344f 100644
--- "a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loops_branches/loops_branches.\173impl\0430\175-fmt.-------.InstrumentCoverage.0.html"
+++ "b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loops_branches/loops_branches.\173impl\0430\175-fmt.-------.InstrumentCoverage.0.html"
@@ -69,35 +69,32 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 8"><span class="line">    <span><span class="code even" style="--layer: 1" title="10:12-10:16: @0[2]: _4 = const true
-10:12-10:16: @0[3]: FakeRead(ForMatchedPlace, _4)"><span class="annotation">@0⦊</span>fn fmt(&amp;self, f: &amp;mut std::fmt::Formatter) -&gt; std::fmt::Result {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="10:12-10:16: @0[2]: _4 = const true
-10:12-10:16: @0[3]: FakeRead(ForMatchedPlace, _4)">        if true<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">            if </span><span><span class="code odd" style="--layer: 1" title="11:16-11:21: @3[2]: _6 = const false
-11:16-11:21: @3[3]: FakeRead(ForMatchedPlace, _6)"><span class="annotation">@1,3⦊</span>false<span class="annotation">⦉@1,3</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">                while </span><span><span class="code even" style="--layer: 1" title="12:23-12:27: @7[1]: _8 = const true
-12:23-12:27: @7[2]: FakeRead(ForMatchedPlace, _8)"><span class="annotation">@6,7⦊</span>true<span class="annotation">⦉@6,7</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="12:28-13:18: @10[0]: _7 = const ()"><span class="annotation">@8,10⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="12:28-13:18: @10[0]: _7 = const ()">                }<span class="annotation">⦉@8,10</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">            }</span><span><span class="code even" style="--layer: 1" title="14:14-14:14: @5[0]: _5 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="15:20-15:21: @11[6]: _13 = &amp;mut (*_2)
-15:23-15:30: @11[11]: _32 = const &lt;DebugTest as Debug&gt;::fmt::promoted[1]
-15:23-15:30: @11[12]: _17 = &amp;(*_32)
-15:23-15:30: @11[13]: _16 = &amp;(*_17)
-15:23-15:30: @11[14]: _15 = move _16 as &amp;[&amp;str] (Pointer(Unsize))
-15:13-15:31: @11[20]: _23 = ()
-15:13-15:31: @11[21]: FakeRead(ForMatchedPlace, _23)
-15:13-15:31: @11[22]: _31 = const &lt;DebugTest as Debug&gt;::fmt::promoted[0]
-15:13-15:31: @11[23]: _21 = &amp;(*_31)
-15:13-15:31: @11[24]: _20 = &amp;(*_21)
-15:13-15:31: @11[25]: _19 = move _20 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-15:13-15:31: @11.Call: _14 = Arguments::new_v1(move _15, move _19) -&gt; [return: bb12, unwind: bb23]
-15:13-15:31: @12.Call: _12 = Formatter::write_fmt(move _13, move _14) -&gt; [return: bb13, unwind: bb23]"><span class="annotation">@11,12,13,14⦊</span>write!(f, "error")<span class="annotation">⦉@11,12,13,14</span></span></span><span><span class="code even" style="--layer: 1" title="15:31-15:32: @18[1]: _25 = ((_11 as Err).0: std::fmt::Error)
-15:31-15:32: @18[4]: _28 = _25
-15:31-15:32: @18.Call: _27 = &lt;std::fmt::Error as From&lt;std::fmt::Error&gt;&gt;::from(move _28) -&gt; [return: bb19, unwind: bb23]"><span class="annotation">@16,18,19,20⦊</span>?<span class="annotation">⦉@16,18,19,20</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<div class="code" style="counter-reset: line 8"><span class="line">    <span><span class="code even" style="--layer: 1" title="10:12-10:16: @0[2]: _4 = const true"><span class="annotation">@0⦊</span>fn fmt(&amp;self, f: &amp;mut std::fmt::Formatter) -&gt; std::fmt::Result {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="10:12-10:16: @0[2]: _4 = const true">        if true<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">            if </span><span><span class="code odd" style="--layer: 1" title="11:16-11:21: @1[2]: _6 = const false"><span class="annotation">@1⦊</span>false<span class="annotation">⦉@1</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">                while </span><span><span class="code even" style="--layer: 1" title="12:23-12:27: @5[1]: _8 = const true
+12:23-12:27: @5[2]: FakeRead(ForMatchedPlace, _8)"><span class="annotation">@4,5⦊</span>true<span class="annotation">⦉@4,5</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="12:28-13:18: @8[0]: _7 = const ()"><span class="annotation">@6,8⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="12:28-13:18: @8[0]: _7 = const ()">                }<span class="annotation">⦉@6,8</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            }</span><span><span class="code even" style="--layer: 1" title="14:14-14:14: @3[0]: _5 = const ()"><span class="annotation">@3⦊</span>‸<span class="annotation">⦉@3</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="15:20-15:21: @9[6]: _13 = &amp;mut (*_2)
+15:23-15:30: @9[11]: _32 = const &lt;DebugTest as Debug&gt;::fmt::promoted[1]
+15:23-15:30: @9[12]: _17 = &amp;(*_32)
+15:23-15:30: @9[13]: _16 = &amp;(*_17)
+15:23-15:30: @9[14]: _15 = move _16 as &amp;[&amp;str] (Pointer(Unsize))
+15:13-15:31: @9[20]: _23 = ()
+15:13-15:31: @9[21]: FakeRead(ForMatchedPlace, _23)
+15:13-15:31: @9[22]: _31 = const &lt;DebugTest as Debug&gt;::fmt::promoted[0]
+15:13-15:31: @9[23]: _21 = &amp;(*_31)
+15:13-15:31: @9[24]: _20 = &amp;(*_21)
+15:13-15:31: @9[25]: _19 = move _20 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+15:13-15:31: @9.Call: _14 = Arguments::new_v1(move _15, move _19) -&gt; [return: bb10, unwind: bb21]
+15:13-15:31: @10.Call: _12 = Formatter::write_fmt(move _13, move _14) -&gt; [return: bb11, unwind: bb21]"><span class="annotation">@9,10,11,12⦊</span>write!(f, "error")<span class="annotation">⦉@9,10,11,12</span></span></span><span><span class="code even" style="--layer: 1" title="15:31-15:32: @16[1]: _25 = ((_11 as Err).0: std::fmt::Error)
+15:31-15:32: @16[4]: _28 = _25
+15:31-15:32: @16.Call: _27 = &lt;std::fmt::Error as From&lt;std::fmt::Error&gt;&gt;::from(move _28) -&gt; [return: bb17, unwind: bb21]"><span class="annotation">@14,16,17,18⦊</span>?<span class="annotation">⦉@14,16,17,18</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">        } else </span><span><span class="code odd" style="--layer: 1" title="16:16-17:10: @2[0]: _3 = const ()"><span class="annotation">@2⦊</span>{</span></span>
 <span class="line"><span class="code odd" style="--layer: 1" title="16:16-17:10: @2[0]: _3 = const ()">        }<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="18:12-18:14: @21[3]: _30 = ()
-18:9-18:15: @21[4]: _0 = std::result::Result::&lt;(), std::fmt::Error&gt;::Ok(move _30)"><span class="annotation">@21⦊</span>Ok(())<span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    }</span><span><span class="code odd" style="--layer: 1" title="19:6-19:6: @22.Return: return"><span class="annotation">@22⦊</span>‸<span class="annotation">⦉@22</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="18:12-18:14: @19[3]: _30 = ()
+18:9-18:15: @19[4]: _0 = std::result::Result::&lt;(), std::fmt::Error&gt;::Ok(move _30)"><span class="annotation">@19⦊</span>Ok(())<span class="annotation">⦉@19</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    }</span><span><span class="code odd" style="--layer: 1" title="19:6-19:6: @20.Return: return"><span class="annotation">@20⦊</span>‸<span class="annotation">⦉@20</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html
index 133a85c..c799261 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html
@@ -69,9 +69,9 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb37]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb36]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:21-9:22: @3[2]: _5 = const 0_u8
@@ -80,11 +80,10 @@
 10:21-10:22: @3[6]: _6 = const 0_u8
 10:9-10:14: @3[7]: FakeRead(ForLet, _6)
 10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
-11:8-11:15: @3[11]: _8 = _1
-11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+11:8-11:15: @3[11]: _8 = _1"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb37]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb36]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:21-9:22: @3[2]: _5 = const 0_u8
@@ -93,11 +92,10 @@
 10:21-10:22: @3[6]: _6 = const 0_u8
 10:9-10:14: @3[7]: FakeRead(ForLet, _6)
 10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
-11:8-11:15: @3[11]: _8 = _1
-11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+11:8-11:15: @3[11]: _8 = _1">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb37]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb36]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:21-9:22: @3[2]: _5 = const 0_u8
@@ -106,11 +104,10 @@
 10:21-10:22: @3[6]: _6 = const 0_u8
 10:9-10:14: @3[7]: FakeRead(ForLet, _6)
 10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
-11:8-11:15: @3[11]: _8 = _1
-11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+11:8-11:15: @3[11]: _8 = _1">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb37]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb36]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:21-9:22: @3[2]: _5 = const 0_u8
@@ -119,11 +116,10 @@
 10:21-10:22: @3[6]: _6 = const 0_u8
 10:9-10:14: @3[7]: FakeRead(ForLet, _6)
 10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
-11:8-11:15: @3[11]: _8 = _1
-11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)">    // dependent conditions.</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+11:8-11:15: @3[11]: _8 = _1">    // dependent conditions.</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb37]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb36]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:21-9:22: @3[2]: _5 = const 0_u8
@@ -132,11 +128,10 @@
 10:21-10:22: @3[6]: _6 = const 0_u8
 10:9-10:14: @3[7]: FakeRead(ForLet, _6)
 10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
-11:8-11:15: @3[11]: _8 = _1
-11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)">    let is_true = std::env::args().len() == 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+11:8-11:15: @3[11]: _8 = _1">    let is_true = std::env::args().len() == 1;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb37]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb36]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:21-9:22: @3[2]: _5 = const 0_u8
@@ -145,11 +140,10 @@
 10:21-10:22: @3[6]: _6 = const 0_u8
 10:9-10:14: @3[7]: FakeRead(ForLet, _6)
 10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
-11:8-11:15: @3[11]: _8 = _1
-11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"></span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+11:8-11:15: @3[11]: _8 = _1"></span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb37]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb36]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:21-9:22: @3[2]: _5 = const 0_u8
@@ -158,11 +152,10 @@
 10:21-10:22: @3[6]: _6 = const 0_u8
 10:9-10:14: @3[7]: FakeRead(ForLet, _6)
 10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
-11:8-11:15: @3[11]: _8 = _1
-11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)">    let mut a: u8 = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+11:8-11:15: @3[11]: _8 = _1">    let mut a: u8 = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb37]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb36]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:21-9:22: @3[2]: _5 = const 0_u8
@@ -171,11 +164,10 @@
 10:21-10:22: @3[6]: _6 = const 0_u8
 10:9-10:14: @3[7]: FakeRead(ForLet, _6)
 10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
-11:8-11:15: @3[11]: _8 = _1
-11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)">    let mut b: u8 = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
+11:8-11:15: @3[11]: _8 = _1">    let mut b: u8 = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb37]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb36]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:21-9:22: @3[2]: _5 = const 0_u8
@@ -184,88 +176,84 @@
 10:21-10:22: @3[6]: _6 = const 0_u8
 10:9-10:14: @3[7]: FakeRead(ForLet, _6)
 10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
-11:8-11:15: @3[11]: _8 = _1
-11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="12:9-12:14: @6[0]: _5 = const 2_u8
-13:9-13:14: @6[1]: _6 = const 0_u8
-11:16-14:6: @6[2]: _7 = const ()"><span class="annotation">@4,6⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:14: @6[0]: _5 = const 2_u8
-13:9-13:14: @6[1]: _6 = const 0_u8
-11:16-14:6: @6[2]: _7 = const ()">        a = 2;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:14: @6[0]: _5 = const 2_u8
-13:9-13:14: @6[1]: _6 = const 0_u8
-11:16-14:6: @6[2]: _7 = const ()">        b = 0;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:14: @6[0]: _5 = const 2_u8
-13:9-13:14: @6[1]: _6 = const 0_u8
-11:16-14:6: @6[2]: _7 = const ()">    }<span class="annotation">⦉@4,6</span></span></span><span><span class="code even" style="--layer: 1" title="14:6-14:6: @5[0]: _7 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    match </span><span><span class="code odd" style="--layer: 1" title="15:12-15:13: @7[5]: _11 = _5
-15:15-15:16: @7[7]: _12 = _6
-15:11-15:17: @7[8]: _10 = (move _11, move _12)
-15:11-15:17: @7[11]: FakeRead(ForMatchedPlace, _10)"><span class="annotation">@7⦊</span>(a, b)<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+11:8-11:15: @3[11]: _8 = _1">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="12:9-12:14: @4[0]: _5 = const 2_u8
+13:9-13:14: @4[1]: _6 = const 0_u8
+11:16-14:6: @4[2]: _7 = const ()"><span class="annotation">@4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:14: @4[0]: _5 = const 2_u8
+13:9-13:14: @4[1]: _6 = const 0_u8
+11:16-14:6: @4[2]: _7 = const ()">        a = 2;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:14: @4[0]: _5 = const 2_u8
+13:9-13:14: @4[1]: _6 = const 0_u8
+11:16-14:6: @4[2]: _7 = const ()">        b = 0;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:14: @4[0]: _5 = const 2_u8
+13:9-13:14: @4[1]: _6 = const 0_u8
+11:16-14:6: @4[2]: _7 = const ()">    }<span class="annotation">⦉@4</span></span></span><span><span class="code even" style="--layer: 1" title="14:6-14:6: @5[0]: _7 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    match </span><span><span class="code odd" style="--layer: 1" title="15:12-15:13: @6[5]: _11 = _5
+15:15-15:16: @6[7]: _12 = _6
+15:11-15:17: @6[8]: _10 = (move _11, move _12)
+15:11-15:17: @6[11]: FakeRead(ForMatchedPlace, _10)"><span class="annotation">@6⦊</span>(a, b)<span class="annotation">⦉@6</span></span></span><span class="code" style="--layer: 0"> {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.</span></span>
 <span class="line"><span class="code" style="--layer: 0">        // This test confirms a fix for Issue #79569.</span></span>
-<span class="line"><span class="code" style="--layer: 0">        (0 | 1, 2 | 3) =&gt; </span><span><span class="code even" style="--layer: 1" title="18:27-18:29: @11[0]: _9 = const ()"><span class="annotation">@10,11⦊</span>{}<span class="annotation">⦉@10,11</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        _ =&gt; </span><span><span class="code odd" style="--layer: 1" title="19:14-19:16: @8[0]: _9 = const ()"><span class="annotation">@8⦊</span>{}<span class="annotation">⦉@8</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        (0 | 1, 2 | 3) =&gt; </span><span><span class="code even" style="--layer: 1" title="18:27-18:29: @10[0]: _9 = const ()"><span class="annotation">@9,10⦊</span>{}<span class="annotation">⦉@9,10</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        _ =&gt; </span><span><span class="code odd" style="--layer: 1" title="19:14-19:16: @7[0]: _9 = const ()"><span class="annotation">@7⦊</span>{}<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="21:8-21:15: @12[4]: _14 = _1
-21:8-21:15: @12[5]: FakeRead(ForMatchedPlace, _14)"><span class="annotation">@12⦊</span>is_true<span class="annotation">⦉@12</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="22:9-22:14: @15[0]: _5 = const 0_u8
-23:9-23:14: @15[1]: _6 = const 0_u8
-21:16-24:6: @15[2]: _13 = const ()"><span class="annotation">@13,15⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="22:9-22:14: @15[0]: _5 = const 0_u8
-23:9-23:14: @15[1]: _6 = const 0_u8
-21:16-24:6: @15[2]: _13 = const ()">        a = 0;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="22:9-22:14: @15[0]: _5 = const 0_u8
-23:9-23:14: @15[1]: _6 = const 0_u8
-21:16-24:6: @15[2]: _13 = const ()">        b = 0;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="22:9-22:14: @15[0]: _5 = const 0_u8
-23:9-23:14: @15[1]: _6 = const 0_u8
-21:16-24:6: @15[2]: _13 = const ()">    }<span class="annotation">⦉@13,15</span></span></span><span><span class="code even" style="--layer: 1" title="24:6-24:6: @14[0]: _13 = const ()"><span class="annotation">@14⦊</span>‸<span class="annotation">⦉@14</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    match </span><span><span class="code odd" style="--layer: 1" title="25:12-25:13: @16[5]: _17 = _5
-25:15-25:16: @16[7]: _18 = _6
-25:11-25:17: @16[8]: _16 = (move _17, move _18)
-25:11-25:17: @16[11]: FakeRead(ForMatchedPlace, _16)"><span class="annotation">@16⦊</span>(a, b)<span class="annotation">⦉@16</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        (0 | 1, 2 | 3) =&gt; </span><span><span class="code even" style="--layer: 1" title="26:27-26:29: @20[0]: _15 = const ()"><span class="annotation">@19,20⦊</span>{}<span class="annotation">⦉@19,20</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        _ =&gt; </span><span><span class="code odd" style="--layer: 1" title="27:14-27:16: @17[0]: _15 = const ()"><span class="annotation">@17⦊</span>{}<span class="annotation">⦉@17</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="21:8-21:15: @11[4]: _14 = _1"><span class="annotation">@11⦊</span>is_true<span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="22:9-22:14: @12[0]: _5 = const 0_u8
+23:9-23:14: @12[1]: _6 = const 0_u8
+21:16-24:6: @12[2]: _13 = const ()"><span class="annotation">@12⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="22:9-22:14: @12[0]: _5 = const 0_u8
+23:9-23:14: @12[1]: _6 = const 0_u8
+21:16-24:6: @12[2]: _13 = const ()">        a = 0;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="22:9-22:14: @12[0]: _5 = const 0_u8
+23:9-23:14: @12[1]: _6 = const 0_u8
+21:16-24:6: @12[2]: _13 = const ()">        b = 0;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="22:9-22:14: @12[0]: _5 = const 0_u8
+23:9-23:14: @12[1]: _6 = const 0_u8
+21:16-24:6: @12[2]: _13 = const ()">    }<span class="annotation">⦉@12</span></span></span><span><span class="code even" style="--layer: 1" title="24:6-24:6: @13[0]: _13 = const ()"><span class="annotation">@13⦊</span>‸<span class="annotation">⦉@13</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    match </span><span><span class="code odd" style="--layer: 1" title="25:12-25:13: @14[5]: _17 = _5
+25:15-25:16: @14[7]: _18 = _6
+25:11-25:17: @14[8]: _16 = (move _17, move _18)
+25:11-25:17: @14[11]: FakeRead(ForMatchedPlace, _16)"><span class="annotation">@14⦊</span>(a, b)<span class="annotation">⦉@14</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        (0 | 1, 2 | 3) =&gt; </span><span><span class="code even" style="--layer: 1" title="26:27-26:29: @18[0]: _15 = const ()"><span class="annotation">@17,18⦊</span>{}<span class="annotation">⦉@17,18</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        _ =&gt; </span><span><span class="code odd" style="--layer: 1" title="27:14-27:16: @15[0]: _15 = const ()"><span class="annotation">@15⦊</span>{}<span class="annotation">⦉@15</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="29:8-29:15: @21[4]: _20 = _1
-29:8-29:15: @21[5]: FakeRead(ForMatchedPlace, _20)"><span class="annotation">@21⦊</span>is_true<span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="30:9-30:14: @24[0]: _5 = const 2_u8
-31:9-31:14: @24[1]: _6 = const 2_u8
-29:16-32:6: @24[2]: _19 = const ()"><span class="annotation">@22,24⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="30:9-30:14: @24[0]: _5 = const 2_u8
-31:9-31:14: @24[1]: _6 = const 2_u8
-29:16-32:6: @24[2]: _19 = const ()">        a = 2;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="30:9-30:14: @24[0]: _5 = const 2_u8
-31:9-31:14: @24[1]: _6 = const 2_u8
-29:16-32:6: @24[2]: _19 = const ()">        b = 2;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="30:9-30:14: @24[0]: _5 = const 2_u8
-31:9-31:14: @24[1]: _6 = const 2_u8
-29:16-32:6: @24[2]: _19 = const ()">    }<span class="annotation">⦉@22,24</span></span></span><span><span class="code even" style="--layer: 1" title="32:6-32:6: @23[0]: _19 = const ()"><span class="annotation">@23⦊</span>‸<span class="annotation">⦉@23</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    match </span><span><span class="code odd" style="--layer: 1" title="33:12-33:13: @25[5]: _23 = _5
-33:15-33:16: @25[7]: _24 = _6
-33:11-33:17: @25[8]: _22 = (move _23, move _24)
-33:11-33:17: @25[11]: FakeRead(ForMatchedPlace, _22)"><span class="annotation">@25⦊</span>(a, b)<span class="annotation">⦉@25</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        (0 | 1, 2 | 3) =&gt; </span><span><span class="code even" style="--layer: 1" title="34:27-34:29: @29[0]: _21 = const ()"><span class="annotation">@28,29⦊</span>{}<span class="annotation">⦉@28,29</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        _ =&gt; </span><span><span class="code odd" style="--layer: 1" title="35:14-35:16: @26[0]: _21 = const ()"><span class="annotation">@26⦊</span>{}<span class="annotation">⦉@26</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="29:8-29:15: @19[4]: _20 = _1"><span class="annotation">@19⦊</span>is_true<span class="annotation">⦉@19</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="30:9-30:14: @20[0]: _5 = const 2_u8
+31:9-31:14: @20[1]: _6 = const 2_u8
+29:16-32:6: @20[2]: _19 = const ()"><span class="annotation">@20⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="30:9-30:14: @20[0]: _5 = const 2_u8
+31:9-31:14: @20[1]: _6 = const 2_u8
+29:16-32:6: @20[2]: _19 = const ()">        a = 2;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="30:9-30:14: @20[0]: _5 = const 2_u8
+31:9-31:14: @20[1]: _6 = const 2_u8
+29:16-32:6: @20[2]: _19 = const ()">        b = 2;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="30:9-30:14: @20[0]: _5 = const 2_u8
+31:9-31:14: @20[1]: _6 = const 2_u8
+29:16-32:6: @20[2]: _19 = const ()">    }<span class="annotation">⦉@20</span></span></span><span><span class="code even" style="--layer: 1" title="32:6-32:6: @21[0]: _19 = const ()"><span class="annotation">@21⦊</span>‸<span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    match </span><span><span class="code odd" style="--layer: 1" title="33:12-33:13: @22[5]: _23 = _5
+33:15-33:16: @22[7]: _24 = _6
+33:11-33:17: @22[8]: _22 = (move _23, move _24)
+33:11-33:17: @22[11]: FakeRead(ForMatchedPlace, _22)"><span class="annotation">@22⦊</span>(a, b)<span class="annotation">⦉@22</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        (0 | 1, 2 | 3) =&gt; </span><span><span class="code even" style="--layer: 1" title="34:27-34:29: @26[0]: _21 = const ()"><span class="annotation">@25,26⦊</span>{}<span class="annotation">⦉@25,26</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        _ =&gt; </span><span><span class="code odd" style="--layer: 1" title="35:14-35:16: @23[0]: _21 = const ()"><span class="annotation">@23⦊</span>{}<span class="annotation">⦉@23</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="37:8-37:15: @30[4]: _26 = _1
-37:8-37:15: @30[5]: FakeRead(ForMatchedPlace, _26)"><span class="annotation">@30⦊</span>is_true<span class="annotation">⦉@30</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="38:9-38:14: @33[0]: _5 = const 0_u8
-39:9-39:14: @33[1]: _6 = const 2_u8
-37:16-40:6: @33[2]: _25 = const ()"><span class="annotation">@31,33⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="38:9-38:14: @33[0]: _5 = const 0_u8
-39:9-39:14: @33[1]: _6 = const 2_u8
-37:16-40:6: @33[2]: _25 = const ()">        a = 0;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="38:9-38:14: @33[0]: _5 = const 0_u8
-39:9-39:14: @33[1]: _6 = const 2_u8
-37:16-40:6: @33[2]: _25 = const ()">        b = 2;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="38:9-38:14: @33[0]: _5 = const 0_u8
-39:9-39:14: @33[1]: _6 = const 2_u8
-37:16-40:6: @33[2]: _25 = const ()">    }<span class="annotation">⦉@31,33</span></span></span><span><span class="code even" style="--layer: 1" title="40:6-40:6: @32[0]: _25 = const ()"><span class="annotation">@32⦊</span>‸<span class="annotation">⦉@32</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    match </span><span><span class="code odd" style="--layer: 1" title="41:12-41:13: @34[4]: _28 = _5
-41:15-41:16: @34[6]: _29 = _6
-41:11-41:17: @34[7]: _27 = (move _28, move _29)
-41:11-41:17: @34[10]: FakeRead(ForMatchedPlace, _27)"><span class="annotation">@34⦊</span>(a, b)<span class="annotation">⦉@34</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        (0 | 1, 2 | 3) =&gt; </span><span><span class="code even" style="--layer: 1" title="42:27-42:29: @38[0]: _0 = const ()"><span class="annotation">@37,38⦊</span>{}<span class="annotation">⦉@37,38</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        _ =&gt; </span><span><span class="code odd" style="--layer: 1" title="43:14-43:16: @35[0]: _0 = const ()"><span class="annotation">@35⦊</span>{}<span class="annotation">⦉@35</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="37:8-37:15: @27[4]: _26 = _1"><span class="annotation">@27⦊</span>is_true<span class="annotation">⦉@27</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="38:9-38:14: @28[0]: _5 = const 0_u8
+39:9-39:14: @28[1]: _6 = const 2_u8
+37:16-40:6: @28[2]: _25 = const ()"><span class="annotation">@28⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="38:9-38:14: @28[0]: _5 = const 0_u8
+39:9-39:14: @28[1]: _6 = const 2_u8
+37:16-40:6: @28[2]: _25 = const ()">        a = 0;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="38:9-38:14: @28[0]: _5 = const 0_u8
+39:9-39:14: @28[1]: _6 = const 2_u8
+37:16-40:6: @28[2]: _25 = const ()">        b = 2;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="38:9-38:14: @28[0]: _5 = const 0_u8
+39:9-39:14: @28[1]: _6 = const 2_u8
+37:16-40:6: @28[2]: _25 = const ()">    }<span class="annotation">⦉@28</span></span></span><span><span class="code even" style="--layer: 1" title="40:6-40:6: @29[0]: _25 = const ()"><span class="annotation">@29⦊</span>‸<span class="annotation">⦉@29</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    match </span><span><span class="code odd" style="--layer: 1" title="41:12-41:13: @30[4]: _28 = _5
+41:15-41:16: @30[6]: _29 = _6
+41:11-41:17: @30[7]: _27 = (move _28, move _29)
+41:11-41:17: @30[10]: FakeRead(ForMatchedPlace, _27)"><span class="annotation">@30⦊</span>(a, b)<span class="annotation">⦉@30</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        (0 | 1, 2 | 3) =&gt; </span><span><span class="code even" style="--layer: 1" title="42:27-42:29: @34[0]: _0 = const ()"><span class="annotation">@33,34⦊</span>{}<span class="annotation">⦉@33,34</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        _ =&gt; </span><span><span class="code odd" style="--layer: 1" title="43:14-43:16: @31[0]: _0 = const ()"><span class="annotation">@31⦊</span>{}<span class="annotation">⦉@31</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code even" style="--layer: 1" title="45:2-45:2: @39.Return: return"><span class="annotation">@39⦊</span>‸<span class="annotation">⦉@39</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code even" style="--layer: 1" title="45:2-45:2: @35.Return: return"><span class="annotation">@35⦊</span>‸<span class="annotation">⦉@35</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html
index cb60276..4dcf6c7 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html
@@ -69,23 +69,23 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 0"><span class="line"><span><span class="code even" style="--layer: 1" title="2:19-2:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb35]
+<div class="code" style="counter-reset: line 0"><span class="line"><span><span class="code even" style="--layer: 1" title="2:19-2:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb32]
 2:19-2:35: @1[0]: _3 = &amp;_4
-2:19-2:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb34]
+2:19-2:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb31]
 2:19-2:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 2:9-2:16: @2[3]: FakeRead(ForLet, _1)
 3:25-3:27: @3[2]: _5 = const 10_i32
 3:9-3:22: @3[3]: FakeRead(ForLet, _5)"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="2:19-2:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb35]
+<span class="line"><span class="code even" style="--layer: 1" title="2:19-2:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb32]
 2:19-2:35: @1[0]: _3 = &amp;_4
-2:19-2:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb34]
+2:19-2:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb31]
 2:19-2:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 2:9-2:16: @2[3]: FakeRead(ForLet, _1)
 3:25-3:27: @3[2]: _5 = const 10_i32
 3:9-3:22: @3[3]: FakeRead(ForLet, _5)">    let is_true = std::env::args().len() == 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="2:19-2:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb35]
+<span class="line"><span class="code even" style="--layer: 1" title="2:19-2:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb32]
 2:19-2:35: @1[0]: _3 = &amp;_4
-2:19-2:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb34]
+2:19-2:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb31]
 2:19-2:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 2:9-2:16: @2[3]: FakeRead(ForLet, _1)
 3:25-3:27: @3[2]: _5 = const 10_i32
@@ -107,67 +107,60 @@
 8:13-8:14: @16[4]: _15 = move _22
 8:13-8:14: @16[5]: _16 = const ()"><span class="annotation">@14,16⦊</span>_<span class="annotation">⦉@14,16</span></span></span><span class="code" style="--layer: 0"> in </span><span><span class="code even" style="--layer: 1" title="8:18-8:23: @11[5]: _19 = &amp;mut _14
 8:18-8:23: @11[6]: _18 = &amp;mut (*_19)
-8:18-8:23: @11.Call: _17 = &lt;std::ops::Range&lt;i32&gt; as Iterator&gt;::next(move _18) -&gt; [return: bb12, unwind: bb35]
+8:18-8:23: @11.Call: _17 = &lt;std::ops::Range&lt;i32&gt; as Iterator&gt;::next(move _18) -&gt; [return: bb12, unwind: bb32]
 8:18-8:23: @12[1]: FakeRead(ForMatchedPlace, _17)"><span class="annotation">@10,11,12⦊</span>0..50<span class="annotation">⦉@10,11,12</span></span></span><span class="code" style="--layer: 0"> {</span></span>
 <span class="line"><span class="code" style="--layer: 0">            if </span><span><span class="code odd" style="--layer: 1" title="9:16-9:17: @16[15]: _27 = _9
-9:16-9:22: @16[16]: _26 = Lt(move _27, const 30_i32)
-9:16-9:22: @16[18]: FakeRead(ForMatchedPlace, _26)"><span class="annotation">@14,16⦊</span>a &lt; 30<span class="annotation">⦉@14,16</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">                </span><span><span class="code even" style="--layer: 1" title="10:17-10:22: @19[0]: _11 = const ()"><span class="annotation">@17,19⦊</span>break<span class="annotation">⦉@17,19</span></span></span><span class="code" style="--layer: 0">;</span></span>
+9:16-9:22: @16[16]: _26 = Lt(move _27, const 30_i32)"><span class="annotation">@14,16⦊</span>a &lt; 30<span class="annotation">⦉@14,16</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">                </span><span><span class="code even" style="--layer: 1" title="10:17-10:22: @17[0]: _11 = const ()"><span class="annotation">@17⦊</span>break<span class="annotation">⦉@17</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">            }</span><span><span class="code odd" style="--layer: 1" title="11:14-11:14: @18[0]: _25 = const ()
 12:13-12:19: @18[3]: _29 = CheckedSub(_9, const 5_i32)
-12:13-12:19: @20[0]: _9 = move (_29.0: i32)
-13:13-13:19: @20[1]: _30 = CheckedSub(_10, const 5_i32)
-13:13-13:19: @21[0]: _10 = move (_30.0: i32)
-14:16-14:17: @21[3]: _32 = _10
-14:16-14:22: @21[4]: _31 = Lt(move _32, const 90_i32)
-14:16-14:22: @21[6]: FakeRead(ForMatchedPlace, _31)"><span class="annotation">@18,20,21⦊</span></span></span>
+12:13-12:19: @19[0]: _9 = move (_29.0: i32)
+13:13-13:19: @19[1]: _30 = CheckedSub(_10, const 5_i32)
+13:13-13:19: @20[0]: _10 = move (_30.0: i32)
+14:16-14:17: @20[3]: _32 = _10
+14:16-14:22: @20[4]: _31 = Lt(move _32, const 90_i32)"><span class="annotation">@18,19,20⦊</span></span></span>
 <span class="line"><span class="code odd" style="--layer: 1" title="11:14-11:14: @18[0]: _25 = const ()
 12:13-12:19: @18[3]: _29 = CheckedSub(_9, const 5_i32)
-12:13-12:19: @20[0]: _9 = move (_29.0: i32)
-13:13-13:19: @20[1]: _30 = CheckedSub(_10, const 5_i32)
-13:13-13:19: @21[0]: _10 = move (_30.0: i32)
-14:16-14:17: @21[3]: _32 = _10
-14:16-14:22: @21[4]: _31 = Lt(move _32, const 90_i32)
-14:16-14:22: @21[6]: FakeRead(ForMatchedPlace, _31)">            a -= 5;</span></span>
+12:13-12:19: @19[0]: _9 = move (_29.0: i32)
+13:13-13:19: @19[1]: _30 = CheckedSub(_10, const 5_i32)
+13:13-13:19: @20[0]: _10 = move (_30.0: i32)
+14:16-14:17: @20[3]: _32 = _10
+14:16-14:22: @20[4]: _31 = Lt(move _32, const 90_i32)">            a -= 5;</span></span>
 <span class="line"><span class="code odd" style="--layer: 1" title="11:14-11:14: @18[0]: _25 = const ()
 12:13-12:19: @18[3]: _29 = CheckedSub(_9, const 5_i32)
-12:13-12:19: @20[0]: _9 = move (_29.0: i32)
-13:13-13:19: @20[1]: _30 = CheckedSub(_10, const 5_i32)
-13:13-13:19: @21[0]: _10 = move (_30.0: i32)
-14:16-14:17: @21[3]: _32 = _10
-14:16-14:22: @21[4]: _31 = Lt(move _32, const 90_i32)
-14:16-14:22: @21[6]: FakeRead(ForMatchedPlace, _31)">            b -= 5;</span></span>
+12:13-12:19: @19[0]: _9 = move (_29.0: i32)
+13:13-13:19: @19[1]: _30 = CheckedSub(_10, const 5_i32)
+13:13-13:19: @20[0]: _10 = move (_30.0: i32)
+14:16-14:17: @20[3]: _32 = _10
+14:16-14:22: @20[4]: _31 = Lt(move _32, const 90_i32)">            b -= 5;</span></span>
 <span class="line"><span class="code odd" style="--layer: 1" title="11:14-11:14: @18[0]: _25 = const ()
 12:13-12:19: @18[3]: _29 = CheckedSub(_9, const 5_i32)
-12:13-12:19: @20[0]: _9 = move (_29.0: i32)
-13:13-13:19: @20[1]: _30 = CheckedSub(_10, const 5_i32)
-13:13-13:19: @21[0]: _10 = move (_30.0: i32)
-14:16-14:17: @21[3]: _32 = _10
-14:16-14:22: @21[4]: _31 = Lt(move _32, const 90_i32)
-14:16-14:22: @21[6]: FakeRead(ForMatchedPlace, _31)">            if b &lt; 90<span class="annotation">⦉@18,20,21</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">                </span><span><span class="code even" style="--layer: 1" title="15:17-15:24: @24[0]: _33 = CheckedSub(_9, const 10_i32)
-15:17-15:24: @25[0]: _9 = move (_33.0: i32)
-16:20-16:27: @25[2]: _34 = _1
-16:20-16:27: @25[3]: FakeRead(ForMatchedPlace, _34)"><span class="annotation">@22,24,25⦊</span>a -= 10;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="15:17-15:24: @24[0]: _33 = CheckedSub(_9, const 10_i32)
-15:17-15:24: @25[0]: _9 = move (_33.0: i32)
-16:20-16:27: @25[2]: _34 = _1
-16:20-16:27: @25[3]: FakeRead(ForMatchedPlace, _34)">                if is_true<span class="annotation">⦉@22,24,25</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">                    </span><span><span class="code odd" style="--layer: 1" title="17:21-17:33: @28[0]: _0 = const ()"><span class="annotation">@26,28⦊</span>break 'outer<span class="annotation">⦉@26,28</span></span></span><span class="code" style="--layer: 0">;</span></span>
-<span class="line"><span class="code" style="--layer: 0">                } else </span><span><span class="code even" style="--layer: 1" title="19:21-19:27: @27[0]: _36 = CheckedSub(_9, const 2_i32)
-19:21-19:27: @29[0]: _9 = move (_36.0: i32)
-18:24-20:18: @29[1]: _24 = const ()"><span class="annotation">@27,29⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="19:21-19:27: @27[0]: _36 = CheckedSub(_9, const 2_i32)
-19:21-19:27: @29[0]: _9 = move (_36.0: i32)
-18:24-20:18: @29[1]: _24 = const ()">                    a -= 2;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="19:21-19:27: @27[0]: _36 = CheckedSub(_9, const 2_i32)
-19:21-19:27: @29[0]: _9 = move (_36.0: i32)
-18:24-20:18: @29[1]: _24 = const ()">                }<span class="annotation">⦉@27,29</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">            }</span><span><span class="code odd" style="--layer: 1" title="21:14-21:14: @23[0]: _24 = const ()"><span class="annotation">@23⦊</span>‸<span class="annotation">⦉@23</span></span></span><span class="code" style="--layer: 0"></span></span>
+12:13-12:19: @19[0]: _9 = move (_29.0: i32)
+13:13-13:19: @19[1]: _30 = CheckedSub(_10, const 5_i32)
+13:13-13:19: @20[0]: _10 = move (_30.0: i32)
+14:16-14:17: @20[3]: _32 = _10
+14:16-14:22: @20[4]: _31 = Lt(move _32, const 90_i32)">            if b &lt; 90<span class="annotation">⦉@18,19,20</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">                </span><span><span class="code even" style="--layer: 1" title="15:17-15:24: @21[0]: _33 = CheckedSub(_9, const 10_i32)
+15:17-15:24: @23[0]: _9 = move (_33.0: i32)
+16:20-16:27: @23[2]: _34 = _1"><span class="annotation">@21,23⦊</span>a -= 10;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="15:17-15:24: @21[0]: _33 = CheckedSub(_9, const 10_i32)
+15:17-15:24: @23[0]: _9 = move (_33.0: i32)
+16:20-16:27: @23[2]: _34 = _1">                if is_true<span class="annotation">⦉@21,23</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">                    </span><span><span class="code odd" style="--layer: 1" title="17:21-17:33: @24[0]: _0 = const ()"><span class="annotation">@24⦊</span>break 'outer<span class="annotation">⦉@24</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">                } else </span><span><span class="code even" style="--layer: 1" title="19:21-19:27: @25[0]: _36 = CheckedSub(_9, const 2_i32)
+19:21-19:27: @26[0]: _9 = move (_36.0: i32)
+18:24-20:18: @26[1]: _24 = const ()"><span class="annotation">@25,26⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="19:21-19:27: @25[0]: _36 = CheckedSub(_9, const 2_i32)
+19:21-19:27: @26[0]: _9 = move (_36.0: i32)
+18:24-20:18: @26[1]: _24 = const ()">                    a -= 2;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="19:21-19:27: @25[0]: _36 = CheckedSub(_9, const 2_i32)
+19:21-19:27: @26[0]: _9 = move (_36.0: i32)
+18:24-20:18: @26[1]: _24 = const ()">                }<span class="annotation">⦉@25,26</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            }</span><span><span class="code odd" style="--layer: 1" title="21:14-21:14: @22[0]: _24 = const ()"><span class="annotation">@22⦊</span>‸<span class="annotation">⦉@22</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        }</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="23:9-23:23: @31[4]: _37 = CheckedSub(_5, const 1_i32)
-23:9-23:23: @32[0]: _5 = move (_37.0: i32)"><span class="annotation">@31,32⦊</span>countdown -= 1<span class="annotation">⦉@31,32</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="23:9-23:23: @28[4]: _37 = CheckedSub(_5, const 1_i32)
+23:9-23:23: @29[0]: _5 = move (_37.0: i32)"><span class="annotation">@28,29⦊</span>countdown -= 1<span class="annotation">⦉@28,29</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="25:2-25:2: @33.Return: return"><span class="annotation">@33⦊</span>‸<span class="annotation">⦉@33</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="25:2-25:2: @30.Return: return"><span class="annotation">@30⦊</span>‸<span class="annotation">⦉@30</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.main.-------.InstrumentCoverage.0.html
index 6739634..ca35156 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.main.-------.InstrumentCoverage.0.html
@@ -77,178 +77,176 @@
 17:11-17:24: @2[3]: _4 = Gt(move _5, const 0_i32)
 17:11-17:24: @2[5]: FakeRead(ForMatchedPlace, _4)"><span class="annotation">@1,2⦊</span>countdown &gt; 0<span class="annotation">⦉@1,2</span></span></span><span class="code" style="--layer: 0"> {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code even" style="--layer: 1" title="18:12-18:21: @5[3]: _8 = _1
-18:12-18:26: @5[4]: _7 = Eq(move _8, const 1_i32)
-18:12-18:26: @5[6]: FakeRead(ForMatchedPlace, _7)"><span class="annotation">@3,5⦊</span>countdown == 1<span class="annotation">⦉@3,5</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="19:26-19:44: @8.Call: _9 = might_overflow(const 10_u32) -&gt; [return: bb9, unwind: bb23]
-19:17-19:23: @9[0]: FakeRead(ForLet, _9)
-20:22-20:34: @9[7]: _51 = const main::promoted[1]
-20:22-20:34: @9[8]: _15 = &amp;(*_51)
-20:22-20:34: @9[9]: _14 = &amp;(*_15)
-20:22-20:34: @9[10]: _13 = move _14 as &amp;[&amp;str] (Pointer(Unsize))
-20:36-20:42: @9[18]: _22 = &amp;_9
-20:13-20:44: @9[19]: _21 = (move _22,)
-20:13-20:44: @9[21]: FakeRead(ForMatchedPlace, _21)
-20:13-20:44: @9[23]: _23 = (_21.0: &amp;u32)
-20:13-20:44: @9[26]: _25 = &amp;(*_23)
-20:13-20:44: @9[28]: _26 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-20:13-20:44: @9.Call: _24 = ArgumentV1::new::&lt;u32&gt;(move _25, move _26) -&gt; [return: bb10, unwind: bb23]
-20:13-20:44: @10[2]: _20 = [move _24]
-20:13-20:44: @10[5]: _19 = &amp;_20
-20:13-20:44: @10[6]: _18 = &amp;(*_19)
-20:13-20:44: @10[7]: _17 = move _18 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-20:13-20:44: @10.Call: _12 = Arguments::new_v1(move _13, move _17) -&gt; [return: bb11, unwind: bb23]
-20:13-20:44: @11.Call: _11 = _print(move _12) -&gt; [return: bb12, unwind: bb23]
-20:13-20:44: @12[6]: _10 = const ()
-18:27-21:10: @12[8]: _6 = const ()"><span class="annotation">@6,8,9,10,11,12⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="19:26-19:44: @8.Call: _9 = might_overflow(const 10_u32) -&gt; [return: bb9, unwind: bb23]
-19:17-19:23: @9[0]: FakeRead(ForLet, _9)
-20:22-20:34: @9[7]: _51 = const main::promoted[1]
-20:22-20:34: @9[8]: _15 = &amp;(*_51)
-20:22-20:34: @9[9]: _14 = &amp;(*_15)
-20:22-20:34: @9[10]: _13 = move _14 as &amp;[&amp;str] (Pointer(Unsize))
-20:36-20:42: @9[18]: _22 = &amp;_9
-20:13-20:44: @9[19]: _21 = (move _22,)
-20:13-20:44: @9[21]: FakeRead(ForMatchedPlace, _21)
-20:13-20:44: @9[23]: _23 = (_21.0: &amp;u32)
-20:13-20:44: @9[26]: _25 = &amp;(*_23)
-20:13-20:44: @9[28]: _26 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-20:13-20:44: @9.Call: _24 = ArgumentV1::new::&lt;u32&gt;(move _25, move _26) -&gt; [return: bb10, unwind: bb23]
-20:13-20:44: @10[2]: _20 = [move _24]
-20:13-20:44: @10[5]: _19 = &amp;_20
-20:13-20:44: @10[6]: _18 = &amp;(*_19)
-20:13-20:44: @10[7]: _17 = move _18 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-20:13-20:44: @10.Call: _12 = Arguments::new_v1(move _13, move _17) -&gt; [return: bb11, unwind: bb23]
-20:13-20:44: @11.Call: _11 = _print(move _12) -&gt; [return: bb12, unwind: bb23]
-20:13-20:44: @12[6]: _10 = const ()
-18:27-21:10: @12[8]: _6 = const ()">            let result = might_overflow(10);</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="19:26-19:44: @8.Call: _9 = might_overflow(const 10_u32) -&gt; [return: bb9, unwind: bb23]
-19:17-19:23: @9[0]: FakeRead(ForLet, _9)
-20:22-20:34: @9[7]: _51 = const main::promoted[1]
-20:22-20:34: @9[8]: _15 = &amp;(*_51)
-20:22-20:34: @9[9]: _14 = &amp;(*_15)
-20:22-20:34: @9[10]: _13 = move _14 as &amp;[&amp;str] (Pointer(Unsize))
-20:36-20:42: @9[18]: _22 = &amp;_9
-20:13-20:44: @9[19]: _21 = (move _22,)
-20:13-20:44: @9[21]: FakeRead(ForMatchedPlace, _21)
-20:13-20:44: @9[23]: _23 = (_21.0: &amp;u32)
-20:13-20:44: @9[26]: _25 = &amp;(*_23)
-20:13-20:44: @9[28]: _26 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-20:13-20:44: @9.Call: _24 = ArgumentV1::new::&lt;u32&gt;(move _25, move _26) -&gt; [return: bb10, unwind: bb23]
-20:13-20:44: @10[2]: _20 = [move _24]
-20:13-20:44: @10[5]: _19 = &amp;_20
-20:13-20:44: @10[6]: _18 = &amp;(*_19)
-20:13-20:44: @10[7]: _17 = move _18 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-20:13-20:44: @10.Call: _12 = Arguments::new_v1(move _13, move _17) -&gt; [return: bb11, unwind: bb23]
-20:13-20:44: @11.Call: _11 = _print(move _12) -&gt; [return: bb12, unwind: bb23]
-20:13-20:44: @12[6]: _10 = const ()
-18:27-21:10: @12[8]: _6 = const ()">            println!("Result: {}", result);</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="19:26-19:44: @8.Call: _9 = might_overflow(const 10_u32) -&gt; [return: bb9, unwind: bb23]
-19:17-19:23: @9[0]: FakeRead(ForLet, _9)
-20:22-20:34: @9[7]: _51 = const main::promoted[1]
-20:22-20:34: @9[8]: _15 = &amp;(*_51)
-20:22-20:34: @9[9]: _14 = &amp;(*_15)
-20:22-20:34: @9[10]: _13 = move _14 as &amp;[&amp;str] (Pointer(Unsize))
-20:36-20:42: @9[18]: _22 = &amp;_9
-20:13-20:44: @9[19]: _21 = (move _22,)
-20:13-20:44: @9[21]: FakeRead(ForMatchedPlace, _21)
-20:13-20:44: @9[23]: _23 = (_21.0: &amp;u32)
-20:13-20:44: @9[26]: _25 = &amp;(*_23)
-20:13-20:44: @9[28]: _26 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-20:13-20:44: @9.Call: _24 = ArgumentV1::new::&lt;u32&gt;(move _25, move _26) -&gt; [return: bb10, unwind: bb23]
-20:13-20:44: @10[2]: _20 = [move _24]
-20:13-20:44: @10[5]: _19 = &amp;_20
-20:13-20:44: @10[6]: _18 = &amp;(*_19)
-20:13-20:44: @10[7]: _17 = move _18 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-20:13-20:44: @10.Call: _12 = Arguments::new_v1(move _13, move _17) -&gt; [return: bb11, unwind: bb23]
-20:13-20:44: @11.Call: _11 = _print(move _12) -&gt; [return: bb12, unwind: bb23]
-20:13-20:44: @12[6]: _10 = const ()
-18:27-21:10: @12[8]: _6 = const ()">        }<span class="annotation">⦉@6,8,9,10,11,12</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code even" style="--layer: 1" title="21:19-21:28: @7[2]: _28 = _1
-21:19-21:32: @7[3]: _27 = Lt(move _28, const 5_i32)
-21:19-21:32: @7[5]: FakeRead(ForMatchedPlace, _27)"><span class="annotation">@7⦊</span>countdown &lt; 5<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="22:26-22:43: @15.Call: _29 = might_overflow(const 1_u32) -&gt; [return: bb16, unwind: bb23]
-22:17-22:23: @16[0]: FakeRead(ForLet, _29)
-23:22-23:34: @16[7]: _50 = const main::promoted[0]
-23:22-23:34: @16[8]: _35 = &amp;(*_50)
-23:22-23:34: @16[9]: _34 = &amp;(*_35)
-23:22-23:34: @16[10]: _33 = move _34 as &amp;[&amp;str] (Pointer(Unsize))
-23:36-23:42: @16[18]: _42 = &amp;_29
-23:13-23:44: @16[19]: _41 = (move _42,)
-23:13-23:44: @16[21]: FakeRead(ForMatchedPlace, _41)
-23:13-23:44: @16[23]: _43 = (_41.0: &amp;u32)
-23:13-23:44: @16[26]: _45 = &amp;(*_43)
-23:13-23:44: @16[28]: _46 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-23:13-23:44: @16.Call: _44 = ArgumentV1::new::&lt;u32&gt;(move _45, move _46) -&gt; [return: bb17, unwind: bb23]
-23:13-23:44: @17[2]: _40 = [move _44]
-23:13-23:44: @17[5]: _39 = &amp;_40
-23:13-23:44: @17[6]: _38 = &amp;(*_39)
-23:13-23:44: @17[7]: _37 = move _38 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-23:13-23:44: @17.Call: _32 = Arguments::new_v1(move _33, move _37) -&gt; [return: bb18, unwind: bb23]
-23:13-23:44: @18.Call: _31 = _print(move _32) -&gt; [return: bb19, unwind: bb23]
-23:13-23:44: @19[6]: _30 = const ()
-21:33-24:10: @19[8]: _6 = const ()"><span class="annotation">@13,15,16,17,18,19⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="22:26-22:43: @15.Call: _29 = might_overflow(const 1_u32) -&gt; [return: bb16, unwind: bb23]
-22:17-22:23: @16[0]: FakeRead(ForLet, _29)
-23:22-23:34: @16[7]: _50 = const main::promoted[0]
-23:22-23:34: @16[8]: _35 = &amp;(*_50)
-23:22-23:34: @16[9]: _34 = &amp;(*_35)
-23:22-23:34: @16[10]: _33 = move _34 as &amp;[&amp;str] (Pointer(Unsize))
-23:36-23:42: @16[18]: _42 = &amp;_29
-23:13-23:44: @16[19]: _41 = (move _42,)
-23:13-23:44: @16[21]: FakeRead(ForMatchedPlace, _41)
-23:13-23:44: @16[23]: _43 = (_41.0: &amp;u32)
-23:13-23:44: @16[26]: _45 = &amp;(*_43)
-23:13-23:44: @16[28]: _46 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-23:13-23:44: @16.Call: _44 = ArgumentV1::new::&lt;u32&gt;(move _45, move _46) -&gt; [return: bb17, unwind: bb23]
-23:13-23:44: @17[2]: _40 = [move _44]
-23:13-23:44: @17[5]: _39 = &amp;_40
-23:13-23:44: @17[6]: _38 = &amp;(*_39)
-23:13-23:44: @17[7]: _37 = move _38 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-23:13-23:44: @17.Call: _32 = Arguments::new_v1(move _33, move _37) -&gt; [return: bb18, unwind: bb23]
-23:13-23:44: @18.Call: _31 = _print(move _32) -&gt; [return: bb19, unwind: bb23]
-23:13-23:44: @19[6]: _30 = const ()
-21:33-24:10: @19[8]: _6 = const ()">            let result = might_overflow(1);</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="22:26-22:43: @15.Call: _29 = might_overflow(const 1_u32) -&gt; [return: bb16, unwind: bb23]
-22:17-22:23: @16[0]: FakeRead(ForLet, _29)
-23:22-23:34: @16[7]: _50 = const main::promoted[0]
-23:22-23:34: @16[8]: _35 = &amp;(*_50)
-23:22-23:34: @16[9]: _34 = &amp;(*_35)
-23:22-23:34: @16[10]: _33 = move _34 as &amp;[&amp;str] (Pointer(Unsize))
-23:36-23:42: @16[18]: _42 = &amp;_29
-23:13-23:44: @16[19]: _41 = (move _42,)
-23:13-23:44: @16[21]: FakeRead(ForMatchedPlace, _41)
-23:13-23:44: @16[23]: _43 = (_41.0: &amp;u32)
-23:13-23:44: @16[26]: _45 = &amp;(*_43)
-23:13-23:44: @16[28]: _46 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-23:13-23:44: @16.Call: _44 = ArgumentV1::new::&lt;u32&gt;(move _45, move _46) -&gt; [return: bb17, unwind: bb23]
-23:13-23:44: @17[2]: _40 = [move _44]
-23:13-23:44: @17[5]: _39 = &amp;_40
-23:13-23:44: @17[6]: _38 = &amp;(*_39)
-23:13-23:44: @17[7]: _37 = move _38 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-23:13-23:44: @17.Call: _32 = Arguments::new_v1(move _33, move _37) -&gt; [return: bb18, unwind: bb23]
-23:13-23:44: @18.Call: _31 = _print(move _32) -&gt; [return: bb19, unwind: bb23]
-23:13-23:44: @19[6]: _30 = const ()
-21:33-24:10: @19[8]: _6 = const ()">            println!("Result: {}", result);</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="22:26-22:43: @15.Call: _29 = might_overflow(const 1_u32) -&gt; [return: bb16, unwind: bb23]
-22:17-22:23: @16[0]: FakeRead(ForLet, _29)
-23:22-23:34: @16[7]: _50 = const main::promoted[0]
-23:22-23:34: @16[8]: _35 = &amp;(*_50)
-23:22-23:34: @16[9]: _34 = &amp;(*_35)
-23:22-23:34: @16[10]: _33 = move _34 as &amp;[&amp;str] (Pointer(Unsize))
-23:36-23:42: @16[18]: _42 = &amp;_29
-23:13-23:44: @16[19]: _41 = (move _42,)
-23:13-23:44: @16[21]: FakeRead(ForMatchedPlace, _41)
-23:13-23:44: @16[23]: _43 = (_41.0: &amp;u32)
-23:13-23:44: @16[26]: _45 = &amp;(*_43)
-23:13-23:44: @16[28]: _46 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-23:13-23:44: @16.Call: _44 = ArgumentV1::new::&lt;u32&gt;(move _45, move _46) -&gt; [return: bb17, unwind: bb23]
-23:13-23:44: @17[2]: _40 = [move _44]
-23:13-23:44: @17[5]: _39 = &amp;_40
-23:13-23:44: @17[6]: _38 = &amp;(*_39)
-23:13-23:44: @17[7]: _37 = move _38 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-23:13-23:44: @17.Call: _32 = Arguments::new_v1(move _33, move _37) -&gt; [return: bb18, unwind: bb23]
-23:13-23:44: @18.Call: _31 = _print(move _32) -&gt; [return: bb19, unwind: bb23]
-23:13-23:44: @19[6]: _30 = const ()
-21:33-24:10: @19[8]: _6 = const ()">        }<span class="annotation">⦉@13,15,16,17,18,19</span></span></span><span><span class="code even" style="--layer: 1" title="24:10-24:10: @14[0]: _6 = const ()"><span class="annotation">@14⦊</span>‸<span class="annotation">⦉@14</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="25:9-25:23: @21[2]: _47 = CheckedSub(_1, const 1_i32)
-25:9-25:23: @22[0]: _1 = move (_47.0: i32)"><span class="annotation">@21,22⦊</span>countdown -= 1<span class="annotation">⦉@21,22</span></span></span><span class="code" style="--layer: 0">;</span></span>
+18:12-18:26: @5[4]: _7 = Eq(move _8, const 1_i32)"><span class="annotation">@3,5⦊</span>countdown == 1<span class="annotation">⦉@3,5</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="19:26-19:44: @6.Call: _9 = might_overflow(const 10_u32) -&gt; [return: bb8, unwind: bb21]
+19:17-19:23: @8[0]: FakeRead(ForLet, _9)
+20:22-20:34: @8[7]: _51 = const main::promoted[1]
+20:22-20:34: @8[8]: _15 = &amp;(*_51)
+20:22-20:34: @8[9]: _14 = &amp;(*_15)
+20:22-20:34: @8[10]: _13 = move _14 as &amp;[&amp;str] (Pointer(Unsize))
+20:36-20:42: @8[18]: _22 = &amp;_9
+20:13-20:44: @8[19]: _21 = (move _22,)
+20:13-20:44: @8[21]: FakeRead(ForMatchedPlace, _21)
+20:13-20:44: @8[23]: _23 = (_21.0: &amp;u32)
+20:13-20:44: @8[26]: _25 = &amp;(*_23)
+20:13-20:44: @8[28]: _26 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+20:13-20:44: @8.Call: _24 = ArgumentV1::new::&lt;u32&gt;(move _25, move _26) -&gt; [return: bb9, unwind: bb21]
+20:13-20:44: @9[2]: _20 = [move _24]
+20:13-20:44: @9[5]: _19 = &amp;_20
+20:13-20:44: @9[6]: _18 = &amp;(*_19)
+20:13-20:44: @9[7]: _17 = move _18 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+20:13-20:44: @9.Call: _12 = Arguments::new_v1(move _13, move _17) -&gt; [return: bb10, unwind: bb21]
+20:13-20:44: @10.Call: _11 = _print(move _12) -&gt; [return: bb11, unwind: bb21]
+20:13-20:44: @11[6]: _10 = const ()
+18:27-21:10: @11[8]: _6 = const ()"><span class="annotation">@6,8,9,10,11⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="19:26-19:44: @6.Call: _9 = might_overflow(const 10_u32) -&gt; [return: bb8, unwind: bb21]
+19:17-19:23: @8[0]: FakeRead(ForLet, _9)
+20:22-20:34: @8[7]: _51 = const main::promoted[1]
+20:22-20:34: @8[8]: _15 = &amp;(*_51)
+20:22-20:34: @8[9]: _14 = &amp;(*_15)
+20:22-20:34: @8[10]: _13 = move _14 as &amp;[&amp;str] (Pointer(Unsize))
+20:36-20:42: @8[18]: _22 = &amp;_9
+20:13-20:44: @8[19]: _21 = (move _22,)
+20:13-20:44: @8[21]: FakeRead(ForMatchedPlace, _21)
+20:13-20:44: @8[23]: _23 = (_21.0: &amp;u32)
+20:13-20:44: @8[26]: _25 = &amp;(*_23)
+20:13-20:44: @8[28]: _26 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+20:13-20:44: @8.Call: _24 = ArgumentV1::new::&lt;u32&gt;(move _25, move _26) -&gt; [return: bb9, unwind: bb21]
+20:13-20:44: @9[2]: _20 = [move _24]
+20:13-20:44: @9[5]: _19 = &amp;_20
+20:13-20:44: @9[6]: _18 = &amp;(*_19)
+20:13-20:44: @9[7]: _17 = move _18 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+20:13-20:44: @9.Call: _12 = Arguments::new_v1(move _13, move _17) -&gt; [return: bb10, unwind: bb21]
+20:13-20:44: @10.Call: _11 = _print(move _12) -&gt; [return: bb11, unwind: bb21]
+20:13-20:44: @11[6]: _10 = const ()
+18:27-21:10: @11[8]: _6 = const ()">            let result = might_overflow(10);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="19:26-19:44: @6.Call: _9 = might_overflow(const 10_u32) -&gt; [return: bb8, unwind: bb21]
+19:17-19:23: @8[0]: FakeRead(ForLet, _9)
+20:22-20:34: @8[7]: _51 = const main::promoted[1]
+20:22-20:34: @8[8]: _15 = &amp;(*_51)
+20:22-20:34: @8[9]: _14 = &amp;(*_15)
+20:22-20:34: @8[10]: _13 = move _14 as &amp;[&amp;str] (Pointer(Unsize))
+20:36-20:42: @8[18]: _22 = &amp;_9
+20:13-20:44: @8[19]: _21 = (move _22,)
+20:13-20:44: @8[21]: FakeRead(ForMatchedPlace, _21)
+20:13-20:44: @8[23]: _23 = (_21.0: &amp;u32)
+20:13-20:44: @8[26]: _25 = &amp;(*_23)
+20:13-20:44: @8[28]: _26 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+20:13-20:44: @8.Call: _24 = ArgumentV1::new::&lt;u32&gt;(move _25, move _26) -&gt; [return: bb9, unwind: bb21]
+20:13-20:44: @9[2]: _20 = [move _24]
+20:13-20:44: @9[5]: _19 = &amp;_20
+20:13-20:44: @9[6]: _18 = &amp;(*_19)
+20:13-20:44: @9[7]: _17 = move _18 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+20:13-20:44: @9.Call: _12 = Arguments::new_v1(move _13, move _17) -&gt; [return: bb10, unwind: bb21]
+20:13-20:44: @10.Call: _11 = _print(move _12) -&gt; [return: bb11, unwind: bb21]
+20:13-20:44: @11[6]: _10 = const ()
+18:27-21:10: @11[8]: _6 = const ()">            println!("Result: {}", result);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="19:26-19:44: @6.Call: _9 = might_overflow(const 10_u32) -&gt; [return: bb8, unwind: bb21]
+19:17-19:23: @8[0]: FakeRead(ForLet, _9)
+20:22-20:34: @8[7]: _51 = const main::promoted[1]
+20:22-20:34: @8[8]: _15 = &amp;(*_51)
+20:22-20:34: @8[9]: _14 = &amp;(*_15)
+20:22-20:34: @8[10]: _13 = move _14 as &amp;[&amp;str] (Pointer(Unsize))
+20:36-20:42: @8[18]: _22 = &amp;_9
+20:13-20:44: @8[19]: _21 = (move _22,)
+20:13-20:44: @8[21]: FakeRead(ForMatchedPlace, _21)
+20:13-20:44: @8[23]: _23 = (_21.0: &amp;u32)
+20:13-20:44: @8[26]: _25 = &amp;(*_23)
+20:13-20:44: @8[28]: _26 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+20:13-20:44: @8.Call: _24 = ArgumentV1::new::&lt;u32&gt;(move _25, move _26) -&gt; [return: bb9, unwind: bb21]
+20:13-20:44: @9[2]: _20 = [move _24]
+20:13-20:44: @9[5]: _19 = &amp;_20
+20:13-20:44: @9[6]: _18 = &amp;(*_19)
+20:13-20:44: @9[7]: _17 = move _18 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+20:13-20:44: @9.Call: _12 = Arguments::new_v1(move _13, move _17) -&gt; [return: bb10, unwind: bb21]
+20:13-20:44: @10.Call: _11 = _print(move _12) -&gt; [return: bb11, unwind: bb21]
+20:13-20:44: @11[6]: _10 = const ()
+18:27-21:10: @11[8]: _6 = const ()">        }<span class="annotation">⦉@6,8,9,10,11</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code even" style="--layer: 1" title="21:19-21:28: @7[2]: _28 = _1
+21:19-21:32: @7[3]: _27 = Lt(move _28, const 5_i32)"><span class="annotation">@7⦊</span>countdown &lt; 5<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="22:26-22:43: @12.Call: _29 = might_overflow(const 1_u32) -&gt; [return: bb14, unwind: bb21]
+22:17-22:23: @14[0]: FakeRead(ForLet, _29)
+23:22-23:34: @14[7]: _50 = const main::promoted[0]
+23:22-23:34: @14[8]: _35 = &amp;(*_50)
+23:22-23:34: @14[9]: _34 = &amp;(*_35)
+23:22-23:34: @14[10]: _33 = move _34 as &amp;[&amp;str] (Pointer(Unsize))
+23:36-23:42: @14[18]: _42 = &amp;_29
+23:13-23:44: @14[19]: _41 = (move _42,)
+23:13-23:44: @14[21]: FakeRead(ForMatchedPlace, _41)
+23:13-23:44: @14[23]: _43 = (_41.0: &amp;u32)
+23:13-23:44: @14[26]: _45 = &amp;(*_43)
+23:13-23:44: @14[28]: _46 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+23:13-23:44: @14.Call: _44 = ArgumentV1::new::&lt;u32&gt;(move _45, move _46) -&gt; [return: bb15, unwind: bb21]
+23:13-23:44: @15[2]: _40 = [move _44]
+23:13-23:44: @15[5]: _39 = &amp;_40
+23:13-23:44: @15[6]: _38 = &amp;(*_39)
+23:13-23:44: @15[7]: _37 = move _38 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+23:13-23:44: @15.Call: _32 = Arguments::new_v1(move _33, move _37) -&gt; [return: bb16, unwind: bb21]
+23:13-23:44: @16.Call: _31 = _print(move _32) -&gt; [return: bb17, unwind: bb21]
+23:13-23:44: @17[6]: _30 = const ()
+21:33-24:10: @17[8]: _6 = const ()"><span class="annotation">@12,14,15,16,17⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="22:26-22:43: @12.Call: _29 = might_overflow(const 1_u32) -&gt; [return: bb14, unwind: bb21]
+22:17-22:23: @14[0]: FakeRead(ForLet, _29)
+23:22-23:34: @14[7]: _50 = const main::promoted[0]
+23:22-23:34: @14[8]: _35 = &amp;(*_50)
+23:22-23:34: @14[9]: _34 = &amp;(*_35)
+23:22-23:34: @14[10]: _33 = move _34 as &amp;[&amp;str] (Pointer(Unsize))
+23:36-23:42: @14[18]: _42 = &amp;_29
+23:13-23:44: @14[19]: _41 = (move _42,)
+23:13-23:44: @14[21]: FakeRead(ForMatchedPlace, _41)
+23:13-23:44: @14[23]: _43 = (_41.0: &amp;u32)
+23:13-23:44: @14[26]: _45 = &amp;(*_43)
+23:13-23:44: @14[28]: _46 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+23:13-23:44: @14.Call: _44 = ArgumentV1::new::&lt;u32&gt;(move _45, move _46) -&gt; [return: bb15, unwind: bb21]
+23:13-23:44: @15[2]: _40 = [move _44]
+23:13-23:44: @15[5]: _39 = &amp;_40
+23:13-23:44: @15[6]: _38 = &amp;(*_39)
+23:13-23:44: @15[7]: _37 = move _38 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+23:13-23:44: @15.Call: _32 = Arguments::new_v1(move _33, move _37) -&gt; [return: bb16, unwind: bb21]
+23:13-23:44: @16.Call: _31 = _print(move _32) -&gt; [return: bb17, unwind: bb21]
+23:13-23:44: @17[6]: _30 = const ()
+21:33-24:10: @17[8]: _6 = const ()">            let result = might_overflow(1);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="22:26-22:43: @12.Call: _29 = might_overflow(const 1_u32) -&gt; [return: bb14, unwind: bb21]
+22:17-22:23: @14[0]: FakeRead(ForLet, _29)
+23:22-23:34: @14[7]: _50 = const main::promoted[0]
+23:22-23:34: @14[8]: _35 = &amp;(*_50)
+23:22-23:34: @14[9]: _34 = &amp;(*_35)
+23:22-23:34: @14[10]: _33 = move _34 as &amp;[&amp;str] (Pointer(Unsize))
+23:36-23:42: @14[18]: _42 = &amp;_29
+23:13-23:44: @14[19]: _41 = (move _42,)
+23:13-23:44: @14[21]: FakeRead(ForMatchedPlace, _41)
+23:13-23:44: @14[23]: _43 = (_41.0: &amp;u32)
+23:13-23:44: @14[26]: _45 = &amp;(*_43)
+23:13-23:44: @14[28]: _46 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+23:13-23:44: @14.Call: _44 = ArgumentV1::new::&lt;u32&gt;(move _45, move _46) -&gt; [return: bb15, unwind: bb21]
+23:13-23:44: @15[2]: _40 = [move _44]
+23:13-23:44: @15[5]: _39 = &amp;_40
+23:13-23:44: @15[6]: _38 = &amp;(*_39)
+23:13-23:44: @15[7]: _37 = move _38 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+23:13-23:44: @15.Call: _32 = Arguments::new_v1(move _33, move _37) -&gt; [return: bb16, unwind: bb21]
+23:13-23:44: @16.Call: _31 = _print(move _32) -&gt; [return: bb17, unwind: bb21]
+23:13-23:44: @17[6]: _30 = const ()
+21:33-24:10: @17[8]: _6 = const ()">            println!("Result: {}", result);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="22:26-22:43: @12.Call: _29 = might_overflow(const 1_u32) -&gt; [return: bb14, unwind: bb21]
+22:17-22:23: @14[0]: FakeRead(ForLet, _29)
+23:22-23:34: @14[7]: _50 = const main::promoted[0]
+23:22-23:34: @14[8]: _35 = &amp;(*_50)
+23:22-23:34: @14[9]: _34 = &amp;(*_35)
+23:22-23:34: @14[10]: _33 = move _34 as &amp;[&amp;str] (Pointer(Unsize))
+23:36-23:42: @14[18]: _42 = &amp;_29
+23:13-23:44: @14[19]: _41 = (move _42,)
+23:13-23:44: @14[21]: FakeRead(ForMatchedPlace, _41)
+23:13-23:44: @14[23]: _43 = (_41.0: &amp;u32)
+23:13-23:44: @14[26]: _45 = &amp;(*_43)
+23:13-23:44: @14[28]: _46 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+23:13-23:44: @14.Call: _44 = ArgumentV1::new::&lt;u32&gt;(move _45, move _46) -&gt; [return: bb15, unwind: bb21]
+23:13-23:44: @15[2]: _40 = [move _44]
+23:13-23:44: @15[5]: _39 = &amp;_40
+23:13-23:44: @15[6]: _38 = &amp;(*_39)
+23:13-23:44: @15[7]: _37 = move _38 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+23:13-23:44: @15.Call: _32 = Arguments::new_v1(move _33, move _37) -&gt; [return: bb16, unwind: bb21]
+23:13-23:44: @16.Call: _31 = _print(move _32) -&gt; [return: bb17, unwind: bb21]
+23:13-23:44: @17[6]: _30 = const ()
+21:33-24:10: @17[8]: _6 = const ()">        }<span class="annotation">⦉@12,14,15,16,17</span></span></span><span><span class="code even" style="--layer: 1" title="24:10-24:10: @13[0]: _6 = const ()"><span class="annotation">@13⦊</span>‸<span class="annotation">⦉@13</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="25:9-25:23: @19[2]: _47 = CheckedSub(_1, const 1_i32)
+25:9-25:23: @20[0]: _1 = move (_47.0: i32)"><span class="annotation">@19,20⦊</span>countdown -= 1<span class="annotation">⦉@19,20</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
 <span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="27:8-27:10: @4[4]: _49 = ()
 27:5-27:11: @4[5]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _49)
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.might_overflow.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.might_overflow.-------.InstrumentCoverage.0.html
index c72ad42..f86cc4b 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.might_overflow.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.might_overflow.-------.InstrumentCoverage.0.html
@@ -70,327 +70,325 @@
 </head>
 <body>
 <div class="code" style="counter-reset: line 3"><span class="line"><span><span class="code even" style="--layer: 1" title="5:8-5:14: @0[3]: _4 = _1
-5:8-5:18: @0[4]: _3 = Gt(move _4, const 5_u32)
-5:8-5:18: @0[6]: FakeRead(ForMatchedPlace, _3)"><span class="annotation">@0⦊</span>fn might_overflow(to_add: u32) -&gt; u32 {</span></span>
+5:8-5:18: @0[4]: _3 = Gt(move _4, const 5_u32)"><span class="annotation">@0⦊</span>fn might_overflow(to_add: u32) -&gt; u32 {</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="5:8-5:14: @0[3]: _4 = _1
-5:8-5:18: @0[4]: _3 = Gt(move _4, const 5_u32)
-5:8-5:18: @0[6]: FakeRead(ForMatchedPlace, _3)">    if to_add &gt; 5<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="6:18-6:47: @3[6]: _61 = const might_overflow::promoted[4]
-6:18-6:47: @3[7]: _10 = &amp;(*_61)
-6:18-6:47: @3[8]: _9 = &amp;(*_10)
-6:18-6:47: @3[9]: _8 = move _9 as &amp;[&amp;str] (Pointer(Unsize))
-6:9-6:49: @3[15]: _16 = ()
-6:9-6:49: @3[16]: FakeRead(ForMatchedPlace, _16)
-6:9-6:49: @3[17]: _60 = const might_overflow::promoted[3]
-6:9-6:49: @3[18]: _14 = &amp;(*_60)
-6:9-6:49: @3[19]: _13 = &amp;(*_14)
-6:9-6:49: @3[20]: _12 = move _13 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-6:9-6:49: @3.Call: _7 = Arguments::new_v1(move _8, move _12) -&gt; [return: bb4, unwind: bb15]
-6:9-6:49: @4.Call: _6 = _print(move _7) -&gt; [return: bb5, unwind: bb15]
-6:9-6:49: @5[5]: _5 = const ()
-5:19-7:6: @5[7]: _2 = const ()"><span class="annotation">@1,3,4,5⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="6:18-6:47: @3[6]: _61 = const might_overflow::promoted[4]
-6:18-6:47: @3[7]: _10 = &amp;(*_61)
-6:18-6:47: @3[8]: _9 = &amp;(*_10)
-6:18-6:47: @3[9]: _8 = move _9 as &amp;[&amp;str] (Pointer(Unsize))
-6:9-6:49: @3[15]: _16 = ()
-6:9-6:49: @3[16]: FakeRead(ForMatchedPlace, _16)
-6:9-6:49: @3[17]: _60 = const might_overflow::promoted[3]
-6:9-6:49: @3[18]: _14 = &amp;(*_60)
-6:9-6:49: @3[19]: _13 = &amp;(*_14)
-6:9-6:49: @3[20]: _12 = move _13 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-6:9-6:49: @3.Call: _7 = Arguments::new_v1(move _8, move _12) -&gt; [return: bb4, unwind: bb15]
-6:9-6:49: @4.Call: _6 = _print(move _7) -&gt; [return: bb5, unwind: bb15]
-6:9-6:49: @5[5]: _5 = const ()
-5:19-7:6: @5[7]: _2 = const ()">        println!("this will probably overflow");</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="6:18-6:47: @3[6]: _61 = const might_overflow::promoted[4]
-6:18-6:47: @3[7]: _10 = &amp;(*_61)
-6:18-6:47: @3[8]: _9 = &amp;(*_10)
-6:18-6:47: @3[9]: _8 = move _9 as &amp;[&amp;str] (Pointer(Unsize))
-6:9-6:49: @3[15]: _16 = ()
-6:9-6:49: @3[16]: FakeRead(ForMatchedPlace, _16)
-6:9-6:49: @3[17]: _60 = const might_overflow::promoted[3]
-6:9-6:49: @3[18]: _14 = &amp;(*_60)
-6:9-6:49: @3[19]: _13 = &amp;(*_14)
-6:9-6:49: @3[20]: _12 = move _13 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-6:9-6:49: @3.Call: _7 = Arguments::new_v1(move _8, move _12) -&gt; [return: bb4, unwind: bb15]
-6:9-6:49: @4.Call: _6 = _print(move _7) -&gt; [return: bb5, unwind: bb15]
-6:9-6:49: @5[5]: _5 = const ()
-5:19-7:6: @5[7]: _2 = const ()">    }<span class="annotation">⦉@1,3,4,5</span></span></span><span><span class="code even" style="--layer: 1" title="7:6-7:6: @2[0]: _2 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code odd" style="--layer: 1" title="8:18-8:30: @6[3]: _18 = CheckedSub(const core::num::&lt;impl u32&gt;::MAX, const 5_u32)
-8:18-8:30: @7[0]: _17 = move (_18.0: u32)
-8:9-8:15: @7[1]: FakeRead(ForLet, _17)
-9:14-9:38: @7[8]: _59 = const might_overflow::promoted[2]
-9:14-9:38: @7[9]: _24 = &amp;(*_59)
-9:14-9:38: @7[10]: _23 = &amp;(*_24)
-9:14-9:38: @7[11]: _22 = move _23 as &amp;[&amp;str] (Pointer(Unsize))
-9:40-9:46: @7[19]: _31 = &amp;_17
-9:48-9:54: @7[21]: _32 = &amp;_1
-9:5-9:56: @7[22]: _30 = (move _31, move _32)
-9:5-9:56: @7[25]: FakeRead(ForMatchedPlace, _30)
-9:5-9:56: @7[27]: _33 = (_30.0: &amp;u32)
-9:5-9:56: @7[29]: _34 = (_30.1: &amp;u32)
-9:5-9:56: @7[32]: _36 = &amp;(*_33)
-9:5-9:56: @7[34]: _37 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-9:5-9:56: @7.Call: _35 = ArgumentV1::new::&lt;u32&gt;(move _36, move _37) -&gt; [return: bb8, unwind: bb15]
-9:5-9:56: @8[4]: _39 = &amp;(*_34)
-9:5-9:56: @8[6]: _40 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-9:5-9:56: @8.Call: _38 = ArgumentV1::new::&lt;u32&gt;(move _39, move _40) -&gt; [return: bb9, unwind: bb15]
-9:5-9:56: @9[2]: _29 = [move _35, move _38]
-9:5-9:56: @9[7]: _28 = &amp;_29
-9:5-9:56: @9[8]: _27 = &amp;(*_28)
-9:5-9:56: @9[9]: _26 = move _27 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-9:5-9:56: @9.Call: _21 = Arguments::new_v1(move _22, move _26) -&gt; [return: bb10, unwind: bb15]
-9:5-9:56: @10.Call: _20 = _print(move _21) -&gt; [return: bb11, unwind: bb15]
-9:5-9:56: @11[6]: _19 = const ()
-10:18-10:24: @11[10]: _42 = _1
-10:27-10:33: @11[12]: _43 = _17
-10:18-10:33: @11[13]: _44 = CheckedAdd(_42, _43)
-10:18-10:33: @12[0]: _41 = move (_44.0: u32)
-10:9-10:15: @12[3]: FakeRead(ForLet, _41)
-11:14-11:47: @12[10]: _58 = const might_overflow::promoted[1]
-11:14-11:47: @12[11]: _50 = &amp;(*_58)
-11:14-11:47: @12[12]: _49 = &amp;(*_50)
-11:14-11:47: @12[13]: _48 = move _49 as &amp;[&amp;str] (Pointer(Unsize))
-11:5-11:49: @12[19]: _56 = ()
-11:5-11:49: @12[20]: FakeRead(ForMatchedPlace, _56)
-11:5-11:49: @12[21]: _57 = const might_overflow::promoted[0]
-11:5-11:49: @12[22]: _54 = &amp;(*_57)
-11:5-11:49: @12[23]: _53 = &amp;(*_54)
-11:5-11:49: @12[24]: _52 = move _53 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-11:5-11:49: @12.Call: _47 = Arguments::new_v1(move _48, move _52) -&gt; [return: bb13, unwind: bb15]
-11:5-11:49: @13.Call: _46 = _print(move _47) -&gt; [return: bb14, unwind: bb15]
-11:5-11:49: @14[5]: _45 = const ()
-12:5-12:11: @14[7]: _0 = _41
-13:2-13:2: @14.Return: return"><span class="annotation">@6,7,8,9,10,11,12,13,14⦊</span>add_to = u32::MAX - 5;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="8:18-8:30: @6[3]: _18 = CheckedSub(const core::num::&lt;impl u32&gt;::MAX, const 5_u32)
-8:18-8:30: @7[0]: _17 = move (_18.0: u32)
-8:9-8:15: @7[1]: FakeRead(ForLet, _17)
-9:14-9:38: @7[8]: _59 = const might_overflow::promoted[2]
-9:14-9:38: @7[9]: _24 = &amp;(*_59)
-9:14-9:38: @7[10]: _23 = &amp;(*_24)
-9:14-9:38: @7[11]: _22 = move _23 as &amp;[&amp;str] (Pointer(Unsize))
-9:40-9:46: @7[19]: _31 = &amp;_17
-9:48-9:54: @7[21]: _32 = &amp;_1
-9:5-9:56: @7[22]: _30 = (move _31, move _32)
-9:5-9:56: @7[25]: FakeRead(ForMatchedPlace, _30)
-9:5-9:56: @7[27]: _33 = (_30.0: &amp;u32)
-9:5-9:56: @7[29]: _34 = (_30.1: &amp;u32)
-9:5-9:56: @7[32]: _36 = &amp;(*_33)
-9:5-9:56: @7[34]: _37 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-9:5-9:56: @7.Call: _35 = ArgumentV1::new::&lt;u32&gt;(move _36, move _37) -&gt; [return: bb8, unwind: bb15]
-9:5-9:56: @8[4]: _39 = &amp;(*_34)
-9:5-9:56: @8[6]: _40 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-9:5-9:56: @8.Call: _38 = ArgumentV1::new::&lt;u32&gt;(move _39, move _40) -&gt; [return: bb9, unwind: bb15]
-9:5-9:56: @9[2]: _29 = [move _35, move _38]
-9:5-9:56: @9[7]: _28 = &amp;_29
-9:5-9:56: @9[8]: _27 = &amp;(*_28)
-9:5-9:56: @9[9]: _26 = move _27 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-9:5-9:56: @9.Call: _21 = Arguments::new_v1(move _22, move _26) -&gt; [return: bb10, unwind: bb15]
-9:5-9:56: @10.Call: _20 = _print(move _21) -&gt; [return: bb11, unwind: bb15]
-9:5-9:56: @11[6]: _19 = const ()
-10:18-10:24: @11[10]: _42 = _1
-10:27-10:33: @11[12]: _43 = _17
-10:18-10:33: @11[13]: _44 = CheckedAdd(_42, _43)
-10:18-10:33: @12[0]: _41 = move (_44.0: u32)
-10:9-10:15: @12[3]: FakeRead(ForLet, _41)
-11:14-11:47: @12[10]: _58 = const might_overflow::promoted[1]
-11:14-11:47: @12[11]: _50 = &amp;(*_58)
-11:14-11:47: @12[12]: _49 = &amp;(*_50)
-11:14-11:47: @12[13]: _48 = move _49 as &amp;[&amp;str] (Pointer(Unsize))
-11:5-11:49: @12[19]: _56 = ()
-11:5-11:49: @12[20]: FakeRead(ForMatchedPlace, _56)
-11:5-11:49: @12[21]: _57 = const might_overflow::promoted[0]
-11:5-11:49: @12[22]: _54 = &amp;(*_57)
-11:5-11:49: @12[23]: _53 = &amp;(*_54)
-11:5-11:49: @12[24]: _52 = move _53 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-11:5-11:49: @12.Call: _47 = Arguments::new_v1(move _48, move _52) -&gt; [return: bb13, unwind: bb15]
-11:5-11:49: @13.Call: _46 = _print(move _47) -&gt; [return: bb14, unwind: bb15]
-11:5-11:49: @14[5]: _45 = const ()
-12:5-12:11: @14[7]: _0 = _41
-13:2-13:2: @14.Return: return">    println!("does {} + {} overflow?", add_to, to_add);</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="8:18-8:30: @6[3]: _18 = CheckedSub(const core::num::&lt;impl u32&gt;::MAX, const 5_u32)
-8:18-8:30: @7[0]: _17 = move (_18.0: u32)
-8:9-8:15: @7[1]: FakeRead(ForLet, _17)
-9:14-9:38: @7[8]: _59 = const might_overflow::promoted[2]
-9:14-9:38: @7[9]: _24 = &amp;(*_59)
-9:14-9:38: @7[10]: _23 = &amp;(*_24)
-9:14-9:38: @7[11]: _22 = move _23 as &amp;[&amp;str] (Pointer(Unsize))
-9:40-9:46: @7[19]: _31 = &amp;_17
-9:48-9:54: @7[21]: _32 = &amp;_1
-9:5-9:56: @7[22]: _30 = (move _31, move _32)
-9:5-9:56: @7[25]: FakeRead(ForMatchedPlace, _30)
-9:5-9:56: @7[27]: _33 = (_30.0: &amp;u32)
-9:5-9:56: @7[29]: _34 = (_30.1: &amp;u32)
-9:5-9:56: @7[32]: _36 = &amp;(*_33)
-9:5-9:56: @7[34]: _37 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-9:5-9:56: @7.Call: _35 = ArgumentV1::new::&lt;u32&gt;(move _36, move _37) -&gt; [return: bb8, unwind: bb15]
-9:5-9:56: @8[4]: _39 = &amp;(*_34)
-9:5-9:56: @8[6]: _40 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-9:5-9:56: @8.Call: _38 = ArgumentV1::new::&lt;u32&gt;(move _39, move _40) -&gt; [return: bb9, unwind: bb15]
-9:5-9:56: @9[2]: _29 = [move _35, move _38]
-9:5-9:56: @9[7]: _28 = &amp;_29
-9:5-9:56: @9[8]: _27 = &amp;(*_28)
-9:5-9:56: @9[9]: _26 = move _27 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-9:5-9:56: @9.Call: _21 = Arguments::new_v1(move _22, move _26) -&gt; [return: bb10, unwind: bb15]
-9:5-9:56: @10.Call: _20 = _print(move _21) -&gt; [return: bb11, unwind: bb15]
-9:5-9:56: @11[6]: _19 = const ()
-10:18-10:24: @11[10]: _42 = _1
-10:27-10:33: @11[12]: _43 = _17
-10:18-10:33: @11[13]: _44 = CheckedAdd(_42, _43)
-10:18-10:33: @12[0]: _41 = move (_44.0: u32)
-10:9-10:15: @12[3]: FakeRead(ForLet, _41)
-11:14-11:47: @12[10]: _58 = const might_overflow::promoted[1]
-11:14-11:47: @12[11]: _50 = &amp;(*_58)
-11:14-11:47: @12[12]: _49 = &amp;(*_50)
-11:14-11:47: @12[13]: _48 = move _49 as &amp;[&amp;str] (Pointer(Unsize))
-11:5-11:49: @12[19]: _56 = ()
-11:5-11:49: @12[20]: FakeRead(ForMatchedPlace, _56)
-11:5-11:49: @12[21]: _57 = const might_overflow::promoted[0]
-11:5-11:49: @12[22]: _54 = &amp;(*_57)
-11:5-11:49: @12[23]: _53 = &amp;(*_54)
-11:5-11:49: @12[24]: _52 = move _53 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-11:5-11:49: @12.Call: _47 = Arguments::new_v1(move _48, move _52) -&gt; [return: bb13, unwind: bb15]
-11:5-11:49: @13.Call: _46 = _print(move _47) -&gt; [return: bb14, unwind: bb15]
-11:5-11:49: @14[5]: _45 = const ()
-12:5-12:11: @14[7]: _0 = _41
-13:2-13:2: @14.Return: return">    let result = to_add + add_to;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="8:18-8:30: @6[3]: _18 = CheckedSub(const core::num::&lt;impl u32&gt;::MAX, const 5_u32)
-8:18-8:30: @7[0]: _17 = move (_18.0: u32)
-8:9-8:15: @7[1]: FakeRead(ForLet, _17)
-9:14-9:38: @7[8]: _59 = const might_overflow::promoted[2]
-9:14-9:38: @7[9]: _24 = &amp;(*_59)
-9:14-9:38: @7[10]: _23 = &amp;(*_24)
-9:14-9:38: @7[11]: _22 = move _23 as &amp;[&amp;str] (Pointer(Unsize))
-9:40-9:46: @7[19]: _31 = &amp;_17
-9:48-9:54: @7[21]: _32 = &amp;_1
-9:5-9:56: @7[22]: _30 = (move _31, move _32)
-9:5-9:56: @7[25]: FakeRead(ForMatchedPlace, _30)
-9:5-9:56: @7[27]: _33 = (_30.0: &amp;u32)
-9:5-9:56: @7[29]: _34 = (_30.1: &amp;u32)
-9:5-9:56: @7[32]: _36 = &amp;(*_33)
-9:5-9:56: @7[34]: _37 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-9:5-9:56: @7.Call: _35 = ArgumentV1::new::&lt;u32&gt;(move _36, move _37) -&gt; [return: bb8, unwind: bb15]
-9:5-9:56: @8[4]: _39 = &amp;(*_34)
-9:5-9:56: @8[6]: _40 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-9:5-9:56: @8.Call: _38 = ArgumentV1::new::&lt;u32&gt;(move _39, move _40) -&gt; [return: bb9, unwind: bb15]
-9:5-9:56: @9[2]: _29 = [move _35, move _38]
-9:5-9:56: @9[7]: _28 = &amp;_29
-9:5-9:56: @9[8]: _27 = &amp;(*_28)
-9:5-9:56: @9[9]: _26 = move _27 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-9:5-9:56: @9.Call: _21 = Arguments::new_v1(move _22, move _26) -&gt; [return: bb10, unwind: bb15]
-9:5-9:56: @10.Call: _20 = _print(move _21) -&gt; [return: bb11, unwind: bb15]
-9:5-9:56: @11[6]: _19 = const ()
-10:18-10:24: @11[10]: _42 = _1
-10:27-10:33: @11[12]: _43 = _17
-10:18-10:33: @11[13]: _44 = CheckedAdd(_42, _43)
-10:18-10:33: @12[0]: _41 = move (_44.0: u32)
-10:9-10:15: @12[3]: FakeRead(ForLet, _41)
-11:14-11:47: @12[10]: _58 = const might_overflow::promoted[1]
-11:14-11:47: @12[11]: _50 = &amp;(*_58)
-11:14-11:47: @12[12]: _49 = &amp;(*_50)
-11:14-11:47: @12[13]: _48 = move _49 as &amp;[&amp;str] (Pointer(Unsize))
-11:5-11:49: @12[19]: _56 = ()
-11:5-11:49: @12[20]: FakeRead(ForMatchedPlace, _56)
-11:5-11:49: @12[21]: _57 = const might_overflow::promoted[0]
-11:5-11:49: @12[22]: _54 = &amp;(*_57)
-11:5-11:49: @12[23]: _53 = &amp;(*_54)
-11:5-11:49: @12[24]: _52 = move _53 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-11:5-11:49: @12.Call: _47 = Arguments::new_v1(move _48, move _52) -&gt; [return: bb13, unwind: bb15]
-11:5-11:49: @13.Call: _46 = _print(move _47) -&gt; [return: bb14, unwind: bb15]
-11:5-11:49: @14[5]: _45 = const ()
-12:5-12:11: @14[7]: _0 = _41
-13:2-13:2: @14.Return: return">    println!("continuing after overflow check");</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="8:18-8:30: @6[3]: _18 = CheckedSub(const core::num::&lt;impl u32&gt;::MAX, const 5_u32)
-8:18-8:30: @7[0]: _17 = move (_18.0: u32)
-8:9-8:15: @7[1]: FakeRead(ForLet, _17)
-9:14-9:38: @7[8]: _59 = const might_overflow::promoted[2]
-9:14-9:38: @7[9]: _24 = &amp;(*_59)
-9:14-9:38: @7[10]: _23 = &amp;(*_24)
-9:14-9:38: @7[11]: _22 = move _23 as &amp;[&amp;str] (Pointer(Unsize))
-9:40-9:46: @7[19]: _31 = &amp;_17
-9:48-9:54: @7[21]: _32 = &amp;_1
-9:5-9:56: @7[22]: _30 = (move _31, move _32)
-9:5-9:56: @7[25]: FakeRead(ForMatchedPlace, _30)
-9:5-9:56: @7[27]: _33 = (_30.0: &amp;u32)
-9:5-9:56: @7[29]: _34 = (_30.1: &amp;u32)
-9:5-9:56: @7[32]: _36 = &amp;(*_33)
-9:5-9:56: @7[34]: _37 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-9:5-9:56: @7.Call: _35 = ArgumentV1::new::&lt;u32&gt;(move _36, move _37) -&gt; [return: bb8, unwind: bb15]
-9:5-9:56: @8[4]: _39 = &amp;(*_34)
-9:5-9:56: @8[6]: _40 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-9:5-9:56: @8.Call: _38 = ArgumentV1::new::&lt;u32&gt;(move _39, move _40) -&gt; [return: bb9, unwind: bb15]
-9:5-9:56: @9[2]: _29 = [move _35, move _38]
-9:5-9:56: @9[7]: _28 = &amp;_29
-9:5-9:56: @9[8]: _27 = &amp;(*_28)
-9:5-9:56: @9[9]: _26 = move _27 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-9:5-9:56: @9.Call: _21 = Arguments::new_v1(move _22, move _26) -&gt; [return: bb10, unwind: bb15]
-9:5-9:56: @10.Call: _20 = _print(move _21) -&gt; [return: bb11, unwind: bb15]
-9:5-9:56: @11[6]: _19 = const ()
-10:18-10:24: @11[10]: _42 = _1
-10:27-10:33: @11[12]: _43 = _17
-10:18-10:33: @11[13]: _44 = CheckedAdd(_42, _43)
-10:18-10:33: @12[0]: _41 = move (_44.0: u32)
-10:9-10:15: @12[3]: FakeRead(ForLet, _41)
-11:14-11:47: @12[10]: _58 = const might_overflow::promoted[1]
-11:14-11:47: @12[11]: _50 = &amp;(*_58)
-11:14-11:47: @12[12]: _49 = &amp;(*_50)
-11:14-11:47: @12[13]: _48 = move _49 as &amp;[&amp;str] (Pointer(Unsize))
-11:5-11:49: @12[19]: _56 = ()
-11:5-11:49: @12[20]: FakeRead(ForMatchedPlace, _56)
-11:5-11:49: @12[21]: _57 = const might_overflow::promoted[0]
-11:5-11:49: @12[22]: _54 = &amp;(*_57)
-11:5-11:49: @12[23]: _53 = &amp;(*_54)
-11:5-11:49: @12[24]: _52 = move _53 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-11:5-11:49: @12.Call: _47 = Arguments::new_v1(move _48, move _52) -&gt; [return: bb13, unwind: bb15]
-11:5-11:49: @13.Call: _46 = _print(move _47) -&gt; [return: bb14, unwind: bb15]
-11:5-11:49: @14[5]: _45 = const ()
-12:5-12:11: @14[7]: _0 = _41
-13:2-13:2: @14.Return: return">    result</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="8:18-8:30: @6[3]: _18 = CheckedSub(const core::num::&lt;impl u32&gt;::MAX, const 5_u32)
-8:18-8:30: @7[0]: _17 = move (_18.0: u32)
-8:9-8:15: @7[1]: FakeRead(ForLet, _17)
-9:14-9:38: @7[8]: _59 = const might_overflow::promoted[2]
-9:14-9:38: @7[9]: _24 = &amp;(*_59)
-9:14-9:38: @7[10]: _23 = &amp;(*_24)
-9:14-9:38: @7[11]: _22 = move _23 as &amp;[&amp;str] (Pointer(Unsize))
-9:40-9:46: @7[19]: _31 = &amp;_17
-9:48-9:54: @7[21]: _32 = &amp;_1
-9:5-9:56: @7[22]: _30 = (move _31, move _32)
-9:5-9:56: @7[25]: FakeRead(ForMatchedPlace, _30)
-9:5-9:56: @7[27]: _33 = (_30.0: &amp;u32)
-9:5-9:56: @7[29]: _34 = (_30.1: &amp;u32)
-9:5-9:56: @7[32]: _36 = &amp;(*_33)
-9:5-9:56: @7[34]: _37 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-9:5-9:56: @7.Call: _35 = ArgumentV1::new::&lt;u32&gt;(move _36, move _37) -&gt; [return: bb8, unwind: bb15]
-9:5-9:56: @8[4]: _39 = &amp;(*_34)
-9:5-9:56: @8[6]: _40 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-9:5-9:56: @8.Call: _38 = ArgumentV1::new::&lt;u32&gt;(move _39, move _40) -&gt; [return: bb9, unwind: bb15]
-9:5-9:56: @9[2]: _29 = [move _35, move _38]
-9:5-9:56: @9[7]: _28 = &amp;_29
-9:5-9:56: @9[8]: _27 = &amp;(*_28)
-9:5-9:56: @9[9]: _26 = move _27 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-9:5-9:56: @9.Call: _21 = Arguments::new_v1(move _22, move _26) -&gt; [return: bb10, unwind: bb15]
-9:5-9:56: @10.Call: _20 = _print(move _21) -&gt; [return: bb11, unwind: bb15]
-9:5-9:56: @11[6]: _19 = const ()
-10:18-10:24: @11[10]: _42 = _1
-10:27-10:33: @11[12]: _43 = _17
-10:18-10:33: @11[13]: _44 = CheckedAdd(_42, _43)
-10:18-10:33: @12[0]: _41 = move (_44.0: u32)
-10:9-10:15: @12[3]: FakeRead(ForLet, _41)
-11:14-11:47: @12[10]: _58 = const might_overflow::promoted[1]
-11:14-11:47: @12[11]: _50 = &amp;(*_58)
-11:14-11:47: @12[12]: _49 = &amp;(*_50)
-11:14-11:47: @12[13]: _48 = move _49 as &amp;[&amp;str] (Pointer(Unsize))
-11:5-11:49: @12[19]: _56 = ()
-11:5-11:49: @12[20]: FakeRead(ForMatchedPlace, _56)
-11:5-11:49: @12[21]: _57 = const might_overflow::promoted[0]
-11:5-11:49: @12[22]: _54 = &amp;(*_57)
-11:5-11:49: @12[23]: _53 = &amp;(*_54)
-11:5-11:49: @12[24]: _52 = move _53 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-11:5-11:49: @12.Call: _47 = Arguments::new_v1(move _48, move _52) -&gt; [return: bb13, unwind: bb15]
-11:5-11:49: @13.Call: _46 = _print(move _47) -&gt; [return: bb14, unwind: bb15]
-11:5-11:49: @14[5]: _45 = const ()
-12:5-12:11: @14[7]: _0 = _41
-13:2-13:2: @14.Return: return">}<span class="annotation">⦉@6,7,8,9,10,11,12,13,14</span></span></span></span></div>
+5:8-5:18: @0[4]: _3 = Gt(move _4, const 5_u32)">    if to_add &gt; 5<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="6:18-6:47: @1[6]: _61 = const might_overflow::promoted[4]
+6:18-6:47: @1[7]: _10 = &amp;(*_61)
+6:18-6:47: @1[8]: _9 = &amp;(*_10)
+6:18-6:47: @1[9]: _8 = move _9 as &amp;[&amp;str] (Pointer(Unsize))
+6:9-6:49: @1[15]: _16 = ()
+6:9-6:49: @1[16]: FakeRead(ForMatchedPlace, _16)
+6:9-6:49: @1[17]: _60 = const might_overflow::promoted[3]
+6:9-6:49: @1[18]: _14 = &amp;(*_60)
+6:9-6:49: @1[19]: _13 = &amp;(*_14)
+6:9-6:49: @1[20]: _12 = move _13 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+6:9-6:49: @1.Call: _7 = Arguments::new_v1(move _8, move _12) -&gt; [return: bb3, unwind: bb14]
+6:9-6:49: @3.Call: _6 = _print(move _7) -&gt; [return: bb4, unwind: bb14]
+6:9-6:49: @4[5]: _5 = const ()
+5:19-7:6: @4[7]: _2 = const ()"><span class="annotation">@1,3,4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="6:18-6:47: @1[6]: _61 = const might_overflow::promoted[4]
+6:18-6:47: @1[7]: _10 = &amp;(*_61)
+6:18-6:47: @1[8]: _9 = &amp;(*_10)
+6:18-6:47: @1[9]: _8 = move _9 as &amp;[&amp;str] (Pointer(Unsize))
+6:9-6:49: @1[15]: _16 = ()
+6:9-6:49: @1[16]: FakeRead(ForMatchedPlace, _16)
+6:9-6:49: @1[17]: _60 = const might_overflow::promoted[3]
+6:9-6:49: @1[18]: _14 = &amp;(*_60)
+6:9-6:49: @1[19]: _13 = &amp;(*_14)
+6:9-6:49: @1[20]: _12 = move _13 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+6:9-6:49: @1.Call: _7 = Arguments::new_v1(move _8, move _12) -&gt; [return: bb3, unwind: bb14]
+6:9-6:49: @3.Call: _6 = _print(move _7) -&gt; [return: bb4, unwind: bb14]
+6:9-6:49: @4[5]: _5 = const ()
+5:19-7:6: @4[7]: _2 = const ()">        println!("this will probably overflow");</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="6:18-6:47: @1[6]: _61 = const might_overflow::promoted[4]
+6:18-6:47: @1[7]: _10 = &amp;(*_61)
+6:18-6:47: @1[8]: _9 = &amp;(*_10)
+6:18-6:47: @1[9]: _8 = move _9 as &amp;[&amp;str] (Pointer(Unsize))
+6:9-6:49: @1[15]: _16 = ()
+6:9-6:49: @1[16]: FakeRead(ForMatchedPlace, _16)
+6:9-6:49: @1[17]: _60 = const might_overflow::promoted[3]
+6:9-6:49: @1[18]: _14 = &amp;(*_60)
+6:9-6:49: @1[19]: _13 = &amp;(*_14)
+6:9-6:49: @1[20]: _12 = move _13 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+6:9-6:49: @1.Call: _7 = Arguments::new_v1(move _8, move _12) -&gt; [return: bb3, unwind: bb14]
+6:9-6:49: @3.Call: _6 = _print(move _7) -&gt; [return: bb4, unwind: bb14]
+6:9-6:49: @4[5]: _5 = const ()
+5:19-7:6: @4[7]: _2 = const ()">    }<span class="annotation">⦉@1,3,4</span></span></span><span><span class="code even" style="--layer: 1" title="7:6-7:6: @2[0]: _2 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code odd" style="--layer: 1" title="8:18-8:30: @5[3]: _18 = CheckedSub(const core::num::&lt;impl u32&gt;::MAX, const 5_u32)
+8:18-8:30: @6[0]: _17 = move (_18.0: u32)
+8:9-8:15: @6[1]: FakeRead(ForLet, _17)
+9:14-9:38: @6[8]: _59 = const might_overflow::promoted[2]
+9:14-9:38: @6[9]: _24 = &amp;(*_59)
+9:14-9:38: @6[10]: _23 = &amp;(*_24)
+9:14-9:38: @6[11]: _22 = move _23 as &amp;[&amp;str] (Pointer(Unsize))
+9:40-9:46: @6[19]: _31 = &amp;_17
+9:48-9:54: @6[21]: _32 = &amp;_1
+9:5-9:56: @6[22]: _30 = (move _31, move _32)
+9:5-9:56: @6[25]: FakeRead(ForMatchedPlace, _30)
+9:5-9:56: @6[27]: _33 = (_30.0: &amp;u32)
+9:5-9:56: @6[29]: _34 = (_30.1: &amp;u32)
+9:5-9:56: @6[32]: _36 = &amp;(*_33)
+9:5-9:56: @6[34]: _37 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+9:5-9:56: @6.Call: _35 = ArgumentV1::new::&lt;u32&gt;(move _36, move _37) -&gt; [return: bb7, unwind: bb14]
+9:5-9:56: @7[4]: _39 = &amp;(*_34)
+9:5-9:56: @7[6]: _40 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+9:5-9:56: @7.Call: _38 = ArgumentV1::new::&lt;u32&gt;(move _39, move _40) -&gt; [return: bb8, unwind: bb14]
+9:5-9:56: @8[2]: _29 = [move _35, move _38]
+9:5-9:56: @8[7]: _28 = &amp;_29
+9:5-9:56: @8[8]: _27 = &amp;(*_28)
+9:5-9:56: @8[9]: _26 = move _27 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+9:5-9:56: @8.Call: _21 = Arguments::new_v1(move _22, move _26) -&gt; [return: bb9, unwind: bb14]
+9:5-9:56: @9.Call: _20 = _print(move _21) -&gt; [return: bb10, unwind: bb14]
+9:5-9:56: @10[6]: _19 = const ()
+10:18-10:24: @10[10]: _42 = _1
+10:27-10:33: @10[12]: _43 = _17
+10:18-10:33: @10[13]: _44 = CheckedAdd(_42, _43)
+10:18-10:33: @11[0]: _41 = move (_44.0: u32)
+10:9-10:15: @11[3]: FakeRead(ForLet, _41)
+11:14-11:47: @11[10]: _58 = const might_overflow::promoted[1]
+11:14-11:47: @11[11]: _50 = &amp;(*_58)
+11:14-11:47: @11[12]: _49 = &amp;(*_50)
+11:14-11:47: @11[13]: _48 = move _49 as &amp;[&amp;str] (Pointer(Unsize))
+11:5-11:49: @11[19]: _56 = ()
+11:5-11:49: @11[20]: FakeRead(ForMatchedPlace, _56)
+11:5-11:49: @11[21]: _57 = const might_overflow::promoted[0]
+11:5-11:49: @11[22]: _54 = &amp;(*_57)
+11:5-11:49: @11[23]: _53 = &amp;(*_54)
+11:5-11:49: @11[24]: _52 = move _53 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+11:5-11:49: @11.Call: _47 = Arguments::new_v1(move _48, move _52) -&gt; [return: bb12, unwind: bb14]
+11:5-11:49: @12.Call: _46 = _print(move _47) -&gt; [return: bb13, unwind: bb14]
+11:5-11:49: @13[5]: _45 = const ()
+12:5-12:11: @13[7]: _0 = _41
+13:2-13:2: @13.Return: return"><span class="annotation">@5,6,7,8,9,10,11,12,13⦊</span>add_to = u32::MAX - 5;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="8:18-8:30: @5[3]: _18 = CheckedSub(const core::num::&lt;impl u32&gt;::MAX, const 5_u32)
+8:18-8:30: @6[0]: _17 = move (_18.0: u32)
+8:9-8:15: @6[1]: FakeRead(ForLet, _17)
+9:14-9:38: @6[8]: _59 = const might_overflow::promoted[2]
+9:14-9:38: @6[9]: _24 = &amp;(*_59)
+9:14-9:38: @6[10]: _23 = &amp;(*_24)
+9:14-9:38: @6[11]: _22 = move _23 as &amp;[&amp;str] (Pointer(Unsize))
+9:40-9:46: @6[19]: _31 = &amp;_17
+9:48-9:54: @6[21]: _32 = &amp;_1
+9:5-9:56: @6[22]: _30 = (move _31, move _32)
+9:5-9:56: @6[25]: FakeRead(ForMatchedPlace, _30)
+9:5-9:56: @6[27]: _33 = (_30.0: &amp;u32)
+9:5-9:56: @6[29]: _34 = (_30.1: &amp;u32)
+9:5-9:56: @6[32]: _36 = &amp;(*_33)
+9:5-9:56: @6[34]: _37 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+9:5-9:56: @6.Call: _35 = ArgumentV1::new::&lt;u32&gt;(move _36, move _37) -&gt; [return: bb7, unwind: bb14]
+9:5-9:56: @7[4]: _39 = &amp;(*_34)
+9:5-9:56: @7[6]: _40 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+9:5-9:56: @7.Call: _38 = ArgumentV1::new::&lt;u32&gt;(move _39, move _40) -&gt; [return: bb8, unwind: bb14]
+9:5-9:56: @8[2]: _29 = [move _35, move _38]
+9:5-9:56: @8[7]: _28 = &amp;_29
+9:5-9:56: @8[8]: _27 = &amp;(*_28)
+9:5-9:56: @8[9]: _26 = move _27 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+9:5-9:56: @8.Call: _21 = Arguments::new_v1(move _22, move _26) -&gt; [return: bb9, unwind: bb14]
+9:5-9:56: @9.Call: _20 = _print(move _21) -&gt; [return: bb10, unwind: bb14]
+9:5-9:56: @10[6]: _19 = const ()
+10:18-10:24: @10[10]: _42 = _1
+10:27-10:33: @10[12]: _43 = _17
+10:18-10:33: @10[13]: _44 = CheckedAdd(_42, _43)
+10:18-10:33: @11[0]: _41 = move (_44.0: u32)
+10:9-10:15: @11[3]: FakeRead(ForLet, _41)
+11:14-11:47: @11[10]: _58 = const might_overflow::promoted[1]
+11:14-11:47: @11[11]: _50 = &amp;(*_58)
+11:14-11:47: @11[12]: _49 = &amp;(*_50)
+11:14-11:47: @11[13]: _48 = move _49 as &amp;[&amp;str] (Pointer(Unsize))
+11:5-11:49: @11[19]: _56 = ()
+11:5-11:49: @11[20]: FakeRead(ForMatchedPlace, _56)
+11:5-11:49: @11[21]: _57 = const might_overflow::promoted[0]
+11:5-11:49: @11[22]: _54 = &amp;(*_57)
+11:5-11:49: @11[23]: _53 = &amp;(*_54)
+11:5-11:49: @11[24]: _52 = move _53 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+11:5-11:49: @11.Call: _47 = Arguments::new_v1(move _48, move _52) -&gt; [return: bb12, unwind: bb14]
+11:5-11:49: @12.Call: _46 = _print(move _47) -&gt; [return: bb13, unwind: bb14]
+11:5-11:49: @13[5]: _45 = const ()
+12:5-12:11: @13[7]: _0 = _41
+13:2-13:2: @13.Return: return">    println!("does {} + {} overflow?", add_to, to_add);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="8:18-8:30: @5[3]: _18 = CheckedSub(const core::num::&lt;impl u32&gt;::MAX, const 5_u32)
+8:18-8:30: @6[0]: _17 = move (_18.0: u32)
+8:9-8:15: @6[1]: FakeRead(ForLet, _17)
+9:14-9:38: @6[8]: _59 = const might_overflow::promoted[2]
+9:14-9:38: @6[9]: _24 = &amp;(*_59)
+9:14-9:38: @6[10]: _23 = &amp;(*_24)
+9:14-9:38: @6[11]: _22 = move _23 as &amp;[&amp;str] (Pointer(Unsize))
+9:40-9:46: @6[19]: _31 = &amp;_17
+9:48-9:54: @6[21]: _32 = &amp;_1
+9:5-9:56: @6[22]: _30 = (move _31, move _32)
+9:5-9:56: @6[25]: FakeRead(ForMatchedPlace, _30)
+9:5-9:56: @6[27]: _33 = (_30.0: &amp;u32)
+9:5-9:56: @6[29]: _34 = (_30.1: &amp;u32)
+9:5-9:56: @6[32]: _36 = &amp;(*_33)
+9:5-9:56: @6[34]: _37 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+9:5-9:56: @6.Call: _35 = ArgumentV1::new::&lt;u32&gt;(move _36, move _37) -&gt; [return: bb7, unwind: bb14]
+9:5-9:56: @7[4]: _39 = &amp;(*_34)
+9:5-9:56: @7[6]: _40 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+9:5-9:56: @7.Call: _38 = ArgumentV1::new::&lt;u32&gt;(move _39, move _40) -&gt; [return: bb8, unwind: bb14]
+9:5-9:56: @8[2]: _29 = [move _35, move _38]
+9:5-9:56: @8[7]: _28 = &amp;_29
+9:5-9:56: @8[8]: _27 = &amp;(*_28)
+9:5-9:56: @8[9]: _26 = move _27 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+9:5-9:56: @8.Call: _21 = Arguments::new_v1(move _22, move _26) -&gt; [return: bb9, unwind: bb14]
+9:5-9:56: @9.Call: _20 = _print(move _21) -&gt; [return: bb10, unwind: bb14]
+9:5-9:56: @10[6]: _19 = const ()
+10:18-10:24: @10[10]: _42 = _1
+10:27-10:33: @10[12]: _43 = _17
+10:18-10:33: @10[13]: _44 = CheckedAdd(_42, _43)
+10:18-10:33: @11[0]: _41 = move (_44.0: u32)
+10:9-10:15: @11[3]: FakeRead(ForLet, _41)
+11:14-11:47: @11[10]: _58 = const might_overflow::promoted[1]
+11:14-11:47: @11[11]: _50 = &amp;(*_58)
+11:14-11:47: @11[12]: _49 = &amp;(*_50)
+11:14-11:47: @11[13]: _48 = move _49 as &amp;[&amp;str] (Pointer(Unsize))
+11:5-11:49: @11[19]: _56 = ()
+11:5-11:49: @11[20]: FakeRead(ForMatchedPlace, _56)
+11:5-11:49: @11[21]: _57 = const might_overflow::promoted[0]
+11:5-11:49: @11[22]: _54 = &amp;(*_57)
+11:5-11:49: @11[23]: _53 = &amp;(*_54)
+11:5-11:49: @11[24]: _52 = move _53 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+11:5-11:49: @11.Call: _47 = Arguments::new_v1(move _48, move _52) -&gt; [return: bb12, unwind: bb14]
+11:5-11:49: @12.Call: _46 = _print(move _47) -&gt; [return: bb13, unwind: bb14]
+11:5-11:49: @13[5]: _45 = const ()
+12:5-12:11: @13[7]: _0 = _41
+13:2-13:2: @13.Return: return">    let result = to_add + add_to;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="8:18-8:30: @5[3]: _18 = CheckedSub(const core::num::&lt;impl u32&gt;::MAX, const 5_u32)
+8:18-8:30: @6[0]: _17 = move (_18.0: u32)
+8:9-8:15: @6[1]: FakeRead(ForLet, _17)
+9:14-9:38: @6[8]: _59 = const might_overflow::promoted[2]
+9:14-9:38: @6[9]: _24 = &amp;(*_59)
+9:14-9:38: @6[10]: _23 = &amp;(*_24)
+9:14-9:38: @6[11]: _22 = move _23 as &amp;[&amp;str] (Pointer(Unsize))
+9:40-9:46: @6[19]: _31 = &amp;_17
+9:48-9:54: @6[21]: _32 = &amp;_1
+9:5-9:56: @6[22]: _30 = (move _31, move _32)
+9:5-9:56: @6[25]: FakeRead(ForMatchedPlace, _30)
+9:5-9:56: @6[27]: _33 = (_30.0: &amp;u32)
+9:5-9:56: @6[29]: _34 = (_30.1: &amp;u32)
+9:5-9:56: @6[32]: _36 = &amp;(*_33)
+9:5-9:56: @6[34]: _37 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+9:5-9:56: @6.Call: _35 = ArgumentV1::new::&lt;u32&gt;(move _36, move _37) -&gt; [return: bb7, unwind: bb14]
+9:5-9:56: @7[4]: _39 = &amp;(*_34)
+9:5-9:56: @7[6]: _40 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+9:5-9:56: @7.Call: _38 = ArgumentV1::new::&lt;u32&gt;(move _39, move _40) -&gt; [return: bb8, unwind: bb14]
+9:5-9:56: @8[2]: _29 = [move _35, move _38]
+9:5-9:56: @8[7]: _28 = &amp;_29
+9:5-9:56: @8[8]: _27 = &amp;(*_28)
+9:5-9:56: @8[9]: _26 = move _27 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+9:5-9:56: @8.Call: _21 = Arguments::new_v1(move _22, move _26) -&gt; [return: bb9, unwind: bb14]
+9:5-9:56: @9.Call: _20 = _print(move _21) -&gt; [return: bb10, unwind: bb14]
+9:5-9:56: @10[6]: _19 = const ()
+10:18-10:24: @10[10]: _42 = _1
+10:27-10:33: @10[12]: _43 = _17
+10:18-10:33: @10[13]: _44 = CheckedAdd(_42, _43)
+10:18-10:33: @11[0]: _41 = move (_44.0: u32)
+10:9-10:15: @11[3]: FakeRead(ForLet, _41)
+11:14-11:47: @11[10]: _58 = const might_overflow::promoted[1]
+11:14-11:47: @11[11]: _50 = &amp;(*_58)
+11:14-11:47: @11[12]: _49 = &amp;(*_50)
+11:14-11:47: @11[13]: _48 = move _49 as &amp;[&amp;str] (Pointer(Unsize))
+11:5-11:49: @11[19]: _56 = ()
+11:5-11:49: @11[20]: FakeRead(ForMatchedPlace, _56)
+11:5-11:49: @11[21]: _57 = const might_overflow::promoted[0]
+11:5-11:49: @11[22]: _54 = &amp;(*_57)
+11:5-11:49: @11[23]: _53 = &amp;(*_54)
+11:5-11:49: @11[24]: _52 = move _53 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+11:5-11:49: @11.Call: _47 = Arguments::new_v1(move _48, move _52) -&gt; [return: bb12, unwind: bb14]
+11:5-11:49: @12.Call: _46 = _print(move _47) -&gt; [return: bb13, unwind: bb14]
+11:5-11:49: @13[5]: _45 = const ()
+12:5-12:11: @13[7]: _0 = _41
+13:2-13:2: @13.Return: return">    println!("continuing after overflow check");</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="8:18-8:30: @5[3]: _18 = CheckedSub(const core::num::&lt;impl u32&gt;::MAX, const 5_u32)
+8:18-8:30: @6[0]: _17 = move (_18.0: u32)
+8:9-8:15: @6[1]: FakeRead(ForLet, _17)
+9:14-9:38: @6[8]: _59 = const might_overflow::promoted[2]
+9:14-9:38: @6[9]: _24 = &amp;(*_59)
+9:14-9:38: @6[10]: _23 = &amp;(*_24)
+9:14-9:38: @6[11]: _22 = move _23 as &amp;[&amp;str] (Pointer(Unsize))
+9:40-9:46: @6[19]: _31 = &amp;_17
+9:48-9:54: @6[21]: _32 = &amp;_1
+9:5-9:56: @6[22]: _30 = (move _31, move _32)
+9:5-9:56: @6[25]: FakeRead(ForMatchedPlace, _30)
+9:5-9:56: @6[27]: _33 = (_30.0: &amp;u32)
+9:5-9:56: @6[29]: _34 = (_30.1: &amp;u32)
+9:5-9:56: @6[32]: _36 = &amp;(*_33)
+9:5-9:56: @6[34]: _37 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+9:5-9:56: @6.Call: _35 = ArgumentV1::new::&lt;u32&gt;(move _36, move _37) -&gt; [return: bb7, unwind: bb14]
+9:5-9:56: @7[4]: _39 = &amp;(*_34)
+9:5-9:56: @7[6]: _40 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+9:5-9:56: @7.Call: _38 = ArgumentV1::new::&lt;u32&gt;(move _39, move _40) -&gt; [return: bb8, unwind: bb14]
+9:5-9:56: @8[2]: _29 = [move _35, move _38]
+9:5-9:56: @8[7]: _28 = &amp;_29
+9:5-9:56: @8[8]: _27 = &amp;(*_28)
+9:5-9:56: @8[9]: _26 = move _27 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+9:5-9:56: @8.Call: _21 = Arguments::new_v1(move _22, move _26) -&gt; [return: bb9, unwind: bb14]
+9:5-9:56: @9.Call: _20 = _print(move _21) -&gt; [return: bb10, unwind: bb14]
+9:5-9:56: @10[6]: _19 = const ()
+10:18-10:24: @10[10]: _42 = _1
+10:27-10:33: @10[12]: _43 = _17
+10:18-10:33: @10[13]: _44 = CheckedAdd(_42, _43)
+10:18-10:33: @11[0]: _41 = move (_44.0: u32)
+10:9-10:15: @11[3]: FakeRead(ForLet, _41)
+11:14-11:47: @11[10]: _58 = const might_overflow::promoted[1]
+11:14-11:47: @11[11]: _50 = &amp;(*_58)
+11:14-11:47: @11[12]: _49 = &amp;(*_50)
+11:14-11:47: @11[13]: _48 = move _49 as &amp;[&amp;str] (Pointer(Unsize))
+11:5-11:49: @11[19]: _56 = ()
+11:5-11:49: @11[20]: FakeRead(ForMatchedPlace, _56)
+11:5-11:49: @11[21]: _57 = const might_overflow::promoted[0]
+11:5-11:49: @11[22]: _54 = &amp;(*_57)
+11:5-11:49: @11[23]: _53 = &amp;(*_54)
+11:5-11:49: @11[24]: _52 = move _53 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+11:5-11:49: @11.Call: _47 = Arguments::new_v1(move _48, move _52) -&gt; [return: bb12, unwind: bb14]
+11:5-11:49: @12.Call: _46 = _print(move _47) -&gt; [return: bb13, unwind: bb14]
+11:5-11:49: @13[5]: _45 = const ()
+12:5-12:11: @13[7]: _0 = _41
+13:2-13:2: @13.Return: return">    result</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="8:18-8:30: @5[3]: _18 = CheckedSub(const core::num::&lt;impl u32&gt;::MAX, const 5_u32)
+8:18-8:30: @6[0]: _17 = move (_18.0: u32)
+8:9-8:15: @6[1]: FakeRead(ForLet, _17)
+9:14-9:38: @6[8]: _59 = const might_overflow::promoted[2]
+9:14-9:38: @6[9]: _24 = &amp;(*_59)
+9:14-9:38: @6[10]: _23 = &amp;(*_24)
+9:14-9:38: @6[11]: _22 = move _23 as &amp;[&amp;str] (Pointer(Unsize))
+9:40-9:46: @6[19]: _31 = &amp;_17
+9:48-9:54: @6[21]: _32 = &amp;_1
+9:5-9:56: @6[22]: _30 = (move _31, move _32)
+9:5-9:56: @6[25]: FakeRead(ForMatchedPlace, _30)
+9:5-9:56: @6[27]: _33 = (_30.0: &amp;u32)
+9:5-9:56: @6[29]: _34 = (_30.1: &amp;u32)
+9:5-9:56: @6[32]: _36 = &amp;(*_33)
+9:5-9:56: @6[34]: _37 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+9:5-9:56: @6.Call: _35 = ArgumentV1::new::&lt;u32&gt;(move _36, move _37) -&gt; [return: bb7, unwind: bb14]
+9:5-9:56: @7[4]: _39 = &amp;(*_34)
+9:5-9:56: @7[6]: _40 = &lt;u32 as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r u32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+9:5-9:56: @7.Call: _38 = ArgumentV1::new::&lt;u32&gt;(move _39, move _40) -&gt; [return: bb8, unwind: bb14]
+9:5-9:56: @8[2]: _29 = [move _35, move _38]
+9:5-9:56: @8[7]: _28 = &amp;_29
+9:5-9:56: @8[8]: _27 = &amp;(*_28)
+9:5-9:56: @8[9]: _26 = move _27 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+9:5-9:56: @8.Call: _21 = Arguments::new_v1(move _22, move _26) -&gt; [return: bb9, unwind: bb14]
+9:5-9:56: @9.Call: _20 = _print(move _21) -&gt; [return: bb10, unwind: bb14]
+9:5-9:56: @10[6]: _19 = const ()
+10:18-10:24: @10[10]: _42 = _1
+10:27-10:33: @10[12]: _43 = _17
+10:18-10:33: @10[13]: _44 = CheckedAdd(_42, _43)
+10:18-10:33: @11[0]: _41 = move (_44.0: u32)
+10:9-10:15: @11[3]: FakeRead(ForLet, _41)
+11:14-11:47: @11[10]: _58 = const might_overflow::promoted[1]
+11:14-11:47: @11[11]: _50 = &amp;(*_58)
+11:14-11:47: @11[12]: _49 = &amp;(*_50)
+11:14-11:47: @11[13]: _48 = move _49 as &amp;[&amp;str] (Pointer(Unsize))
+11:5-11:49: @11[19]: _56 = ()
+11:5-11:49: @11[20]: FakeRead(ForMatchedPlace, _56)
+11:5-11:49: @11[21]: _57 = const might_overflow::promoted[0]
+11:5-11:49: @11[22]: _54 = &amp;(*_57)
+11:5-11:49: @11[23]: _53 = &amp;(*_54)
+11:5-11:49: @11[24]: _52 = move _53 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+11:5-11:49: @11.Call: _47 = Arguments::new_v1(move _48, move _52) -&gt; [return: bb12, unwind: bb14]
+11:5-11:49: @12.Call: _46 = _print(move _47) -&gt; [return: bb13, unwind: bb14]
+11:5-11:49: @13[5]: _45 = const ()
+12:5-12:11: @13[7]: _0 = _41
+13:2-13:2: @13.Return: return">}<span class="annotation">⦉@5,6,7,8,9,10,11,12,13</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.main.-------.InstrumentCoverage.0.html
index bd6aac4..5b097f1 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.main.-------.InstrumentCoverage.0.html
@@ -77,22 +77,20 @@
 15:11-15:24: @2[3]: _4 = Gt(move _5, const 0_i32)
 15:11-15:24: @2[5]: FakeRead(ForMatchedPlace, _4)"><span class="annotation">@1,2⦊</span>countdown &gt; 0<span class="annotation">⦉@1,2</span></span></span><span class="code" style="--layer: 0"> {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code even" style="--layer: 1" title="16:12-16:21: @5[3]: _8 = _1
-16:12-16:26: @5[4]: _7 = Eq(move _8, const 1_i32)
-16:12-16:26: @5[6]: FakeRead(ForMatchedPlace, _7)"><span class="annotation">@3,5⦊</span>countdown == 1<span class="annotation">⦉@3,5</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="17:13-17:30: @8.Call: _9 = might_panic(const true) -&gt; [return: bb9, unwind: bb17]
-16:27-18:10: @9[1]: _6 = const ()"><span class="annotation">@6,8,9⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="17:13-17:30: @8.Call: _9 = might_panic(const true) -&gt; [return: bb9, unwind: bb17]
-16:27-18:10: @9[1]: _6 = const ()">            might_panic(true);</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="17:13-17:30: @8.Call: _9 = might_panic(const true) -&gt; [return: bb9, unwind: bb17]
-16:27-18:10: @9[1]: _6 = const ()">        }<span class="annotation">⦉@6,8,9</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code even" style="--layer: 1" title="18:19-18:28: @7[2]: _11 = _1
-18:19-18:32: @7[3]: _10 = Lt(move _11, const 5_i32)
-18:19-18:32: @7[5]: FakeRead(ForMatchedPlace, _10)"><span class="annotation">@7⦊</span>countdown &lt; 5<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="19:13-19:31: @12.Call: _12 = might_panic(const false) -&gt; [return: bb13, unwind: bb17]
-18:33-20:10: @13[1]: _6 = const ()"><span class="annotation">@10,12,13⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="19:13-19:31: @12.Call: _12 = might_panic(const false) -&gt; [return: bb13, unwind: bb17]
-18:33-20:10: @13[1]: _6 = const ()">            might_panic(false);</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="19:13-19:31: @12.Call: _12 = might_panic(const false) -&gt; [return: bb13, unwind: bb17]
-18:33-20:10: @13[1]: _6 = const ()">        }<span class="annotation">⦉@10,12,13</span></span></span><span><span class="code even" style="--layer: 1" title="20:10-20:10: @11[0]: _6 = const ()"><span class="annotation">@11⦊</span>‸<span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="21:9-21:23: @15[2]: _13 = CheckedSub(_1, const 1_i32)
-21:9-21:23: @16[0]: _1 = move (_13.0: i32)"><span class="annotation">@15,16⦊</span>countdown -= 1<span class="annotation">⦉@15,16</span></span></span><span class="code" style="--layer: 0">;</span></span>
+16:12-16:26: @5[4]: _7 = Eq(move _8, const 1_i32)"><span class="annotation">@3,5⦊</span>countdown == 1<span class="annotation">⦉@3,5</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="17:13-17:30: @6.Call: _9 = might_panic(const true) -&gt; [return: bb8, unwind: bb15]
+16:27-18:10: @8[1]: _6 = const ()"><span class="annotation">@6,8⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="17:13-17:30: @6.Call: _9 = might_panic(const true) -&gt; [return: bb8, unwind: bb15]
+16:27-18:10: @8[1]: _6 = const ()">            might_panic(true);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="17:13-17:30: @6.Call: _9 = might_panic(const true) -&gt; [return: bb8, unwind: bb15]
+16:27-18:10: @8[1]: _6 = const ()">        }<span class="annotation">⦉@6,8</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code even" style="--layer: 1" title="18:19-18:28: @7[2]: _11 = _1
+18:19-18:32: @7[3]: _10 = Lt(move _11, const 5_i32)"><span class="annotation">@7⦊</span>countdown &lt; 5<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="19:13-19:31: @9.Call: _12 = might_panic(const false) -&gt; [return: bb11, unwind: bb15]
+18:33-20:10: @11[1]: _6 = const ()"><span class="annotation">@9,11⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="19:13-19:31: @9.Call: _12 = might_panic(const false) -&gt; [return: bb11, unwind: bb15]
+18:33-20:10: @11[1]: _6 = const ()">            might_panic(false);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="19:13-19:31: @9.Call: _12 = might_panic(const false) -&gt; [return: bb11, unwind: bb15]
+18:33-20:10: @11[1]: _6 = const ()">        }<span class="annotation">⦉@9,11</span></span></span><span><span class="code even" style="--layer: 1" title="20:10-20:10: @10[0]: _6 = const ()"><span class="annotation">@10⦊</span>‸<span class="annotation">⦉@10</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="21:9-21:23: @13[2]: _13 = CheckedSub(_1, const 1_i32)
+21:9-21:23: @14[0]: _1 = move (_13.0: i32)"><span class="annotation">@13,14⦊</span>countdown -= 1<span class="annotation">⦉@13,14</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
 <span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="23:8-23:10: @4[4]: _15 = ()
 23:5-23:11: @4[5]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _15)
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.might_panic.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.might_panic.-------.InstrumentCoverage.0.html
index 290b7b8..86d9875 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.might_panic.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.might_panic.-------.InstrumentCoverage.0.html
@@ -70,36 +70,35 @@
 </head>
 <body>
 <div class="code" style="counter-reset: line 3"><span class="line"><span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>fn might_panic(should_panic: bool) <span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">{</span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="5:8-5:20: @0[1]: _2 = _1
-5:8-5:20: @0[2]: FakeRead(ForMatchedPlace, _2)"><span class="annotation">@0⦊</span>should_panic<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="6:18-6:32: @3[6]: _33 = const might_panic::promoted[3]
-6:18-6:32: @3[7]: _9 = &amp;(*_33)
-6:18-6:32: @3[8]: _8 = &amp;(*_9)
-6:18-6:32: @3[9]: _7 = move _8 as &amp;[&amp;str] (Pointer(Unsize))
-6:9-6:34: @3[15]: _15 = ()
-6:9-6:34: @3[16]: FakeRead(ForMatchedPlace, _15)
-6:9-6:34: @3[17]: _32 = const might_panic::promoted[2]
-6:9-6:34: @3[18]: _13 = &amp;(*_32)
-6:9-6:34: @3[19]: _12 = &amp;(*_13)
-6:9-6:34: @3[20]: _11 = move _12 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-6:9-6:34: @3.Call: _6 = Arguments::new_v1(move _7, move _11) -&gt; [return: bb4, unwind: bb8]
-6:9-6:34: @4.Call: _5 = _print(move _6) -&gt; [return: bb5, unwind: bb8]
-6:9-6:34: @5[5]: _4 = const ()
-7:9-7:26: @5.Call: begin_panic::&lt;&amp;str&gt;(const &quot;panics&quot;) -&gt; bb8"><span class="annotation">@1,3,4,5⦊</span>println!("panicking...");</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="6:18-6:32: @3[6]: _33 = const might_panic::promoted[3]
-6:18-6:32: @3[7]: _9 = &amp;(*_33)
-6:18-6:32: @3[8]: _8 = &amp;(*_9)
-6:18-6:32: @3[9]: _7 = move _8 as &amp;[&amp;str] (Pointer(Unsize))
-6:9-6:34: @3[15]: _15 = ()
-6:9-6:34: @3[16]: FakeRead(ForMatchedPlace, _15)
-6:9-6:34: @3[17]: _32 = const might_panic::promoted[2]
-6:9-6:34: @3[18]: _13 = &amp;(*_32)
-6:9-6:34: @3[19]: _12 = &amp;(*_13)
-6:9-6:34: @3[20]: _11 = move _12 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-6:9-6:34: @3.Call: _6 = Arguments::new_v1(move _7, move _11) -&gt; [return: bb4, unwind: bb8]
-6:9-6:34: @4.Call: _5 = _print(move _6) -&gt; [return: bb5, unwind: bb8]
-6:9-6:34: @5[5]: _4 = const ()
-7:9-7:26: @5.Call: begin_panic::&lt;&amp;str&gt;(const &quot;panics&quot;) -&gt; bb8">        panic!("panics");<span class="annotation">⦉@1,3,4,5</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="5:8-5:20: @0[1]: _2 = _1"><span class="annotation">@0⦊</span>should_panic<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="6:18-6:32: @1[6]: _33 = const might_panic::promoted[3]
+6:18-6:32: @1[7]: _9 = &amp;(*_33)
+6:18-6:32: @1[8]: _8 = &amp;(*_9)
+6:18-6:32: @1[9]: _7 = move _8 as &amp;[&amp;str] (Pointer(Unsize))
+6:9-6:34: @1[15]: _15 = ()
+6:9-6:34: @1[16]: FakeRead(ForMatchedPlace, _15)
+6:9-6:34: @1[17]: _32 = const might_panic::promoted[2]
+6:9-6:34: @1[18]: _13 = &amp;(*_32)
+6:9-6:34: @1[19]: _12 = &amp;(*_13)
+6:9-6:34: @1[20]: _11 = move _12 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+6:9-6:34: @1.Call: _6 = Arguments::new_v1(move _7, move _11) -&gt; [return: bb3, unwind: bb7]
+6:9-6:34: @3.Call: _5 = _print(move _6) -&gt; [return: bb4, unwind: bb7]
+6:9-6:34: @4[5]: _4 = const ()
+7:9-7:26: @4.Call: begin_panic::&lt;&amp;str&gt;(const &quot;panics&quot;) -&gt; bb7"><span class="annotation">@1,3,4⦊</span>println!("panicking...");</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="6:18-6:32: @1[6]: _33 = const might_panic::promoted[3]
+6:18-6:32: @1[7]: _9 = &amp;(*_33)
+6:18-6:32: @1[8]: _8 = &amp;(*_9)
+6:18-6:32: @1[9]: _7 = move _8 as &amp;[&amp;str] (Pointer(Unsize))
+6:9-6:34: @1[15]: _15 = ()
+6:9-6:34: @1[16]: FakeRead(ForMatchedPlace, _15)
+6:9-6:34: @1[17]: _32 = const might_panic::promoted[2]
+6:9-6:34: @1[18]: _13 = &amp;(*_32)
+6:9-6:34: @1[19]: _12 = &amp;(*_13)
+6:9-6:34: @1[20]: _11 = move _12 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+6:9-6:34: @1.Call: _6 = Arguments::new_v1(move _7, move _11) -&gt; [return: bb3, unwind: bb7]
+6:9-6:34: @3.Call: _5 = _print(move _6) -&gt; [return: bb4, unwind: bb7]
+6:9-6:34: @4[5]: _4 = const ()
+7:9-7:26: @4.Call: begin_panic::&lt;&amp;str&gt;(const &quot;panics&quot;) -&gt; bb7">        panic!("panics");<span class="annotation">⦉@1,3,4</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    } else </span><span><span class="code even" style="--layer: 1" title="9:18-9:31: @2[6]: _31 = const might_panic::promoted[1]
 9:18-9:31: @2[7]: _23 = &amp;(*_31)
 9:18-9:31: @2[8]: _22 = &amp;(*_23)
@@ -110,11 +109,11 @@
 9:9-9:33: @2[18]: _27 = &amp;(*_30)
 9:9-9:33: @2[19]: _26 = &amp;(*_27)
 9:9-9:33: @2[20]: _25 = move _26 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-9:9-9:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb6, unwind: bb8]
-9:9-9:33: @6.Call: _19 = _print(move _20) -&gt; [return: bb7, unwind: bb8]
-9:9-9:33: @7[5]: _18 = const ()
-8:12-10:6: @7[7]: _0 = const ()
-11:2-11:2: @7.Return: return"><span class="annotation">@2,6,7⦊</span>{</span></span>
+9:9-9:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb5, unwind: bb7]
+9:9-9:33: @5.Call: _19 = _print(move _20) -&gt; [return: bb6, unwind: bb7]
+9:9-9:33: @6[5]: _18 = const ()
+8:12-10:6: @6[7]: _0 = const ()
+11:2-11:2: @6.Return: return"><span class="annotation">@2,5,6⦊</span>{</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="9:18-9:31: @2[6]: _31 = const might_panic::promoted[1]
 9:18-9:31: @2[7]: _23 = &amp;(*_31)
 9:18-9:31: @2[8]: _22 = &amp;(*_23)
@@ -125,11 +124,11 @@
 9:9-9:33: @2[18]: _27 = &amp;(*_30)
 9:9-9:33: @2[19]: _26 = &amp;(*_27)
 9:9-9:33: @2[20]: _25 = move _26 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-9:9-9:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb6, unwind: bb8]
-9:9-9:33: @6.Call: _19 = _print(move _20) -&gt; [return: bb7, unwind: bb8]
-9:9-9:33: @7[5]: _18 = const ()
-8:12-10:6: @7[7]: _0 = const ()
-11:2-11:2: @7.Return: return">        println!("Don't Panic");</span></span>
+9:9-9:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb5, unwind: bb7]
+9:9-9:33: @5.Call: _19 = _print(move _20) -&gt; [return: bb6, unwind: bb7]
+9:9-9:33: @6[5]: _18 = const ()
+8:12-10:6: @6[7]: _0 = const ()
+11:2-11:2: @6.Return: return">        println!("Don't Panic");</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="9:18-9:31: @2[6]: _31 = const might_panic::promoted[1]
 9:18-9:31: @2[7]: _23 = &amp;(*_31)
 9:18-9:31: @2[8]: _22 = &amp;(*_23)
@@ -140,11 +139,11 @@
 9:9-9:33: @2[18]: _27 = &amp;(*_30)
 9:9-9:33: @2[19]: _26 = &amp;(*_27)
 9:9-9:33: @2[20]: _25 = move _26 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-9:9-9:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb6, unwind: bb8]
-9:9-9:33: @6.Call: _19 = _print(move _20) -&gt; [return: bb7, unwind: bb8]
-9:9-9:33: @7[5]: _18 = const ()
-8:12-10:6: @7[7]: _0 = const ()
-11:2-11:2: @7.Return: return">    }</span></span>
+9:9-9:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb5, unwind: bb7]
+9:9-9:33: @5.Call: _19 = _print(move _20) -&gt; [return: bb6, unwind: bb7]
+9:9-9:33: @6[5]: _18 = const ()
+8:12-10:6: @6[7]: _0 = const ()
+11:2-11:2: @6.Return: return">    }</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="9:18-9:31: @2[6]: _31 = const might_panic::promoted[1]
 9:18-9:31: @2[7]: _23 = &amp;(*_31)
 9:18-9:31: @2[8]: _22 = &amp;(*_23)
@@ -155,10 +154,10 @@
 9:9-9:33: @2[18]: _27 = &amp;(*_30)
 9:9-9:33: @2[19]: _26 = &amp;(*_27)
 9:9-9:33: @2[20]: _25 = move _26 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-9:9-9:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb6, unwind: bb8]
-9:9-9:33: @6.Call: _19 = _print(move _20) -&gt; [return: bb7, unwind: bb8]
-9:9-9:33: @7[5]: _18 = const ()
-8:12-10:6: @7[7]: _0 = const ()
-11:2-11:2: @7.Return: return">}<span class="annotation">⦉@2,6,7</span></span></span></span></div>
+9:9-9:33: @2.Call: _20 = Arguments::new_v1(move _21, move _25) -&gt; [return: bb5, unwind: bb7]
+9:9-9:33: @5.Call: _19 = _print(move _20) -&gt; [return: bb6, unwind: bb7]
+9:9-9:33: @6[5]: _18 = const ()
+8:12-10:6: @6[7]: _0 = const ()
+11:2-11:2: @6.Return: return">}<span class="annotation">⦉@2,5,6</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_loop/simple_loop.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_loop/simple_loop.main.-------.InstrumentCoverage.0.html
index 1233dfb..f528b69 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_loop/simple_loop.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_loop/simple_loop.main.-------.InstrumentCoverage.0.html
@@ -69,138 +69,125 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb15]
+<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb14]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-12:9-12:16: @3[6]: _7 = _1
-12:9-12:16: @3[7]: FakeRead(ForMatchedPlace, _7)"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb15]
+12:9-12:16: @3[6]: _7 = _1"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb14]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-12:9-12:16: @3[6]: _7 = _1
-12:9-12:16: @3[7]: FakeRead(ForMatchedPlace, _7)">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb15]
+12:9-12:16: @3[6]: _7 = _1">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb14]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-12:9-12:16: @3[6]: _7 = _1
-12:9-12:16: @3[7]: FakeRead(ForMatchedPlace, _7)">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb15]
+12:9-12:16: @3[6]: _7 = _1">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb14]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-12:9-12:16: @3[6]: _7 = _1
-12:9-12:16: @3[7]: FakeRead(ForMatchedPlace, _7)">    // dependent conditions.</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb15]
+12:9-12:16: @3[6]: _7 = _1">    // dependent conditions.</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb14]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-12:9-12:16: @3[6]: _7 = _1
-12:9-12:16: @3[7]: FakeRead(ForMatchedPlace, _7)">    let is_true = std::env::args().len() == 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb15]
+12:9-12:16: @3[6]: _7 = _1">    let is_true = std::env::args().len() == 1;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb14]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-12:9-12:16: @3[6]: _7 = _1
-12:9-12:16: @3[7]: FakeRead(ForMatchedPlace, _7)"></span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb15]
+12:9-12:16: @3[6]: _7 = _1"></span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb14]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-12:9-12:16: @3[6]: _7 = _1
-12:9-12:16: @3[7]: FakeRead(ForMatchedPlace, _7)">    let mut countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb15]
+12:9-12:16: @3[6]: _7 = _1">    let mut countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb14]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-12:9-12:16: @3[6]: _7 = _1
-12:9-12:16: @3[7]: FakeRead(ForMatchedPlace, _7)"></span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb15]
+12:9-12:16: @3[6]: _7 = _1"></span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb14]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-12:9-12:16: @3[6]: _7 = _1
-12:9-12:16: @3[7]: FakeRead(ForMatchedPlace, _7)">    if</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb15]
+12:9-12:16: @3[6]: _7 = _1">    if</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb13]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb14]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb12]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 0_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-12:9-12:16: @3[6]: _7 = _1
-12:9-12:16: @3[7]: FakeRead(ForMatchedPlace, _7)">        is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="14:9-16:15: @6[0]: _5 = const 10_i32
-13:5-18:6: @6[1]: _6 = const ()"><span class="annotation">@4,6⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="14:9-16:15: @6[0]: _5 = const 10_i32
-13:5-18:6: @6[1]: _6 = const ()">        countdown</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="14:9-16:15: @6[0]: _5 = const 10_i32
-13:5-18:6: @6[1]: _6 = const ()">        =</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="14:9-16:15: @6[0]: _5 = const 10_i32
-13:5-18:6: @6[1]: _6 = const ()">            10</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="14:9-16:15: @6[0]: _5 = const 10_i32
-13:5-18:6: @6[1]: _6 = const ()">        ;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="14:9-16:15: @6[0]: _5 = const 10_i32
-13:5-18:6: @6[1]: _6 = const ()">    }<span class="annotation">⦉@4,6</span></span></span><span><span class="code even" style="--layer: 1" title="18:6-18:6: @5[0]: _6 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+12:9-12:16: @3[6]: _7 = _1">        is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="14:9-16:15: @4[0]: _5 = const 10_i32
+13:5-18:6: @4[1]: _6 = const ()"><span class="annotation">@4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="14:9-16:15: @4[0]: _5 = const 10_i32
+13:5-18:6: @4[1]: _6 = const ()">        countdown</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="14:9-16:15: @4[0]: _5 = const 10_i32
+13:5-18:6: @4[1]: _6 = const ()">        =</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="14:9-16:15: @4[0]: _5 = const 10_i32
+13:5-18:6: @4[1]: _6 = const ()">            10</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="14:9-16:15: @4[0]: _5 = const 10_i32
+13:5-18:6: @4[1]: _6 = const ()">        ;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="14:9-16:15: @4[0]: _5 = const 10_i32
+13:5-18:6: @4[1]: _6 = const ()">    }<span class="annotation">⦉@4</span></span></span><span><span class="code even" style="--layer: 1" title="18:6-18:6: @5[0]: _6 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    loop</span></span>
 <span class="line"><span class="code" style="--layer: 0">    {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        if</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="23:13-23:22: @9[3]: _11 = _5
-23:13-25:14: @9[4]: _10 = Eq(move _11, const 0_i32)
-23:13-25:14: @9[6]: FakeRead(ForMatchedPlace, _10)"><span class="annotation">@8,9⦊</span>countdown</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="23:13-23:22: @9[3]: _11 = _5
-23:13-25:14: @9[4]: _10 = Eq(move _11, const 0_i32)
-23:13-25:14: @9[6]: FakeRead(ForMatchedPlace, _10)">                ==</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="23:13-23:22: @9[3]: _11 = _5
-23:13-25:14: @9[4]: _10 = Eq(move _11, const 0_i32)
-23:13-25:14: @9[6]: FakeRead(ForMatchedPlace, _10)">            0<span class="annotation">⦉@8,9</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="23:13-23:22: @8[3]: _11 = _5
+23:13-25:14: @8[4]: _10 = Eq(move _11, const 0_i32)"><span class="annotation">@7,8⦊</span>countdown</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="23:13-23:22: @8[3]: _11 = _5
+23:13-25:14: @8[4]: _10 = Eq(move _11, const 0_i32)">                ==</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="23:13-23:22: @8[3]: _11 = _5
+23:13-25:14: @8[4]: _10 = Eq(move _11, const 0_i32)">            0<span class="annotation">⦉@7,8</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        {</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="27:13-27:18: @12[0]: _0 = const ()"><span class="annotation">@10,12⦊</span>break<span class="annotation">⦉@10,12</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="27:13-27:18: @9[0]: _0 = const ()"><span class="annotation">@9⦊</span>break<span class="annotation">⦉@9</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">            ;</span></span>
-<span class="line"><span class="code" style="--layer: 0">        }</span><span><span class="code odd" style="--layer: 1" title="29:10-29:10: @11[0]: _9 = const ()
-30:9-32:10: @11[3]: _13 = CheckedSub(_5, const 1_i32)
-30:9-32:10: @13[0]: _5 = move (_13.0: i32)"><span class="annotation">@11,13⦊</span></span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="29:10-29:10: @11[0]: _9 = const ()
-30:9-32:10: @11[3]: _13 = CheckedSub(_5, const 1_i32)
-30:9-32:10: @13[0]: _5 = move (_13.0: i32)">        countdown</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="29:10-29:10: @11[0]: _9 = const ()
-30:9-32:10: @11[3]: _13 = CheckedSub(_5, const 1_i32)
-30:9-32:10: @13[0]: _5 = move (_13.0: i32)">        -=</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="29:10-29:10: @11[0]: _9 = const ()
-30:9-32:10: @11[3]: _13 = CheckedSub(_5, const 1_i32)
-30:9-32:10: @13[0]: _5 = move (_13.0: i32)">        1<span class="annotation">⦉@11,13</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        }</span><span><span class="code odd" style="--layer: 1" title="29:10-29:10: @10[0]: _9 = const ()
+30:9-32:10: @10[3]: _13 = CheckedSub(_5, const 1_i32)
+30:9-32:10: @11[0]: _5 = move (_13.0: i32)"><span class="annotation">@10,11⦊</span></span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="29:10-29:10: @10[0]: _9 = const ()
+30:9-32:10: @10[3]: _13 = CheckedSub(_5, const 1_i32)
+30:9-32:10: @11[0]: _5 = move (_13.0: i32)">        countdown</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="29:10-29:10: @10[0]: _9 = const ()
+30:9-32:10: @10[3]: _13 = CheckedSub(_5, const 1_i32)
+30:9-32:10: @11[0]: _5 = move (_13.0: i32)">        -=</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="29:10-29:10: @10[0]: _9 = const ()
+30:9-32:10: @10[3]: _13 = CheckedSub(_5, const 1_i32)
+30:9-32:10: @11[0]: _5 = move (_13.0: i32)">        1<span class="annotation">⦉@10,11</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        ;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code even" style="--layer: 1" title="35:2-35:2: @12.Return: return"><span class="annotation">@10,12⦊</span>‸<span class="annotation">⦉@10,12</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code even" style="--layer: 1" title="35:2-35:2: @9.Return: return"><span class="annotation">@9⦊</span>‸<span class="annotation">⦉@9</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_match/simple_match.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_match/simple_match.main.-------.InstrumentCoverage.0.html
index a8bae32..8e49e45 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_match/simple_match.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_match/simple_match.main.-------.InstrumentCoverage.0.html
@@ -69,162 +69,154 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb22]
+<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb21]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb21]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb20]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 1_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[6]: _7 = _1
-10:8-10:15: @3[7]: FakeRead(ForMatchedPlace, _7)"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb22]
+10:8-10:15: @3[6]: _7 = _1"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb21]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb21]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb20]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 1_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[6]: _7 = _1
-10:8-10:15: @3[7]: FakeRead(ForMatchedPlace, _7)">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb22]
+10:8-10:15: @3[6]: _7 = _1">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb21]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb21]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb20]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 1_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[6]: _7 = _1
-10:8-10:15: @3[7]: FakeRead(ForMatchedPlace, _7)">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb22]
+10:8-10:15: @3[6]: _7 = _1">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb21]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb21]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb20]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 1_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[6]: _7 = _1
-10:8-10:15: @3[7]: FakeRead(ForMatchedPlace, _7)">    // dependent conditions.</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb22]
+10:8-10:15: @3[6]: _7 = _1">    // dependent conditions.</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb21]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb21]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb20]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 1_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[6]: _7 = _1
-10:8-10:15: @3[7]: FakeRead(ForMatchedPlace, _7)">    let is_true = std::env::args().len() == 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb22]
+10:8-10:15: @3[6]: _7 = _1">    let is_true = std::env::args().len() == 1;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb21]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb21]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb20]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 1_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[6]: _7 = _1
-10:8-10:15: @3[7]: FakeRead(ForMatchedPlace, _7)"></span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb22]
+10:8-10:15: @3[6]: _7 = _1"></span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb21]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb21]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb20]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 1_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[6]: _7 = _1
-10:8-10:15: @3[7]: FakeRead(ForMatchedPlace, _7)">    let mut countdown = 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb22]
+10:8-10:15: @3[6]: _7 = _1">    let mut countdown = 1;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb21]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb21]
+7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb20]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:25-9:26: @3[2]: _5 = const 1_i32
 9:9-9:22: @3[3]: FakeRead(ForLet, _5)
-10:8-10:15: @3[6]: _7 = _1
-10:8-10:15: @3[7]: FakeRead(ForMatchedPlace, _7)">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="11:9-11:22: @6[0]: _5 = const 0_i32
-10:16-12:6: @6[1]: _6 = const ()"><span class="annotation">@4,6⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:22: @6[0]: _5 = const 0_i32
-10:16-12:6: @6[1]: _6 = const ()">        countdown = 0;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:22: @6[0]: _5 = const 0_i32
-10:16-12:6: @6[1]: _6 = const ()">    }<span class="annotation">⦉@4,6</span></span></span><span><span class="code even" style="--layer: 1" title="12:6-12:6: @5[0]: _6 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+10:8-10:15: @3[6]: _7 = _1">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="11:9-11:22: @4[0]: _5 = const 0_i32
+10:16-12:6: @4[1]: _6 = const ()"><span class="annotation">@4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:22: @4[0]: _5 = const 0_i32
+10:16-12:6: @4[1]: _6 = const ()">        countdown = 0;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="11:9-11:22: @4[0]: _5 = const 0_i32
+10:16-12:6: @4[1]: _6 = const ()">    }<span class="annotation">⦉@4</span></span></span><span><span class="code even" style="--layer: 1" title="12:6-12:6: @5[0]: _6 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    for</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="15:9-15:10: @15[1]: _18 = ((_14 as Some).0: i32)
-15:9-15:10: @15[3]: _19 = _18
-15:9-15:10: @15[4]: _12 = move _19
-15:9-15:10: @15[5]: _13 = const ()"><span class="annotation">@13,15,17⦊</span>_<span class="annotation">⦉@13,15,17</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="15:9-15:10: @14[1]: _18 = ((_14 as Some).0: i32)
+15:9-15:10: @14[3]: _19 = _18
+15:9-15:10: @14[4]: _12 = move _19
+15:9-15:10: @14[5]: _13 = const ()"><span class="annotation">@12,14,16⦊</span>_<span class="annotation">⦉@12,14,16</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    in</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="17:9-17:13: @10[5]: _16 = &amp;mut _10
-17:9-17:13: @10[6]: _15 = &amp;mut (*_16)
-17:9-17:13: @10.Call: _14 = &lt;std::ops::Range&lt;i32&gt; as Iterator&gt;::next(move _15) -&gt; [return: bb11, unwind: bb22]
-17:9-17:13: @11[1]: FakeRead(ForMatchedPlace, _14)"><span class="annotation">@9,10,11⦊</span>0..2<span class="annotation">⦉@9,10,11</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="17:9-17:13: @9[5]: _16 = &amp;mut _10
+17:9-17:13: @9[6]: _15 = &amp;mut (*_16)
+17:9-17:13: @9.Call: _14 = &lt;std::ops::Range&lt;i32&gt; as Iterator&gt;::next(move _15) -&gt; [return: bb10, unwind: bb21]
+17:9-17:13: @10[1]: FakeRead(ForMatchedPlace, _14)"><span class="annotation">@8,9,10⦊</span>0..2<span class="annotation">⦉@8,9,10</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        let z</span></span>
 <span class="line"><span class="code" style="--layer: 0">        ;</span></span>
 <span class="line"><span class="code" style="--layer: 0">        match</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="22:13-22:22: @15[13]: FakeRead(ForMatchedPlace, _5)"><span class="annotation">@13,15,17⦊</span>countdown<span class="annotation">⦉@13,15,17</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="22:13-22:22: @14[13]: FakeRead(ForMatchedPlace, _5)"><span class="annotation">@12,14,16⦊</span>countdown<span class="annotation">⦉@12,14,16</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        {</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="24:13-24:14: @18[3]: _23 = _5"><span class="annotation">@18⦊</span>x<span class="annotation">⦉@18</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="24:13-24:14: @17[3]: _23 = _5"><span class="annotation">@17⦊</span>x<span class="annotation">⦉@17</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">            if</span></span>
-<span class="line"><span class="code" style="--layer: 0">                </span><span><span class="code odd" style="--layer: 1" title="26:17-26:18: @17[4]: _26 = (*_24)
-26:17-28:18: @17[5]: _25 = Lt(move _26, const 1_i32)"><span class="annotation">@13,15,17⦊</span>x</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="26:17-26:18: @17[4]: _26 = (*_24)
-26:17-28:18: @17[5]: _25 = Lt(move _26, const 1_i32)">                    &lt;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="26:17-26:18: @17[4]: _26 = (*_24)
-26:17-28:18: @17[5]: _25 = Lt(move _26, const 1_i32)">                1<span class="annotation">⦉@13,15,17</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">                </span><span><span class="code odd" style="--layer: 1" title="26:17-26:18: @16[4]: _26 = (*_24)
+26:17-28:18: @16[5]: _25 = Lt(move _26, const 1_i32)"><span class="annotation">@12,14,16⦊</span>x</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="26:17-26:18: @16[4]: _26 = (*_24)
+26:17-28:18: @16[5]: _25 = Lt(move _26, const 1_i32)">                    &lt;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="26:17-26:18: @16[4]: _26 = (*_24)
+26:17-28:18: @16[5]: _25 = Lt(move _26, const 1_i32)">                1<span class="annotation">⦉@12,14,16</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">            =&gt;</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="31:21-31:30: @18[5]: _27 = _5
-31:17-31:30: @18[6]: _22 = move _27
-33:25-33:34: @18[9]: _28 = _5
-33:21-33:22: @18[10]: FakeRead(ForLet, _28)
-35:17-35:31: @18[11]: _5 = const 10_i32
-30:13-37:14: @18[12]: _21 = const ()"><span class="annotation">@18⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="31:21-31:30: @18[5]: _27 = _5
-31:17-31:30: @18[6]: _22 = move _27
-33:25-33:34: @18[9]: _28 = _5
-33:21-33:22: @18[10]: FakeRead(ForLet, _28)
-35:17-35:31: @18[11]: _5 = const 10_i32
-30:13-37:14: @18[12]: _21 = const ()">                z = countdown</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="31:21-31:30: @18[5]: _27 = _5
-31:17-31:30: @18[6]: _22 = move _27
-33:25-33:34: @18[9]: _28 = _5
-33:21-33:22: @18[10]: FakeRead(ForLet, _28)
-35:17-35:31: @18[11]: _5 = const 10_i32
-30:13-37:14: @18[12]: _21 = const ()">                ;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="31:21-31:30: @18[5]: _27 = _5
-31:17-31:30: @18[6]: _22 = move _27
-33:25-33:34: @18[9]: _28 = _5
-33:21-33:22: @18[10]: FakeRead(ForLet, _28)
-35:17-35:31: @18[11]: _5 = const 10_i32
-30:13-37:14: @18[12]: _21 = const ()">                let y = countdown</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="31:21-31:30: @18[5]: _27 = _5
-31:17-31:30: @18[6]: _22 = move _27
-33:25-33:34: @18[9]: _28 = _5
-33:21-33:22: @18[10]: FakeRead(ForLet, _28)
-35:17-35:31: @18[11]: _5 = const 10_i32
-30:13-37:14: @18[12]: _21 = const ()">                ;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="31:21-31:30: @18[5]: _27 = _5
-31:17-31:30: @18[6]: _22 = move _27
-33:25-33:34: @18[9]: _28 = _5
-33:21-33:22: @18[10]: FakeRead(ForLet, _28)
-35:17-35:31: @18[11]: _5 = const 10_i32
-30:13-37:14: @18[12]: _21 = const ()">                countdown = 10</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="31:21-31:30: @18[5]: _27 = _5
-31:17-31:30: @18[6]: _22 = move _27
-33:25-33:34: @18[9]: _28 = _5
-33:21-33:22: @18[10]: FakeRead(ForLet, _28)
-35:17-35:31: @18[11]: _5 = const 10_i32
-30:13-37:14: @18[12]: _21 = const ()">                ;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="31:21-31:30: @18[5]: _27 = _5
-31:17-31:30: @18[6]: _22 = move _27
-33:25-33:34: @18[9]: _28 = _5
-33:21-33:22: @18[10]: FakeRead(ForLet, _28)
-35:17-35:31: @18[11]: _5 = const 10_i32
-30:13-37:14: @18[12]: _21 = const ()">            }<span class="annotation">⦉@18</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="31:21-31:30: @17[5]: _27 = _5
+31:17-31:30: @17[6]: _22 = move _27
+33:25-33:34: @17[9]: _28 = _5
+33:21-33:22: @17[10]: FakeRead(ForLet, _28)
+35:17-35:31: @17[11]: _5 = const 10_i32
+30:13-37:14: @17[12]: _21 = const ()"><span class="annotation">@17⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:21-31:30: @17[5]: _27 = _5
+31:17-31:30: @17[6]: _22 = move _27
+33:25-33:34: @17[9]: _28 = _5
+33:21-33:22: @17[10]: FakeRead(ForLet, _28)
+35:17-35:31: @17[11]: _5 = const 10_i32
+30:13-37:14: @17[12]: _21 = const ()">                z = countdown</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:21-31:30: @17[5]: _27 = _5
+31:17-31:30: @17[6]: _22 = move _27
+33:25-33:34: @17[9]: _28 = _5
+33:21-33:22: @17[10]: FakeRead(ForLet, _28)
+35:17-35:31: @17[11]: _5 = const 10_i32
+30:13-37:14: @17[12]: _21 = const ()">                ;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:21-31:30: @17[5]: _27 = _5
+31:17-31:30: @17[6]: _22 = move _27
+33:25-33:34: @17[9]: _28 = _5
+33:21-33:22: @17[10]: FakeRead(ForLet, _28)
+35:17-35:31: @17[11]: _5 = const 10_i32
+30:13-37:14: @17[12]: _21 = const ()">                let y = countdown</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:21-31:30: @17[5]: _27 = _5
+31:17-31:30: @17[6]: _22 = move _27
+33:25-33:34: @17[9]: _28 = _5
+33:21-33:22: @17[10]: FakeRead(ForLet, _28)
+35:17-35:31: @17[11]: _5 = const 10_i32
+30:13-37:14: @17[12]: _21 = const ()">                ;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:21-31:30: @17[5]: _27 = _5
+31:17-31:30: @17[6]: _22 = move _27
+33:25-33:34: @17[9]: _28 = _5
+33:21-33:22: @17[10]: FakeRead(ForLet, _28)
+35:17-35:31: @17[11]: _5 = const 10_i32
+30:13-37:14: @17[12]: _21 = const ()">                countdown = 10</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:21-31:30: @17[5]: _27 = _5
+31:17-31:30: @17[6]: _22 = move _27
+33:25-33:34: @17[9]: _28 = _5
+33:21-33:22: @17[10]: FakeRead(ForLet, _28)
+35:17-35:31: @17[11]: _5 = const 10_i32
+30:13-37:14: @17[12]: _21 = const ()">                ;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:21-31:30: @17[5]: _27 = _5
+31:17-31:30: @17[6]: _22 = move _27
+33:25-33:34: @17[9]: _28 = _5
+33:21-33:22: @17[10]: FakeRead(ForLet, _28)
+35:17-35:31: @17[11]: _5 = const 10_i32
+30:13-37:14: @17[12]: _21 = const ()">            }<span class="annotation">⦉@17</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">            _</span></span>
 <span class="line"><span class="code" style="--layer: 0">            =&gt;</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="40:13-40:15: @16[0]: _21 = const ()"><span class="annotation">@16⦊</span>{}<span class="annotation">⦉@16</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="40:13-40:15: @15[0]: _21 = const ()"><span class="annotation">@15⦊</span>{}<span class="annotation">⦉@15</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        }</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code even" style="--layer: 1" title="43:2-43:2: @12.Return: return"><span class="annotation">@12⦊</span>‸<span class="annotation">⦉@12</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code even" style="--layer: 1" title="43:2-43:2: @11.Return: return"><span class="annotation">@11⦊</span>‸<span class="annotation">⦉@11</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.tight_inf_loop/tight_inf_loop.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.tight_inf_loop/tight_inf_loop.main.-------.InstrumentCoverage.0.html
index d0ee798..8cbd265 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.tight_inf_loop/tight_inf_loop.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.tight_inf_loop/tight_inf_loop.main.-------.InstrumentCoverage.0.html
@@ -69,12 +69,10 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 0"><span class="line"><span><span class="code even" style="--layer: 1" title="2:8-2:13: @0[1]: _1 = const false
-2:8-2:13: @0[2]: FakeRead(ForMatchedPlace, _1)"><span class="annotation">@0⦊</span>fn main() {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="2:8-2:13: @0[1]: _1 = const false
-2:8-2:13: @0[2]: FakeRead(ForMatchedPlace, _1)">    if false<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="3:9-3:16: @4.FalseUnwind: falseUnwind -&gt; [real: bb5, cleanup: bb6]
-3:14-3:16: @5[0]: _3 = const ()"><span class="annotation">@4,5⦊</span>loop {}<span class="annotation">⦉@4,5</span></span></span><span class="code" style="--layer: 0"></span></span>
+<div class="code" style="counter-reset: line 0"><span class="line"><span><span class="code even" style="--layer: 1" title="2:8-2:13: @0[1]: _1 = const false"><span class="annotation">@0⦊</span>fn main() {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="2:8-2:13: @0[1]: _1 = const false">    if false<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="3:9-3:16: @3.FalseUnwind: falseUnwind -&gt; [real: bb4, cleanup: bb5]
+3:14-3:16: @4[0]: _3 = const ()"><span class="annotation">@3,4⦊</span>loop {}<span class="annotation">⦉@3,4</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span><span><span class="code even" style="--layer: 1" title="4:6-4:6: @2[0]: _0 = const ()
 5:2-5:2: @2.Return: return"><span class="annotation">@2⦊</span></span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="4:6-4:6: @2[0]: _0 = const ()
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html
index 804d2f4..a8a3139 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html
@@ -69,16 +69,14 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 3"><span class="line"><span><span class="code even" style="--layer: 1" title="5:8-5:20: @0[1]: _2 = _1
-5:8-5:20: @0[2]: FakeRead(ForMatchedPlace, _2)"><span class="annotation">@0⦊</span>fn call(return_error: bool) -&gt; Result&lt;(),()&gt; {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="5:8-5:20: @0[1]: _2 = _1
-5:8-5:20: @0[2]: FakeRead(ForMatchedPlace, _2)">    if return_error<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="6:13-6:15: @3[1]: _3 = ()
-6:9-6:16: @3[2]: _0 = std::result::Result::&lt;(), ()&gt;::Err(move _3)"><span class="annotation">@1,3⦊</span>Err(())<span class="annotation">⦉@1,3</span></span></span><span class="code" style="--layer: 0"></span></span>
+<div class="code" style="counter-reset: line 3"><span class="line"><span><span class="code even" style="--layer: 1" title="5:8-5:20: @0[1]: _2 = _1"><span class="annotation">@0⦊</span>fn call(return_error: bool) -&gt; Result&lt;(),()&gt; {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="5:8-5:20: @0[1]: _2 = _1">    if return_error<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="6:13-6:15: @1[1]: _3 = ()
+6:9-6:16: @1[2]: _0 = std::result::Result::&lt;(), ()&gt;::Err(move _3)"><span class="annotation">@1⦊</span>Err(())<span class="annotation">⦉@1</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    } else {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="8:12-8:14: @2[1]: _4 = ()
 8:9-8:15: @2[2]: _0 = std::result::Result::&lt;(), ()&gt;::Ok(move _4)"><span class="annotation">@2⦊</span>Ok(())<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="10:2-10:2: @4.Return: return"><span class="annotation">@4⦊</span>‸<span class="annotation">⦉@4</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="10:2-10:2: @3.Return: return"><span class="annotation">@3⦊</span>‸<span class="annotation">⦉@3</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html
index 3091eab..4140475 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html
@@ -84,51 +84,46 @@
 <span class="line"><span class="code" style="--layer: 0">    in</span></span>
 <span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="19:9-19:14: @3[5]: _11 = &amp;mut _5
 19:9-19:14: @3[6]: _10 = &amp;mut (*_11)
-19:9-19:14: @3.Call: _9 = &lt;std::ops::Range&lt;i32&gt; as Iterator&gt;::next(move _10) -&gt; [return: bb4, unwind: bb40]
+19:9-19:14: @3.Call: _9 = &lt;std::ops::Range&lt;i32&gt; as Iterator&gt;::next(move _10) -&gt; [return: bb4, unwind: bb39]
 19:9-19:14: @4[1]: FakeRead(ForMatchedPlace, _9)"><span class="annotation">@2,3,4⦊</span>0..10<span class="annotation">⦉@2,3,4</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="21:9-22:17: @8[12]: _17 = CheckedSub(_1, const 1_i32)
 21:9-22:17: @9[0]: _1 = move (_17.0: i32)
 25:13-25:22: @9[3]: _19 = _1
-25:13-25:26: @9[4]: _18 = Lt(move _19, const 5_i32)
-25:13-25:26: @9[6]: FakeRead(ForMatchedPlace, _18)"><span class="annotation">@6,8,9⦊</span>countdown</span></span>
+25:13-25:26: @9[4]: _18 = Lt(move _19, const 5_i32)"><span class="annotation">@6,8,9⦊</span>countdown</span></span>
 <span class="line"><span class="code odd" style="--layer: 1" title="21:9-22:17: @8[12]: _17 = CheckedSub(_1, const 1_i32)
 21:9-22:17: @9[0]: _1 = move (_17.0: i32)
 25:13-25:22: @9[3]: _19 = _1
-25:13-25:26: @9[4]: _18 = Lt(move _19, const 5_i32)
-25:13-25:26: @9[6]: FakeRead(ForMatchedPlace, _18)">            -= 1</span></span>
+25:13-25:26: @9[4]: _18 = Lt(move _19, const 5_i32)">            -= 1</span></span>
 <span class="line"><span class="code odd" style="--layer: 1" title="21:9-22:17: @8[12]: _17 = CheckedSub(_1, const 1_i32)
 21:9-22:17: @9[0]: _1 = move (_17.0: i32)
 25:13-25:22: @9[3]: _19 = _1
-25:13-25:26: @9[4]: _18 = Lt(move _19, const 5_i32)
-25:13-25:26: @9[6]: FakeRead(ForMatchedPlace, _18)">        ;</span></span>
+25:13-25:26: @9[4]: _18 = Lt(move _19, const 5_i32)">        ;</span></span>
 <span class="line"><span class="code odd" style="--layer: 1" title="21:9-22:17: @8[12]: _17 = CheckedSub(_1, const 1_i32)
 21:9-22:17: @9[0]: _1 = move (_17.0: i32)
 25:13-25:22: @9[3]: _19 = _1
-25:13-25:26: @9[4]: _18 = Lt(move _19, const 5_i32)
-25:13-25:26: @9[6]: FakeRead(ForMatchedPlace, _18)">        if</span></span>
+25:13-25:26: @9[4]: _18 = Lt(move _19, const 5_i32)">        if</span></span>
 <span class="line"><span class="code odd" style="--layer: 1" title="21:9-22:17: @8[12]: _17 = CheckedSub(_1, const 1_i32)
 21:9-22:17: @9[0]: _1 = move (_17.0: i32)
 25:13-25:22: @9[3]: _19 = _1
-25:13-25:26: @9[4]: _18 = Lt(move _19, const 5_i32)
-25:13-25:26: @9[6]: FakeRead(ForMatchedPlace, _18)">            countdown &lt; 5<span class="annotation">⦉@6,8,9</span></span></span><span class="code" style="--layer: 0"></span></span>
+25:13-25:26: @9[4]: _18 = Lt(move _19, const 5_i32)">            countdown &lt; 5<span class="annotation">⦉@6,8,9</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        {</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="27:13-27:41: @12.Call: _22 = call(const true) -&gt; [return: bb13, unwind: bb40]"><span class="annotation">@10,12,13,14⦊</span>call(/*return_error=*/ true)<span class="annotation">⦉@10,12,13,14</span></span></span><span><span class="code odd" style="--layer: 1" title="27:41-27:42: @18[1]: _24 = ((_21 as Err).0: ())
-27:41-27:42: @18[4]: _27 = _24
-27:41-27:42: @18.Call: _26 = &lt;() as From&lt;()&gt;&gt;::from(move _27) -&gt; [return: bb19, unwind: bb40]"><span class="annotation">@16,18,19,20⦊</span>?<span class="annotation">⦉@16,18,19,20</span></span></span><span class="code" style="--layer: 0">;</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="28:13-28:42: @15.Call: _31 = call(const false) -&gt; [return: bb21, unwind: bb40]"><span class="annotation">@15,21,22⦊</span>call(/*return_error=*/ false)<span class="annotation">⦉@15,21,22</span></span></span><span><span class="code odd" style="--layer: 1" title="28:42-28:43: @26[1]: _33 = ((_30 as Err).0: ())
-28:42-28:43: @26[4]: _36 = _33
-28:42-28:43: @26.Call: _35 = &lt;() as From&lt;()&gt;&gt;::from(move _36) -&gt; [return: bb27, unwind: bb40]"><span class="annotation">@24,26,27,28⦊</span>?<span class="annotation">⦉@24,26,27,28</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="27:13-27:41: @10.Call: _22 = call(const true) -&gt; [return: bb12, unwind: bb39]"><span class="annotation">@10,12,13⦊</span>call(/*return_error=*/ true)<span class="annotation">⦉@10,12,13</span></span></span><span><span class="code odd" style="--layer: 1" title="27:41-27:42: @17[1]: _24 = ((_21 as Err).0: ())
+27:41-27:42: @17[4]: _27 = _24
+27:41-27:42: @17.Call: _26 = &lt;() as From&lt;()&gt;&gt;::from(move _27) -&gt; [return: bb18, unwind: bb39]"><span class="annotation">@15,17,18,19⦊</span>?<span class="annotation">⦉@15,17,18,19</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="28:13-28:42: @14.Call: _31 = call(const false) -&gt; [return: bb20, unwind: bb39]"><span class="annotation">@14,20,21⦊</span>call(/*return_error=*/ false)<span class="annotation">⦉@14,20,21</span></span></span><span><span class="code odd" style="--layer: 1" title="28:42-28:43: @25[1]: _33 = ((_30 as Err).0: ())
+28:42-28:43: @25[4]: _36 = _33
+28:42-28:43: @25.Call: _35 = &lt;() as From&lt;()&gt;&gt;::from(move _36) -&gt; [return: bb26, unwind: bb39]"><span class="annotation">@23,25,26,27⦊</span>?<span class="annotation">⦉@23,25,26,27</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">        }</span></span>
 <span class="line"><span class="code" style="--layer: 0">        else</span></span>
 <span class="line"><span class="code" style="--layer: 0">        {</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="32:13-32:42: @11.Call: _40 = call(const false) -&gt; [return: bb29, unwind: bb40]"><span class="annotation">@11,29,30⦊</span>call(/*return_error=*/ false)<span class="annotation">⦉@11,29,30</span></span></span><span><span class="code odd" style="--layer: 1" title="32:42-32:43: @34[1]: _42 = ((_39 as Err).0: ())
-32:42-32:43: @34[4]: _45 = _42
-32:42-32:43: @34.Call: _44 = &lt;() as From&lt;()&gt;&gt;::from(move _45) -&gt; [return: bb35, unwind: bb40]"><span class="annotation">@32,34,35,36⦊</span>?<span class="annotation">⦉@32,34,35,36</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="32:13-32:42: @11.Call: _40 = call(const false) -&gt; [return: bb28, unwind: bb39]"><span class="annotation">@11,28,29⦊</span>call(/*return_error=*/ false)<span class="annotation">⦉@11,28,29</span></span></span><span><span class="code odd" style="--layer: 1" title="32:42-32:43: @33[1]: _42 = ((_39 as Err).0: ())
+32:42-32:43: @33[4]: _45 = _42
+32:42-32:43: @33.Call: _44 = &lt;() as From&lt;()&gt;&gt;::from(move _45) -&gt; [return: bb34, unwind: bb39]"><span class="annotation">@31,33,34,35⦊</span>?<span class="annotation">⦉@31,33,34,35</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">        }</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
 <span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="35:8-35:10: @5[9]: _47 = ()
 35:5-35:11: @5[10]: _0 = std::result::Result::&lt;(), ()&gt;::Ok(move _47)"><span class="annotation">@5⦊</span>Ok(())<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="36:2-36:2: @39.Return: return"><span class="annotation">@39⦊</span>‸<span class="annotation">⦉@39</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="36:2-36:2: @38.Return: return"><span class="annotation">@38⦊</span>‸<span class="annotation">⦉@38</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_function.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_function.-------.InstrumentCoverage.0.html
index 47fe96e..4af7b17 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_function.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_function.-------.InstrumentCoverage.0.html
@@ -69,51 +69,47 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 36"><span class="line"><span><span class="code even" style="--layer: 1" title="38:19-38:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+<div class="code" style="counter-reset: line 36"><span class="line"><span><span class="code even" style="--layer: 1" title="38:19-38:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 38:19-38:35: @1[0]: _3 = &amp;_4
-38:19-38:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+38:19-38:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 38:19-38:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 38:9-38:16: @2[3]: FakeRead(ForLet, _1)
 39:25-39:26: @3[2]: _5 = const 2_i32
 39:9-39:22: @3[3]: FakeRead(ForLet, _5)
 40:9-40:16: @3[6]: _7 = _1
-40:8-40:16: @3[7]: _6 = Not(move _7)
-40:8-40:16: @3[9]: FakeRead(ForMatchedPlace, _6)"><span class="annotation">@0,1,2,3⦊</span>pub fn unused_function() {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="38:19-38:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+40:8-40:16: @3[7]: _6 = Not(move _7)"><span class="annotation">@0,1,2,3⦊</span>pub fn unused_function() {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="38:19-38:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 38:19-38:35: @1[0]: _3 = &amp;_4
-38:19-38:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+38:19-38:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 38:19-38:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 38:9-38:16: @2[3]: FakeRead(ForLet, _1)
 39:25-39:26: @3[2]: _5 = const 2_i32
 39:9-39:22: @3[3]: FakeRead(ForLet, _5)
 40:9-40:16: @3[6]: _7 = _1
-40:8-40:16: @3[7]: _6 = Not(move _7)
-40:8-40:16: @3[9]: FakeRead(ForMatchedPlace, _6)">    let is_true = std::env::args().len() == 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="38:19-38:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+40:8-40:16: @3[7]: _6 = Not(move _7)">    let is_true = std::env::args().len() == 1;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="38:19-38:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 38:19-38:35: @1[0]: _3 = &amp;_4
-38:19-38:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+38:19-38:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 38:19-38:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 38:9-38:16: @2[3]: FakeRead(ForLet, _1)
 39:25-39:26: @3[2]: _5 = const 2_i32
 39:9-39:22: @3[3]: FakeRead(ForLet, _5)
 40:9-40:16: @3[6]: _7 = _1
-40:8-40:16: @3[7]: _6 = Not(move _7)
-40:8-40:16: @3[9]: FakeRead(ForMatchedPlace, _6)">    let mut countdown = 2;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="38:19-38:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+40:8-40:16: @3[7]: _6 = Not(move _7)">    let mut countdown = 2;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="38:19-38:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 38:19-38:35: @1[0]: _3 = &amp;_4
-38:19-38:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+38:19-38:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 38:19-38:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 38:9-38:16: @2[3]: FakeRead(ForLet, _1)
 39:25-39:26: @3[2]: _5 = const 2_i32
 39:9-39:22: @3[3]: FakeRead(ForLet, _5)
 40:9-40:16: @3[6]: _7 = _1
-40:8-40:16: @3[7]: _6 = Not(move _7)
-40:8-40:16: @3[9]: FakeRead(ForMatchedPlace, _6)">    if !is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="41:9-41:23: @6[0]: _5 = const 20_i32
-40:17-42:6: @6[1]: _0 = const ()"><span class="annotation">@4,6⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="41:9-41:23: @6[0]: _5 = const 20_i32
-40:17-42:6: @6[1]: _0 = const ()">        countdown = 20;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="41:9-41:23: @6[0]: _5 = const 20_i32
-40:17-42:6: @6[1]: _0 = const ()">    }<span class="annotation">⦉@4,6</span></span></span><span><span class="code even" style="--layer: 1" title="42:6-42:6: @5[0]: _0 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="43:2-43:2: @7.Return: return"><span class="annotation">@7⦊</span>‸<span class="annotation">⦉@7</span></span></span></span></div>
+40:8-40:16: @3[7]: _6 = Not(move _7)">    if !is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="41:9-41:23: @4[0]: _5 = const 20_i32
+40:17-42:6: @4[1]: _0 = const ()"><span class="annotation">@4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="41:9-41:23: @4[0]: _5 = const 20_i32
+40:17-42:6: @4[1]: _0 = const ()">        countdown = 20;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="41:9-41:23: @4[0]: _5 = const 20_i32
+40:17-42:6: @4[1]: _0 = const ()">    }<span class="annotation">⦉@4</span></span></span><span><span class="code even" style="--layer: 1" title="42:6-42:6: @5[0]: _0 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="43:2-43:2: @6.Return: return"><span class="annotation">@6⦊</span>‸<span class="annotation">⦉@6</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_private_function.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_private_function.-------.InstrumentCoverage.0.html
index 361c579..6424e03 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_private_function.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_private_function.-------.InstrumentCoverage.0.html
@@ -69,51 +69,47 @@
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 44"><span class="line"><span><span class="code even" style="--layer: 1" title="46:19-46:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+<div class="code" style="counter-reset: line 44"><span class="line"><span><span class="code even" style="--layer: 1" title="46:19-46:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 46:19-46:35: @1[0]: _3 = &amp;_4
-46:19-46:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+46:19-46:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 46:19-46:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 46:9-46:16: @2[3]: FakeRead(ForLet, _1)
 47:25-47:26: @3[2]: _5 = const 2_i32
 47:9-47:22: @3[3]: FakeRead(ForLet, _5)
 48:9-48:16: @3[6]: _7 = _1
-48:8-48:16: @3[7]: _6 = Not(move _7)
-48:8-48:16: @3[9]: FakeRead(ForMatchedPlace, _6)"><span class="annotation">@0,1,2,3⦊</span>fn unused_private_function() {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="46:19-46:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+48:8-48:16: @3[7]: _6 = Not(move _7)"><span class="annotation">@0,1,2,3⦊</span>fn unused_private_function() {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="46:19-46:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 46:19-46:35: @1[0]: _3 = &amp;_4
-46:19-46:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+46:19-46:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 46:19-46:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 46:9-46:16: @2[3]: FakeRead(ForLet, _1)
 47:25-47:26: @3[2]: _5 = const 2_i32
 47:9-47:22: @3[3]: FakeRead(ForLet, _5)
 48:9-48:16: @3[6]: _7 = _1
-48:8-48:16: @3[7]: _6 = Not(move _7)
-48:8-48:16: @3[9]: FakeRead(ForMatchedPlace, _6)">    let is_true = std::env::args().len() == 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="46:19-46:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+48:8-48:16: @3[7]: _6 = Not(move _7)">    let is_true = std::env::args().len() == 1;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="46:19-46:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 46:19-46:35: @1[0]: _3 = &amp;_4
-46:19-46:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+46:19-46:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 46:19-46:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 46:9-46:16: @2[3]: FakeRead(ForLet, _1)
 47:25-47:26: @3[2]: _5 = const 2_i32
 47:9-47:22: @3[3]: FakeRead(ForLet, _5)
 48:9-48:16: @3[6]: _7 = _1
-48:8-48:16: @3[7]: _6 = Not(move _7)
-48:8-48:16: @3[9]: FakeRead(ForMatchedPlace, _6)">    let mut countdown = 2;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="46:19-46:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
+48:8-48:16: @3[7]: _6 = Not(move _7)">    let mut countdown = 2;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="46:19-46:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb8]
 46:19-46:35: @1[0]: _3 = &amp;_4
-46:19-46:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
+46:19-46:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb7]
 46:19-46:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 46:9-46:16: @2[3]: FakeRead(ForLet, _1)
 47:25-47:26: @3[2]: _5 = const 2_i32
 47:9-47:22: @3[3]: FakeRead(ForLet, _5)
 48:9-48:16: @3[6]: _7 = _1
-48:8-48:16: @3[7]: _6 = Not(move _7)
-48:8-48:16: @3[9]: FakeRead(ForMatchedPlace, _6)">    if !is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="49:9-49:23: @6[0]: _5 = const 20_i32
-48:17-50:6: @6[1]: _0 = const ()"><span class="annotation">@4,6⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="49:9-49:23: @6[0]: _5 = const 20_i32
-48:17-50:6: @6[1]: _0 = const ()">        countdown = 20;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="49:9-49:23: @6[0]: _5 = const 20_i32
-48:17-50:6: @6[1]: _0 = const ()">    }<span class="annotation">⦉@4,6</span></span></span><span><span class="code even" style="--layer: 1" title="50:6-50:6: @5[0]: _0 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="51:2-51:2: @7.Return: return"><span class="annotation">@7⦊</span>‸<span class="annotation">⦉@7</span></span></span></span></div>
+48:8-48:16: @3[7]: _6 = Not(move _7)">    if !is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="49:9-49:23: @4[0]: _5 = const 20_i32
+48:17-50:6: @4[1]: _0 = const ()"><span class="annotation">@4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="49:9-49:23: @4[0]: _5 = const 20_i32
+48:17-50:6: @4[1]: _0 = const ()">        countdown = 20;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="49:9-49:23: @4[0]: _5 = const 20_i32
+48:17-50:6: @4[1]: _0 = const ()">    }<span class="annotation">⦉@4</span></span></span><span><span class="code even" style="--layer: 1" title="50:6-50:6: @5[0]: _0 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="51:2-51:2: @6.Return: return"><span class="annotation">@6⦊</span>‸<span class="annotation">⦉@6</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_function.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_function.-------.InstrumentCoverage.0.html
index 2ffd9bf..d35f191 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_function.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_function.-------.InstrumentCoverage.0.html
@@ -73,41 +73,38 @@
 <span class="line"><span class="code" style="--layer: 0">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
 <span class="line"><span class="code" style="--layer: 0">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
 <span class="line"><span class="code" style="--layer: 0">    // dependent conditions.</span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="9:19-9:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb10]
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="9:19-9:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
 9:19-9:35: @1[0]: _3 = &amp;_4
-9:19-9:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb9]
+9:19-9:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
 9:19-9:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 9:9-9:16: @2[3]: FakeRead(ForLet, _1)
 10:25-10:26: @3[2]: _5 = const 0_i32
 10:9-10:22: @3[3]: FakeRead(ForLet, _5)
-11:8-11:15: @3[6]: _7 = _1
-11:8-11:15: @3[7]: FakeRead(ForMatchedPlace, _7)"><span class="annotation">@0,1,2,3⦊</span>is_true = std::env::args().len() == 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="9:19-9:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb10]
+11:8-11:15: @3[6]: _7 = _1"><span class="annotation">@0,1,2,3⦊</span>is_true = std::env::args().len() == 1;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="9:19-9:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
 9:19-9:35: @1[0]: _3 = &amp;_4
-9:19-9:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb9]
+9:19-9:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
 9:19-9:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 9:9-9:16: @2[3]: FakeRead(ForLet, _1)
 10:25-10:26: @3[2]: _5 = const 0_i32
 10:9-10:22: @3[3]: FakeRead(ForLet, _5)
-11:8-11:15: @3[6]: _7 = _1
-11:8-11:15: @3[7]: FakeRead(ForMatchedPlace, _7)">    let mut countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="9:19-9:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb10]
+11:8-11:15: @3[6]: _7 = _1">    let mut countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="9:19-9:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb9]
 9:19-9:35: @1[0]: _3 = &amp;_4
-9:19-9:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb9]
+9:19-9:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb8]
 9:19-9:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 9:9-9:16: @2[3]: FakeRead(ForLet, _1)
 10:25-10:26: @3[2]: _5 = const 0_i32
 10:9-10:22: @3[3]: FakeRead(ForLet, _5)
-11:8-11:15: @3[6]: _7 = _1
-11:8-11:15: @3[7]: FakeRead(ForMatchedPlace, _7)">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="12:9-12:23: @6[0]: _5 = const 10_i32
-11:16-13:6: @6[1]: _6 = const ()"><span class="annotation">@4,6⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:23: @6[0]: _5 = const 10_i32
-11:16-13:6: @6[1]: _6 = const ()">        countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:23: @6[0]: _5 = const 10_i32
-11:16-13:6: @6[1]: _6 = const ()">    }<span class="annotation">⦉@4,6</span></span></span><span><span class="code even" style="--layer: 1" title="13:6-13:6: @5[0]: _6 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="14:5-14:25: @7.Call: _8 = use_this_lib_crate() -&gt; [return: bb8, unwind: bb10]
-15:2-15:2: @8.Return: return"><span class="annotation">@7,8⦊</span>use_this_lib_crate();</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="14:5-14:25: @7.Call: _8 = use_this_lib_crate() -&gt; [return: bb8, unwind: bb10]
-15:2-15:2: @8.Return: return">}<span class="annotation">⦉@7,8</span></span></span></span></div>
+11:8-11:15: @3[6]: _7 = _1">    if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="12:9-12:23: @4[0]: _5 = const 10_i32
+11:16-13:6: @4[1]: _6 = const ()"><span class="annotation">@4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:23: @4[0]: _5 = const 10_i32
+11:16-13:6: @4[1]: _6 = const ()">        countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:23: @4[0]: _5 = const 10_i32
+11:16-13:6: @4[1]: _6 = const ()">    }<span class="annotation">⦉@4</span></span></span><span><span class="code even" style="--layer: 1" title="13:6-13:6: @5[0]: _6 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="14:5-14:25: @6.Call: _8 = use_this_lib_crate() -&gt; [return: bb7, unwind: bb9]
+15:2-15:2: @7.Return: return"><span class="annotation">@6,7⦊</span>use_this_lib_crate();</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="14:5-14:25: @6.Call: _8 = use_this_lib_crate() -&gt; [return: bb7, unwind: bb9]
+15:2-15:2: @7.Return: return">}<span class="annotation">⦉@6,7</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.while_early_ret/while_early_ret.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.while_early_ret/while_early_ret.main.-------.InstrumentCoverage.0.html
index 4cab153..fcb5418 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.while_early_ret/while_early_ret.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.while_early_ret/while_early_ret.main.-------.InstrumentCoverage.0.html
@@ -86,51 +86,45 @@
 <span class="line"><span class="code" style="--layer: 0">    {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        if</span></span>
 <span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="12:13-12:22: @5[3]: _8 = _1
-12:13-14:14: @5[4]: _7 = Lt(move _8, const 5_i32)
-12:13-14:14: @5[6]: FakeRead(ForMatchedPlace, _7)"><span class="annotation">@3,5⦊</span>countdown</span></span>
+12:13-14:14: @5[4]: _7 = Lt(move _8, const 5_i32)"><span class="annotation">@3,5⦊</span>countdown</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="12:13-12:22: @5[3]: _8 = _1
-12:13-14:14: @5[4]: _7 = Lt(move _8, const 5_i32)
-12:13-14:14: @5[6]: FakeRead(ForMatchedPlace, _7)">                &lt;</span></span>
+12:13-14:14: @5[4]: _7 = Lt(move _8, const 5_i32)">                &lt;</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="12:13-12:22: @5[3]: _8 = _1
-12:13-14:14: @5[4]: _7 = Lt(move _8, const 5_i32)
-12:13-14:14: @5[6]: FakeRead(ForMatchedPlace, _7)">            5<span class="annotation">⦉@3,5</span></span></span><span class="code" style="--layer: 0"></span></span>
+12:13-14:14: @5[4]: _7 = Lt(move _8, const 5_i32)">            5<span class="annotation">⦉@3,5</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        {</span></span>
 <span class="line"><span class="code" style="--layer: 0">            return</span></span>
 <span class="line"><span class="code" style="--layer: 0">                if</span></span>
-<span class="line"><span class="code" style="--layer: 0">                    </span><span><span class="code odd" style="--layer: 1" title="18:21-18:30: @8[2]: _11 = _1
-18:21-20:22: @8[3]: _10 = Gt(move _11, const 8_i32)
-18:21-20:22: @8[5]: FakeRead(ForMatchedPlace, _10)"><span class="annotation">@6,8⦊</span>countdown</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="18:21-18:30: @8[2]: _11 = _1
-18:21-20:22: @8[3]: _10 = Gt(move _11, const 8_i32)
-18:21-20:22: @8[5]: FakeRead(ForMatchedPlace, _10)">                        &gt;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="18:21-18:30: @8[2]: _11 = _1
-18:21-20:22: @8[3]: _10 = Gt(move _11, const 8_i32)
-18:21-20:22: @8[5]: FakeRead(ForMatchedPlace, _10)">                    8<span class="annotation">⦉@6,8</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">                    </span><span><span class="code odd" style="--layer: 1" title="18:21-18:30: @6[2]: _11 = _1
+18:21-20:22: @6[3]: _10 = Gt(move _11, const 8_i32)"><span class="annotation">@6⦊</span>countdown</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="18:21-18:30: @6[2]: _11 = _1
+18:21-20:22: @6[3]: _10 = Gt(move _11, const 8_i32)">                        &gt;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="18:21-18:30: @6[2]: _11 = _1
+18:21-20:22: @6[3]: _10 = Gt(move _11, const 8_i32)">                    8<span class="annotation">⦉@6</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">                {</span></span>
-<span class="line"><span class="code" style="--layer: 0">                    </span><span><span class="code even" style="--layer: 1" title="22:24-22:26: @11[1]: _12 = ()
-22:21-22:27: @11[2]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _12)"><span class="annotation">@9,11⦊</span>Ok(())<span class="annotation">⦉@9,11</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">                    </span><span><span class="code even" style="--layer: 1" title="22:24-22:26: @8[1]: _12 = ()
+22:21-22:27: @8[2]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _12)"><span class="annotation">@8⦊</span>Ok(())<span class="annotation">⦉@8</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">                }</span></span>
 <span class="line"><span class="code" style="--layer: 0">                else</span></span>
 <span class="line"><span class="code" style="--layer: 0">                {</span></span>
-<span class="line"><span class="code" style="--layer: 0">                    </span><span><span class="code odd" style="--layer: 1" title="26:21-26:27: @10[0]: _0 = std::result::Result::&lt;(), u8&gt;::Err(const 1_u8)"><span class="annotation">@10⦊</span>Err(1)<span class="annotation">⦉@10</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">                    </span><span><span class="code odd" style="--layer: 1" title="26:21-26:27: @9[0]: _0 = std::result::Result::&lt;(), u8&gt;::Err(const 1_u8)"><span class="annotation">@9⦊</span>Err(1)<span class="annotation">⦉@9</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">                }</span></span>
 <span class="line"><span class="code" style="--layer: 0">                ;</span></span>
 <span class="line"><span class="code" style="--layer: 0">        }</span><span><span class="code even" style="--layer: 1" title="29:10-29:10: @7[0]: _6 = const ()
 30:9-32:10: @7[3]: _13 = CheckedSub(_1, const 1_i32)
-30:9-32:10: @12[0]: _1 = move (_13.0: i32)"><span class="annotation">@7,12⦊</span></span></span>
+30:9-32:10: @11[0]: _1 = move (_13.0: i32)"><span class="annotation">@7,11⦊</span></span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="29:10-29:10: @7[0]: _6 = const ()
 30:9-32:10: @7[3]: _13 = CheckedSub(_1, const 1_i32)
-30:9-32:10: @12[0]: _1 = move (_13.0: i32)">        countdown</span></span>
+30:9-32:10: @11[0]: _1 = move (_13.0: i32)">        countdown</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="29:10-29:10: @7[0]: _6 = const ()
 30:9-32:10: @7[3]: _13 = CheckedSub(_1, const 1_i32)
-30:9-32:10: @12[0]: _1 = move (_13.0: i32)">            -=</span></span>
+30:9-32:10: @11[0]: _1 = move (_13.0: i32)">            -=</span></span>
 <span class="line"><span class="code even" style="--layer: 1" title="29:10-29:10: @7[0]: _6 = const ()
 30:9-32:10: @7[3]: _13 = CheckedSub(_1, const 1_i32)
-30:9-32:10: @12[0]: _1 = move (_13.0: i32)">        1<span class="annotation">⦉@7,12</span></span></span><span class="code" style="--layer: 0"></span></span>
+30:9-32:10: @11[0]: _1 = move (_13.0: i32)">        1<span class="annotation">⦉@7,11</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        ;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
 <span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="35:8-35:10: @4[4]: _15 = ()
 35:5-35:11: @4[5]: _0 = std::result::Result::&lt;(), u8&gt;::Ok(move _15)"><span class="annotation">@4⦊</span>Ok(())<span class="annotation">⦉@4</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code even" style="--layer: 1" title="36:2-36:2: @14.Return: return"><span class="annotation">@14⦊</span>‸<span class="annotation">⦉@14</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code even" style="--layer: 1" title="36:2-36:2: @12.Return: return"><span class="annotation">@12⦊</span>‸<span class="annotation">⦉@12</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage/doctest.rs b/src/test/run-make-fulldeps/coverage/doctest.rs
index e41d669..ec04ea5 100644
--- a/src/test/run-make-fulldeps/coverage/doctest.rs
+++ b/src/test/run-make-fulldeps/coverage/doctest.rs
@@ -20,13 +20,21 @@
 //!
 //! doctest returning a result:
 //! ```
-//! #[derive(Debug)]
-//! struct SomeError;
-//! let mut res = Err(SomeError);
+//! #[derive(Debug, PartialEq)]
+//! struct SomeError {
+//!     msg: String,
+//! }
+//! let mut res = Err(SomeError { msg: String::from("a message") });
 //! if res.is_ok() {
-//!   res?;
+//!     res?;
 //! } else {
-//!   res = Ok(0);
+//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+//!         println!("{:?}", res);
+//!     }
+//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+//!         res = Ok(1);
+//!     }
+//!     res = Ok(0);
 //! }
 //! // need to be explicit because rustdoc cant infer the return type
 //! Ok::<(), SomeError>(())
@@ -34,12 +42,17 @@
 //!
 //! doctest with custom main:
 //! ```
+//! fn some_func() {
+//!     println!("called some_func()");
+//! }
+//!
 //! #[derive(Debug)]
 //! struct SomeError;
 //!
 //! extern crate doctest_crate;
 //!
 //! fn doctest_main() -> Result<(), SomeError> {
+//!     some_func();
 //!     doctest_crate::fn_run_in_doctests(2);
 //!     Ok(())
 //! }
@@ -64,3 +77,23 @@
         assert_eq!(1, 2);
     }
 }
+
+// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
+// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
+// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
+//
+// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
+// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
+// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
+// one character past, the `if` block's closing brace. In both cases, these are most likely off
+// by the number of characters stripped from the beginning of each doc comment line: indent
+// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
+// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
+// more pronounced, and show up in more places, with background color used to show some distinct
+// code regions with different coverage counts.
+//
+// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
+// character stripped from the beginning of doc comment lines with a space. This will give coverage
+// results the correct column offsets, and I think it should compile correctly, but I don't know
+// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
+// if the indentation changed. I don't know if there is a more viable solution.
diff --git a/src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/staticlib.rs b/src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/staticlib.rs
index b24522e..34951dd 100644
--- a/src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/staticlib.rs
+++ b/src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/staticlib.rs
@@ -3,6 +3,6 @@
 extern crate upstream;
 
 #[no_mangle]
-pub extern fn bar() {
+pub extern "C" fn bar() {
     upstream::foo();
 }
diff --git a/src/test/run-make-fulldeps/extern-fn-generic/test.rs b/src/test/run-make-fulldeps/extern-fn-generic/test.rs
index 0666bf4..c9baa48 100644
--- a/src/test/run-make-fulldeps/extern-fn-generic/test.rs
+++ b/src/test/run-make-fulldeps/extern-fn-generic/test.rs
@@ -1,22 +1,20 @@
 extern crate testcrate;
 
-extern "C" fn bar<T>(ts: testcrate::TestStruct<T>) -> T { ts.y }
+extern "C" fn bar<T>(ts: testcrate::TestStruct<T>) -> T {
+    ts.y
+}
 
 #[link(name = "test", kind = "static")]
-extern {
+extern "C" {
     fn call(c: extern "C" fn(testcrate::TestStruct<i32>) -> i32) -> i32;
 }
 
 fn main() {
     // Let's test calling it cross crate
-    let back = unsafe {
-        testcrate::call(testcrate::foo::<i32>)
-    };
+    let back = unsafe { testcrate::call(testcrate::foo::<i32>) };
     assert_eq!(3, back);
 
     // And just within this crate
-    let back = unsafe {
-        call(bar::<i32>)
-    };
+    let back = unsafe { call(bar::<i32>) };
     assert_eq!(3, back);
 }
diff --git a/src/test/run-make-fulldeps/extern-fn-generic/testcrate.rs b/src/test/run-make-fulldeps/extern-fn-generic/testcrate.rs
index f0a721d..39f76e5 100644
--- a/src/test/run-make-fulldeps/extern-fn-generic/testcrate.rs
+++ b/src/test/run-make-fulldeps/extern-fn-generic/testcrate.rs
@@ -3,12 +3,14 @@
 #[repr(C)]
 pub struct TestStruct<T> {
     pub x: u8,
-    pub y: T
+    pub y: T,
 }
 
-pub extern "C" fn foo<T>(ts: TestStruct<T>) -> T { ts.y }
+pub extern "C" fn foo<T>(ts: TestStruct<T>) -> T {
+    ts.y
+}
 
 #[link(name = "test", kind = "static")]
-extern {
+extern "C" {
     pub fn call(c: extern "C" fn(TestStruct<i32>) -> i32) -> i32;
 }
diff --git a/src/test/run-make-fulldeps/extern-fn-mangle/test.rs b/src/test/run-make-fulldeps/extern-fn-mangle/test.rs
index b213534..40b08f1 100644
--- a/src/test/run-make-fulldeps/extern-fn-mangle/test.rs
+++ b/src/test/run-make-fulldeps/extern-fn-mangle/test.rs
@@ -1,11 +1,15 @@
 #[no_mangle]
-pub extern "C" fn foo() -> i32 { 3 }
+pub extern "C" fn foo() -> i32 {
+    3
+}
 
 #[no_mangle]
-pub extern "C" fn bar() -> i32 { 5 }
+pub extern "C" fn bar() -> i32 {
+    5
+}
 
 #[link(name = "test", kind = "static")]
-extern {
+extern "C" {
     fn add() -> i32;
 }
 
diff --git a/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.rs b/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.rs
index 615163d..afe0f52 100644
--- a/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.rs
+++ b/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.rs
@@ -7,7 +7,7 @@
     a: i32,
     b: i32,
     c: i32,
-    d: i32
+    d: i32,
 }
 
 #[derive(Clone, Copy, Debug, PartialEq)]
@@ -15,7 +15,7 @@
 struct BiggerRect {
     s: Rect,
     a: i32,
-    b: i32
+    b: i32,
 }
 
 #[derive(Clone, Copy, Debug, PartialEq)]
@@ -23,7 +23,7 @@
 struct FloatRect {
     a: i32,
     b: i32,
-    c: f64
+    c: f64,
 }
 
 #[derive(Clone, Copy, Debug, PartialEq)]
@@ -33,14 +33,14 @@
     b: i32,
     c: i32,
     d: i32,
-    e: i32
+    e: i32,
 }
 
 #[derive(Clone, Copy, Debug, PartialEq)]
 #[repr(C)]
 struct FloatPoint {
     x: f64,
-    y: f64
+    y: f64,
 }
 
 #[derive(Clone, Copy, Debug, PartialEq)]
@@ -58,13 +58,22 @@
 }
 
 #[link(name = "test", kind = "static")]
-extern {
+extern "C" {
     fn byval_rect(a: i32, b: i32, c: i32, d: i32, e: i32, s: Rect);
 
     fn byval_many_rect(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, s: Rect);
 
-    fn byval_rect_floats(a: f32, b: f32, c: f64, d: f32, e: f32,
-                         f: f32, g: f64, s: Rect, t: FloatRect);
+    fn byval_rect_floats(
+        a: f32,
+        b: f32,
+        c: f64,
+        d: f32,
+        e: f32,
+        f: f32,
+        g: f64,
+        s: Rect,
+        t: FloatRect,
+    );
 
     fn byval_rect_with_float(a: i32, b: i32, c: f32, d: i32, e: i32, f: i32, s: Rect);
 
@@ -107,12 +116,7 @@
         byval_many_rect(1, 2, 3, 4, 5, 6, s);
         byval_rect_floats(1., 2., 3., 4., 5., 6., 7., s, u);
         byval_rect_with_float(1, 2, 3.0, 4, 5, 6, s);
-        byval_rect_with_many_huge(v, v, v, v, v, v, Rect {
-            a: 123,
-            b: 456,
-            c: 789,
-            d: 420
-        });
+        byval_rect_with_many_huge(v, v, v, v, v, v, Rect { a: 123, b: 456, c: 789, d: 420 });
         split_rect(1, 2, s);
         split_rect_floats(1., 2., u);
         split_rect_with_floats(1, 2, 3.0, 4, 5.0, 6, s);
diff --git a/src/test/run-make-fulldeps/extern-fn-with-extern-types/test.rs b/src/test/run-make-fulldeps/extern-fn-with-extern-types/test.rs
index 6c027cc..90a6eba 100644
--- a/src/test/run-make-fulldeps/extern-fn-with-extern-types/test.rs
+++ b/src/test/run-make-fulldeps/extern-fn-with-extern-types/test.rs
@@ -1,7 +1,7 @@
 #![feature(extern_types)]
 
 #[link(name = "ctest", kind = "static")]
-extern {
+extern "C" {
     type data;
 
     fn data_create(magic: u32) -> *mut data;
diff --git a/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.rs b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.rs
index 7d7658c..2f261ef 100644
--- a/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.rs
+++ b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.rs
@@ -3,11 +3,11 @@
 struct Foo {
     a: i8,
     b: i16,
-    c: i8
+    c: i8,
 }
 
 #[link(name = "test", kind = "static")]
-extern {
+extern "C" {
     fn foo(f: Foo) -> Foo;
 }
 
diff --git a/src/test/run-make-fulldeps/extern-fn-with-union/test.rs b/src/test/run-make-fulldeps/extern-fn-with-union/test.rs
index 007dfdb..438fbdd 100644
--- a/src/test/run-make-fulldeps/extern-fn-with-union/test.rs
+++ b/src/test/run-make-fulldeps/extern-fn-with-union/test.rs
@@ -2,7 +2,7 @@
 
 use std::mem;
 
-extern {
+extern "C" {
     fn give_back(tu: testcrate::TestUnion) -> u64;
 }
 
@@ -10,14 +10,10 @@
     let magic: u64 = 0xDEADBEEF;
 
     // Let's test calling it cross crate
-    let back = unsafe {
-        testcrate::give_back(mem::transmute(magic))
-    };
+    let back = unsafe { testcrate::give_back(mem::transmute(magic)) };
     assert_eq!(magic, back);
 
     // And just within this crate
-    let back = unsafe {
-        give_back(mem::transmute(magic))
-    };
+    let back = unsafe { give_back(mem::transmute(magic)) };
     assert_eq!(magic, back);
 }
diff --git a/src/test/run-make-fulldeps/extern-fn-with-union/testcrate.rs b/src/test/run-make-fulldeps/extern-fn-with-union/testcrate.rs
index b51526d..28d91ff 100644
--- a/src/test/run-make-fulldeps/extern-fn-with-union/testcrate.rs
+++ b/src/test/run-make-fulldeps/extern-fn-with-union/testcrate.rs
@@ -2,10 +2,10 @@
 
 #[repr(C)]
 pub struct TestUnion {
-    _val: u64
+    _val: u64,
 }
 
 #[link(name = "ctest", kind = "static")]
-extern {
+extern "C" {
     pub fn give_back(tu: TestUnion) -> u64;
 }
diff --git a/src/test/run-make-fulldeps/glibc-staticlib-args/library.rs b/src/test/run-make-fulldeps/glibc-staticlib-args/library.rs
index 991981d..5ab627a 100644
--- a/src/test/run-make-fulldeps/glibc-staticlib-args/library.rs
+++ b/src/test/run-make-fulldeps/glibc-staticlib-args/library.rs
@@ -1,4 +1,4 @@
 #[no_mangle]
-pub extern fn args_check() {
+pub extern "C" fn args_check() {
     assert_ne!(std::env::args_os().count(), 0);
 }
diff --git a/src/test/run-make-fulldeps/interdependent-c-libraries/bar.rs b/src/test/run-make-fulldeps/interdependent-c-libraries/bar.rs
index 2794be5..3c2c3f2 100644
--- a/src/test/run-make-fulldeps/interdependent-c-libraries/bar.rs
+++ b/src/test/run-make-fulldeps/interdependent-c-libraries/bar.rs
@@ -3,10 +3,12 @@
 extern crate foo;
 
 #[link(name = "bar", kind = "static")]
-extern {
+extern "C" {
     fn bar();
 }
 
 pub fn doit() {
-    unsafe { bar(); }
+    unsafe {
+        bar();
+    }
 }
diff --git a/src/test/run-make-fulldeps/interdependent-c-libraries/foo.rs b/src/test/run-make-fulldeps/interdependent-c-libraries/foo.rs
index 891c47d..a698097 100644
--- a/src/test/run-make-fulldeps/interdependent-c-libraries/foo.rs
+++ b/src/test/run-make-fulldeps/interdependent-c-libraries/foo.rs
@@ -1,10 +1,12 @@
 #![crate_type = "rlib"]
 
 #[link(name = "foo", kind = "static")]
-extern {
+extern "C" {
     fn foo();
 }
 
 pub fn doit() {
-    unsafe { foo(); }
+    unsafe {
+        foo();
+    }
 }
diff --git a/src/test/run-make-fulldeps/issue-14500/foo.rs b/src/test/run-make-fulldeps/issue-14500/foo.rs
index feebef1..7c19c1f 100644
--- a/src/test/run-make-fulldeps/issue-14500/foo.rs
+++ b/src/test/run-make-fulldeps/issue-14500/foo.rs
@@ -1,5 +1,5 @@
 #[no_mangle]
-pub extern fn foo() {}
+pub extern "C" fn foo() {}
 
 #[no_mangle]
 pub static FOO_STATIC: u8 = 0;
diff --git a/src/test/run-make-fulldeps/issue-15460/foo.rs b/src/test/run-make-fulldeps/issue-15460/foo.rs
index 9beafd9..b4eaa0b 100644
--- a/src/test/run-make-fulldeps/issue-15460/foo.rs
+++ b/src/test/run-make-fulldeps/issue-15460/foo.rs
@@ -1,6 +1,6 @@
 #![crate_type = "dylib"]
 
 #[link(name = "foo", kind = "static")]
-extern {
+extern "C" {
     pub fn foo();
 }
diff --git a/src/test/run-make-fulldeps/issue-25581/test.rs b/src/test/run-make-fulldeps/issue-25581/test.rs
index 5dfa6bb..ba6749c 100644
--- a/src/test/run-make-fulldeps/issue-25581/test.rs
+++ b/src/test/run-make-fulldeps/issue-25581/test.rs
@@ -1,11 +1,11 @@
 #[link(name = "test", kind = "static")]
-extern {
+extern "C" {
     fn slice_len(s: &[u8]) -> usize;
     fn slice_elem(s: &[u8], idx: usize) -> u8;
 }
 
 fn main() {
-    let data = [1,2,3,4,5];
+    let data = [1, 2, 3, 4, 5];
 
     unsafe {
         assert_eq!(data.len(), slice_len(&data) as usize);
diff --git a/src/test/run-make-fulldeps/issue-28595/a.rs b/src/test/run-make-fulldeps/issue-28595/a.rs
index 4483641..07863cf 100644
--- a/src/test/run-make-fulldeps/issue-28595/a.rs
+++ b/src/test/run-make-fulldeps/issue-28595/a.rs
@@ -1,6 +1,6 @@
 #![crate_type = "rlib"]
 
 #[link(name = "a", kind = "static")]
-extern {
+extern "C" {
     pub fn a();
 }
diff --git a/src/test/run-make-fulldeps/issue-28595/b.rs b/src/test/run-make-fulldeps/issue-28595/b.rs
index 24ab412..1f38985 100644
--- a/src/test/run-make-fulldeps/issue-28595/b.rs
+++ b/src/test/run-make-fulldeps/issue-28595/b.rs
@@ -1,11 +1,12 @@
 extern crate a;
 
 #[link(name = "b", kind = "static")]
-extern {
+extern "C" {
     pub fn b();
 }
 
-
 fn main() {
-    unsafe { b(); }
+    unsafe {
+        b();
+    }
 }
diff --git a/src/test/run-make-fulldeps/link-cfg/dep-with-staticlib.rs b/src/test/run-make-fulldeps/link-cfg/dep-with-staticlib.rs
index 55c96df..5ad6647 100644
--- a/src/test/run-make-fulldeps/link-cfg/dep-with-staticlib.rs
+++ b/src/test/run-make-fulldeps/link-cfg/dep-with-staticlib.rs
@@ -3,6 +3,6 @@
 
 #[link(name = "return1", cfg(foo))]
 #[link(name = "return3", kind = "static", cfg(bar))]
-extern {
+extern "C" {
     pub fn my_function() -> i32;
 }
diff --git a/src/test/run-make-fulldeps/link-cfg/dep.rs b/src/test/run-make-fulldeps/link-cfg/dep.rs
index 149ae61..40de77f 100644
--- a/src/test/run-make-fulldeps/link-cfg/dep.rs
+++ b/src/test/run-make-fulldeps/link-cfg/dep.rs
@@ -3,6 +3,6 @@
 
 #[link(name = "return1", cfg(foo))]
 #[link(name = "return2", cfg(bar))]
-extern {
+extern "C" {
     pub fn my_function() -> i32;
 }
diff --git a/src/test/run-make-fulldeps/link-cfg/no-deps.rs b/src/test/run-make-fulldeps/link-cfg/no-deps.rs
index 6dba7fe..ba5a871 100644
--- a/src/test/run-make-fulldeps/link-cfg/no-deps.rs
+++ b/src/test/run-make-fulldeps/link-cfg/no-deps.rs
@@ -2,7 +2,7 @@
 
 #[link(name = "return1", cfg(foo))]
 #[link(name = "return2", cfg(bar))]
-extern {
+extern "C" {
     fn my_function() -> i32;
 }
 
diff --git a/src/test/run-make-fulldeps/link-path-order/main.rs b/src/test/run-make-fulldeps/link-path-order/main.rs
index 10f1282..8024e34 100644
--- a/src/test/run-make-fulldeps/link-path-order/main.rs
+++ b/src/test/run-make-fulldeps/link-path-order/main.rs
@@ -2,15 +2,13 @@
 
 extern crate libc;
 
-#[link(name="foo", kind = "static")]
-extern {
+#[link(name = "foo", kind = "static")]
+extern "C" {
     fn should_return_one() -> libc::c_int;
 }
 
 fn main() {
-    let result = unsafe {
-        should_return_one()
-    };
+    let result = unsafe { should_return_one() };
 
     if result != 1 {
         std::process::exit(255);
diff --git a/src/test/run-make-fulldeps/linkage-attr-on-static/bar.rs b/src/test/run-make-fulldeps/linkage-attr-on-static/bar.rs
index b827532..68607cb 100644
--- a/src/test/run-make-fulldeps/linkage-attr-on-static/bar.rs
+++ b/src/test/run-make-fulldeps/linkage-attr-on-static/bar.rs
@@ -5,7 +5,7 @@
 static BAZ: i32 = 21;
 
 #[link(name = "foo", kind = "static")]
-extern {
+extern "C" {
     fn what() -> i32;
 }
 
diff --git a/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs b/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs
index f313798..db238c0 100644
--- a/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs
+++ b/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs
@@ -25,7 +25,7 @@
         writeln!(f, "#[link(name = \"S{}{}S\")]", prefix, i).unwrap();
         libs.insert(format!("{}{}", prefix, i));
     }
-    writeln!(f, "extern {{}}\nfn main() {{}}").unwrap();
+    writeln!(f, "extern \"C\" {{}}\nfn main() {{}}").unwrap();
     f.into_inner().unwrap();
 
     libs
diff --git a/src/test/run-make-fulldeps/longjmp-across-rust/main.rs b/src/test/run-make-fulldeps/longjmp-across-rust/main.rs
index 5b43c1c..cc1d5b1 100644
--- a/src/test/run-make-fulldeps/longjmp-across-rust/main.rs
+++ b/src/test/run-make-fulldeps/longjmp-across-rust/main.rs
@@ -1,6 +1,6 @@
 #[link(name = "foo", kind = "static")]
-extern {
-    fn test_start(f: extern fn());
+extern "C" {
+    fn test_start(f: extern "C" fn());
     fn test_end();
 }
 
@@ -13,11 +13,10 @@
 struct A;
 
 impl Drop for A {
-    fn drop(&mut self) {
-    }
+    fn drop(&mut self) {}
 }
 
-extern fn test_middle() {
+extern "C" fn test_middle() {
     let _a = A;
     foo();
 }
diff --git a/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib1.rs b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib1.rs
index 4b43b86..f70bb33 100644
--- a/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib1.rs
+++ b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib1.rs
@@ -1,7 +1,7 @@
 #![crate_type = "rlib"]
 
 #[link(name = "foo", kind = "static")]
-extern {
+extern "C" {
     fn foo() -> i32;
 }
 
diff --git a/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib2.rs b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib2.rs
index c9e1baa..2dec2a2 100644
--- a/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib2.rs
+++ b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib2.rs
@@ -3,7 +3,7 @@
 extern crate lib1;
 
 #[link(name = "bar", kind = "static")]
-extern {
+extern "C" {
     fn foo() -> i32;
 }
 
diff --git a/src/test/run-make-fulldeps/manual-link/foo.rs b/src/test/run-make-fulldeps/manual-link/foo.rs
index f5cd598..c1f2823 100644
--- a/src/test/run-make-fulldeps/manual-link/foo.rs
+++ b/src/test/run-make-fulldeps/manual-link/foo.rs
@@ -1,9 +1,11 @@
 #![crate_type = "rlib"]
 
-extern {
+extern "C" {
     fn bar();
 }
 
 pub fn foo() {
-    unsafe { bar(); }
+    unsafe {
+        bar();
+    }
 }
diff --git a/src/test/run-make-fulldeps/no-duplicate-libs/main.rs b/src/test/run-make-fulldeps/no-duplicate-libs/main.rs
index 298018c..b25ef35 100644
--- a/src/test/run-make-fulldeps/no-duplicate-libs/main.rs
+++ b/src/test/run-make-fulldeps/no-duplicate-libs/main.rs
@@ -1,7 +1,7 @@
 #[link(name = "foo")] // linker should drop this library, no symbols used
 #[link(name = "bar")] // symbol comes from this library
 #[link(name = "foo")] // now linker picks up `foo` b/c `bar` library needs it
-extern {
+extern "C" {
     fn bar();
 }
 
diff --git a/src/test/run-make-fulldeps/sanitizer-cdylib-link/library.rs b/src/test/run-make-fulldeps/sanitizer-cdylib-link/library.rs
index bf11553..f2a52cb 100644
--- a/src/test/run-make-fulldeps/sanitizer-cdylib-link/library.rs
+++ b/src/test/run-make-fulldeps/sanitizer-cdylib-link/library.rs
@@ -1,5 +1,5 @@
 #[no_mangle]
-pub extern fn overflow() {
+pub extern "C" fn overflow() {
     let xs = [0, 1, 2, 3];
     let _y = unsafe { *xs.as_ptr().offset(4) };
 }
diff --git a/src/test/run-make-fulldeps/sanitizer-cdylib-link/program.rs b/src/test/run-make-fulldeps/sanitizer-cdylib-link/program.rs
index 3bbbcd9..ef053aa 100644
--- a/src/test/run-make-fulldeps/sanitizer-cdylib-link/program.rs
+++ b/src/test/run-make-fulldeps/sanitizer-cdylib-link/program.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     fn overflow();
 }
 
diff --git a/src/test/run-make-fulldeps/sanitizer-dylib-link/library.rs b/src/test/run-make-fulldeps/sanitizer-dylib-link/library.rs
index bf11553..f2a52cb 100644
--- a/src/test/run-make-fulldeps/sanitizer-dylib-link/library.rs
+++ b/src/test/run-make-fulldeps/sanitizer-dylib-link/library.rs
@@ -1,5 +1,5 @@
 #[no_mangle]
-pub extern fn overflow() {
+pub extern "C" fn overflow() {
     let xs = [0, 1, 2, 3];
     let _y = unsafe { *xs.as_ptr().offset(4) };
 }
diff --git a/src/test/run-make-fulldeps/sanitizer-dylib-link/program.rs b/src/test/run-make-fulldeps/sanitizer-dylib-link/program.rs
index 3bbbcd9..ef053aa 100644
--- a/src/test/run-make-fulldeps/sanitizer-dylib-link/program.rs
+++ b/src/test/run-make-fulldeps/sanitizer-dylib-link/program.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     fn overflow();
 }
 
diff --git a/src/test/run-make-fulldeps/sanitizer-staticlib-link/library.rs b/src/test/run-make-fulldeps/sanitizer-staticlib-link/library.rs
index bf11553..f2a52cb 100644
--- a/src/test/run-make-fulldeps/sanitizer-staticlib-link/library.rs
+++ b/src/test/run-make-fulldeps/sanitizer-staticlib-link/library.rs
@@ -1,5 +1,5 @@
 #[no_mangle]
-pub extern fn overflow() {
+pub extern "C" fn overflow() {
     let xs = [0, 1, 2, 3];
     let _y = unsafe { *xs.as_ptr().offset(4) };
 }
diff --git a/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.rs b/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.rs
index 21e1ade..ec59bdb 100644
--- a/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.rs
+++ b/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.rs
@@ -1,5 +1,5 @@
 #[link(name = "library")]
-extern {
+extern "C" {
     fn overflow();
 }
 
diff --git a/src/test/run-make-fulldeps/save-analysis-fail/foo.rs b/src/test/run-make-fulldeps/save-analysis-fail/foo.rs
index 5d504ce..94879c2 100644
--- a/src/test/run-make-fulldeps/save-analysis-fail/foo.rs
+++ b/src/test/run-make-fulldeps/save-analysis-fail/foo.rs
@@ -1,4 +1,4 @@
-#![ crate_name = "test" ]
+#![crate_name = "test"]
 #![feature(box_syntax)]
 #![feature(rustc_private)]
 
@@ -9,11 +9,10 @@
 extern crate krate2 as krate3;
 
 use rustc_graphviz::RenderOption;
-use std::collections::{HashMap,HashSet};
 use std::cell::RefCell;
+use std::collections::{HashMap, HashSet};
 use std::io::Write;
 
-
 use sub::sub2 as msalias;
 use sub::sub2;
 use sub::sub2::nested_struct as sub_struct;
@@ -30,7 +29,7 @@
 // buglink test - see issue #1337.
 
 fn test_alias<I: Iterator>(i: Option<<I as Iterator>::Item>) {
-    let s = sub_struct{ field2: 45u32, };
+    let s = sub_struct { field2: 45u32 };
 
     // import tests
     fn foo(x: &Write) {}
@@ -80,7 +79,7 @@
 
         pub enum nested_enum {
             Nest2 = 2,
-            Nest3 = 3
+            Nest3 = 3,
         }
     }
 }
@@ -101,7 +100,9 @@
 type SF = some_fields;
 
 trait SuperTrait {
-    fn qux(&self) { panic!(); }
+    fn qux(&self) {
+        panic!();
+    }
 }
 
 trait SomeTrait: SuperTrait {
@@ -136,8 +137,7 @@
     }
 }
 
-impl SuperTrait for some_fields {
-}
+impl SuperTrait for some_fields {}
 
 impl SubTrait for some_fields {}
 
@@ -150,17 +150,14 @@
         42
     }
 
-    fn align_to<T>(&mut self) {
-
-    }
+    fn align_to<T>(&mut self) {}
 
     fn test(&mut self) {
         self.align_to::<bool>();
     }
 }
 
-impl SuperTrait for nofields {
-}
+impl SuperTrait for nofields {}
 impl SomeTrait for nofields {
     fn Method(&self, x: u32) -> u32 {
         self.Method(x);
@@ -186,59 +183,70 @@
     Ints(isize, isize),
     Floats(f64, f64),
     Strings(&'a str, &'a str, &'a str),
-    MyTypes(MyType, MyType)
+    MyTypes(MyType, MyType),
 }
 
 #[derive(Copy, Clone)]
 enum SomeOtherEnum {
     SomeConst1,
     SomeConst2,
-    SomeConst3
+    SomeConst3,
 }
 
 enum SomeStructEnum {
-    EnumStruct{a:isize, b:isize},
-    EnumStruct2{f1:MyType, f2:MyType},
-    EnumStruct3{f1:MyType, f2:MyType, f3:SomeEnum<'static>}
+    EnumStruct { a: isize, b: isize },
+    EnumStruct2 { f1: MyType, f2: MyType },
+    EnumStruct3 { f1: MyType, f2: MyType, f3: SomeEnum<'static> },
 }
 
 fn matchSomeEnum(val: SomeEnum) {
     match val {
-        SomeEnum::Ints(int1, int2) => { println(&(int1+int2).to_string()); }
-        SomeEnum::Floats(float1, float2) => { println(&(float2*float1).to_string()); }
-        SomeEnum::Strings(.., s3) => { println(s3); }
-        SomeEnum::MyTypes(mt1, mt2) => { println(&(mt1.field1 - mt2.field1).to_string()); }
+        SomeEnum::Ints(int1, int2) => {
+            println(&(int1 + int2).to_string());
+        }
+        SomeEnum::Floats(float1, float2) => {
+            println(&(float2 * float1).to_string());
+        }
+        SomeEnum::Strings(.., s3) => {
+            println(s3);
+        }
+        SomeEnum::MyTypes(mt1, mt2) => {
+            println(&(mt1.field1 - mt2.field1).to_string());
+        }
     }
 }
 
 fn matchSomeStructEnum(se: SomeStructEnum) {
     match se {
-        SomeStructEnum::EnumStruct{a:a, ..} => println(&a.to_string()),
-        SomeStructEnum::EnumStruct2{f1:f1, f2:f_2} => println(&f_2.field1.to_string()),
-        SomeStructEnum::EnumStruct3{f1, ..} => println(&f1.field1.to_string()),
+        SomeStructEnum::EnumStruct { a: a, .. } => println(&a.to_string()),
+        SomeStructEnum::EnumStruct2 { f1: f1, f2: f_2 } => println(&f_2.field1.to_string()),
+        SomeStructEnum::EnumStruct3 { f1, .. } => println(&f1.field1.to_string()),
     }
 }
 
-
 fn matchSomeStructEnum2(se: SomeStructEnum) {
     use SomeStructEnum::*;
     match se {
-        EnumStruct{a: ref aaa, ..} => println(&aaa.to_string()),
-        EnumStruct2{f1, f2: f2} => println(&f1.field1.to_string()),
-        EnumStruct3{f1, f3: SomeEnum::Ints(..), f2} => println(&f1.field1.to_string()),
-        _ => {},
+        EnumStruct { a: ref aaa, .. } => println(&aaa.to_string()),
+        EnumStruct2 { f1, f2: f2 } => println(&f1.field1.to_string()),
+        EnumStruct3 { f1, f3: SomeEnum::Ints(..), f2 } => println(&f1.field1.to_string()),
+        _ => {}
     }
 }
 
 fn matchSomeOtherEnum(val: SomeOtherEnum) {
     use SomeOtherEnum::{SomeConst2, SomeConst3};
     match val {
-        SomeOtherEnum::SomeConst1 => { println("I'm const1."); }
-        SomeConst2 | SomeConst3 => { println("I'm const2 or const3."); }
+        SomeOtherEnum::SomeConst1 => {
+            println("I'm const1.");
+        }
+        SomeConst2 | SomeConst3 => {
+            println("I'm const2 or const3.");
+        }
     }
 }
 
-fn hello<X: SomeTrait>((z, a) : (u32, String), ex: X) {
+fn hello<X: SomeTrait>((z, a): (u32, String), ex: X) {
     SameDir2::hello(43);
 
     println(&yy.to_string());
@@ -253,8 +261,8 @@
     let x = 32.0f32;
     let _ = (x + ((x * x) + 1.0).sqrt()).ln();
 
-    let s: Box<SomeTrait> = box some_fields {field1: 43};
-    let s2: Box<some_fields> =  box some_fields {field1: 43};
+    let s: Box<SomeTrait> = box some_fields { field1: 43 };
+    let s2: Box<some_fields> = box some_fields { field1: 43 };
     let s3 = box nofields;
 
     s.Method(43);
@@ -307,8 +315,9 @@
     }
 }
 
-fn main() { // foo
-    let s = box some_fields {field1: 43};
+fn main() {
+    // foo
+    let s = box some_fields { field1: 43 };
     hello((43, "a".to_string()), *s);
     sub::sub2::hello();
     sub2::sub3::hello();
@@ -329,26 +338,24 @@
     let vs = variable_str!(32);
 
     let mut candidates: RefCell<HashMap<&'static str, &'static str>> = RefCell::new(HashMap::new());
-    let _ = blah {
-        used_link_args: RefCell::new([]),
-    };
+    let _ = blah { used_link_args: RefCell::new([]) };
     let s1 = nofields;
-    let s2 = SF { field1: 55};
-    let s3: some_fields = some_fields{ field1: 55};
-    let s4: msalias::nested_struct = sub::sub2::nested_struct{ field2: 55};
-    let s4: msalias::nested_struct = sub2::nested_struct{ field2: 55};
+    let s2 = SF { field1: 55 };
+    let s3: some_fields = some_fields { field1: 55 };
+    let s4: msalias::nested_struct = sub::sub2::nested_struct { field2: 55 };
+    let s4: msalias::nested_struct = sub2::nested_struct { field2: 55 };
     println(&s2.field1.to_string());
-    let s5: MyType = box some_fields{ field1: 55};
-    let s = SameDir::SameStruct{name: "Bob".to_string()};
-    let s = SubDir::SubStruct{name:"Bob".to_string()};
+    let s5: MyType = box some_fields { field1: 55 };
+    let s = SameDir::SameStruct { name: "Bob".to_string() };
+    let s = SubDir::SubStruct { name: "Bob".to_string() };
     let s6: SomeEnum = SomeEnum::MyTypes(box s2.clone(), s5);
     let s7: SomeEnum = SomeEnum::Strings("one", "two", "three");
     matchSomeEnum(s6);
     matchSomeEnum(s7);
     let s8: SomeOtherEnum = SomeOtherEnum::SomeConst2;
     matchSomeOtherEnum(s8);
-    let s9: SomeStructEnum = SomeStructEnum::EnumStruct2{ f1: box some_fields{ field1:10 },
-                                                          f2: box s2 };
+    let s9: SomeStructEnum =
+        SomeStructEnum::EnumStruct2 { f1: box some_fields { field1: 10 }, f2: box s2 };
     matchSomeStructEnum(s9);
 
     for x in &vec![1, 2, 3] {
@@ -409,8 +416,7 @@
 
 struct CharSearcher<'a>(<CharEqPattern as Pattern<'a>>::Searcher);
 
-pub trait Error {
-}
+pub trait Error {}
 
 impl Error + 'static {
     pub fn is<T: Error + 'static>(&self) -> bool {
@@ -437,13 +443,13 @@
     print!("x is {}, y is {1}, name is {n}", x, y, n = name);
 }
 
-extern {
+extern "C" {
     static EXTERN_FOO: u8;
     fn extern_foo(a: u8, b: i32) -> String;
 }
 
 struct Rls699 {
-  f: u32,
+    f: u32,
 }
 
 fn new(f: u32) -> Rls699 {
diff --git a/src/test/run-make-fulldeps/static-dylib-by-default/bar.rs b/src/test/run-make-fulldeps/static-dylib-by-default/bar.rs
index 5381e7f..1442116 100644
--- a/src/test/run-make-fulldeps/static-dylib-by-default/bar.rs
+++ b/src/test/run-make-fulldeps/static-dylib-by-default/bar.rs
@@ -3,6 +3,6 @@
 extern crate foo;
 
 #[no_mangle]
-pub extern fn bar() {
+pub extern "C" fn bar() {
     foo::foo();
 }
diff --git a/src/test/run-make-fulldeps/static-nobundle/bbb.rs b/src/test/run-make-fulldeps/static-nobundle/bbb.rs
index 0e10fc3..69d1668 100644
--- a/src/test/run-make-fulldeps/static-nobundle/bbb.rs
+++ b/src/test/run-make-fulldeps/static-nobundle/bbb.rs
@@ -2,7 +2,7 @@
 #![feature(static_nobundle)]
 
 #[link(name = "aaa", kind = "static-nobundle")]
-extern {
+extern "C" {
     pub fn native_func();
 }
 
diff --git a/src/test/run-make-fulldeps/staticlib-blank-lib/foo.rs b/src/test/run-make-fulldeps/staticlib-blank-lib/foo.rs
index 48ba8b7..bf48d06 100644
--- a/src/test/run-make-fulldeps/staticlib-blank-lib/foo.rs
+++ b/src/test/run-make-fulldeps/staticlib-blank-lib/foo.rs
@@ -1,6 +1,6 @@
 #![crate_type = "staticlib"]
 
 #[link(name = "foo", kind = "static")]
-extern {}
+extern "C" {}
 
 fn main() {}
diff --git a/src/test/run-make-fulldeps/std-core-cycle/foo.rs b/src/test/run-make-fulldeps/std-core-cycle/foo.rs
index 3c80bc4..6aa6e1a 100644
--- a/src/test/run-make-fulldeps/std-core-cycle/foo.rs
+++ b/src/test/run-make-fulldeps/std-core-cycle/foo.rs
@@ -6,6 +6,6 @@
 static A: bar::A = bar::A;
 
 #[no_mangle]
-pub extern fn a(a: u32, b: u32) -> u32 {
+pub extern "C" fn a(a: u32, b: u32) -> u32 {
     a / b
 }
diff --git a/src/test/run-make-fulldeps/target-specs/foo.rs b/src/test/run-make-fulldeps/target-specs/foo.rs
index ee443eb..9ff33e2 100644
--- a/src/test/run-make-fulldeps/target-specs/foo.rs
+++ b/src/test/run-make-fulldeps/target-specs/foo.rs
@@ -1,19 +1,21 @@
 #![feature(lang_items, no_core, auto_traits)]
 #![no_core]
 
-#[lang="copy"]
-trait Copy { }
+#[lang = "copy"]
+trait Copy {}
 
-#[lang="sized"]
-trait Sized { }
+#[lang = "sized"]
+trait Sized {}
 
 #[lang = "freeze"]
 auto trait Freeze {}
 
-#[lang="start"]
-fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize { 0 }
+#[lang = "start"]
+fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize {
+    0
+}
 
-extern {
+extern "C" {
     fn _foo() -> [u8; 16];
 }
 
diff --git a/src/test/run-make/const_fn_mir/Makefile b/src/test/run-make/const_fn_mir/Makefile
new file mode 100644
index 0000000..2aa0bc9
--- /dev/null
+++ b/src/test/run-make/const_fn_mir/Makefile
@@ -0,0 +1,10 @@
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTC) main.rs --emit=mir -o "$(TMPDIR)"/dump.mir
+
+ifdef RUSTC_BLESS_TEST
+	cp "$(TMPDIR)"/dump.mir dump.mir
+else
+	$(DIFF) dump.mir "$(TMPDIR)"/dump.mir
+endif
diff --git a/src/test/run-make/const_fn_mir/dump.mir b/src/test/run-make/const_fn_mir/dump.mir
new file mode 100644
index 0000000..3dac42c
--- /dev/null
+++ b/src/test/run-make/const_fn_mir/dump.mir
@@ -0,0 +1,45 @@
+// WARNING: This output format is intended for human consumers only
+// and is subject to change without notice. Knock yourself out.
+fn main() -> () {
+    let mut _0: ();                      // return place in scope 0 at main.rs:8:11: 8:11
+    let _1: i32;                         // in scope 0 at main.rs:9:5: 9:10
+
+    bb0: {
+        StorageLive(_1);                 // scope 0 at main.rs:9:5: 9:10
+        _1 = foo() -> bb1;               // scope 0 at main.rs:9:5: 9:10
+                                         // mir::Constant
+                                         // + span: main.rs:9:5: 9:8
+                                         // + literal: Const { ty: fn() -> i32 {foo}, val: Value(Scalar(<ZST>)) }
+    }
+
+    bb1: {
+        StorageDead(_1);                 // scope 0 at main.rs:9:10: 9:11
+        _0 = const ();                   // scope 0 at main.rs:8:11: 10:2
+        return;                          // scope 0 at main.rs:10:2: 10:2
+    }
+}
+
+fn foo() -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at main.rs:4:19: 4:22
+
+    bb0: {
+        _0 = const 11_i32;               // scope 0 at main.rs:5:5: 5:10
+        return;                          // scope 0 at main.rs:6:2: 6:2
+    }
+}
+
+// MIR FOR CTFE
+fn foo() -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at main.rs:4:19: 4:22
+    let mut _1: (i32, bool);             // in scope 0 at main.rs:5:5: 5:10
+
+    bb0: {
+        _1 = CheckedAdd(const 5_i32, const 6_i32); // scope 0 at main.rs:5:5: 5:10
+        assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 5_i32, const 6_i32) -> bb1; // scope 0 at main.rs:5:5: 5:10
+    }
+
+    bb1: {
+        _0 = move (_1.0: i32);           // scope 0 at main.rs:5:5: 5:10
+        return;                          // scope 0 at main.rs:6:2: 6:2
+    }
+}
diff --git a/src/test/run-make/const_fn_mir/main.rs b/src/test/run-make/const_fn_mir/main.rs
new file mode 100644
index 0000000..e8552bd
--- /dev/null
+++ b/src/test/run-make/const_fn_mir/main.rs
@@ -0,0 +1,10 @@
+// emit-mir
+// check-pass
+
+const fn foo() -> i32 {
+    5 + 6
+}
+
+fn main() {
+    foo();
+}
diff --git a/src/test/run-make/issue-36710/foo.rs b/src/test/run-make/issue-36710/foo.rs
index 061f07c..845844f 100644
--- a/src/test/run-make/issue-36710/foo.rs
+++ b/src/test/run-make/issue-36710/foo.rs
@@ -3,7 +3,9 @@
 // For linking libstdc++ on MinGW
 #![cfg_attr(all(windows, target_env = "gnu"), feature(static_nobundle))]
 
-extern { fn get() -> u32; }
+extern "C" {
+    fn get() -> u32;
+}
 
 fn main() {
     let i = unsafe { get() };
diff --git a/src/test/run-make/wasm-import-module/bar.rs b/src/test/run-make/wasm-import-module/bar.rs
index 206f7c6..1b988c7 100644
--- a/src/test/run-make/wasm-import-module/bar.rs
+++ b/src/test/run-make/wasm-import-module/bar.rs
@@ -4,13 +4,13 @@
 extern crate foo;
 
 #[link(wasm_import_module = "./me")]
-extern {
+extern "C" {
     #[link_name = "me_in_dep"]
     fn dep();
 }
 
 #[no_mangle]
-pub extern fn foo() {
+pub extern "C" fn foo() {
     unsafe {
         foo::dep();
         dep();
diff --git a/src/test/run-make/wasm-import-module/foo.rs b/src/test/run-make/wasm-import-module/foo.rs
index b9f87f1..bbeaf99 100644
--- a/src/test/run-make/wasm-import-module/foo.rs
+++ b/src/test/run-make/wasm-import-module/foo.rs
@@ -2,6 +2,6 @@
 #![deny(warnings)]
 
 #[link(wasm_import_module = "./dep")]
-extern {
+extern "C" {
     pub fn dep();
 }
diff --git a/src/test/run-pass-valgrind/osx-frameworks.rs b/src/test/run-pass-valgrind/osx-frameworks.rs
index ea14036..571621c 100644
--- a/src/test/run-pass-valgrind/osx-frameworks.rs
+++ b/src/test/run-pass-valgrind/osx-frameworks.rs
@@ -6,13 +6,15 @@
 
 #[cfg(target_os = "macos")]
 #[link(name = "CoreFoundation", kind = "framework")]
-extern {
+extern "C" {
     fn CFRunLoopGetTypeID() -> libc::c_ulong;
 }
 
 #[cfg(target_os = "macos")]
 pub fn main() {
-    unsafe { CFRunLoopGetTypeID(); }
+    unsafe {
+        CFRunLoopGetTypeID();
+    }
 }
 
 #[cfg(not(target_os = "macos"))]
diff --git a/src/test/rustdoc-json/compare.py b/src/test/rustdoc-json/compare.py
index b0c5b16..6a92126 100644
--- a/src/test/rustdoc-json/compare.py
+++ b/src/test/rustdoc-json/compare.py
@@ -7,6 +7,9 @@
 # and then create `yourtest.expected` by stripping unnecessary details from `yourtest.json`. If
 # you're on windows, replace `\` with `/`.
 
+# WARNING: The error messages produced by this may be misleading, in the case of list re-ordering
+#          it may point to apparently unrelated keys.
+
 import copy
 import sys
 import json
diff --git a/src/test/rustdoc-json/nested.expected b/src/test/rustdoc-json/nested.expected
index 65bb0c5..80070e7 100644
--- a/src/test/rustdoc-json/nested.expected
+++ b/src/test/rustdoc-json/nested.expected
@@ -41,8 +41,8 @@
       "inner": {
         "is_crate": false,
         "items": [
-          "0:7",
-          "0:4"
+          "0:4",
+          "0:7"
         ]
       },
       "kind": "module",
diff --git a/src/test/rustdoc-ui/auxiliary/issue-61592.rs b/src/test/rustdoc-ui/auxiliary/issue-61592.rs
new file mode 100644
index 0000000..57a365b
--- /dev/null
+++ b/src/test/rustdoc-ui/auxiliary/issue-61592.rs
@@ -0,0 +1,3 @@
+#![crate_name = "foo"]
+
+pub trait Foo {}
diff --git a/src/test/rustdoc-ui/check-doc-alias-attr-location.rs b/src/test/rustdoc-ui/check-doc-alias-attr-location.rs
index 7de2caa..6de1960 100644
--- a/src/test/rustdoc-ui/check-doc-alias-attr-location.rs
+++ b/src/test/rustdoc-ui/check-doc-alias-attr-location.rs
@@ -5,7 +5,7 @@
 }
 
 #[doc(alias = "foo")] //~ ERROR
-extern {}
+extern "C" {}
 
 #[doc(alias = "bar")] //~ ERROR
 impl Bar {
@@ -17,5 +17,7 @@
 impl Foo for Bar {
     #[doc(alias = "assoc")] //~ ERROR
     type X = i32;
-    fn foo() -> Self::X { 0 }
+    fn foo() -> Self::X {
+        0
+    }
 }
diff --git a/src/test/rustdoc-ui/coverage/basic.rs b/src/test/rustdoc-ui/coverage/basic.rs
index 98507f9..6c26b75 100644
--- a/src/test/rustdoc-ui/coverage/basic.rs
+++ b/src/test/rustdoc-ui/coverage/basic.rs
@@ -45,6 +45,6 @@
     () => {};
 }
 
-extern {
+extern "C" {
     pub type ExternType;
 }
diff --git a/src/test/rustdoc-ui/deref-recursive-cycle.rs b/src/test/rustdoc-ui/deref-recursive-cycle.rs
new file mode 100644
index 0000000..4cb518c
--- /dev/null
+++ b/src/test/rustdoc-ui/deref-recursive-cycle.rs
@@ -0,0 +1,17 @@
+// check-pass
+// #26207: Ensure `Deref` cycles are properly handled without errors.
+
+#[derive(Copy, Clone)]
+struct S;
+
+impl std::ops::Deref for S {
+    type Target = S;
+
+    fn deref(&self) -> &S {
+        self
+    }
+}
+
+fn main() {
+    let s: S = *******S;
+}
diff --git a/src/test/rustdoc-ui/doc-alias-crate-level.rs b/src/test/rustdoc-ui/doc-alias-crate-level.rs
index 309d0bc..70618ac 100644
--- a/src/test/rustdoc-ui/doc-alias-crate-level.rs
+++ b/src/test/rustdoc-ui/doc-alias-crate-level.rs
@@ -1,5 +1,3 @@
-#![feature(doc_alias)]
-
 #![doc(alias = "crate-level-not-working")] //~ ERROR
 
 #[doc(alias = "shouldn't work!")] //~ ERROR
diff --git a/src/test/rustdoc-ui/doc-alias-crate-level.stderr b/src/test/rustdoc-ui/doc-alias-crate-level.stderr
index a58e91c..9e746cb 100644
--- a/src/test/rustdoc-ui/doc-alias-crate-level.stderr
+++ b/src/test/rustdoc-ui/doc-alias-crate-level.stderr
@@ -1,11 +1,11 @@
 error: '\'' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/doc-alias-crate-level.rs:5:15
+  --> $DIR/doc-alias-crate-level.rs:3:15
    |
 LL | #[doc(alias = "shouldn't work!")]
    |               ^^^^^^^^^^^^^^^^^
 
 error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute
-  --> $DIR/doc-alias-crate-level.rs:3:8
+  --> $DIR/doc-alias-crate-level.rs:1:8
    |
 LL | #![doc(alias = "crate-level-not-working")]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/rustdoc-ui/doc-alias-same-name.rs b/src/test/rustdoc-ui/doc-alias-same-name.rs
new file mode 100644
index 0000000..da97c26
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-alias-same-name.rs
@@ -0,0 +1,4 @@
+#![crate_type = "lib"]
+
+#[doc(alias = "Foo")] //~ ERROR
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/doc-alias-same-name.stderr b/src/test/rustdoc-ui/doc-alias-same-name.stderr
new file mode 100644
index 0000000..5ba09a2
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-alias-same-name.stderr
@@ -0,0 +1,8 @@
+error: `#[doc(alias = "...")]` is the same as the item's name
+  --> $DIR/doc-alias-same-name.rs:3:7
+   |
+LL | #[doc(alias = "Foo")]
+   |       ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/ignore-block-help.rs b/src/test/rustdoc-ui/ignore-block-help.rs
new file mode 100644
index 0000000..c22dddd
--- /dev/null
+++ b/src/test/rustdoc-ui/ignore-block-help.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+/// ```ignore (to-prevent-tidy-error)
+/// let heart = '❤️';
+/// ```
+//~^^^ WARN
+pub struct X;
diff --git a/src/test/rustdoc-ui/ignore-block-help.stderr b/src/test/rustdoc-ui/ignore-block-help.stderr
new file mode 100644
index 0000000..d45cd92
--- /dev/null
+++ b/src/test/rustdoc-ui/ignore-block-help.stderr
@@ -0,0 +1,17 @@
+warning: could not parse code block as Rust code
+  --> $DIR/ignore-block-help.rs:3:5
+   |
+LL |   /// ```ignore (to-prevent-tidy-error)
+   |  _____^
+LL | | /// let heart = '❤️';
+LL | | /// ```
+   | |_______^
+   |
+   = note: error from rustc: character literal may only contain one codepoint
+help: `ignore` code blocks require valid Rust code for syntax highlighting. Mark blocks that do not contain Rust code as text
+   |
+LL | /// ```text,ignore (to-prevent-tidy-error)
+   |     ^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.rs b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.rs
new file mode 100644
index 0000000..0d1d5d1
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.rs
@@ -0,0 +1,3 @@
+#![deny(broken_intra_doc_links)]
+//! [static@u8::MIN]
+//~^ ERROR incompatible link kind
diff --git a/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr
new file mode 100644
index 0000000..ed1c10f
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr
@@ -0,0 +1,15 @@
+error: incompatible link kind for `u8::MIN`
+  --> $DIR/incompatible-primitive-disambiguator.rs:2:6
+   |
+LL | //! [static@u8::MIN]
+   |      ^^^^^^^^^^^^^^ help: to link to the associated constant, prefix with `const@`: `const@u8::MIN`
+   |
+note: the lint level is defined here
+  --> $DIR/incompatible-primitive-disambiguator.rs:1:9
+   |
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = note: this link resolved to an associated constant, which is not a static
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/intra-doc/unused-extern-crate.rs b/src/test/rustdoc-ui/intra-doc/unused-extern-crate.rs
new file mode 100644
index 0000000..186503c
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/unused-extern-crate.rs
@@ -0,0 +1,5 @@
+// compile-flags: --extern zip=whatever.rlib
+#![deny(broken_intra_doc_links)]
+/// See [zip] crate.
+//~^ ERROR unresolved
+pub struct ArrayZip;
diff --git a/src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr b/src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr
new file mode 100644
index 0000000..b3b57fd
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr
@@ -0,0 +1,15 @@
+error: unresolved link to `zip`
+  --> $DIR/unused-extern-crate.rs:3:10
+   |
+LL | /// See [zip] crate.
+   |          ^^^ no item named `zip` in scope
+   |
+note: the lint level is defined here
+  --> $DIR/unused-extern-crate.rs:2:9
+   |
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr
index 9a7a4d2..75acdc5 100644
--- a/src/test/rustdoc-ui/invalid-syntax.stderr
+++ b/src/test/rustdoc-ui/invalid-syntax.stderr
@@ -127,8 +127,10 @@
 warning: could not parse code block as Rust code
   --> $DIR/invalid-syntax.rs:92:9
    |
-LL | ///     \____/
-   |         ^^^^^^
+LL |   ///     \____/
+   |  _________^
+LL | | ///
+   | |_
    |
    = note: error from rustc: unknown start of token: \
 
diff --git a/src/test/rustdoc-ui/issue-61592-2.rs b/src/test/rustdoc-ui/issue-61592-2.rs
new file mode 100644
index 0000000..5b4fc5e
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61592-2.rs
@@ -0,0 +1,10 @@
+// aux-build:issue-61592.rs
+
+extern crate foo;
+
+#[doc = "bar"]
+#[doc(inline)] //~ ERROR
+#[doc = "baz"]
+pub use foo::Foo as _;
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/issue-61592-2.stderr b/src/test/rustdoc-ui/issue-61592-2.stderr
new file mode 100644
index 0000000..1b7f8bb
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61592-2.stderr
@@ -0,0 +1,12 @@
+error[E0780]: anonymous imports cannot be inlined
+  --> $DIR/issue-61592-2.rs:6:7
+   |
+LL | #[doc(inline)]
+   |       ^^^^^^
+LL | #[doc = "baz"]
+LL | pub use foo::Foo as _;
+   | ---------------------- anonymous import
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0780`.
diff --git a/src/test/rustdoc-ui/issue-61592.rs b/src/test/rustdoc-ui/issue-61592.rs
new file mode 100644
index 0000000..6677255
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61592.rs
@@ -0,0 +1,8 @@
+// aux-build:issue-61592.rs
+
+extern crate foo;
+
+#[doc(inline)] //~ ERROR
+pub use foo::Foo as _;
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/issue-61592.stderr b/src/test/rustdoc-ui/issue-61592.stderr
new file mode 100644
index 0000000..9c9c910
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61592.stderr
@@ -0,0 +1,11 @@
+error[E0780]: anonymous imports cannot be inlined
+  --> $DIR/issue-61592.rs:5:7
+   |
+LL | #[doc(inline)]
+   |       ^^^^^^
+LL | pub use foo::Foo as _;
+   | ---------------------- anonymous import
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0780`.
diff --git a/src/test/rustdoc-ui/issue-80992.rs b/src/test/rustdoc-ui/issue-80992.rs
new file mode 100644
index 0000000..8983439
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-80992.rs
@@ -0,0 +1,11 @@
+// check-pass
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+pub fn test() -> Result<(), ()> {
+    //! ```compile_fail
+    //! fn test() -> Result< {}
+    //! ```
+    Ok(())
+}
diff --git a/src/test/rustdoc-ui/issue-80992.stdout b/src/test/rustdoc-ui/issue-80992.stdout
new file mode 100644
index 0000000..1dd19f4
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-80992.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/issue-80992.rs - test (line 7) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/range-pattern.rs b/src/test/rustdoc-ui/range-pattern.rs
new file mode 100644
index 0000000..fd255d0
--- /dev/null
+++ b/src/test/rustdoc-ui/range-pattern.rs
@@ -0,0 +1,3 @@
+// check-pass
+
+fn func(0u8..=255: u8) {}
diff --git a/src/test/rustdoc-ui/reference-link-reports-error-once.rs b/src/test/rustdoc-ui/reference-link-reports-error-once.rs
new file mode 100644
index 0000000..7957ee3
--- /dev/null
+++ b/src/test/rustdoc-ui/reference-link-reports-error-once.rs
@@ -0,0 +1,20 @@
+#![deny(broken_intra_doc_links)]
+
+/// Links to [a] [link][a]
+/// And also a [third link][a]
+/// And also a [reference link][b]
+///
+/// Other links to the same target should still emit error: [ref] //~ERROR unresolved link to `ref`
+/// Duplicate [ref] //~ERROR unresolved link to `ref`
+///
+/// Other links to other targets should still emit error: [ref2] //~ERROR unresolved link to `ref2`
+/// Duplicate [ref2] //~ERROR unresolved link to `ref2`
+///
+/// [a]: ref
+//~^ ERROR unresolved link to `ref`
+/// [b]: ref2
+//~^ ERROR unresolved link to
+
+/// [ref][]
+//~^ ERROR unresolved link
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/reference-link-reports-error-once.stderr b/src/test/rustdoc-ui/reference-link-reports-error-once.stderr
new file mode 100644
index 0000000..218eb33
--- /dev/null
+++ b/src/test/rustdoc-ui/reference-link-reports-error-once.stderr
@@ -0,0 +1,63 @@
+error: unresolved link to `ref`
+  --> $DIR/reference-link-reports-error-once.rs:13:10
+   |
+LL | /// [a]: ref
+   |          ^^^ no item named `ref` in scope
+   |
+note: the lint level is defined here
+  --> $DIR/reference-link-reports-error-once.rs:1:9
+   |
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref2`
+  --> $DIR/reference-link-reports-error-once.rs:15:10
+   |
+LL | /// [b]: ref2
+   |          ^^^^ no item named `ref2` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref`
+  --> $DIR/reference-link-reports-error-once.rs:7:62
+   |
+LL | /// Other links to the same target should still emit error: [ref]
+   |                                                              ^^^ no item named `ref` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref`
+  --> $DIR/reference-link-reports-error-once.rs:8:16
+   |
+LL | /// Duplicate [ref]
+   |                ^^^ no item named `ref` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref2`
+  --> $DIR/reference-link-reports-error-once.rs:10:60
+   |
+LL | /// Other links to other targets should still emit error: [ref2]
+   |                                                            ^^^^ no item named `ref2` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref2`
+  --> $DIR/reference-link-reports-error-once.rs:11:16
+   |
+LL | /// Duplicate [ref2]
+   |                ^^^^ no item named `ref2` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref`
+  --> $DIR/reference-link-reports-error-once.rs:18:6
+   |
+LL | /// [ref][]
+   |      ^^^ no item named `ref` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/rustdoc-ui/reference-links.rs b/src/test/rustdoc-ui/reference-links.rs
index 7c1a797..6e00b9f 100644
--- a/src/test/rustdoc-ui/reference-links.rs
+++ b/src/test/rustdoc-ui/reference-links.rs
@@ -4,4 +4,3 @@
 //!
 //! [a]: std::process::Comman
 //~^ ERROR unresolved
-//~| ERROR unresolved
diff --git a/src/test/rustdoc-ui/reference-links.stderr b/src/test/rustdoc-ui/reference-links.stderr
index 6ba73fb..3df89df 100644
--- a/src/test/rustdoc-ui/reference-links.stderr
+++ b/src/test/rustdoc-ui/reference-links.stderr
@@ -10,11 +10,5 @@
 LL | #![deny(broken_intra_doc_links)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
-error: unresolved link to `std::process::Comman`
-  --> $DIR/reference-links.rs:5:10
-   |
-LL | //! [a]: std::process::Comman
-   |          ^^^^^^^^^^^^^^^^^^^^ no item named `Comman` in module `process`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/rustdoc/auxiliary/issue-34274.rs b/src/test/rustdoc/auxiliary/issue-34274.rs
index b0c3b4f..c466605 100644
--- a/src/test/rustdoc/auxiliary/issue-34274.rs
+++ b/src/test/rustdoc/auxiliary/issue-34274.rs
@@ -1,3 +1,3 @@
-extern {
+extern "C" {
     pub fn extern_c_fn();
 }
diff --git a/src/test/rustdoc/auxiliary/issue-61592.rs b/src/test/rustdoc/auxiliary/issue-61592.rs
new file mode 100644
index 0000000..6e16a4c
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/issue-61592.rs
@@ -0,0 +1,4 @@
+#![crate_name = "foo"]
+
+pub trait FooTrait {}
+pub struct FooStruct;
diff --git a/src/test/rustdoc/auxiliary/macro_pub_in_module.rs b/src/test/rustdoc/auxiliary/macro_pub_in_module.rs
new file mode 100644
index 0000000..137b123
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/macro_pub_in_module.rs
@@ -0,0 +1,13 @@
+// edition:2018
+
+#![feature(decl_macro)]
+#![crate_name = "external_crate"]
+
+pub mod some_module {
+    /* == Make sure the logic is not affected by a re-export == */
+    mod private {
+        pub macro external_macro() {}
+    }
+
+    pub use private::external_macro;
+}
diff --git a/src/test/rustdoc/deref-recursive-pathbuf.rs b/src/test/rustdoc/deref-recursive-pathbuf.rs
new file mode 100644
index 0000000..759e881
--- /dev/null
+++ b/src/test/rustdoc/deref-recursive-pathbuf.rs
@@ -0,0 +1,26 @@
+// ignore-tidy-linelength
+
+// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing
+// levels and across multiple crates.
+
+// @has 'foo/struct.Foo.html'
+// @has '-' '//*[@id="deref-methods-PathBuf"]' 'Methods from Deref<Target = PathBuf>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.as_path"]' 'pub fn as_path(&self)'
+// @has '-' '//*[@id="deref-methods-Path"]' 'Methods from Deref<Target = Path>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.exists"]' 'pub fn exists(&self)'
+// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods-PathBuf"]' 'Methods from Deref<Target=PathBuf>'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.as_path"]' 'as_path'
+// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods-Path"]' 'Methods from Deref<Target=Path>'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.exists"]' 'exists'
+
+#![crate_name = "foo"]
+
+use std::ops::Deref;
+use std::path::PathBuf;
+
+pub struct Foo(PathBuf);
+
+impl Deref for Foo {
+    type Target = PathBuf;
+    fn deref(&self) -> &PathBuf { &self.0 }
+}
diff --git a/src/test/rustdoc/deref-recursive.rs b/src/test/rustdoc/deref-recursive.rs
new file mode 100644
index 0000000..5aef87c
--- /dev/null
+++ b/src/test/rustdoc/deref-recursive.rs
@@ -0,0 +1,42 @@
+// ignore-tidy-linelength
+
+// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing
+// levels if needed.
+
+// @has 'foo/struct.Foo.html'
+// @has '-' '//*[@id="deref-methods-Bar"]' 'Methods from Deref<Target = Bar>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.bar"]' 'pub fn bar(&self)'
+// @has '-' '//*[@id="deref-methods-Baz"]' 'Methods from Deref<Target = Baz>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.baz"]' 'pub fn baz(&self)'
+// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods-Bar"]' 'Methods from Deref<Target=Bar>'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.bar"]' 'bar'
+// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods-Baz"]' 'Methods from Deref<Target=Baz>'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.baz"]' 'baz'
+
+#![crate_name = "foo"]
+
+use std::ops::Deref;
+
+pub struct Foo(Bar);
+pub struct Bar(Baz);
+pub struct Baz;
+
+impl Deref for Foo {
+    type Target = Bar;
+    fn deref(&self) -> &Bar { &self.0 }
+}
+
+impl Deref for Bar {
+    type Target = Baz;
+    fn deref(&self) -> &Baz { &self.0 }
+}
+
+impl Bar {
+    /// This appears under `Foo` methods
+    pub fn bar(&self) {}
+}
+
+impl Baz {
+    /// This should also appear in `Foo` methods when recursing
+    pub fn baz(&self) {}
+}
diff --git a/src/test/rustdoc/deref-typedef.rs b/src/test/rustdoc/deref-typedef.rs
index 770f8d7..589f133 100644
--- a/src/test/rustdoc/deref-typedef.rs
+++ b/src/test/rustdoc/deref-typedef.rs
@@ -1,18 +1,29 @@
+// ignore-tidy-linelength
+
 #![crate_name = "foo"]
 
 // @has 'foo/struct.Bar.html'
-// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooC>'
+// @has '-' '//*[@id="deref-methods-FooJ"]' 'Methods from Deref<Target = FooJ>'
 // @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="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)'
+// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods-FooJ"]' 'Methods from Deref<Target=FooJ>'
 // @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'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_j"]' 'foo_j'
 
 pub struct FooA;
 pub type FooB = FooA;
 pub type FooC = FooB;
+pub type FooD = FooC;
+pub type FooE = FooD;
+pub type FooF = FooE;
+pub type FooG = FooF;
+pub type FooH = FooG;
+pub type FooI = FooH;
+pub type FooJ = FooI;
 
 impl FooA {
     pub fn foo_a(&self) {}
@@ -26,8 +37,12 @@
     pub fn foo_c(&self) {}
 }
 
+impl FooJ {
+    pub fn foo_j(&self) {}
+}
+
 pub struct Bar;
 impl std::ops::Deref for Bar {
-    type Target = FooC;
+    type Target = FooJ;
     fn deref(&self) -> &Self::Target { unimplemented!() }
 }
diff --git a/src/test/rustdoc/foreigntype-reexport.rs b/src/test/rustdoc/foreigntype-reexport.rs
index 616826c..1dec0ef 100644
--- a/src/test/rustdoc/foreigntype-reexport.rs
+++ b/src/test/rustdoc/foreigntype-reexport.rs
@@ -1,7 +1,7 @@
 #![feature(extern_types)]
 
 mod sub {
-    extern {
+    extern "C" {
         /// Another extern type.
         pub type C2;
         pub fn f2();
@@ -10,7 +10,7 @@
 }
 
 pub mod sub2 {
-    extern {
+    extern "C" {
         // @has foreigntype_reexport/sub2/foreigntype.C.html
         pub type C;
         // @has foreigntype_reexport/sub2/fn.f.html
@@ -21,7 +21,7 @@
 }
 
 mod sub3 {
-    extern {
+    extern "C" {
         pub type C4;
         pub fn f4();
         pub static K4: usize;
@@ -35,7 +35,7 @@
 // @has foreigntype_reexport/index.html '//a[@class="foreigntype"]' 'C2'
 // @has foreigntype_reexport/index.html '//a[@class="fn"]' 'f2'
 // @has foreigntype_reexport/index.html '//a[@class="static"]' 'K2'
-pub use self::sub::{C2, f2, K as K2};
+pub use self::sub::{f2, C2, K as K2};
 
 // @has foreigntype_reexport/index.html '//a[@class="foreigntype"]' 'C'
 // @has foreigntype_reexport/index.html '//a[@class="fn"]' 'f'
@@ -43,7 +43,7 @@
 // @has foreigntype_reexport/index.html '//code' 'pub use self::sub2::C as C3;'
 // @has foreigntype_reexport/index.html '//code' 'pub use self::sub2::f as f3;'
 // @has foreigntype_reexport/index.html '//code' 'pub use self::sub2::K3;'
-pub use self::sub2::{C as C3, f as f3, K3};
+pub use self::sub2::{f as f3, C as C3, K3};
 
 // @has foreigntype_reexport/foreigntype.C4.html
 // @has foreigntype_reexport/fn.f4.html
diff --git a/src/test/rustdoc/foreigntype.rs b/src/test/rustdoc/foreigntype.rs
index bd8766c..891cdd5 100644
--- a/src/test/rustdoc/foreigntype.rs
+++ b/src/test/rustdoc/foreigntype.rs
@@ -1,6 +1,6 @@
 #![feature(extern_types)]
 
-extern {
+extern "C" {
     // @has foreigntype/foreigntype.ExtType.html
     pub type ExtType;
 }
diff --git a/src/test/rustdoc/inline_local/glob-extern-no-defaults.rs b/src/test/rustdoc/inline_local/glob-extern-no-defaults.rs
index 276e409..55c75df 100644
--- a/src/test/rustdoc/inline_local/glob-extern-no-defaults.rs
+++ b/src/test/rustdoc/inline_local/glob-extern-no-defaults.rs
@@ -3,7 +3,7 @@
 #![crate_name = "foo"]
 
 mod mod1 {
-    extern {
+    extern "C" {
         pub fn public_fn();
         fn private_fn();
     }
diff --git a/src/test/rustdoc/inline_local/glob-extern.rs b/src/test/rustdoc/inline_local/glob-extern.rs
index a23ec36..686e55d 100644
--- a/src/test/rustdoc/inline_local/glob-extern.rs
+++ b/src/test/rustdoc/inline_local/glob-extern.rs
@@ -1,7 +1,7 @@
 #![crate_name = "foo"]
 
 mod mod1 {
-    extern {
+    extern "C" {
         pub fn public_fn();
         fn private_fn();
     }
diff --git a/src/test/rustdoc/inline_local/trait-vis.rs b/src/test/rustdoc/inline_local/trait-vis.rs
index a997d1e..a9b54fb 100644
--- a/src/test/rustdoc/inline_local/trait-vis.rs
+++ b/src/test/rustdoc/inline_local/trait-vis.rs
@@ -14,5 +14,5 @@
 
 // @has trait_vis/struct.SomeStruct.html
 // @has - '//code' 'impl ThisTrait for SomeStruct'
-// !@has - '//code' 'impl PrivateTrait for SomeStruct'
+// @!has - '//code' 'impl PrivateTrait for SomeStruct'
 pub use asdf::SomeStruct;
diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/self.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/self.rs
index cdfe842..54902f1 100644
--- a/src/test/rustdoc/intra-doc-crate/auxiliary/self.rs
+++ b/src/test/rustdoc/intra-doc-crate/auxiliary/self.rs
@@ -1,4 +1,7 @@
 #![crate_name = "cross_crate_self"]
+
+/// Link to [Self]
+/// Link to [crate]
 pub struct S;
 
 impl S {
diff --git a/src/test/rustdoc/intra-doc-crate/self.rs b/src/test/rustdoc/intra-doc-crate/self.rs
index 62aef8e..4db63b1 100644
--- a/src/test/rustdoc/intra-doc-crate/self.rs
+++ b/src/test/rustdoc/intra-doc-crate/self.rs
@@ -1,6 +1,9 @@
 // aux-build:self.rs
+// build-aux-docs
 
 extern crate cross_crate_self;
 
 // @has self/struct.S.html '//a[@href="../self/struct.S.html#method.f"]' "Self::f"
+// @has self/struct.S.html '//a[@href="../self/struct.S.html"]' "Self"
+// @has self/struct.S.html '//a[@href="../cross_crate_self/index.html"]' "crate"
 pub use cross_crate_self::S;
diff --git a/src/test/rustdoc/intra-doc/non-path-primitives.rs b/src/test/rustdoc/intra-doc/non-path-primitives.rs
index ad4f6dd..2c7e7b5 100644
--- a/src/test/rustdoc/intra-doc/non-path-primitives.rs
+++ b/src/test/rustdoc/intra-doc/non-path-primitives.rs
@@ -8,14 +8,21 @@
 // @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.array.html#method.map"]' 'array::map'
 //! [array::map]
 
+// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'owned str'
+// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'str ref'
+// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.is_empty"]' 'str::is_empty'
+// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.len"]' '&str::len'
+//! [owned str][str]
+//! [str ref][&str]
+//! [str::is_empty]
+//! [&str::len]
+
 // @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' 'pointer::is_null'
 // @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' '*const::is_null'
 // @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' '*mut::is_null'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' '*::is_null'
 //! [pointer::is_null]
 //! [*const::is_null]
 //! [*mut::is_null]
-//! [*::is_null]
 
 // @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.unit.html"]' 'unit'
 //! [unit]
diff --git a/src/test/rustdoc/intra-doc/primitive-disambiguators.rs b/src/test/rustdoc/intra-doc/primitive-disambiguators.rs
new file mode 100644
index 0000000..acdd075
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/primitive-disambiguators.rs
@@ -0,0 +1,4 @@
+#![deny(broken_intra_doc_links)]
+// @has primitive_disambiguators/index.html
+// @has - '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim'
+//! [str::trim()]
diff --git a/src/test/rustdoc/issue-22038.rs b/src/test/rustdoc/issue-22038.rs
index 2db42b5..ff5813d 100644
--- a/src/test/rustdoc/issue-22038.rs
+++ b/src/test/rustdoc/issue-22038.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     // @has issue_22038/fn.foo1.html \
     //      '//*[@class="rust fn"]' 'pub unsafe extern "C" fn foo1()'
     pub fn foo1();
@@ -12,7 +12,7 @@
 
 // @has issue_22038/fn.bar.html \
 //      '//*[@class="rust fn"]' 'pub extern "C" fn bar()'
-pub extern fn bar() {}
+pub extern "C" fn bar() {}
 
 // @has issue_22038/fn.baz.html \
 //      '//*[@class="rust fn"]' 'pub extern "system" fn baz()'
diff --git a/src/test/rustdoc/issue-61592.rs b/src/test/rustdoc/issue-61592.rs
new file mode 100644
index 0000000..aef038c
--- /dev/null
+++ b/src/test/rustdoc/issue-61592.rs
@@ -0,0 +1,15 @@
+// aux-build:issue-61592.rs
+
+extern crate foo;
+
+// @has issue_61592/index.html
+// @has - '//a[@href="#reexports"]' 'Re-exports'
+// @has - '//code' 'pub use foo::FooTrait as _;'
+// @!has - '//a[@href="trait._.html"]'
+pub use foo::FooTrait as _;
+
+// @has issue_61592/index.html
+// @has - '//a[@href="#reexports"]' 'Re-exports'
+// @has - '//code' 'pub use foo::FooStruct as _;'
+// @!has - '//a[@href="struct._.html"]'
+pub use foo::FooStruct as _;
diff --git a/src/test/rustdoc/issue-74083.rs b/src/test/rustdoc/issue-74083.rs
index 28585da..c7f5d7e 100644
--- a/src/test/rustdoc/issue-74083.rs
+++ b/src/test/rustdoc/issue-74083.rs
@@ -7,7 +7,7 @@
 }
 
 // @has issue_74083/struct.Bar.html
-// !@has - '//div[@class="sidebar-links"]/a[@href="#method.foo"]' 'foo'
+// @!has - '//div[@class="sidebar-links"]/a[@href="#method.foo"]' 'foo'
 pub struct Bar {
     foo: Foo,
 }
diff --git a/src/test/rustdoc/issue-80233-normalize-auto-trait.rs b/src/test/rustdoc/issue-80233-normalize-auto-trait.rs
new file mode 100644
index 0000000..585a086
--- /dev/null
+++ b/src/test/rustdoc/issue-80233-normalize-auto-trait.rs
@@ -0,0 +1,37 @@
+// Regression test for issue #80233
+// Tests that we don't ICE when processing auto traits
+
+#![crate_type = "lib"]
+pub trait Trait1 {}
+
+pub trait Trait2 {
+    type Type2;
+}
+
+pub trait Trait3 {
+    type Type3;
+}
+
+impl Trait2 for Struct1 {
+    type Type2 = Struct1;
+}
+
+impl<I: Trait2> Trait2 for Vec<I> {
+    type Type2 = Vec<I::Type2>;
+}
+
+impl<T: Trait1> Trait3 for T {
+    type Type3 = Struct1;
+}
+
+impl<T: Trait3> Trait3 for Vec<T> {
+    type Type3 = Vec<T::Type3>;
+}
+
+pub struct Struct1 {}
+
+// @has issue_80233_normalize_auto_trait/struct.Question.html
+// @has - '//code' 'impl<T> Send for Question<T>'
+pub struct Question<T: Trait1> {
+    pub ins: <<Vec<T> as Trait3>::Type3 as Trait2>::Type2,
+}
diff --git a/src/test/rustdoc/issue-80893.rs b/src/test/rustdoc/issue-80893.rs
new file mode 100644
index 0000000..7c958a8
--- /dev/null
+++ b/src/test/rustdoc/issue-80893.rs
@@ -0,0 +1,6 @@
+// compile-flags: --test -Z unstable-options --test-builder true
+
+/// ```no_run
+/// This tests that `--test-builder` is accepted as a flag by rustdoc.
+/// ```
+pub struct Foo;
diff --git a/src/test/rustdoc/macro_pub_in_module.rs b/src/test/rustdoc/macro_pub_in_module.rs
new file mode 100644
index 0000000..4fd85d6
--- /dev/null
+++ b/src/test/rustdoc/macro_pub_in_module.rs
@@ -0,0 +1,82 @@
+// aux-build:macro_pub_in_module.rs
+// edition:2018
+// build-aux-docs
+
+//! See issue #74355
+#![feature(decl_macro, no_core, rustc_attrs)]
+#![crate_name = "krate"]
+#![no_core]
+
+ // @has external_crate/some_module/macro.external_macro.html
+  // @!has external_crate/macro.external_macro.html
+extern crate external_crate;
+
+pub mod inner {
+    // @has krate/inner/macro.raw_const.html
+    // @!has krate/macro.raw_const.html
+    pub macro raw_const() {}
+
+    // @has krate/inner/macro.test.html
+    // @!has krate/macro.test.html
+    #[rustc_builtin_macro]
+    pub macro test($item:item) {}
+
+    // @has krate/inner/macro.Clone.html
+    // @!has krate/macro.Clone.html
+    #[rustc_builtin_macro]
+    pub macro Clone($item:item) {}
+
+    // Make sure the logic is not affected by re-exports.
+    mod unrenamed {
+        // @!has krate/macro.unrenamed.html
+        #[rustc_macro_transparency = "semitransparent"]
+        pub macro unrenamed() {}
+    }
+    // @has krate/inner/macro.unrenamed.html
+    pub use unrenamed::unrenamed;
+
+    mod private {
+        // @!has krate/macro.m.html
+        pub macro m() {}
+    }
+    // @has krate/inner/macro.renamed.html
+    // @!has krate/macro.renamed.html
+    pub use private::m as renamed;
+
+    mod private2 {
+        // @!has krate/macro.m2.html
+        pub macro m2() {}
+    }
+    use private2 as renamed_mod;
+    // @has krate/inner/macro.m2.html
+    pub use renamed_mod::m2;
+
+    // @has krate/inner/macro.external_macro.html
+    // @!has krate/macro.external_macro.html
+    pub use ::external_crate::some_module::external_macro;
+}
+
+// Namespaces: Make sure the logic does not mix up a function name with a module name…
+fn both_fn_and_mod() {
+    // @!has krate/macro.in_both_fn_and_mod.html
+    pub macro in_both_fn_and_mod() {}
+}
+pub mod both_fn_and_mod {
+    // @!has krate/both_fn_and_mod/macro.in_both_fn_and_mod.html
+}
+
+const __: () = {
+    // @!has krate/macro.in_both_const_and_mod.html
+    pub macro in_both_const_and_mod() {}
+};
+pub mod __ {
+    // @!has krate/__/macro.in_both_const_and_mod.html
+}
+
+enum Enum {
+    Crazy = {
+        // @!has krate/macro.this_is_getting_weird.html;
+        pub macro this_is_getting_weird() {}
+        42
+    },
+}
diff --git a/src/test/rustdoc/macros.rs b/src/test/rustdoc/macros.rs
index fb4f02a..ae0cf7a 100644
--- a/src/test/rustdoc/macros.rs
+++ b/src/test/rustdoc/macros.rs
@@ -8,3 +8,17 @@
     ($a:tt) => ();
     ($e:expr) => {};
 }
+
+// Check that exported macro defined in a module are shown at crate root.
+// @has macros/macro.my_sub_macro.html //pre 'macro_rules! my_sub_macro {'
+// @has - //pre '() => { ... };'
+// @has - //pre '($a:tt) => { ... };'
+// @has - //pre '($e:expr) => { ... };'
+mod sub {
+    #[macro_export]
+    macro_rules! my_sub_macro {
+        () => {};
+        ($a:tt) => {};
+        ($e:expr) => {};
+    }
+}
diff --git a/src/test/rustdoc/pub-restricted.rs b/src/test/rustdoc/pub-restricted.rs
deleted file mode 100644
index 6720d84..0000000
--- a/src/test/rustdoc/pub-restricted.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-// compile-flags: --document-private-items
-
-#![feature(crate_visibility_modifier)]
-
-#![crate_name = "foo"]
-
-// @has 'foo/struct.FooPublic.html' '//pre' 'pub struct FooPublic'
-pub struct FooPublic;
-// @has 'foo/struct.FooJustCrate.html' '//pre' 'pub(crate) struct FooJustCrate'
-crate struct FooJustCrate;
-// @has 'foo/struct.FooPubCrate.html' '//pre' 'pub(crate) struct FooPubCrate'
-pub(crate) struct FooPubCrate;
-// @has 'foo/struct.FooSelf.html' '//pre' 'pub(crate) struct FooSelf'
-pub(self) struct FooSelf;
-// @has 'foo/struct.FooInSelf.html' '//pre' 'pub(crate) struct FooInSelf'
-pub(in self) struct FooInSelf;
-mod a {
-    // @has 'foo/a/struct.FooSuper.html' '//pre' 'pub(crate) struct FooSuper'
-    pub(super) struct FooSuper;
-    // @has 'foo/a/struct.FooInSuper.html' '//pre' 'pub(crate) struct FooInSuper'
-    pub(in super) struct FooInSuper;
-    // @has 'foo/a/struct.FooInA.html' '//pre' 'pub(in a) struct FooInA'
-    pub(in a) struct FooInA;
-    mod b {
-        // @has 'foo/a/b/struct.FooInSelfSuperB.html' '//pre' 'pub(in a::b) struct FooInSelfSuperB'
-        pub(in a::b) struct FooInSelfSuperB;
-        // @has 'foo/a/b/struct.FooInSuperSuper.html' '//pre' 'pub(crate) struct FooInSuperSuper'
-        pub(in super::super) struct FooInSuperSuper;
-        // @has 'foo/a/b/struct.FooInAB.html' '//pre' 'pub(in a::b) struct FooInAB'
-        pub(in a::b) struct FooInAB;
-    }
-}
diff --git a/src/test/rustdoc/range-arg-pattern.rs b/src/test/rustdoc/range-arg-pattern.rs
new file mode 100644
index 0000000..f4cc36b
--- /dev/null
+++ b/src/test/rustdoc/range-arg-pattern.rs
@@ -0,0 +1,5 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.f.html
+// @has - '//*[@class="rust fn"]' 'pub fn f(0u8 ...255: u8)'
+pub fn f(0u8...255: u8) {}
diff --git a/src/test/rustdoc/remove-url-from-headings.rs b/src/test/rustdoc/remove-url-from-headings.rs
index 9761c1d..e2b232a 100644
--- a/src/test/rustdoc/remove-url-from-headings.rs
+++ b/src/test/rustdoc/remove-url-from-headings.rs
@@ -1,7 +1,7 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.foo.html
-// !@has - '//a[@href="http://a.a"]'
+// @!has - '//a[@href="http://a.a"]'
 // @has - '//a[@href="#implementing-stuff-somewhere"]' 'Implementing stuff somewhere'
 // @has - '//a[@href="#another-one-urg"]' 'Another one urg'
 
diff --git a/src/test/rustdoc/sanitizer-option.rs b/src/test/rustdoc/sanitizer-option.rs
index a79b37e..1abba46 100644
--- a/src/test/rustdoc/sanitizer-option.rs
+++ b/src/test/rustdoc/sanitizer-option.rs
@@ -7,7 +7,7 @@
 // correctly, then linking will fail.
 
 /// ```
-/// extern {
+/// extern "C" {
 ///     fn __sanitizer_print_stack_trace();
 /// }
 ///
diff --git a/src/test/rustdoc/titles.rs b/src/test/rustdoc/titles.rs
index 3b4c42d..2084e85 100644
--- a/src/test/rustdoc/titles.rs
+++ b/src/test/rustdoc/titles.rs
@@ -7,7 +7,7 @@
     pub struct __Thing {}
 }
 
-extern {
+extern "C" {
     // @matches 'foo/fn.foo_ffn.html' '//h1' 'Function foo::foo_ffn'
     pub fn foo_ffn();
 }
@@ -30,7 +30,7 @@
 // @matches 'foo/macro.foo_macro.html' '//h1' 'Macro foo::foo_macro'
 #[macro_export]
 macro_rules! foo_macro {
-    () => ();
+    () => {};
 }
 
 // @matches 'foo/primitive.bool.html' '//h1' 'Primitive Type bool'
@@ -40,7 +40,7 @@
 // @matches 'foo/static.FOO_STATIC.html' '//h1' 'Static foo::FOO_STATIC'
 pub static FOO_STATIC: FooStruct = FooStruct;
 
-extern {
+extern "C" {
     // @matches 'foo/static.FOO_FSTATIC.html' '//h1' 'Static foo::FOO_FSTATIC'
     pub static FOO_FSTATIC: FooStruct;
 }
diff --git a/src/test/rustdoc/visibility.rs b/src/test/rustdoc/visibility.rs
new file mode 100644
index 0000000..5942769
--- /dev/null
+++ b/src/test/rustdoc/visibility.rs
@@ -0,0 +1,44 @@
+// compile-flags: --document-private-items
+
+#![feature(crate_visibility_modifier)]
+
+#![crate_name = "foo"]
+
+// @has 'foo/struct.FooPublic.html' '//pre' 'pub struct FooPublic'
+pub struct FooPublic;
+// @has 'foo/struct.FooJustCrate.html' '//pre' 'pub(crate) struct FooJustCrate'
+crate struct FooJustCrate;
+// @has 'foo/struct.FooPubCrate.html' '//pre' 'pub(crate) struct FooPubCrate'
+pub(crate) struct FooPubCrate;
+// @has 'foo/struct.FooSelf.html' '//pre' 'pub(crate) struct FooSelf'
+pub(self) struct FooSelf;
+// @has 'foo/struct.FooInSelf.html' '//pre' 'pub(crate) struct FooInSelf'
+pub(in self) struct FooInSelf;
+// @has 'foo/struct.FooPriv.html' '//pre' 'pub(crate) struct FooPriv'
+struct FooPriv;
+
+mod a {
+    // @has 'foo/a/struct.FooASuper.html' '//pre' 'pub(crate) struct FooASuper'
+    pub(super) struct FooASuper;
+    // @has 'foo/a/struct.FooAInSuper.html' '//pre' 'pub(crate) struct FooAInSuper'
+    pub(in super) struct FooAInSuper;
+    // @has 'foo/a/struct.FooAInA.html' '//pre' 'struct FooAInA'
+    // @!has 'foo/a/struct.FooAInA.html' '//pre' 'pub'
+    pub(in a) struct FooAInA;
+    // @has 'foo/a/struct.FooAPriv.html' '//pre' 'struct FooAPriv'
+    // @!has 'foo/a/struct.FooAPriv.html' '//pre' 'pub'
+    struct FooAPriv;
+
+    mod b {
+        // @has 'foo/a/b/struct.FooBSuper.html' '//pre' 'pub(super) struct FooBSuper'
+        pub(super) struct FooBSuper;
+        // @has 'foo/a/b/struct.FooBInSuperSuper.html' '//pre' 'pub(crate) struct FooBInSuperSuper'
+        pub(in super::super) struct FooBInSuperSuper;
+        // @has 'foo/a/b/struct.FooBInAB.html' '//pre' 'struct FooBInAB'
+        // @!has 'foo/a/b/struct.FooBInAB.html' '//pre' 'pub'
+        pub(in a::b) struct FooBInAB;
+        // @has 'foo/a/b/struct.FooBPriv.html' '//pre' 'struct FooBPriv'
+        // @!has 'foo/a/b/struct.FooBPriv.html' '//pre' 'pub'
+        struct FooBPriv;
+    }
+}
diff --git a/src/test/ui-fulldeps/switch-stdout.rs b/src/test/ui-fulldeps/switch-stdout.rs
index e105637..e9501a8 100644
--- a/src/test/ui-fulldeps/switch-stdout.rs
+++ b/src/test/ui-fulldeps/switch-stdout.rs
@@ -9,7 +9,7 @@
 fn switch_stdout_to(file: File) {
     use std::os::unix::prelude::*;
 
-    extern {
+    extern "C" {
         fn dup2(old: i32, new: i32) -> i32;
     }
 
@@ -29,8 +29,7 @@
     const STD_OUTPUT_HANDLE: u32 = (-11i32) as u32;
 
     unsafe {
-        let rc = SetStdHandle(STD_OUTPUT_HANDLE,
-                              file.into_raw_handle() as *mut _);
+        let rc = SetStdHandle(STD_OUTPUT_HANDLE, file.into_raw_handle() as *mut _);
         assert!(rc != 0);
     }
 }
diff --git a/src/test/ui/abi/anon-extern-mod.rs b/src/test/ui/abi/anon-extern-mod.rs
index 37a6787..6c7d60d 100644
--- a/src/test/ui/abi/anon-extern-mod.rs
+++ b/src/test/ui/abi/anon-extern-mod.rs
@@ -7,7 +7,7 @@
 extern crate libc;
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     fn rust_get_test_int() -> libc::intptr_t;
 }
 
diff --git a/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs
index 948b5e6..5cbf809 100644
--- a/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs
+++ b/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs
@@ -1,9 +1,9 @@
-#![crate_name="anonexternmod"]
+#![crate_name = "anonexternmod"]
 #![feature(rustc_private)]
 
 extern crate libc;
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_get_test_int() -> libc::intptr_t;
 }
diff --git a/src/test/ui/abi/auxiliary/foreign_lib.rs b/src/test/ui/abi/auxiliary/foreign_lib.rs
index de6b0e2..3c649b7 100644
--- a/src/test/ui/abi/auxiliary/foreign_lib.rs
+++ b/src/test/ui/abi/auxiliary/foreign_lib.rs
@@ -1,12 +1,11 @@
-#![crate_name="foreign_lib"]
-
+#![crate_name = "foreign_lib"]
 #![feature(rustc_private)]
 
 pub mod rustrt {
     extern crate libc;
 
     #[link(name = "rust_test_helpers", kind = "static")]
-    extern {
+    extern "C" {
         pub fn rust_get_test_int() -> libc::intptr_t;
     }
 }
@@ -14,7 +13,7 @@
 pub mod rustrt2 {
     extern crate libc;
 
-    extern {
+    extern "C" {
         pub fn rust_get_test_int() -> libc::intptr_t;
     }
 }
@@ -24,7 +23,7 @@
     // Ensures that we don't ICE or trigger LLVM asserts when
     // importing the same symbol under different types.
     // See https://github.com/rust-lang/rust/issues/32740.
-    extern {
+    extern "C" {
         pub fn rust_get_test_int() -> *const u8;
     }
 }
diff --git a/src/test/ui/abi/c-stack-as-value.rs b/src/test/ui/abi/c-stack-as-value.rs
index 7595b76..5bece0b 100644
--- a/src/test/ui/abi/c-stack-as-value.rs
+++ b/src/test/ui/abi/c-stack-as-value.rs
@@ -8,7 +8,7 @@
     extern crate libc;
 
     #[link(name = "rust_test_helpers", kind = "static")]
-    extern {
+    extern "C" {
         pub fn rust_get_test_int() -> libc::intptr_t;
     }
 }
diff --git a/src/test/ui/abi/cabi-int-widening.rs b/src/test/ui/abi/cabi-int-widening.rs
index 240eaeb..1dbab27 100644
--- a/src/test/ui/abi/cabi-int-widening.rs
+++ b/src/test/ui/abi/cabi-int-widening.rs
@@ -2,7 +2,7 @@
 // ignore-wasm32-bare no libc to test ffi with
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     fn rust_int8_to_int32(_: i8) -> i32;
 }
 
diff --git a/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs
index 948b5e6..5cbf809 100644
--- a/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs
+++ b/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs
@@ -1,9 +1,9 @@
-#![crate_name="anonexternmod"]
+#![crate_name = "anonexternmod"]
 #![feature(rustc_private)]
 
 extern crate libc;
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_get_test_int() -> libc::intptr_t;
 }
diff --git a/src/test/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs
index 948b5e6..5cbf809 100644
--- a/src/test/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs
+++ b/src/test/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs
@@ -1,9 +1,9 @@
-#![crate_name="anonexternmod"]
+#![crate_name = "anonexternmod"]
 #![feature(rustc_private)]
 
 extern crate libc;
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_get_test_int() -> libc::intptr_t;
 }
diff --git a/src/test/ui/abi/extern/auxiliary/extern-crosscrate-source.rs b/src/test/ui/abi/extern/auxiliary/extern-crosscrate-source.rs
index d4568d3..9c61518 100644
--- a/src/test/ui/abi/extern/auxiliary/extern-crosscrate-source.rs
+++ b/src/test/ui/abi/extern/auxiliary/extern-crosscrate-source.rs
@@ -1,4 +1,4 @@
-#![crate_name="externcallback"]
+#![crate_name = "externcallback"]
 #![crate_type = "lib"]
 #![feature(rustc_private)]
 
@@ -8,10 +8,11 @@
     extern crate libc;
 
     #[link(name = "rust_test_helpers", kind = "static")]
-    extern {
-        pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
-                             data: libc::uintptr_t)
-                             -> libc::uintptr_t;
+    extern "C" {
+        pub fn rust_dbg_call(
+            cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
+            data: libc::uintptr_t,
+        ) -> libc::uintptr_t;
     }
 }
 
@@ -22,10 +23,6 @@
     }
 }
 
-pub extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
-    if data == 1 {
-        data
-    } else {
-        fact(data - 1) * data
-    }
+pub extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
+    if data == 1 { data } else { fact(data - 1) * data }
 }
diff --git a/src/test/ui/abi/extern/extern-call-deep.rs b/src/test/ui/abi/extern/extern-call-deep.rs
index 81f884d..db5f2ca 100644
--- a/src/test/ui/abi/extern/extern-call-deep.rs
+++ b/src/test/ui/abi/extern/extern-call-deep.rs
@@ -10,19 +10,16 @@
     extern crate libc;
 
     #[link(name = "rust_test_helpers", kind = "static")]
-    extern {
-        pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
-                             data: libc::uintptr_t)
-                             -> libc::uintptr_t;
+    extern "C" {
+        pub fn rust_dbg_call(
+            cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
+            data: libc::uintptr_t,
+        ) -> libc::uintptr_t;
     }
 }
 
-extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
-    if data == 1 {
-        data
-    } else {
-        count(data - 1) + 1
-    }
+extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
+    if data == 1 { data } else { count(data - 1) + 1 }
 }
 
 fn count(n: libc::uintptr_t) -> libc::uintptr_t {
diff --git a/src/test/ui/abi/extern/extern-call-deep2.rs b/src/test/ui/abi/extern/extern-call-deep2.rs
index b31489b..60e8db1 100644
--- a/src/test/ui/abi/extern/extern-call-deep2.rs
+++ b/src/test/ui/abi/extern/extern-call-deep2.rs
@@ -1,7 +1,6 @@
 // run-pass
 #![allow(unused_must_use)]
 // ignore-emscripten no threads support
-
 #![feature(rustc_private)]
 
 extern crate libc;
@@ -11,19 +10,16 @@
     extern crate libc;
 
     #[link(name = "rust_test_helpers", kind = "static")]
-    extern {
-        pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
-                             data: libc::uintptr_t)
-                             -> libc::uintptr_t;
+    extern "C" {
+        pub fn rust_dbg_call(
+            cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
+            data: libc::uintptr_t,
+        ) -> libc::uintptr_t;
     }
 }
 
-extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
-    if data == 1 {
-        data
-    } else {
-        count(data - 1) + 1
-    }
+extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
+    if data == 1 { data } else { count(data - 1) + 1 }
 }
 
 fn count(n: libc::uintptr_t) -> libc::uintptr_t {
@@ -36,9 +32,10 @@
 pub fn main() {
     // Make sure we're on a thread with small Rust stacks (main currently
     // has a large stack)
-    thread::spawn(move|| {
+    thread::spawn(move || {
         let result = count(1000);
         println!("result = {}", result);
         assert_eq!(result, 1000);
-    }).join();
+    })
+    .join();
 }
diff --git a/src/test/ui/abi/extern/extern-call-direct.rs b/src/test/ui/abi/extern/extern-call-direct.rs
index 7204176..19b901d 100644
--- a/src/test/ui/abi/extern/extern-call-direct.rs
+++ b/src/test/ui/abi/extern/extern-call-direct.rs
@@ -2,7 +2,7 @@
 // Test direct calls to extern fns.
 
 
-extern fn f(x: usize) -> usize { x * 2 }
+extern "C" fn f(x: usize) -> usize { x * 2 }
 
 pub fn main() {
     let x = f(22);
diff --git a/src/test/ui/abi/extern/extern-call-indirect.rs b/src/test/ui/abi/extern/extern-call-indirect.rs
index 158b54e..886e8f6 100644
--- a/src/test/ui/abi/extern/extern-call-indirect.rs
+++ b/src/test/ui/abi/extern/extern-call-indirect.rs
@@ -9,19 +9,16 @@
     extern crate libc;
 
     #[link(name = "rust_test_helpers", kind = "static")]
-    extern {
-        pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
-                             data: libc::uintptr_t)
-                             -> libc::uintptr_t;
+    extern "C" {
+        pub fn rust_dbg_call(
+            cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
+            data: libc::uintptr_t,
+        ) -> libc::uintptr_t;
     }
 }
 
-extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
-    if data == 1 {
-        data
-    } else {
-        fact(data - 1) * data
-    }
+extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
+    if data == 1 { data } else { fact(data - 1) * data }
 }
 
 fn fact(n: libc::uintptr_t) -> libc::uintptr_t {
diff --git a/src/test/ui/abi/extern/extern-call-scrub.rs b/src/test/ui/abi/extern/extern-call-scrub.rs
index a7b1065..ff33cf3 100644
--- a/src/test/ui/abi/extern/extern-call-scrub.rs
+++ b/src/test/ui/abi/extern/extern-call-scrub.rs
@@ -5,7 +5,6 @@
 // directions
 
 // ignore-emscripten no threads support
-
 #![feature(rustc_private)]
 
 extern crate libc;
@@ -15,19 +14,16 @@
     extern crate libc;
 
     #[link(name = "rust_test_helpers", kind = "static")]
-    extern {
-        pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
-                             data: libc::uintptr_t)
-                             -> libc::uintptr_t;
+    extern "C" {
+        pub fn rust_dbg_call(
+            cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
+            data: libc::uintptr_t,
+        ) -> libc::uintptr_t;
     }
 }
 
-extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
-    if data == 1 {
-        data
-    } else {
-        count(data - 1) + count(data - 1)
-    }
+extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
+    if data == 1 { data } else { count(data - 1) + count(data - 1) }
 }
 
 fn count(n: libc::uintptr_t) -> libc::uintptr_t {
@@ -40,9 +36,10 @@
 pub fn main() {
     // Make sure we're on a thread with small Rust stacks (main currently
     // has a large stack)
-    thread::spawn(move|| {
+    thread::spawn(move || {
         let result = count(12);
         println!("result = {}", result);
         assert_eq!(result, 2048);
-    }).join();
+    })
+    .join();
 }
diff --git a/src/test/ui/abi/extern/extern-pass-TwoU16s.rs b/src/test/ui/abi/extern/extern-pass-TwoU16s.rs
index 285bce2..cff2551 100644
--- a/src/test/ui/abi/extern/extern-pass-TwoU16s.rs
+++ b/src/test/ui/abi/extern/extern-pass-TwoU16s.rs
@@ -8,17 +8,18 @@
 
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub struct TwoU16s {
-    one: u16, two: u16
+    one: u16,
+    two: u16,
 }
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s;
 }
 
 pub fn main() {
     unsafe {
-        let x = TwoU16s {one: 22, two: 23};
+        let x = TwoU16s { one: 22, two: 23 };
         let y = rust_dbg_extern_identity_TwoU16s(x);
         assert_eq!(x, y);
     }
diff --git a/src/test/ui/abi/extern/extern-pass-TwoU32s.rs b/src/test/ui/abi/extern/extern-pass-TwoU32s.rs
index fb18aa8..03a8ecf 100644
--- a/src/test/ui/abi/extern/extern-pass-TwoU32s.rs
+++ b/src/test/ui/abi/extern/extern-pass-TwoU32s.rs
@@ -8,17 +8,18 @@
 
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub struct TwoU32s {
-    one: u32, two: u32
+    one: u32,
+    two: u32,
 }
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s;
 }
 
 pub fn main() {
     unsafe {
-        let x = TwoU32s {one: 22, two: 23};
+        let x = TwoU32s { one: 22, two: 23 };
         let y = rust_dbg_extern_identity_TwoU32s(x);
         assert_eq!(x, y);
     }
diff --git a/src/test/ui/abi/extern/extern-pass-TwoU64s.rs b/src/test/ui/abi/extern/extern-pass-TwoU64s.rs
index 4196482..8bbc987 100644
--- a/src/test/ui/abi/extern/extern-pass-TwoU64s.rs
+++ b/src/test/ui/abi/extern/extern-pass-TwoU64s.rs
@@ -8,17 +8,18 @@
 
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub struct TwoU64s {
-    one: u64, two: u64
+    one: u64,
+    two: u64,
 }
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s;
 }
 
 pub fn main() {
     unsafe {
-        let x = TwoU64s {one: 22, two: 23};
+        let x = TwoU64s { one: 22, two: 23 };
         let y = rust_dbg_extern_identity_TwoU64s(x);
         assert_eq!(x, y);
     }
diff --git a/src/test/ui/abi/extern/extern-pass-TwoU8s.rs b/src/test/ui/abi/extern/extern-pass-TwoU8s.rs
index 53a6a0f..55a53c2 100644
--- a/src/test/ui/abi/extern/extern-pass-TwoU8s.rs
+++ b/src/test/ui/abi/extern/extern-pass-TwoU8s.rs
@@ -8,17 +8,18 @@
 
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub struct TwoU8s {
-    one: u8, two: u8
+    one: u8,
+    two: u8,
 }
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s;
 }
 
 pub fn main() {
     unsafe {
-        let x = TwoU8s {one: 22, two: 23};
+        let x = TwoU8s { one: 22, two: 23 };
         let y = rust_dbg_extern_identity_TwoU8s(x);
         assert_eq!(x, y);
     }
diff --git a/src/test/ui/abi/extern/extern-pass-char.rs b/src/test/ui/abi/extern/extern-pass-char.rs
index 22f841b4..2b10d26 100644
--- a/src/test/ui/abi/extern/extern-pass-char.rs
+++ b/src/test/ui/abi/extern/extern-pass-char.rs
@@ -3,9 +3,8 @@
 
 // Test a function that takes/returns a u8.
 
-
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_dbg_extern_identity_u8(v: u8) -> u8;
 }
 
diff --git a/src/test/ui/abi/extern/extern-pass-double.rs b/src/test/ui/abi/extern/extern-pass-double.rs
index dbd0a2d..0b556c9 100644
--- a/src/test/ui/abi/extern/extern-pass-double.rs
+++ b/src/test/ui/abi/extern/extern-pass-double.rs
@@ -2,7 +2,7 @@
 // ignore-wasm32-bare no libc for ffi testing
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_dbg_extern_identity_double(v: f64) -> f64;
 }
 
diff --git a/src/test/ui/abi/extern/extern-pass-empty.rs b/src/test/ui/abi/extern/extern-pass-empty.rs
index 07099a2..ee974f6 100644
--- a/src/test/ui/abi/extern/extern-pass-empty.rs
+++ b/src/test/ui/abi/extern/extern-pass-empty.rs
@@ -27,7 +27,7 @@
 struct Empty;
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     fn rust_dbg_extern_empty_struct(v1: ManyInts, e: Empty, v2: ManyInts);
 }
 
@@ -39,7 +39,7 @@
             arg3: 4,
             arg4: 5,
             arg5: 6,
-            arg6: TwoU8s { one: 7, two: 8, }
+            arg6: TwoU8s { one: 7, two: 8 },
         };
         let y = ManyInts {
             arg1: 1,
@@ -47,7 +47,7 @@
             arg3: 3,
             arg4: 4,
             arg5: 5,
-            arg6: TwoU8s { one: 6, two: 7, }
+            arg6: TwoU8s { one: 6, two: 7 },
         };
         let empty = Empty;
         rust_dbg_extern_empty_struct(x, empty, y);
diff --git a/src/test/ui/abi/extern/extern-pass-u32.rs b/src/test/ui/abi/extern/extern-pass-u32.rs
index f2efdb7..c9b8d52 100644
--- a/src/test/ui/abi/extern/extern-pass-u32.rs
+++ b/src/test/ui/abi/extern/extern-pass-u32.rs
@@ -3,9 +3,8 @@
 
 // Test a function that takes/returns a u32.
 
-
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_dbg_extern_identity_u32(v: u32) -> u32;
 }
 
diff --git a/src/test/ui/abi/extern/extern-pass-u64.rs b/src/test/ui/abi/extern/extern-pass-u64.rs
index 975446d..5103129 100644
--- a/src/test/ui/abi/extern/extern-pass-u64.rs
+++ b/src/test/ui/abi/extern/extern-pass-u64.rs
@@ -3,9 +3,8 @@
 
 // Test a call to a function that takes/returns a u64.
 
-
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_dbg_extern_identity_u64(v: u64) -> u64;
 }
 
diff --git a/src/test/ui/abi/extern/extern-return-TwoU16s.rs b/src/test/ui/abi/extern/extern-return-TwoU16s.rs
index dd884ee..2551c93 100644
--- a/src/test/ui/abi/extern/extern-return-TwoU16s.rs
+++ b/src/test/ui/abi/extern/extern-return-TwoU16s.rs
@@ -4,11 +4,12 @@
 // ignore-wasm32-bare no libc to test ffi with
 
 pub struct TwoU16s {
-    one: u16, two: u16
+    one: u16,
+    two: u16,
 }
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_dbg_extern_return_TwoU16s() -> TwoU16s;
 }
 
diff --git a/src/test/ui/abi/extern/extern-return-TwoU32s.rs b/src/test/ui/abi/extern/extern-return-TwoU32s.rs
index d6aaf5c..70a4289 100644
--- a/src/test/ui/abi/extern/extern-return-TwoU32s.rs
+++ b/src/test/ui/abi/extern/extern-return-TwoU32s.rs
@@ -4,11 +4,12 @@
 // ignore-wasm32-bare no libc to test ffi with
 
 pub struct TwoU32s {
-    one: u32, two: u32
+    one: u32,
+    two: u32,
 }
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s;
 }
 
diff --git a/src/test/ui/abi/extern/extern-return-TwoU64s.rs b/src/test/ui/abi/extern/extern-return-TwoU64s.rs
index c5e4eba..dd264fb 100644
--- a/src/test/ui/abi/extern/extern-return-TwoU64s.rs
+++ b/src/test/ui/abi/extern/extern-return-TwoU64s.rs
@@ -4,11 +4,12 @@
 // ignore-wasm32-bare no libc to test ffi with
 
 pub struct TwoU64s {
-    one: u64, two: u64
+    one: u64,
+    two: u64,
 }
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_dbg_extern_return_TwoU64s() -> TwoU64s;
 }
 
diff --git a/src/test/ui/abi/extern/extern-return-TwoU8s.rs b/src/test/ui/abi/extern/extern-return-TwoU8s.rs
index a7cd21b..b60387a 100644
--- a/src/test/ui/abi/extern/extern-return-TwoU8s.rs
+++ b/src/test/ui/abi/extern/extern-return-TwoU8s.rs
@@ -4,11 +4,12 @@
 // ignore-wasm32-bare no libc to test ffi with
 
 pub struct TwoU8s {
-    one: u8, two: u8
+    one: u8,
+    two: u8,
 }
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_dbg_extern_return_TwoU8s() -> TwoU8s;
 }
 
diff --git a/src/test/ui/abi/foreign/auxiliary/foreign_lib.rs b/src/test/ui/abi/foreign/auxiliary/foreign_lib.rs
index de6b0e2..3c649b7 100644
--- a/src/test/ui/abi/foreign/auxiliary/foreign_lib.rs
+++ b/src/test/ui/abi/foreign/auxiliary/foreign_lib.rs
@@ -1,12 +1,11 @@
-#![crate_name="foreign_lib"]
-
+#![crate_name = "foreign_lib"]
 #![feature(rustc_private)]
 
 pub mod rustrt {
     extern crate libc;
 
     #[link(name = "rust_test_helpers", kind = "static")]
-    extern {
+    extern "C" {
         pub fn rust_get_test_int() -> libc::intptr_t;
     }
 }
@@ -14,7 +13,7 @@
 pub mod rustrt2 {
     extern crate libc;
 
-    extern {
+    extern "C" {
         pub fn rust_get_test_int() -> libc::intptr_t;
     }
 }
@@ -24,7 +23,7 @@
     // Ensures that we don't ICE or trigger LLVM asserts when
     // importing the same symbol under different types.
     // See https://github.com/rust-lang/rust/issues/32740.
-    extern {
+    extern "C" {
         pub fn rust_get_test_int() -> *const u8;
     }
 }
diff --git a/src/test/ui/abi/foreign/foreign-call-no-runtime.rs b/src/test/ui/abi/foreign/foreign-call-no-runtime.rs
index c6afa07..d5b90a3 100644
--- a/src/test/ui/abi/foreign/foreign-call-no-runtime.rs
+++ b/src/test/ui/abi/foreign/foreign-call-no-runtime.rs
@@ -9,45 +9,50 @@
 use std::thread;
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
-    fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t),
-                     data: libc::uintptr_t) -> libc::uintptr_t;
+extern "C" {
+    fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t), data: libc::uintptr_t) -> libc::uintptr_t;
 }
 
 pub fn main() {
     unsafe {
-        thread::spawn(move|| {
+        thread::spawn(move || {
             let i: isize = 100;
             rust_dbg_call(callback_isize, mem::transmute(&i));
-        }).join().unwrap();
+        })
+        .join()
+        .unwrap();
 
-        thread::spawn(move|| {
+        thread::spawn(move || {
             let i: i32 = 100;
             rust_dbg_call(callback_i32, mem::transmute(&i));
-        }).join().unwrap();
+        })
+        .join()
+        .unwrap();
 
-        thread::spawn(move|| {
+        thread::spawn(move || {
             let i: i64 = 100;
             rust_dbg_call(callback_i64, mem::transmute(&i));
-        }).join().unwrap();
+        })
+        .join()
+        .unwrap();
     }
 }
 
-extern fn callback_isize(data: libc::uintptr_t) {
+extern "C" fn callback_isize(data: libc::uintptr_t) {
     unsafe {
         let data: *const isize = mem::transmute(data);
         assert_eq!(*data, 100);
     }
 }
 
-extern fn callback_i64(data: libc::uintptr_t) {
+extern "C" fn callback_i64(data: libc::uintptr_t) {
     unsafe {
         let data: *const i64 = mem::transmute(data);
         assert_eq!(*data, 100);
     }
 }
 
-extern fn callback_i32(data: libc::uintptr_t) {
+extern "C" fn callback_i32(data: libc::uintptr_t) {
     unsafe {
         let data: *const i32 = mem::transmute(data);
         assert_eq!(*data, 100);
diff --git a/src/test/ui/abi/foreign/foreign-fn-with-byval.rs b/src/test/ui/abi/foreign/foreign-fn-with-byval.rs
index 3a35599..f366b6e 100644
--- a/src/test/ui/abi/foreign/foreign-fn-with-byval.rs
+++ b/src/test/ui/abi/foreign/foreign-fn-with-byval.rs
@@ -11,17 +11,15 @@
 }
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn get_x(x: S) -> u64;
     pub fn get_y(x: S) -> u64;
     pub fn get_z(x: S) -> u64;
 }
 
 #[inline(never)]
-fn indirect_call(func: unsafe extern fn(s: S) -> u64, s: S) -> u64 {
-    unsafe {
-        func(s)
-    }
+fn indirect_call(func: unsafe extern "C" fn(s: S) -> u64, s: S) -> u64 {
+    unsafe { func(s) }
 }
 
 fn main() {
diff --git a/src/test/ui/abi/foreign/foreign-no-abi.rs b/src/test/ui/abi/foreign/foreign-no-abi.rs
index 2f33fb4..3f4f70c 100644
--- a/src/test/ui/abi/foreign/foreign-no-abi.rs
+++ b/src/test/ui/abi/foreign/foreign-no-abi.rs
@@ -10,7 +10,7 @@
     extern crate libc;
 
     #[link(name = "rust_test_helpers", kind = "static")]
-    extern {
+    extern "C" {
         pub fn rust_get_test_int() -> libc::intptr_t;
     }
 }
diff --git a/src/test/ui/abi/issue-28676.rs b/src/test/ui/abi/issue-28676.rs
new file mode 100644
index 0000000..347a840
--- /dev/null
+++ b/src/test/ui/abi/issue-28676.rs
@@ -0,0 +1,40 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(improper_ctypes)]
+
+// ignore-wasm32-bare no libc to test ffi with
+
+#[derive(Copy, Clone)]
+pub struct Quad {
+    a: u64,
+    b: u64,
+    c: u64,
+    d: u64,
+}
+
+mod rustrt {
+    use super::Quad;
+
+    #[link(name = "rust_test_helpers", kind = "static")]
+    extern "C" {
+        pub fn get_c_many_params(
+            _: *const (),
+            _: *const (),
+            _: *const (),
+            _: *const (),
+            f: Quad,
+        ) -> u64;
+    }
+}
+
+fn test() {
+    unsafe {
+        let null = std::ptr::null();
+        let q = Quad { a: 1, b: 2, c: 3, d: 4 };
+        assert_eq!(rustrt::get_c_many_params(null, null, null, null, q), q.c);
+    }
+}
+
+pub fn main() {
+    test();
+}
diff --git a/src/test/ui/abi/issues/issue-22565-rust-call.rs b/src/test/ui/abi/issues/issue-22565-rust-call.rs
index 055d959..a08e0bf 100644
--- a/src/test/ui/abi/issues/issue-22565-rust-call.rs
+++ b/src/test/ui/abi/issues/issue-22565-rust-call.rs
@@ -1,8 +1,32 @@
 #![feature(unboxed_closures)]
 
 extern "rust-call" fn b(_i: i32) {}
-//~^ ERROR A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+//~^ ERROR functions with the "rust-call" ABI must take a single non-self argument that is a tuple
+
+trait Tr {
+    extern "rust-call" fn a();
+
+    extern "rust-call" fn b() {}
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
+}
+
+struct Foo;
+
+impl Foo {
+    extern "rust-call" fn bar() {}
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
+}
+
+impl Tr for Foo {
+    extern "rust-call" fn a() {}
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
+}
 
 fn main () {
     b(10);
+
+    Foo::bar();
+
+    <Foo as Tr>::a();
+    <Foo as Tr>::b();
 }
diff --git a/src/test/ui/abi/issues/issue-22565-rust-call.stderr b/src/test/ui/abi/issues/issue-22565-rust-call.stderr
index 31fb035..3eee10b 100644
--- a/src/test/ui/abi/issues/issue-22565-rust-call.stderr
+++ b/src/test/ui/abi/issues/issue-22565-rust-call.stderr
@@ -1,8 +1,26 @@
-error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
   --> $DIR/issue-22565-rust-call.rs:3:1
    |
 LL | extern "rust-call" fn b(_i: i32) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
+  --> $DIR/issue-22565-rust-call.rs:9:5
+   |
+LL |     extern "rust-call" fn b() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
+  --> $DIR/issue-22565-rust-call.rs:16:5
+   |
+LL |     extern "rust-call" fn bar() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
+  --> $DIR/issue-22565-rust-call.rs:21:5
+   |
+LL |     extern "rust-call" fn a() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs b/src/test/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs
index df81930..29b2405 100644
--- a/src/test/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs
+++ b/src/test/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs
@@ -5,13 +5,18 @@
 // ignore-wasm32-bare no libc to test ffi with
 
 #[derive(Copy, Clone)]
-pub struct QuadFloats { a: f32, b: f32, c: f32, d: f32 }
+pub struct QuadFloats {
+    a: f32,
+    b: f32,
+    c: f32,
+    d: f32,
+}
 
 mod rustrt {
     use super::QuadFloats;
 
     #[link(name = "rust_test_helpers", kind = "static")]
-    extern {
+    extern "C" {
         pub fn get_c_exhaust_sysv64_ints(
             _: *const (),
             _: *const (),
@@ -28,12 +33,7 @@
 fn test() {
     unsafe {
         let null = std::ptr::null();
-        let q = QuadFloats {
-            a: 10.2,
-            b: 20.3,
-            c: 30.4,
-            d: 40.5
-        };
+        let q = QuadFloats { a: 10.2, b: 20.3, c: 30.4, d: 40.5 };
         assert_eq!(
             rustrt::get_c_exhaust_sysv64_ints(null, null, null, null, null, null, null, q),
             q.c,
diff --git a/src/test/ui/abi/mir/mir_codegen_calls_variadic.rs b/src/test/ui/abi/mir/mir_codegen_calls_variadic.rs
index dc9fee0..b3392b9 100644
--- a/src/test/ui/abi/mir/mir_codegen_calls_variadic.rs
+++ b/src/test/ui/abi/mir/mir_codegen_calls_variadic.rs
@@ -2,21 +2,18 @@
 // ignore-wasm32-bare no libc to test ffi with
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     fn rust_interesting_average(_: i64, ...) -> f64;
 }
 
 fn test<T, U>(a: i64, b: i64, c: i64, d: i64, e: i64, f: T, g: U) -> i64 {
     unsafe {
-        rust_interesting_average(6, a, a as f64,
-                                    b, b as f64,
-                                    c, c as f64,
-                                    d, d as f64,
-                                    e, e as f64,
-                                    f, g) as i64
+        rust_interesting_average(
+            6, a, a as f64, b, b as f64, c, c as f64, d, d as f64, e, e as f64, f, g,
+        ) as i64
     }
 }
 
-fn main(){
+fn main() {
     assert_eq!(test(10, 20, 30, 40, 50, 60_i64, 60.0_f64), 70);
 }
diff --git a/src/test/ui/abi/segfault-no-out-of-stack.rs b/src/test/ui/abi/segfault-no-out-of-stack.rs
index 0128e5e..ad4faf9 100644
--- a/src/test/ui/abi/segfault-no-out-of-stack.rs
+++ b/src/test/ui/abi/segfault-no-out-of-stack.rs
@@ -3,39 +3,37 @@
 #![allow(unused_imports)]
 // ignore-emscripten can't run commands
 // ignore-sgx no processes
-
 #![feature(rustc_private)]
 
 extern crate libc;
 
-use std::process::{Command, ExitStatus};
 use std::env;
+use std::process::{Command, ExitStatus};
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     fn rust_get_null_ptr() -> *mut ::libc::c_char;
 }
 
 #[cfg(unix)]
-fn check_status(status: std::process::ExitStatus)
-{
+fn check_status(status: std::process::ExitStatus) {
     use libc;
     use std::os::unix::process::ExitStatusExt;
 
-    assert!(status.signal() == Some(libc::SIGSEGV)
-            || status.signal() == Some(libc::SIGBUS));
+    assert!(status.signal() == Some(libc::SIGSEGV) || status.signal() == Some(libc::SIGBUS));
 }
 
 #[cfg(not(unix))]
-fn check_status(status: std::process::ExitStatus)
-{
+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] == "segfault" {
-        unsafe { *rust_get_null_ptr() = 1; }; // trigger a segfault
+        unsafe {
+            *rust_get_null_ptr() = 1;
+        }; // trigger a segfault
     } else {
         let segfault = Command::new(&args[0]).arg("segfault").output().unwrap();
         let stderr = String::from_utf8_lossy(&segfault.stderr);
diff --git a/src/test/ui/abi/stack-probes.rs b/src/test/ui/abi/stack-probes.rs
index 6c83e01..e998dd0 100644
--- a/src/test/ui/abi/stack-probes.rs
+++ b/src/test/ui/abi/stack-probes.rs
@@ -11,13 +11,13 @@
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
+use std::env;
 use std::mem::MaybeUninit;
 use std::process::Command;
 use std::thread;
-use std::env;
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     #[link_name = "rust_dbg_extern_identity_u64"]
     fn black_box(u: u64);
 }
@@ -30,7 +30,7 @@
             "child-thread" => thread::spawn(|| recurse(&MaybeUninit::uninit())).join().unwrap(),
             _ => panic!(),
         }
-        return
+        return;
     }
 
     let me = env::current_exe().unwrap();
diff --git a/src/test/ui/abi/statics/static-mut-foreign.rs b/src/test/ui/abi/statics/static-mut-foreign.rs
index 5d6fa41..ecd8ee9 100644
--- a/src/test/ui/abi/statics/static-mut-foreign.rs
+++ b/src/test/ui/abi/statics/static-mut-foreign.rs
@@ -10,7 +10,7 @@
 extern crate libc;
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     static mut rust_dbg_static_mut: libc::c_int;
     pub fn rust_dbg_static_mut_check_four();
 }
diff --git a/src/test/ui/abi/struct-enums/struct-return.rs b/src/test/ui/abi/struct-enums/struct-return.rs
index a3e70bb..1a7984e 100644
--- a/src/test/ui/abi/struct-enums/struct-return.rs
+++ b/src/test/ui/abi/struct-enums/struct-return.rs
@@ -4,25 +4,42 @@
 
 #[repr(C)]
 #[derive(Copy, Clone)]
-pub struct Quad { a: u64, b: u64, c: u64, d: u64 }
+pub struct Quad {
+    a: u64,
+    b: u64,
+    c: u64,
+    d: u64,
+}
 
 #[repr(C)]
 #[derive(Copy, Clone)]
-pub struct Floats { a: f64, b: u8, c: f64 }
+pub struct Floats {
+    a: f64,
+    b: u8,
+    c: f64,
+}
 
 #[repr(C)]
 #[derive(Copy, Clone)]
-pub struct CharCharDouble { a: u8, b: u8, c: f64 }
+pub struct CharCharDouble {
+    a: u8,
+    b: u8,
+    c: f64,
+}
 
 #[repr(C)]
 #[derive(Copy, Clone)]
-pub struct CharCharFloat { a: u8, b: u8, c: f32 }
+pub struct CharCharFloat {
+    a: u8,
+    b: u8,
+    c: f32,
+}
 
 mod rustrt {
-    use super::{Floats, Quad, CharCharDouble, CharCharFloat};
+    use super::{CharCharDouble, CharCharFloat, Floats, Quad};
 
     #[link(name = "rust_test_helpers", kind = "static")]
-    extern {
+    extern "C" {
         pub fn rust_dbg_abi_1(q: Quad) -> Quad;
         pub fn rust_dbg_abi_2(f: Floats) -> Floats;
         pub fn rust_dbg_abi_3(a: CharCharDouble) -> CharCharDouble;
@@ -32,10 +49,12 @@
 
 fn test1() {
     unsafe {
-        let q = Quad { a: 0xaaaa_aaaa_aaaa_aaaa,
-                 b: 0xbbbb_bbbb_bbbb_bbbb,
-                 c: 0xcccc_cccc_cccc_cccc,
-                 d: 0xdddd_dddd_dddd_dddd };
+        let q = Quad {
+            a: 0xaaaa_aaaa_aaaa_aaaa,
+            b: 0xbbbb_bbbb_bbbb_bbbb,
+            c: 0xcccc_cccc_cccc_cccc,
+            d: 0xdddd_dddd_dddd_dddd,
+        };
         let qq = rustrt::rust_dbg_abi_1(q);
         println!("a: {:x}", qq.a as usize);
         println!("b: {:x}", qq.b as usize);
@@ -51,9 +70,7 @@
 #[cfg(target_pointer_width = "64")]
 fn test2() {
     unsafe {
-        let f = Floats { a: 1.234567890e-15_f64,
-                 b: 0b_1010_1010,
-                 c: 1.0987654321e-15_f64 };
+        let f = Floats { a: 1.234567890e-15_f64, b: 0b_1010_1010, c: 1.0987654321e-15_f64 };
         let ff = rustrt::rust_dbg_abi_2(f);
         println!("a: {}", ff.a as f64);
         println!("b: {}", ff.b as usize);
@@ -65,17 +82,12 @@
 }
 
 #[cfg(target_pointer_width = "32")]
-fn test2() {
-}
+fn test2() {}
 
 #[cfg(target_pointer_width = "64")]
 fn test3() {
     unsafe {
-        let a = CharCharDouble {
-            a: 1,
-            b: 2,
-            c: 3.,
-        };
+        let a = CharCharDouble { a: 1, b: 2, c: 3. };
         let b = rustrt::rust_dbg_abi_3(a);
         println!("a: {}", b.a);
         println!("b: {}", b.b);
@@ -91,11 +103,7 @@
 
 fn test4() {
     unsafe {
-        let a = CharCharFloat {
-            a: 1,
-            b: 2,
-            c: 3.,
-        };
+        let a = CharCharFloat { a: 1, b: 2, c: 3. };
         let b = rustrt::rust_dbg_abi_4(a);
         println!("a: {}", b.a);
         println!("b: {}", b.b);
diff --git a/src/test/ui/abi/variadic-ffi.rs b/src/test/ui/abi/variadic-ffi.rs
index 3232a11..a952ea0 100644
--- a/src/test/ui/abi/variadic-ffi.rs
+++ b/src/test/ui/abi/variadic-ffi.rs
@@ -5,7 +5,7 @@
 use std::ffi::VaList;
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     fn rust_interesting_average(_: u64, ...) -> f64;
 
     // FIXME: we need to disable this lint for `VaList`,
@@ -61,7 +61,7 @@
     }
 
     // A function that takes a function pointer
-    unsafe fn call(fp: unsafe extern fn(u64, ...) -> f64) {
+    unsafe fn call(fp: unsafe extern "C" fn(u64, ...) -> f64) {
         let (x1, x2, x3, x4) = (10i64, 10.0f64, 20i64, 20.0f64);
         assert_eq!(fp(2, x1, x2, x3, x4) as i64, 30);
     }
@@ -70,7 +70,7 @@
         call(rust_interesting_average);
 
         // Make a function pointer, pass indirectly
-        let x: unsafe extern fn(u64, ...) -> f64 = rust_interesting_average;
+        let x: unsafe extern "C" fn(u64, ...) -> f64 = rust_interesting_average;
         call(x);
     }
 
diff --git a/src/test/ui/array-break-length.rs b/src/test/ui/array-slice-vec/array-break-length.rs
similarity index 100%
rename from src/test/ui/array-break-length.rs
rename to src/test/ui/array-slice-vec/array-break-length.rs
diff --git a/src/test/ui/array-break-length.stderr b/src/test/ui/array-slice-vec/array-break-length.stderr
similarity index 100%
rename from src/test/ui/array-break-length.stderr
rename to src/test/ui/array-slice-vec/array-break-length.stderr
diff --git a/src/test/ui/array-not-vector.rs b/src/test/ui/array-slice-vec/array-not-vector.rs
similarity index 100%
rename from src/test/ui/array-not-vector.rs
rename to src/test/ui/array-slice-vec/array-not-vector.rs
diff --git a/src/test/ui/array-not-vector.stderr b/src/test/ui/array-slice-vec/array-not-vector.stderr
similarity index 100%
rename from src/test/ui/array-not-vector.stderr
rename to src/test/ui/array-slice-vec/array-not-vector.stderr
diff --git a/src/test/ui/array_const_index-0.rs b/src/test/ui/array-slice-vec/array_const_index-0.rs
similarity index 100%
rename from src/test/ui/array_const_index-0.rs
rename to src/test/ui/array-slice-vec/array_const_index-0.rs
diff --git a/src/test/ui/array_const_index-0.stderr b/src/test/ui/array-slice-vec/array_const_index-0.stderr
similarity index 100%
rename from src/test/ui/array_const_index-0.stderr
rename to src/test/ui/array-slice-vec/array_const_index-0.stderr
diff --git a/src/test/ui/array-slice-vec/array_const_index-1.rs b/src/test/ui/array-slice-vec/array_const_index-1.rs
index 8ee225f..d0ee179 100644
--- a/src/test/ui/array-slice-vec/array_const_index-1.rs
+++ b/src/test/ui/array-slice-vec/array_const_index-1.rs
@@ -1,12 +1,8 @@
-// run-pass
-#![allow(dead_code)]
-#![allow(stable_features)]
-
-#![feature(const_indexing)]
+const A: [i32; 0] = [];
+const B: i32 = A[1];
+//~^ index out of bounds: the length is 0 but the index is 1
+//~| ERROR any use of this value will cause an error
 
 fn main() {
-    const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47];
-    const IDX: usize = 3;
-    const VAL: i32 = ARR[IDX];
-    const BLUB: [i32; (ARR[0] - 41) as usize] = [5];
+    let _ = B;
 }
diff --git a/src/test/ui/array_const_index-1.stderr b/src/test/ui/array-slice-vec/array_const_index-1.stderr
similarity index 100%
rename from src/test/ui/array_const_index-1.stderr
rename to src/test/ui/array-slice-vec/array_const_index-1.stderr
diff --git a/src/test/ui/array-slice-vec/array_const_index-2.rs b/src/test/ui/array-slice-vec/array_const_index-2.rs
new file mode 100644
index 0000000..8ee225f
--- /dev/null
+++ b/src/test/ui/array-slice-vec/array_const_index-2.rs
@@ -0,0 +1,12 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(stable_features)]
+
+#![feature(const_indexing)]
+
+fn main() {
+    const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47];
+    const IDX: usize = 3;
+    const VAL: i32 = ARR[IDX];
+    const BLUB: [i32; (ARR[0] - 41) as usize] = [5];
+}
diff --git a/src/test/ui/issues/issue-15730.rs b/src/test/ui/array-slice-vec/issue-15730.rs
similarity index 100%
rename from src/test/ui/issues/issue-15730.rs
rename to src/test/ui/array-slice-vec/issue-15730.rs
diff --git a/src/test/ui/slice-2.rs b/src/test/ui/array-slice-vec/slice-2.rs
similarity index 100%
rename from src/test/ui/slice-2.rs
rename to src/test/ui/array-slice-vec/slice-2.rs
diff --git a/src/test/ui/slice-2.stderr b/src/test/ui/array-slice-vec/slice-2.stderr
similarity index 100%
rename from src/test/ui/slice-2.stderr
rename to src/test/ui/array-slice-vec/slice-2.stderr
diff --git a/src/test/ui/slice-mut-2.rs b/src/test/ui/array-slice-vec/slice-mut-2.rs
similarity index 100%
rename from src/test/ui/slice-mut-2.rs
rename to src/test/ui/array-slice-vec/slice-mut-2.rs
diff --git a/src/test/ui/slice-mut-2.stderr b/src/test/ui/array-slice-vec/slice-mut-2.stderr
similarity index 100%
rename from src/test/ui/slice-mut-2.stderr
rename to src/test/ui/array-slice-vec/slice-mut-2.stderr
diff --git a/src/test/ui/slice-mut.rs b/src/test/ui/array-slice-vec/slice-mut.rs
similarity index 100%
rename from src/test/ui/slice-mut.rs
rename to src/test/ui/array-slice-vec/slice-mut.rs
diff --git a/src/test/ui/slice-mut.stderr b/src/test/ui/array-slice-vec/slice-mut.stderr
similarity index 100%
rename from src/test/ui/slice-mut.stderr
rename to src/test/ui/array-slice-vec/slice-mut.stderr
diff --git a/src/test/ui/slice-to-vec-comparison.rs b/src/test/ui/array-slice-vec/slice-to-vec-comparison.rs
similarity index 100%
rename from src/test/ui/slice-to-vec-comparison.rs
rename to src/test/ui/array-slice-vec/slice-to-vec-comparison.rs
diff --git a/src/test/ui/slice-to-vec-comparison.stderr b/src/test/ui/array-slice-vec/slice-to-vec-comparison.stderr
similarity index 100%
rename from src/test/ui/slice-to-vec-comparison.stderr
rename to src/test/ui/array-slice-vec/slice-to-vec-comparison.stderr
diff --git a/src/test/ui/vec/vec-macro-with-comma-only.rs b/src/test/ui/array-slice-vec/vec-macro-with-comma-only.rs
similarity index 100%
rename from src/test/ui/vec/vec-macro-with-comma-only.rs
rename to src/test/ui/array-slice-vec/vec-macro-with-comma-only.rs
diff --git a/src/test/ui/vec/vec-macro-with-comma-only.stderr b/src/test/ui/array-slice-vec/vec-macro-with-comma-only.stderr
similarity index 100%
rename from src/test/ui/vec/vec-macro-with-comma-only.stderr
rename to src/test/ui/array-slice-vec/vec-macro-with-comma-only.stderr
diff --git a/src/test/ui/vec/vec-mut-iter-borrow.rs b/src/test/ui/array-slice-vec/vec-mut-iter-borrow.rs
similarity index 100%
rename from src/test/ui/vec/vec-mut-iter-borrow.rs
rename to src/test/ui/array-slice-vec/vec-mut-iter-borrow.rs
diff --git a/src/test/ui/vec/vec-mut-iter-borrow.stderr b/src/test/ui/array-slice-vec/vec-mut-iter-borrow.stderr
similarity index 100%
rename from src/test/ui/vec/vec-mut-iter-borrow.stderr
rename to src/test/ui/array-slice-vec/vec-mut-iter-borrow.stderr
diff --git a/src/test/ui/vec/vec-overrun.rs b/src/test/ui/array-slice-vec/vec-overrun.rs
similarity index 100%
rename from src/test/ui/vec/vec-overrun.rs
rename to src/test/ui/array-slice-vec/vec-overrun.rs
diff --git a/src/test/ui/vec/vec-res-add.rs b/src/test/ui/array-slice-vec/vec-res-add.rs
similarity index 100%
rename from src/test/ui/vec/vec-res-add.rs
rename to src/test/ui/array-slice-vec/vec-res-add.rs
diff --git a/src/test/ui/vec/vec-res-add.stderr b/src/test/ui/array-slice-vec/vec-res-add.stderr
similarity index 100%
rename from src/test/ui/vec/vec-res-add.stderr
rename to src/test/ui/array-slice-vec/vec-res-add.stderr
diff --git a/src/test/ui/vector-cast-weirdness.rs b/src/test/ui/array-slice-vec/vector-cast-weirdness.rs
similarity index 100%
rename from src/test/ui/vector-cast-weirdness.rs
rename to src/test/ui/array-slice-vec/vector-cast-weirdness.rs
diff --git a/src/test/ui/vector-cast-weirdness.stderr b/src/test/ui/array-slice-vec/vector-cast-weirdness.stderr
similarity index 100%
rename from src/test/ui/vector-cast-weirdness.stderr
rename to src/test/ui/array-slice-vec/vector-cast-weirdness.stderr
diff --git a/src/test/ui/vector-no-ann.rs b/src/test/ui/array-slice-vec/vector-no-ann.rs
similarity index 100%
rename from src/test/ui/vector-no-ann.rs
rename to src/test/ui/array-slice-vec/vector-no-ann.rs
diff --git a/src/test/ui/vector-no-ann.stderr b/src/test/ui/array-slice-vec/vector-no-ann.stderr
similarity index 100%
rename from src/test/ui/vector-no-ann.stderr
rename to src/test/ui/array-slice-vec/vector-no-ann.stderr
diff --git a/src/test/ui/array_const_index-1.rs b/src/test/ui/array_const_index-1.rs
deleted file mode 100644
index d0ee179..0000000
--- a/src/test/ui/array_const_index-1.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-const A: [i32; 0] = [];
-const B: i32 = A[1];
-//~^ index out of bounds: the length is 0 but the index is 1
-//~| ERROR any use of this value will cause an error
-
-fn main() {
-    let _ = B;
-}
diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr
index d9bb738..61b16cb 100644
--- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr
+++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr
@@ -30,7 +30,7 @@
    |
 LL |     const BAR: u32 = IMPL_REF_BAR;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires optimizing MIR for `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
+note: ...which requires caching mir of `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR` for CTFE...
   --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
    |
 LL |     const BAR: u32 = IMPL_REF_BAR;
diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr
index d000d8a..494dc0c 100644
--- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr
+++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr
@@ -30,7 +30,7 @@
    |
 LL |     const BAR: u32 = DEFAULT_REF_BAR;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires optimizing MIR for `FooDefault::BAR`...
+note: ...which requires caching mir of `FooDefault::BAR` for CTFE...
   --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
    |
 LL |     const BAR: u32 = DEFAULT_REF_BAR;
diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr
index 62d2051..4ff253b 100644
--- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr
+++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr
@@ -30,7 +30,7 @@
    |
 LL |     const BAR: u32 = TRAIT_REF_BAR;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires optimizing MIR for `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
+note: ...which requires caching mir of `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR` for CTFE...
   --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
    |
 LL |     const BAR: u32 = TRAIT_REF_BAR;
diff --git a/src/test/ui/associated-item/associated-item-two-bounds.rs b/src/test/ui/associated-item/associated-item-two-bounds.rs
new file mode 100644
index 0000000..25b0d5a
--- /dev/null
+++ b/src/test/ui/associated-item/associated-item-two-bounds.rs
@@ -0,0 +1,16 @@
+// This test is a regression test for #34792
+
+// check-pass
+
+pub struct A;
+pub struct B;
+
+pub trait Foo {
+    type T: PartialEq<A> + PartialEq<B>;
+}
+
+pub fn generic<F: Foo>(t: F::T, a: A, b: B) -> bool {
+    t == a && t == b
+}
+
+pub fn main() {}
diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr
index 811c9a8..e2847b6 100644
--- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr
+++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr
@@ -2,10 +2,15 @@
   --> $DIR/higher-ranked-projection.rs:25:5
    |
 LL |     foo(());
-   |     ^^^ one type is more general than the other
+   |     ^^^ lifetime mismatch
    |
    = note: expected type `&'a ()`
               found type `&()`
+note: the lifetime requirement is introduced here
+  --> $DIR/higher-ranked-projection.rs:15:33
+   |
+LL |     where for<'a> &'a T: Mirror<Image=U>
+   |                                 ^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-24338.rs b/src/test/ui/associated-types/issue-24338.rs
similarity index 100%
rename from src/test/ui/issues/issue-24338.rs
rename to src/test/ui/associated-types/issue-24338.rs
diff --git a/src/test/ui/issues/issue-48551.rs b/src/test/ui/associated-types/issue-48551.rs
similarity index 100%
rename from src/test/ui/issues/issue-48551.rs
rename to src/test/ui/associated-types/issue-48551.rs
diff --git a/src/test/ui/issues/issue-50301.rs b/src/test/ui/associated-types/issue-50301.rs
similarity index 100%
rename from src/test/ui/issues/issue-50301.rs
rename to src/test/ui/associated-types/issue-50301.rs
diff --git a/src/test/ui/object-method-numbering.rs b/src/test/ui/associated-types/object-method-numbering.rs
similarity index 100%
rename from src/test/ui/object-method-numbering.rs
rename to src/test/ui/associated-types/object-method-numbering.rs
diff --git a/src/test/ui/ast-json/ast-json-noexpand-output.stdout b/src/test/ui/ast-json/ast-json-noexpand-output.stdout
index deb2a1a..9c29a5f 100644
--- a/src/test/ui/ast-json/ast-json-noexpand-output.stdout
+++ b/src/test/ui/ast-json/ast-json-noexpand-output.stdout
@@ -1 +1 @@
-{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":null}]}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":null}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout
index 71336f4..cccd519 100644
--- a/src/test/ui/ast-json/ast-json-output.stdout
+++ b/src/test/ui/ast-json/ast-json-output.stdout
@@ -1 +1 @@
-{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":null}]}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":null}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.rs b/src/test/ui/async-await/edition-deny-async-fns-2015.rs
index 5d2d186..e5dc9c8 100644
--- a/src/test/ui/async-await/edition-deny-async-fns-2015.rs
+++ b/src/test/ui/async-await/edition-deny-async-fns-2015.rs
@@ -1,21 +1,21 @@
 // edition:2015
 
-async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015
 
-fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in the 2015 edition
+fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in Rust 2015
 
-async fn async_baz() { //~ ERROR `async fn` is not permitted in the 2015 edition
-    async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+async fn async_baz() { //~ ERROR `async fn` is not permitted in Rust 2015
+    async fn bar() {} //~ ERROR `async fn` is not permitted in Rust 2015
 }
 
 struct Foo {}
 
 impl Foo {
-    async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+    async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015
 }
 
 trait Bar {
-    async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+    async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015
                       //~^ ERROR functions in traits cannot be declared `async`
 }
 
@@ -23,16 +23,16 @@
     macro_rules! accept_item { ($x:item) => {} }
 
     accept_item! {
-        async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+        async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015
     }
 
     accept_item! {
         impl Foo {
-            async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+            async fn bar() {} //~ ERROR `async fn` is not permitted in Rust 2015
         }
     }
 
     let inside_closure = || {
-        async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+        async fn bar() {} //~ ERROR `async fn` is not permitted in Rust 2015
     };
 }
diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
index 8bffeb2..43364a8 100644
--- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
+++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
@@ -1,80 +1,80 @@
-error[E0670]: `async fn` is not permitted in the 2015 edition
+error[E0670]: `async fn` is not permitted in Rust 2015
   --> $DIR/edition-deny-async-fns-2015.rs:3:1
    |
 LL | async fn foo() {}
-   | ^^^^^ to use `async fn`, switch to Rust 2018
+   | ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
-error[E0670]: `async fn` is not permitted in the 2015 edition
+error[E0670]: `async fn` is not permitted in Rust 2015
   --> $DIR/edition-deny-async-fns-2015.rs:5:12
    |
 LL | fn baz() { async fn foo() {} }
-   |            ^^^^^ to use `async fn`, switch to Rust 2018
+   |            ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
-error[E0670]: `async fn` is not permitted in the 2015 edition
+error[E0670]: `async fn` is not permitted in Rust 2015
   --> $DIR/edition-deny-async-fns-2015.rs:7:1
    |
 LL | async fn async_baz() {
-   | ^^^^^ to use `async fn`, switch to Rust 2018
+   | ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
-error[E0670]: `async fn` is not permitted in the 2015 edition
+error[E0670]: `async fn` is not permitted in Rust 2015
   --> $DIR/edition-deny-async-fns-2015.rs:8:5
    |
 LL |     async fn bar() {}
-   |     ^^^^^ to use `async fn`, switch to Rust 2018
+   |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
-error[E0670]: `async fn` is not permitted in the 2015 edition
+error[E0670]: `async fn` is not permitted in Rust 2015
   --> $DIR/edition-deny-async-fns-2015.rs:14:5
    |
 LL |     async fn foo() {}
-   |     ^^^^^ to use `async fn`, switch to Rust 2018
+   |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
-error[E0670]: `async fn` is not permitted in the 2015 edition
+error[E0670]: `async fn` is not permitted in Rust 2015
   --> $DIR/edition-deny-async-fns-2015.rs:18:5
    |
 LL |     async fn foo() {}
-   |     ^^^^^ to use `async fn`, switch to Rust 2018
+   |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
-error[E0670]: `async fn` is not permitted in the 2015 edition
+error[E0670]: `async fn` is not permitted in Rust 2015
   --> $DIR/edition-deny-async-fns-2015.rs:36:9
    |
 LL |         async fn bar() {}
-   |         ^^^^^ to use `async fn`, switch to Rust 2018
+   |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
-error[E0670]: `async fn` is not permitted in the 2015 edition
+error[E0670]: `async fn` is not permitted in Rust 2015
   --> $DIR/edition-deny-async-fns-2015.rs:26:9
    |
 LL |         async fn foo() {}
-   |         ^^^^^ to use `async fn`, switch to Rust 2018
+   |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
-error[E0670]: `async fn` is not permitted in the 2015 edition
+error[E0670]: `async fn` is not permitted in Rust 2015
   --> $DIR/edition-deny-async-fns-2015.rs:31:13
    |
 LL |             async fn bar() {}
-   |             ^^^^^ to use `async fn`, switch to Rust 2018
+   |             ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
diff --git a/src/test/ui/async-await/feature-async-closure.stderr b/src/test/ui/async-await/feature-async-closure.stderr
index ba851ba..485a838 100644
--- a/src/test/ui/async-await/feature-async-closure.stderr
+++ b/src/test/ui/async-await/feature-async-closure.stderr
@@ -6,6 +6,7 @@
    |
    = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
    = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = help: to use an async block, remove the `||`: `async {`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-76547.nll.stderr b/src/test/ui/async-await/issue-76547.nll.stderr
similarity index 100%
rename from src/test/ui/issues/issue-76547.nll.stderr
rename to src/test/ui/async-await/issue-76547.nll.stderr
diff --git a/src/test/ui/issues/issue-76547.rs b/src/test/ui/async-await/issue-76547.rs
similarity index 100%
rename from src/test/ui/issues/issue-76547.rs
rename to src/test/ui/async-await/issue-76547.rs
diff --git a/src/test/ui/issues/issue-76547.stderr b/src/test/ui/async-await/issue-76547.stderr
similarity index 100%
rename from src/test/ui/issues/issue-76547.stderr
rename to src/test/ui/async-await/issue-76547.stderr
diff --git a/src/test/ui/async-await/issues/issue-65159.rs b/src/test/ui/async-await/issues/issue-65159.rs
index 4f160fc..ce3fa91 100644
--- a/src/test/ui/async-await/issues/issue-65159.rs
+++ b/src/test/ui/async-await/issues/issue-65159.rs
@@ -2,7 +2,8 @@
 //
 // edition:2018
 
-async fn copy() -> Result<()> //~ ERROR wrong number of type arguments
+async fn copy() -> Result<()>
+//~^ ERROR this enum takes 2 type arguments but only 1 type argument was supplied
 {
     Ok(())
     //~^ ERROR type annotations needed
diff --git a/src/test/ui/async-await/issues/issue-65159.stderr b/src/test/ui/async-await/issues/issue-65159.stderr
index 04cfa52..bcb4c29 100644
--- a/src/test/ui/async-await/issues/issue-65159.stderr
+++ b/src/test/ui/async-await/issues/issue-65159.stderr
@@ -1,11 +1,23 @@
-error[E0107]: wrong number of type arguments: expected 2, found 1
+error[E0107]: this enum takes 2 type arguments but only 1 type argument was supplied
   --> $DIR/issue-65159.rs:5:20
    |
 LL | async fn copy() -> Result<()>
-   |                    ^^^^^^^^^^ expected 2 type arguments
+   |                    ^^^^^^ -- supplied 1 type argument
+   |                    |
+   |                    expected 2 type arguments
+   |
+note: enum defined here, with 2 type parameters: `T`, `E`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   |          ^^^^^^ -  -
+help: add missing type argument
+   |
+LL | async fn copy() -> Result<(), E>
+   |                             ^^^
 
 error[E0282]: type annotations needed
-  --> $DIR/issue-65159.rs:7:5
+  --> $DIR/issue-65159.rs:8:5
    |
 LL |     Ok(())
    |     ^^ cannot infer type for type parameter `E` declared on the enum `Result`
diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.rs b/src/test/ui/async-await/issues/issue-78938-async-block.rs
new file mode 100644
index 0000000..36f7160
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-78938-async-block.rs
@@ -0,0 +1,33 @@
+// edition:2018
+
+use std::{sync::Arc, future::Future, pin::Pin, task::{Context, Poll}};
+
+async fn f() {
+    let room_ref = Arc::new(Vec::new());
+
+    let gameloop_handle = spawn(async { //~ ERROR E0373
+        game_loop(Arc::clone(&room_ref))
+    });
+    gameloop_handle.await;
+}
+
+fn game_loop(v: Arc<Vec<usize>>) {}
+
+fn spawn<F>(future: F) -> JoinHandle
+where
+    F: Future + Send + 'static,
+    F::Output: Send + 'static,
+{
+    loop {}
+}
+
+struct JoinHandle;
+
+impl Future for JoinHandle {
+    type Output = ();
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        loop {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.stderr b/src/test/ui/async-await/issues/issue-78938-async-block.stderr
new file mode 100644
index 0000000..01ffc48
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-78938-async-block.stderr
@@ -0,0 +1,21 @@
+error[E0373]: async block may outlive the current function, but it borrows `room_ref`, which is owned by the current function
+  --> $DIR/issue-78938-async-block.rs:8:39
+   |
+LL |       let gameloop_handle = spawn(async {
+   |  _______________________________________^
+LL | |         game_loop(Arc::clone(&room_ref))
+   | |                               -------- `room_ref` is borrowed here
+LL | |     });
+   | |_____^ may outlive borrowed value `room_ref`
+   |
+   = note: async blocks are not executed immediately and must either take a reference or ownership of outside variables they use
+help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword
+   |
+LL |     let gameloop_handle = spawn(async move {
+LL |         game_loop(Arc::clone(&room_ref))
+LL |     });
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/async-await/suggest-switching-edition-on-await.stderr b/src/test/ui/async-await/suggest-switching-edition-on-await.stderr
index 695d7dd..9ac2bc5 100644
--- a/src/test/ui/async-await/suggest-switching-edition-on-await.stderr
+++ b/src/test/ui/async-await/suggest-switching-edition-on-await.stderr
@@ -4,7 +4,7 @@
 LL |     x.await;
    |       ^^^^^ unknown field
    |
-   = note: to `.await` a `Future`, switch to Rust 2018
+   = note: to `.await` a `Future`, switch to Rust 2018 or later
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
@@ -14,7 +14,7 @@
 LL |     x.await;
    |       ^^^^^ help: a field with a similar name exists: `awai`
    |
-   = note: to `.await` a `Future`, switch to Rust 2018
+   = note: to `.await` a `Future`, switch to Rust 2018 or later
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
@@ -24,7 +24,7 @@
 LL |     x.await;
    |       ^^^^^ unknown field
    |
-   = note: to `.await` a `Future`, switch to Rust 2018
+   = note: to `.await` a `Future`, switch to Rust 2018 or later
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
@@ -34,7 +34,7 @@
 LL |     x.await;
    |       ^^^^^
    |
-   = note: to `.await` a `Future`, switch to Rust 2018
+   = note: to `.await` a `Future`, switch to Rust 2018 or later
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
diff --git a/src/test/ui/async-await/unused-lifetime.rs b/src/test/ui/async-await/unused-lifetime.rs
index 1cf546b..5bd6ae8 100644
--- a/src/test/ui/async-await/unused-lifetime.rs
+++ b/src/test/ui/async-await/unused-lifetime.rs
@@ -1,42 +1,47 @@
+// Check "unused_lifetimes" lint on both async and sync functions
+
 // edition:2018
 
-// Avoid spurious warnings of unused lifetime. The below async functions
-// are desugered to have an unused lifetime
-// but we don't want to warn about that as there's nothing they can do about it.
-
 #![deny(unused_lifetimes)]
-#![allow(dead_code)]
 
-pub async fn october(s: &str) {
-    println!("{}", s);
-}
 
-pub async fn async_fn(&mut ref s: &mut[i32]) {
-    println!("{:?}", s);
-}
+// Async part with unused lifetimes
+//
+// Even wrong cases don't cause errors because async functions are desugared with all lifetimes
+// involved in the signature. So, we cannot predict what lifetimes are unused in async function.
+async fn async_wrong_without_args<'a>() {}
 
-macro_rules! foo_macro {
-    () => {
-        pub async fn async_fn_in_macro(&mut ref _s: &mut[i32]) {}
-    };
-}
+async fn async_wrong_1_lifetime<'a>(_: &i32) {}
 
-foo_macro!();
+async fn async_wrong_2_lifetimes<'a, 'b>(_: &'a i32, _: &i32) {}
 
-pub async fn func_with_unused_lifetime<'a>(s: &'a str) {
-    //~^ ERROR lifetime parameter `'a` never used
-    println!("{}", s);
-}
+async fn async_right_1_lifetime<'a>(_: &'a i32) {}
 
-pub async fn func_with_two_unused_lifetime<'a, 'b>(s: &'a str, t: &'b str) {
-    //~^ ERROR lifetime parameter `'a` never used
-    //~^^ ERROR lifetime parameter `'b` never used
-    println!("{}", s);
-}
+async fn async_right_2_lifetimes<'a, 'b>(_: &'a i32, _: &'b i32) {}
 
-pub async fn func_with_unused_lifetime_in_two_params<'c>(s: &'c str, t: &'c str) {
-    //~^ ERROR lifetime parameter `'c` never used
-    println!("{}", s);
-}
+async fn async_right_trait_bound_lifetime<'a, I>(_: I)
+where
+    I: Iterator<Item = &'a i32>
+{}
+
+
+// Sync part with unused lifetimes
+//
+// These functions are compiled as supposed
+fn wrong_without_args<'a>() {} //~ ERROR lifetime parameter `'a` never used
+
+fn wrong_1_lifetime<'a>(_: &i32) {} //~ ERROR lifetime parameter `'a` never used
+
+fn wrong_2_lifetimes<'a, 'b>(_: &'a i32, _: &i32) {} //~ ERROR lifetime parameter `'b` never used
+
+fn right_1_lifetime<'a>(_: &'a i32) {}
+
+fn right_2_lifetimes<'a, 'b>(_: &'a i32, _: &'b i32) {}
+
+fn right_trait_bound_lifetime<'a, I>(_: I)
+where
+    I: Iterator<Item = &'a i32>
+{}
+
 
 fn main() {}
diff --git a/src/test/ui/async-await/unused-lifetime.stderr b/src/test/ui/async-await/unused-lifetime.stderr
index 2a7a12a..4e90f43 100644
--- a/src/test/ui/async-await/unused-lifetime.stderr
+++ b/src/test/ui/async-await/unused-lifetime.stderr
@@ -1,32 +1,28 @@
 error: lifetime parameter `'a` never used
-  --> $DIR/unused-lifetime.rs:26:40
+  --> $DIR/unused-lifetime.rs:31:23
    |
-LL | pub async fn func_with_unused_lifetime<'a>(s: &'a str) {
-   |                                        ^^
+LL | fn wrong_without_args<'a>() {}
+   |                      -^^- help: elide the unused lifetime
    |
 note: the lint level is defined here
-  --> $DIR/unused-lifetime.rs:7:9
+  --> $DIR/unused-lifetime.rs:5:9
    |
 LL | #![deny(unused_lifetimes)]
    |         ^^^^^^^^^^^^^^^^
 
 error: lifetime parameter `'a` never used
-  --> $DIR/unused-lifetime.rs:31:44
+  --> $DIR/unused-lifetime.rs:33:21
    |
-LL | pub async fn func_with_two_unused_lifetime<'a, 'b>(s: &'a str, t: &'b str) {
-   |                                            ^^
+LL | fn wrong_1_lifetime<'a>(_: &i32) {}
+   |                    -^^- help: elide the unused lifetime
 
 error: lifetime parameter `'b` never used
-  --> $DIR/unused-lifetime.rs:31:48
+  --> $DIR/unused-lifetime.rs:35:26
    |
-LL | pub async fn func_with_two_unused_lifetime<'a, 'b>(s: &'a str, t: &'b str) {
-   |                                                ^^
+LL | fn wrong_2_lifetimes<'a, 'b>(_: &'a i32, _: &i32) {}
+   |                        --^^
+   |                        |
+   |                        help: elide the unused lifetime
 
-error: lifetime parameter `'c` never used
-  --> $DIR/unused-lifetime.rs:37:54
-   |
-LL | pub async fn func_with_unused_lifetime_in_two_params<'c>(s: &'c str, t: &'c str) {
-   |                                                      ^^
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/attributes/item-attributes.rs b/src/test/ui/attributes/item-attributes.rs
index a3d5933..c6bf6c6 100644
--- a/src/test/ui/attributes/item-attributes.rs
+++ b/src/test/ui/attributes/item-attributes.rs
@@ -5,7 +5,6 @@
 // check-pass
 
 #![feature(rustc_attrs)]
-
 #![rustc_dummy = "val"]
 #![rustc_dummy = "val"]
 #![rustc_dummy]
@@ -21,14 +20,14 @@
     pub static X: isize = 10;
 
     #[rustc_dummy = "val"]
-    pub fn f() { }
+    pub fn f() {}
 
     #[rustc_dummy = "val"]
     pub mod mod1 {}
 
     pub mod rustrt {
         #[rustc_dummy = "val"]
-        extern {}
+        extern "C" {}
     }
 }
 
@@ -39,7 +38,7 @@
 
     #[rustc_dummy = "val"]
     #[rustc_dummy = "val"]
-    pub fn f() { }
+    pub fn f() {}
 
     #[rustc_dummy = "val"]
     #[rustc_dummy = "val"]
@@ -48,12 +47,14 @@
     pub mod rustrt {
         #[rustc_dummy = "val"]
         #[rustc_dummy = "val"]
-        extern {}
+        extern "C" {}
     }
 
     #[rustc_dummy = "val"]
     #[rustc_dummy = "val"]
-    struct T {x: isize}
+    struct T {
+        x: isize,
+    }
 }
 
 mod test_stmt_single_attr_outer {
@@ -62,41 +63,36 @@
         static X: isize = 10;
 
         #[rustc_dummy = "val"]
-        fn f() { }
+        fn f() {}
 
         #[rustc_dummy = "val"]
-        mod mod1 {
-        }
+        mod mod1 {}
 
         mod rustrt {
             #[rustc_dummy = "val"]
-            extern {
-            }
+            extern "C" {}
         }
     }
 }
 
 mod test_stmt_multi_attr_outer {
     pub fn f() {
-
         #[rustc_dummy = "val"]
         #[rustc_dummy = "val"]
         static X: isize = 10;
 
         #[rustc_dummy = "val"]
         #[rustc_dummy = "val"]
-        fn f() { }
+        fn f() {}
 
         #[rustc_dummy = "val"]
         #[rustc_dummy = "val"]
-        mod mod1 {
-        }
+        mod mod1 {}
 
         mod rustrt {
             #[rustc_dummy = "val"]
             #[rustc_dummy = "val"]
-            extern {
-            }
+            extern "C" {}
         }
     }
 }
@@ -114,7 +110,7 @@
         #![rustc_dummy = "val"]
         // This is an attribute of fn f
         #[rustc_dummy = "val"]
-        fn f() { }
+        fn f() {}
     }
 }
 
@@ -126,7 +122,7 @@
         // This is an attribute of fn f
         #[rustc_dummy = "val"]
         #[rustc_dummy = "val"]
-        fn f() { }
+        fn f() {}
     }
 }
 
@@ -134,7 +130,7 @@
     pub fn f() {
         format!("test{}", "s");
         #[rustc_dummy = "val"]
-        fn g() { }
+        fn g() {}
     }
 }
 
@@ -143,12 +139,12 @@
     #[rustc_dummy(word)]
     #[rustc_dummy(attr(word))]
     #[rustc_dummy(key1 = "val", key2 = "val", attr)]
-    pub fn f() { }
+    pub fn f() {}
 }
 
 mod test_foreign_items {
     pub mod rustrt {
-        extern {
+        extern "C" {
             #![rustc_dummy]
 
             #[rustc_dummy]
@@ -157,7 +153,6 @@
     }
 }
 
-
 // FIXME(#623): - these aren't supported yet
 /*mod test_literals {
     #![str = "s"]
diff --git a/src/test/ui/attributes/key-value-expansion-on-mac.rs b/src/test/ui/attributes/key-value-expansion-on-mac.rs
new file mode 100644
index 0000000..1247ff2
--- /dev/null
+++ b/src/test/ui/attributes/key-value-expansion-on-mac.rs
@@ -0,0 +1,15 @@
+#![feature(extended_key_value_attributes)]
+#![feature(rustc_attrs)]
+
+#[rustc_dummy = stringify!(a)] // OK
+macro_rules! bar {
+    () => {};
+}
+
+// FIXME?: `bar` here expands before `stringify` has a chance to expand.
+// `#[rustc_dummy = ...]` is validated and dropped during expansion of `bar`,
+// the "unexpected token" errors comes from the validation.
+#[rustc_dummy = stringify!(b)] //~ ERROR unexpected token: `stringify!(b)`
+bar!();
+
+fn main() {}
diff --git a/src/test/ui/attributes/key-value-expansion-on-mac.stderr b/src/test/ui/attributes/key-value-expansion-on-mac.stderr
new file mode 100644
index 0000000..b74f351
--- /dev/null
+++ b/src/test/ui/attributes/key-value-expansion-on-mac.stderr
@@ -0,0 +1,8 @@
+error: unexpected token: `stringify!(b)`
+  --> $DIR/key-value-expansion-on-mac.rs:12:17
+   |
+LL | #[rustc_dummy = stringify!(b)]
+   |                 ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/obsolete-attr.rs b/src/test/ui/attributes/obsolete-attr.rs
index 42f90ed..7019abc 100644
--- a/src/test/ui/attributes/obsolete-attr.rs
+++ b/src/test/ui/attributes/obsolete-attr.rs
@@ -1,6 +1,6 @@
 // Obsolete attributes fall back to unstable custom attributes.
 
-#[ab_isize="stdcall"] extern {}
+#[ab_isize = "stdcall"] extern "C" {}
 //~^ ERROR cannot find attribute `ab_isize` in this scope
 
 #[fixed_stack_segment] fn f() {}
diff --git a/src/test/ui/attributes/obsolete-attr.stderr b/src/test/ui/attributes/obsolete-attr.stderr
index 2d7c257..37c1cd0 100644
--- a/src/test/ui/attributes/obsolete-attr.stderr
+++ b/src/test/ui/attributes/obsolete-attr.stderr
@@ -7,7 +7,7 @@
 error: cannot find attribute `ab_isize` in this scope
   --> $DIR/obsolete-attr.rs:3:3
    |
-LL | #[ab_isize="stdcall"] extern {}
+LL | #[ab_isize = "stdcall"] extern "C" {}
    |   ^^^^^^^^
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-38940.rs b/src/test/ui/autoref-autoderef/issue-38940.rs
similarity index 100%
rename from src/test/ui/issues/issue-38940.rs
rename to src/test/ui/autoref-autoderef/issue-38940.rs
diff --git a/src/test/ui/issues/issue-38940.stderr b/src/test/ui/autoref-autoderef/issue-38940.stderr
similarity index 100%
rename from src/test/ui/issues/issue-38940.stderr
rename to src/test/ui/autoref-autoderef/issue-38940.stderr
diff --git a/src/test/ui/auxiliary/extern-statics.rs b/src/test/ui/auxiliary/extern-statics.rs
index 725fde5..c090bc7 100644
--- a/src/test/ui/auxiliary/extern-statics.rs
+++ b/src/test/ui/auxiliary/extern-statics.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     pub static XA: u8;
     pub static mut XB: u8;
 }
diff --git a/src/test/ui/auxiliary/link-cfg-works-transitive-dylib.rs b/src/test/ui/auxiliary/link-cfg-works-transitive-dylib.rs
index fa4f33b..0d92711 100644
--- a/src/test/ui/auxiliary/link-cfg-works-transitive-dylib.rs
+++ b/src/test/ui/auxiliary/link-cfg-works-transitive-dylib.rs
@@ -1,4 +1,4 @@
 #![feature(link_cfg)]
 
 #[link(name = "foo", cfg(foo))]
-extern {}
+extern "C" {}
diff --git a/src/test/ui/auxiliary/link-cfg-works-transitive-rlib.rs b/src/test/ui/auxiliary/link-cfg-works-transitive-rlib.rs
index b365ed9..0a296f0 100644
--- a/src/test/ui/auxiliary/link-cfg-works-transitive-rlib.rs
+++ b/src/test/ui/auxiliary/link-cfg-works-transitive-rlib.rs
@@ -4,4 +4,4 @@
 #![crate_type = "rlib"]
 
 #[link(name = "foo", cfg(foo))]
-extern {}
+extern "C" {}
diff --git a/src/test/ui/auxiliary/lto-duplicate-symbols1.rs b/src/test/ui/auxiliary/lto-duplicate-symbols1.rs
index 9d510f2..ec6d056 100644
--- a/src/test/ui/auxiliary/lto-duplicate-symbols1.rs
+++ b/src/test/ui/auxiliary/lto-duplicate-symbols1.rs
@@ -3,4 +3,4 @@
 #![crate_type = "rlib"]
 
 #[no_mangle]
-pub extern fn foo() {}
+pub extern "C" fn foo() {}
diff --git a/src/test/ui/auxiliary/lto-duplicate-symbols2.rs b/src/test/ui/auxiliary/lto-duplicate-symbols2.rs
index 9d510f2..ec6d056 100644
--- a/src/test/ui/auxiliary/lto-duplicate-symbols2.rs
+++ b/src/test/ui/auxiliary/lto-duplicate-symbols2.rs
@@ -3,4 +3,4 @@
 #![crate_type = "rlib"]
 
 #[no_mangle]
-pub extern fn foo() {}
+pub extern "C" fn foo() {}
diff --git a/src/test/ui/auxiliary/trait_superkinds_in_metadata.rs b/src/test/ui/auxiliary/trait_superkinds_in_metadata.rs
deleted file mode 100644
index acfd1e1..0000000
--- a/src/test/ui/auxiliary/trait_superkinds_in_metadata.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// Test library crate for cross-crate usages of traits inheriting
-// from the builtin kinds. Mostly tests metadata correctness.
-
-#![crate_type="lib"]
-
-pub trait RequiresShare : Sync { }
-pub trait RequiresRequiresShareAndSend : RequiresShare + Send { }
-pub trait RequiresCopy : Copy { }
diff --git a/src/test/ui/bad/bad-extern-link-attrs.rs b/src/test/ui/bad/bad-extern-link-attrs.rs
index f042832..43fe8c1 100644
--- a/src/test/ui/bad/bad-extern-link-attrs.rs
+++ b/src/test/ui/bad/bad-extern-link-attrs.rs
@@ -2,6 +2,6 @@
 #[link(name = "")] //~ ERROR: with empty name
 #[link(name = "foo")]
 #[link(name = "foo", kind = "bar")] //~ ERROR: unknown kind
-extern {}
+extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/bad/bad-mid-path-type-params.rs b/src/test/ui/bad/bad-mid-path-type-params.rs
index 016b1d6..c42ce60 100644
--- a/src/test/ui/bad/bad-mid-path-type-params.rs
+++ b/src/test/ui/bad/bad-mid-path-type-params.rs
@@ -28,16 +28,17 @@
 
 fn foo<'a>() {
     let _ = S::new::<isize,f64>(1, 1.0);
-    //~^ ERROR wrong number of type arguments
+    //~^ ERROR this associated function takes 1 type argument but 2 type arguments were supplied
 
     let _ = S::<'a,isize>::new::<f64>(1, 1.0);
-    //~^ ERROR wrong number of lifetime arguments
+    //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
 
     let _: S2 = Trait::new::<isize,f64>(1, 1.0);
-    //~^ ERROR wrong number of type arguments
+    //~^ ERROR this associated function takes 1 type argument but 2 type arguments were supplied
 
-    let _: S2 = Trait::<'a,isize>::new::<f64>(1, 1.0);
-    //~^ ERROR wrong number of lifetime arguments
+    let _: S2 = Trait::<'a,isize>::new::<f64,f64>(1, 1.0);
+    //~^ ERROR this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+    //~| ERROR this associated function takes 1 type argument but 2 type arguments were supplied
 }
 
 fn main() {}
diff --git a/src/test/ui/bad/bad-mid-path-type-params.stderr b/src/test/ui/bad/bad-mid-path-type-params.stderr
index ef53c9a..dd96856 100644
--- a/src/test/ui/bad/bad-mid-path-type-params.stderr
+++ b/src/test/ui/bad/bad-mid-path-type-params.stderr
@@ -1,27 +1,73 @@
-error[E0107]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/bad-mid-path-type-params.rs:30:28
+error[E0107]: this associated function takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/bad-mid-path-type-params.rs:30:16
    |
 LL |     let _ = S::new::<isize,f64>(1, 1.0);
-   |                            ^^^ unexpected type argument
+   |                ^^^        ---- help: remove this type argument
+   |                |
+   |                expected 1 type argument
+   |
+note: associated function defined here, with 1 type parameter: `U`
+  --> $DIR/bad-mid-path-type-params.rs:6:8
+   |
+LL |     fn new<U>(x: T, _: U) -> S<T> {
+   |        ^^^ -
 
-error[E0107]: wrong number of lifetime arguments: expected 0, found 1
-  --> $DIR/bad-mid-path-type-params.rs:33:17
+error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/bad-mid-path-type-params.rs:33:13
    |
 LL |     let _ = S::<'a,isize>::new::<f64>(1, 1.0);
-   |                 ^^ unexpected lifetime argument
+   |             ^   --- help: remove this lifetime argument
+   |             |
+   |             expected 0 lifetime arguments
+   |
+note: struct defined here, with 0 lifetime parameters
+  --> $DIR/bad-mid-path-type-params.rs:1:8
+   |
+LL | struct S<T> {
+   |        ^
 
-error[E0107]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/bad-mid-path-type-params.rs:36:36
+error[E0107]: this associated function takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/bad-mid-path-type-params.rs:36:24
    |
 LL |     let _: S2 = Trait::new::<isize,f64>(1, 1.0);
-   |                                    ^^^ unexpected type argument
-
-error[E0107]: wrong number of lifetime arguments: expected 0, found 1
-  --> $DIR/bad-mid-path-type-params.rs:39:25
+   |                        ^^^        ---- help: remove this type argument
+   |                        |
+   |                        expected 1 type argument
    |
-LL |     let _: S2 = Trait::<'a,isize>::new::<f64>(1, 1.0);
-   |                         ^^ unexpected lifetime argument
+note: associated function defined here, with 1 type parameter: `U`
+  --> $DIR/bad-mid-path-type-params.rs:14:8
+   |
+LL |     fn new<U>(x: T, y: U) -> Self;
+   |        ^^^ -
 
-error: aborting due to 4 previous errors
+error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/bad-mid-path-type-params.rs:39:17
+   |
+LL |     let _: S2 = Trait::<'a,isize>::new::<f64,f64>(1, 1.0);
+   |                 ^^^^^   --- help: remove this lifetime argument
+   |                 |
+   |                 expected 0 lifetime arguments
+   |
+note: trait defined here, with 0 lifetime parameters
+  --> $DIR/bad-mid-path-type-params.rs:13:7
+   |
+LL | trait Trait<T> {
+   |       ^^^^^
+
+error[E0107]: this associated function takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/bad-mid-path-type-params.rs:39:36
+   |
+LL |     let _: S2 = Trait::<'a,isize>::new::<f64,f64>(1, 1.0);
+   |                                    ^^^      ---- help: remove this type argument
+   |                                    |
+   |                                    expected 1 type argument
+   |
+note: associated function defined here, with 1 type parameter: `U`
+  --> $DIR/bad-mid-path-type-params.rs:14:8
+   |
+LL |     fn new<U>(x: T, y: U) -> Self;
+   |        ^^^ -
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/binary-minus-without-space.rs b/src/test/ui/binop/binary-minus-without-space.rs
similarity index 100%
rename from src/test/ui/binary-minus-without-space.rs
rename to src/test/ui/binop/binary-minus-without-space.rs
diff --git a/src/test/ui/binary-op-on-double-ref.fixed b/src/test/ui/binop/binary-op-on-double-ref.fixed
similarity index 100%
rename from src/test/ui/binary-op-on-double-ref.fixed
rename to src/test/ui/binop/binary-op-on-double-ref.fixed
diff --git a/src/test/ui/binary-op-on-double-ref.rs b/src/test/ui/binop/binary-op-on-double-ref.rs
similarity index 100%
rename from src/test/ui/binary-op-on-double-ref.rs
rename to src/test/ui/binop/binary-op-on-double-ref.rs
diff --git a/src/test/ui/binary-op-on-double-ref.stderr b/src/test/ui/binop/binary-op-on-double-ref.stderr
similarity index 100%
rename from src/test/ui/binary-op-on-double-ref.stderr
rename to src/test/ui/binop/binary-op-on-double-ref.stderr
diff --git a/src/test/ui/binops-issue-22743.rs b/src/test/ui/binop/binops-issue-22743.rs
similarity index 100%
rename from src/test/ui/binops-issue-22743.rs
rename to src/test/ui/binop/binops-issue-22743.rs
diff --git a/src/test/ui/binops.rs b/src/test/ui/binop/binops.rs
similarity index 100%
rename from src/test/ui/binops.rs
rename to src/test/ui/binop/binops.rs
diff --git a/src/test/ui/issues/issue-25916.rs b/src/test/ui/binop/issue-25916.rs
similarity index 100%
rename from src/test/ui/issues/issue-25916.rs
rename to src/test/ui/binop/issue-25916.rs
diff --git a/src/test/ui/issues/issue-28837.rs b/src/test/ui/binop/issue-28837.rs
similarity index 100%
rename from src/test/ui/issues/issue-28837.rs
rename to src/test/ui/binop/issue-28837.rs
diff --git a/src/test/ui/issues/issue-28837.stderr b/src/test/ui/binop/issue-28837.stderr
similarity index 100%
rename from src/test/ui/issues/issue-28837.stderr
rename to src/test/ui/binop/issue-28837.stderr
diff --git a/src/test/ui/issues/issue-17263.rs b/src/test/ui/borrowck/issue-17263.rs
similarity index 100%
rename from src/test/ui/issues/issue-17263.rs
rename to src/test/ui/borrowck/issue-17263.rs
diff --git a/src/test/ui/issues/issue-17545.rs b/src/test/ui/borrowck/issue-17545.rs
similarity index 100%
rename from src/test/ui/issues/issue-17545.rs
rename to src/test/ui/borrowck/issue-17545.rs
diff --git a/src/test/ui/issues/issue-17545.stderr b/src/test/ui/borrowck/issue-17545.stderr
similarity index 100%
rename from src/test/ui/issues/issue-17545.stderr
rename to src/test/ui/borrowck/issue-17545.stderr
diff --git a/src/test/ui/issues/issue-20801.rs b/src/test/ui/borrowck/issue-20801.rs
similarity index 100%
rename from src/test/ui/issues/issue-20801.rs
rename to src/test/ui/borrowck/issue-20801.rs
diff --git a/src/test/ui/issues/issue-20801.stderr b/src/test/ui/borrowck/issue-20801.stderr
similarity index 100%
rename from src/test/ui/issues/issue-20801.stderr
rename to src/test/ui/borrowck/issue-20801.stderr
diff --git a/src/test/ui/issues/issue-24267-flow-exit.rs b/src/test/ui/borrowck/issue-24267-flow-exit.rs
similarity index 100%
rename from src/test/ui/issues/issue-24267-flow-exit.rs
rename to src/test/ui/borrowck/issue-24267-flow-exit.rs
diff --git a/src/test/ui/issues/issue-24267-flow-exit.stderr b/src/test/ui/borrowck/issue-24267-flow-exit.stderr
similarity index 100%
rename from src/test/ui/issues/issue-24267-flow-exit.stderr
rename to src/test/ui/borrowck/issue-24267-flow-exit.stderr
diff --git a/src/test/ui/issues/issue-25793.rs b/src/test/ui/borrowck/issue-25793.rs
similarity index 100%
rename from src/test/ui/issues/issue-25793.rs
rename to src/test/ui/borrowck/issue-25793.rs
diff --git a/src/test/ui/issues/issue-25793.stderr b/src/test/ui/borrowck/issue-25793.stderr
similarity index 100%
rename from src/test/ui/issues/issue-25793.stderr
rename to src/test/ui/borrowck/issue-25793.stderr
diff --git a/src/test/ui/issues/issue-27282-move-match-input-into-guard.rs b/src/test/ui/borrowck/issue-27282-move-match-input-into-guard.rs
similarity index 100%
rename from src/test/ui/issues/issue-27282-move-match-input-into-guard.rs
rename to src/test/ui/borrowck/issue-27282-move-match-input-into-guard.rs
diff --git a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/borrowck/issue-27282-move-match-input-into-guard.stderr
similarity index 100%
rename from src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr
rename to src/test/ui/borrowck/issue-27282-move-match-input-into-guard.stderr
diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.rs b/src/test/ui/borrowck/issue-27282-mutate-before-diverging-arm-2.rs
similarity index 100%
rename from src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.rs
rename to src/test/ui/borrowck/issue-27282-mutate-before-diverging-arm-2.rs
diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr b/src/test/ui/borrowck/issue-27282-mutate-before-diverging-arm-2.stderr
similarity index 100%
rename from src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr
rename to src/test/ui/borrowck/issue-27282-mutate-before-diverging-arm-2.stderr
diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs b/src/test/ui/borrowck/issue-27282-reborrow-ref-mut-in-guard.rs
similarity index 100%
rename from src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs
rename to src/test/ui/borrowck/issue-27282-reborrow-ref-mut-in-guard.rs
diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr b/src/test/ui/borrowck/issue-27282-reborrow-ref-mut-in-guard.stderr
similarity index 100%
rename from src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr
rename to src/test/ui/borrowck/issue-27282-reborrow-ref-mut-in-guard.stderr
diff --git a/src/test/ui/issues/issue-45199.rs b/src/test/ui/borrowck/issue-45199.rs
similarity index 100%
rename from src/test/ui/issues/issue-45199.rs
rename to src/test/ui/borrowck/issue-45199.rs
diff --git a/src/test/ui/issues/issue-45199.stderr b/src/test/ui/borrowck/issue-45199.stderr
similarity index 100%
rename from src/test/ui/issues/issue-45199.stderr
rename to src/test/ui/borrowck/issue-45199.stderr
diff --git a/src/test/ui/issues/issue-46471.rs b/src/test/ui/borrowck/issue-46471.rs
similarity index 100%
rename from src/test/ui/issues/issue-46471.rs
rename to src/test/ui/borrowck/issue-46471.rs
diff --git a/src/test/ui/issues/issue-46471.stderr b/src/test/ui/borrowck/issue-46471.stderr
similarity index 100%
rename from src/test/ui/issues/issue-46471.stderr
rename to src/test/ui/borrowck/issue-46471.stderr
diff --git a/src/test/ui/borrowck/move-in-pattern-mut-in-loop.rs b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.rs
new file mode 100644
index 0000000..4b42f9d
--- /dev/null
+++ b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.rs
@@ -0,0 +1,10 @@
+// Regression test for #80913.
+
+fn main() {
+    let mut x = 42_i32;
+    let mut opt = Some(&mut x);
+    for _ in 0..5 {
+        if let Some(mut _x) = opt {}
+        //~^ ERROR: use of moved value
+    }
+}
diff --git a/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr
new file mode 100644
index 0000000..9373e4d
--- /dev/null
+++ b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr
@@ -0,0 +1,15 @@
+error[E0382]: use of moved value
+  --> $DIR/move-in-pattern-mut-in-loop.rs:7:21
+   |
+LL |         if let Some(mut _x) = opt {}
+   |                     ^^^^^^ value moved here, in previous iteration of loop
+   |
+   = note: move occurs because value has type `&mut i32`, which does not implement the `Copy` trait
+help: borrow this field in the pattern to avoid moving `opt.0`
+   |
+LL |         if let Some(ref mut _x) = opt {}
+   |                     ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/builtin-superkinds-capabilities-transitive.rs b/src/test/ui/builtin-superkinds/builtin-superkinds-capabilities-transitive.rs
similarity index 100%
rename from src/test/ui/builtin-superkinds-capabilities-transitive.rs
rename to src/test/ui/builtin-superkinds/builtin-superkinds-capabilities-transitive.rs
diff --git a/src/test/ui/builtin-superkinds-capabilities-xc.rs b/src/test/ui/builtin-superkinds/builtin-superkinds-capabilities-xc.rs
similarity index 100%
rename from src/test/ui/builtin-superkinds-capabilities-xc.rs
rename to src/test/ui/builtin-superkinds/builtin-superkinds-capabilities-xc.rs
diff --git a/src/test/ui/builtin-superkinds-capabilities.rs b/src/test/ui/builtin-superkinds/builtin-superkinds-capabilities.rs
similarity index 100%
rename from src/test/ui/builtin-superkinds-capabilities.rs
rename to src/test/ui/builtin-superkinds/builtin-superkinds-capabilities.rs
diff --git a/src/test/ui/builtin-superkinds-in-metadata.rs b/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs
similarity index 100%
rename from src/test/ui/builtin-superkinds-in-metadata.rs
rename to src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs
diff --git a/src/test/ui/builtin-superkinds-phantom-typaram.rs b/src/test/ui/builtin-superkinds/builtin-superkinds-phantom-typaram.rs
similarity index 100%
rename from src/test/ui/builtin-superkinds-phantom-typaram.rs
rename to src/test/ui/builtin-superkinds/builtin-superkinds-phantom-typaram.rs
diff --git a/src/test/ui/builtin-superkinds-simple.rs b/src/test/ui/builtin-superkinds/builtin-superkinds-simple2.rs
similarity index 100%
rename from src/test/ui/builtin-superkinds-simple.rs
rename to src/test/ui/builtin-superkinds/builtin-superkinds-simple2.rs
diff --git a/src/test/ui/builtin-superkinds-typaram.rs b/src/test/ui/builtin-superkinds/builtin-superkinds-typaram.rs
similarity index 100%
rename from src/test/ui/builtin-superkinds-typaram.rs
rename to src/test/ui/builtin-superkinds/builtin-superkinds-typaram.rs
diff --git a/src/test/ui/c-stack-returning-int64.rs b/src/test/ui/c-stack-returning-int64.rs
index 388d280..fb3cb20 100644
--- a/src/test/ui/c-stack-returning-int64.rs
+++ b/src/test/ui/c-stack-returning-int64.rs
@@ -11,7 +11,7 @@
 mod mlibc {
     use libc::{c_char, c_long, c_longlong};
 
-    extern {
+    extern "C" {
         pub fn atol(x: *const c_char) -> c_long;
         pub fn atoll(x: *const c_char) -> c_longlong;
     }
@@ -29,6 +29,8 @@
 
 pub fn main() {
     assert_eq!(atol("1024".to_string()) * 10, atol("10240".to_string()));
-    assert_eq!((atoll("11111111111111111".to_string()) * 10),
-             atoll("111111111111111110".to_string()));
+    assert_eq!(
+        (atoll("11111111111111111".to_string()) * 10),
+        atoll("111111111111111110".to_string())
+    );
 }
diff --git a/src/test/ui/c-variadic/variadic-ffi-1.rs b/src/test/ui/c-variadic/variadic-ffi-1.rs
index a7824d9..2c02a0d 100644
--- a/src/test/ui/c-variadic/variadic-ffi-1.rs
+++ b/src/test/ui/c-variadic/variadic-ffi-1.rs
@@ -6,7 +6,7 @@
     fn printf(_: *const u8, ...); //~ ERROR: variadic function must have C or cdecl calling
 }
 
-extern {
+extern "C" {
     fn foo(f: isize, x: u8, ...);
 }
 
@@ -14,7 +14,7 @@
 
 fn main() {
     unsafe {
-        foo();  //~ ERROR this function takes at least 2 arguments but 0 arguments were supplied
+        foo(); //~ ERROR this function takes at least 2 arguments but 0 arguments were supplied
         foo(1); //~ ERROR this function takes at least 2 arguments but 1 argument was supplied
 
         let x: unsafe extern "C" fn(f: isize, x: u8) = foo; //~ ERROR mismatched types
@@ -22,8 +22,8 @@
 
         foo(1, 2, 3f32); //~ ERROR can't pass
         foo(1, 2, true); //~ ERROR can't pass
-        foo(1, 2, 1i8);  //~ ERROR can't pass
-        foo(1, 2, 1u8);  //~ ERROR can't pass
+        foo(1, 2, 1i8); //~ ERROR can't pass
+        foo(1, 2, 1u8); //~ ERROR can't pass
         foo(1, 2, 1i16); //~ ERROR can't pass
         foo(1, 2, 1u16); //~ ERROR can't pass
     }
diff --git a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.rs b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.rs
index e3b642a..588c15a 100644
--- a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.rs
+++ b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.rs
@@ -1,6 +1,6 @@
-extern {
+extern "C" {
     fn foo(...);
-    //~^ ERROR C-variadic function must be declared with at least one named argument
+//~^ ERROR C-variadic function must be declared with at least one named argument
 }
 
 fn main() {}
diff --git a/src/test/ui/cast-char.rs b/src/test/ui/cast/cast-char.rs
similarity index 100%
rename from src/test/ui/cast-char.rs
rename to src/test/ui/cast/cast-char.rs
diff --git a/src/test/ui/cast-char.stderr b/src/test/ui/cast/cast-char.stderr
similarity index 100%
rename from src/test/ui/cast-char.stderr
rename to src/test/ui/cast/cast-char.stderr
diff --git a/src/test/ui/cast-does-fallback.rs b/src/test/ui/cast/cast-does-fallback.rs
similarity index 100%
rename from src/test/ui/cast-does-fallback.rs
rename to src/test/ui/cast/cast-does-fallback.rs
diff --git a/src/test/ui/cast-region-to-uint.rs b/src/test/ui/cast/cast-region-to-uint.rs
similarity index 100%
rename from src/test/ui/cast-region-to-uint.rs
rename to src/test/ui/cast/cast-region-to-uint.rs
diff --git a/src/test/ui/cast-rfc0401-vtable-kinds.rs b/src/test/ui/cast/cast-rfc0401-vtable-kinds.rs
similarity index 100%
rename from src/test/ui/cast-rfc0401-vtable-kinds.rs
rename to src/test/ui/cast/cast-rfc0401-vtable-kinds.rs
diff --git a/src/test/ui/cast-rfc0401.rs b/src/test/ui/cast/cast-rfc0401.rs
similarity index 100%
rename from src/test/ui/cast-rfc0401.rs
rename to src/test/ui/cast/cast-rfc0401.rs
diff --git a/src/test/ui/cast-to-infer-ty.rs b/src/test/ui/cast/cast-to-infer-ty.rs
similarity index 100%
rename from src/test/ui/cast-to-infer-ty.rs
rename to src/test/ui/cast/cast-to-infer-ty.rs
diff --git a/src/test/ui/cast.rs b/src/test/ui/cast/cast.rs
similarity index 100%
rename from src/test/ui/cast.rs
rename to src/test/ui/cast/cast.rs
diff --git a/src/test/ui/casts-differing-anon.rs b/src/test/ui/cast/casts-differing-anon.rs
similarity index 100%
rename from src/test/ui/casts-differing-anon.rs
rename to src/test/ui/cast/casts-differing-anon.rs
diff --git a/src/test/ui/casts-differing-anon.stderr b/src/test/ui/cast/casts-differing-anon.stderr
similarity index 100%
rename from src/test/ui/casts-differing-anon.stderr
rename to src/test/ui/cast/casts-differing-anon.stderr
diff --git a/src/test/ui/casts-issue-46365.rs b/src/test/ui/cast/casts-issue-46365.rs
similarity index 100%
rename from src/test/ui/casts-issue-46365.rs
rename to src/test/ui/cast/casts-issue-46365.rs
diff --git a/src/test/ui/casts-issue-46365.stderr b/src/test/ui/cast/casts-issue-46365.stderr
similarity index 100%
rename from src/test/ui/casts-issue-46365.stderr
rename to src/test/ui/cast/casts-issue-46365.stderr
diff --git a/src/test/ui/cfg/conditional-compile.rs b/src/test/ui/cfg/conditional-compile.rs
index de5bd5f..69f4de4 100644
--- a/src/test/ui/cfg/conditional-compile.rs
+++ b/src/test/ui/cfg/conditional-compile.rs
@@ -16,13 +16,13 @@
 
 mod rustrt {
     #[cfg(bogus)]
-    extern {
+    extern "C" {
         // This symbol doesn't exist and would be a link error if this
         // module was codegened
         pub fn bogus();
     }
 
-    extern {}
+    extern "C" {}
 }
 
 #[cfg(bogus)]
@@ -31,52 +31,56 @@
 type t = bool;
 
 #[cfg(bogus)]
-enum tg { foo, }
+enum tg {
+    foo,
+}
 
-enum tg { bar, }
-
-#[cfg(bogus)]
-struct r {
-  i: isize,
+enum tg {
+    bar,
 }
 
 #[cfg(bogus)]
-fn r(i:isize) -> r {
-    r {
-        i: i
-    }
+struct r {
+    i: isize,
+}
+
+#[cfg(bogus)]
+fn r(i: isize) -> r {
+    r { i: i }
 }
 
 struct r {
-  i: isize,
+    i: isize,
 }
 
-fn r(i:isize) -> r {
-    r {
-        i: i
-    }
+fn r(i: isize) -> r {
+    r { i: i }
 }
 
 #[cfg(bogus)]
 mod m {
     // This needs to parse but would fail in typeck. Since it's not in
     // the current config it should not be typechecked.
-    pub fn bogus() { return 0; }
+    pub fn bogus() {
+        return 0;
+    }
 }
 
 mod m {
     // Submodules have slightly different code paths than the top-level
     // module, so let's make sure this jazz works here as well
     #[cfg(bogus)]
-    pub fn f() { }
+    pub fn f() {}
 
-    pub fn f() { }
+    pub fn f() {}
 }
 
 // Since the bogus configuration isn't defined main will just be
 // parsed, but nothing further will be done with it
 #[cfg(bogus)]
-pub fn main() { panic!() }
+pub fn main() {
+    panic!()
+}
 
 pub fn main() {
     // Exercise some of the configured items in ways that wouldn't be possible
@@ -90,8 +94,10 @@
 
 fn test_in_fn_ctxt() {
     #[cfg(bogus)]
-    fn f() { panic!() }
-    fn f() { }
+    fn f() {
+        panic!()
+    }
+    fn f() {}
     f();
 
     #[cfg(bogus)]
@@ -102,7 +108,7 @@
 
 mod test_foreign_items {
     pub mod rustrt {
-        extern {
+        extern "C" {
             #[cfg(bogus)]
             pub fn write() -> String;
             pub fn write() -> String;
@@ -117,19 +123,19 @@
 
 mod test_methods {
     struct Foo {
-        bar: usize
+        bar: usize,
     }
 
     impl Fooable for Foo {
         #[cfg(bogus)]
-        fn what(&self) { }
+        fn what(&self) {}
 
-        fn what(&self) { }
+        fn what(&self) {}
 
         #[cfg(bogus)]
-        fn the(&self) { }
+        fn the(&self) {}
 
-        fn the(&self) { }
+        fn the(&self) {}
     }
 
     trait Fooable {
diff --git a/src/test/ui/check-doc-alias-attr-location.rs b/src/test/ui/check-doc-alias-attr-location.rs
index dac9b73..007d2ae 100644
--- a/src/test/ui/check-doc-alias-attr-location.rs
+++ b/src/test/ui/check-doc-alias-attr-location.rs
@@ -1,5 +1,4 @@
 #![crate_type="lib"]
-#![feature(doc_alias)]
 
 pub struct Bar;
 pub trait Foo {
@@ -8,7 +7,7 @@
 }
 
 #[doc(alias = "foo")] //~ ERROR
-extern {}
+extern "C" {}
 
 #[doc(alias = "bar")] //~ ERROR
 impl Bar {
@@ -20,5 +19,7 @@
 impl Foo for Bar {
     #[doc(alias = "assoc")] //~ ERROR
     type X = i32;
-    fn foo() -> Self::X { 0 }
+    fn foo() -> Self::X {
+        0
+    }
 }
diff --git a/src/test/ui/check-doc-alias-attr-location.stderr b/src/test/ui/check-doc-alias-attr-location.stderr
index 29a99e4..a66e993 100644
--- a/src/test/ui/check-doc-alias-attr-location.stderr
+++ b/src/test/ui/check-doc-alias-attr-location.stderr
@@ -1,23 +1,23 @@
 error: `#[doc(alias = "...")]` isn't allowed on extern block
-  --> $DIR/check-doc-alias-attr-location.rs:10:7
+  --> $DIR/check-doc-alias-attr-location.rs:9:7
    |
 LL | #[doc(alias = "foo")]
    |       ^^^^^^^^^^^^^
 
 error: `#[doc(alias = "...")]` isn't allowed on implementation block
-  --> $DIR/check-doc-alias-attr-location.rs:13:7
+  --> $DIR/check-doc-alias-attr-location.rs:12:7
    |
 LL | #[doc(alias = "bar")]
    |       ^^^^^^^^^^^^^
 
 error: `#[doc(alias = "...")]` isn't allowed on implementation block
-  --> $DIR/check-doc-alias-attr-location.rs:19:7
+  --> $DIR/check-doc-alias-attr-location.rs:18:7
    |
 LL | #[doc(alias = "foobar")]
    |       ^^^^^^^^^^^^^^^^
 
 error: `#[doc(alias = "...")]` isn't allowed on type alias in implementation block
-  --> $DIR/check-doc-alias-attr-location.rs:21:11
+  --> $DIR/check-doc-alias-attr-location.rs:20:11
    |
 LL |     #[doc(alias = "assoc")]
    |           ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/check-doc-alias-attr.rs b/src/test/ui/check-doc-alias-attr.rs
index 0ca2349..912e35f 100644
--- a/src/test/ui/check-doc-alias-attr.rs
+++ b/src/test/ui/check-doc-alias-attr.rs
@@ -1,5 +1,4 @@
 #![crate_type = "lib"]
-#![feature(doc_alias)]
 
 #[doc(alias = "foo")] // ok!
 pub struct Bar;
diff --git a/src/test/ui/check-doc-alias-attr.stderr b/src/test/ui/check-doc-alias-attr.stderr
index dce325f..1c7fc83 100644
--- a/src/test/ui/check-doc-alias-attr.stderr
+++ b/src/test/ui/check-doc-alias-attr.stderr
@@ -1,35 +1,35 @@
 error: doc alias attribute expects a string: #[doc(alias = "a")]
-  --> $DIR/check-doc-alias-attr.rs:7:7
+  --> $DIR/check-doc-alias-attr.rs:6:7
    |
 LL | #[doc(alias)]
    |       ^^^^^
 
 error: doc alias attribute expects a string: #[doc(alias = "a")]
-  --> $DIR/check-doc-alias-attr.rs:8:7
+  --> $DIR/check-doc-alias-attr.rs:7:7
    |
 LL | #[doc(alias = 0)]
    |       ^^^^^^^^^
 
 error: doc alias attribute expects a string: #[doc(alias = "a")]
-  --> $DIR/check-doc-alias-attr.rs:9:7
+  --> $DIR/check-doc-alias-attr.rs:8:7
    |
 LL | #[doc(alias("bar"))]
    |       ^^^^^^^^^^^^
 
 error: '\"' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/check-doc-alias-attr.rs:10:15
+  --> $DIR/check-doc-alias-attr.rs:9:15
    |
 LL | #[doc(alias = "\"")]
    |               ^^^^
 
 error: '\n' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/check-doc-alias-attr.rs:11:15
+  --> $DIR/check-doc-alias-attr.rs:10:15
    |
 LL | #[doc(alias = "\n")]
    |               ^^^^
 
 error: '\n' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/check-doc-alias-attr.rs:12:15
+  --> $DIR/check-doc-alias-attr.rs:11:15
    |
 LL |   #[doc(alias = "
    |  _______________^
@@ -37,19 +37,19 @@
    | |_^
 
 error: '\t' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/check-doc-alias-attr.rs:14:15
+  --> $DIR/check-doc-alias-attr.rs:13:15
    |
 LL | #[doc(alias = "\t")]
    |               ^^^^
 
 error: `#[doc(alias = "...")]` cannot start or end with ' '
-  --> $DIR/check-doc-alias-attr.rs:15:15
+  --> $DIR/check-doc-alias-attr.rs:14:15
    |
 LL | #[doc(alias = " hello")]
    |               ^^^^^^^^
 
 error: `#[doc(alias = "...")]` cannot start or end with ' '
-  --> $DIR/check-doc-alias-attr.rs:16:15
+  --> $DIR/check-doc-alias-attr.rs:15:15
    |
 LL | #[doc(alias = "hello ")]
    |               ^^^^^^^^
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs
new file mode 100644
index 0000000..2916d8c
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs
@@ -0,0 +1,31 @@
+#![feature(capture_disjoint_fields)]
+//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+//~| `#[warn(incomplete_features)]` on by default
+//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+
+// Check that precise paths are being reported back in the error message.
+
+
+enum MultiVariant {
+    Point(i32, i32),
+    Meta(i32)
+}
+
+fn main() {
+    let mut point = MultiVariant::Point(10, -10,);
+
+    let mut meta = MultiVariant::Meta(1);
+
+    let c = || {
+        if let MultiVariant::Point(ref mut x, _) = point {
+            *x += 1;
+        }
+
+        if let MultiVariant::Meta(ref mut v) = meta {
+            *v += 1;
+        }
+    };
+
+    let a = c;
+    let b = c; //~ ERROR use of moved value: `c` [E0382]
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr
new file mode 100644
index 0000000..de0bfe3
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr
@@ -0,0 +1,26 @@
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/closure-origin-multi-variant-diagnostics.rs:1:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error[E0382]: use of moved value: `c`
+  --> $DIR/closure-origin-multi-variant-diagnostics.rs:30:13
+   |
+LL |     let a = c;
+   |             - value moved here
+LL |     let b = c;
+   |             ^ value used here after move
+   |
+note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment
+  --> $DIR/closure-origin-multi-variant-diagnostics.rs:20:52
+   |
+LL |         if let MultiVariant::Point(ref mut x, _) = point {
+   |                                                    ^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs
new file mode 100644
index 0000000..8486f03
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs
@@ -0,0 +1,26 @@
+#![feature(capture_disjoint_fields)]
+//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+//~| `#[warn(incomplete_features)]` on by default
+//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+
+// Check that precise paths are being reported back in the error message.
+
+enum SingleVariant {
+    Point(i32, i32),
+}
+
+fn main() {
+    let mut point = SingleVariant::Point(10, -10);
+
+    let c = || {
+        // FIXME(project-rfc-2229#24): Change this to be a destructure pattern
+        // once this is fixed, to remove the warning.
+        if let SingleVariant::Point(ref mut x, _) = point {
+            //~^ WARNING: irrefutable if-let pattern
+            *x += 1;
+        }
+    };
+
+    let b = c;
+    let a = c; //~ ERROR use of moved value: `c` [E0382]
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr
new file mode 100644
index 0000000..ad66f6d
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr
@@ -0,0 +1,37 @@
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/closure-origin-single-variant-diagnostics.rs:1:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+warning: irrefutable if-let pattern
+  --> $DIR/closure-origin-single-variant-diagnostics.rs:18:9
+   |
+LL | /         if let SingleVariant::Point(ref mut x, _) = point {
+LL | |
+LL | |             *x += 1;
+LL | |         }
+   | |_________^
+   |
+   = note: `#[warn(irrefutable_let_patterns)]` on by default
+
+error[E0382]: use of moved value: `c`
+  --> $DIR/closure-origin-single-variant-diagnostics.rs:25:13
+   |
+LL |     let b = c;
+   |             - value moved here
+LL |     let a = c;
+   |             ^ value used here after move
+   |
+note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment
+  --> $DIR/closure-origin-single-variant-diagnostics.rs:18:53
+   |
+LL |         if let SingleVariant::Point(ref mut x, _) = point {
+   |                                                     ^^^^^
+
+error: aborting due to previous error; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs
new file mode 100644
index 0000000..103890f
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs
@@ -0,0 +1,25 @@
+#![feature(capture_disjoint_fields)]
+//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+//~| `#[warn(incomplete_features)]` on by default
+//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+
+// Check that precise paths are being reported back in the error message.
+
+struct Y {
+    y: X
+}
+
+struct X {
+    a: u32,
+    b: u32,
+}
+
+fn main() {
+    let mut x = Y { y: X { a: 5, b: 0 } };
+    let hello = || {
+        x.y.a += 1;
+    };
+
+    let b = hello;
+    let c = hello; //~ ERROR use of moved value: `hello` [E0382]
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr
new file mode 100644
index 0000000..474d77b
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr
@@ -0,0 +1,26 @@
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/closure-origin-struct-diagnostics.rs:1:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error[E0382]: use of moved value: `hello`
+  --> $DIR/closure-origin-struct-diagnostics.rs:24:13
+   |
+LL |     let b = hello;
+   |             ----- value moved here
+LL |     let c = hello;
+   |             ^^^^^ value used here after move
+   |
+note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.y.a` out of its environment
+  --> $DIR/closure-origin-struct-diagnostics.rs:20:9
+   |
+LL |         x.y.a += 1;
+   |         ^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs
new file mode 100644
index 0000000..6b078d2
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs
@@ -0,0 +1,16 @@
+#![feature(capture_disjoint_fields)]
+//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+//~| `#[warn(incomplete_features)]` on by default
+//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+
+// Check that precise paths are being reported back in the error message.
+
+fn main() {
+    let mut x = (5, 0);
+    let hello = || {
+        x.0 += 1;
+    };
+
+    let b = hello;
+    let c = hello; //~ ERROR use of moved value: `hello` [E0382]
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr
new file mode 100644
index 0000000..716728e
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr
@@ -0,0 +1,26 @@
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/closure-origin-tuple-diagnostics-1.rs:1:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error[E0382]: use of moved value: `hello`
+  --> $DIR/closure-origin-tuple-diagnostics-1.rs:15:13
+   |
+LL |     let b = hello;
+   |             ----- value moved here
+LL |     let c = hello;
+   |             ^^^^^ value used here after move
+   |
+note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.0` out of its environment
+  --> $DIR/closure-origin-tuple-diagnostics-1.rs:11:9
+   |
+LL |         x.0 += 1;
+   |         ^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs
new file mode 100644
index 0000000..0638db6
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs
@@ -0,0 +1,15 @@
+#![feature(capture_disjoint_fields)]
+//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+//~| `#[warn(incomplete_features)]` on by default
+//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+struct S(String, String);
+
+fn expect_fn<F: Fn()>(_f: F) {}
+
+fn main() {
+    let s = S(format!("s"), format!("s"));
+    let c = || { //~ ERROR expected a closure that implements the `Fn`
+        let s = s.1;
+    };
+    expect_fn(c);
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr
new file mode 100644
index 0000000..77eb2a9
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr
@@ -0,0 +1,23 @@
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/closure-origin-tuple-diagnostics.rs:1:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
+  --> $DIR/closure-origin-tuple-diagnostics.rs:11:13
+   |
+LL |     let c = || {
+   |             ^^ this closure implements `FnOnce`, not `Fn`
+LL |         let s = s.1;
+   |                 --- closure is `FnOnce` because it moves the variable `s.1` out of its environment
+LL |     };
+LL |     expect_fn(c);
+   |     --------- the requirement to implement `Fn` derives from here
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0525`.
diff --git a/src/test/ui/closures/closure-no-fn-1.stderr b/src/test/ui/closures/closure-no-fn-1.stderr
index 7613631..2b53802 100644
--- a/src/test/ui/closures/closure-no-fn-1.stderr
+++ b/src/test/ui/closures/closure-no-fn-1.stderr
@@ -8,6 +8,11 @@
    |
    = note: expected fn pointer `fn(u8) -> u8`
                  found closure `[closure@$DIR/closure-no-fn-1.rs:6:29: 6:50]`
+note: closures can only be coerced to `fn` types if they do not capture any variables
+  --> $DIR/closure-no-fn-1.rs:6:39
+   |
+LL |     let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
+   |                                       ^ `a` captured here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/closure-no-fn-2.stderr b/src/test/ui/closures/closure-no-fn-2.stderr
index 85cbdbe..ed9f87a 100644
--- a/src/test/ui/closures/closure-no-fn-2.stderr
+++ b/src/test/ui/closures/closure-no-fn-2.stderr
@@ -8,6 +8,11 @@
    |
    = note: expected fn pointer `fn() -> u8`
                  found closure `[closure@$DIR/closure-no-fn-2.rs:6:27: 6:35]`
+note: closures can only be coerced to `fn` types if they do not capture any variables
+  --> $DIR/closure-no-fn-2.rs:6:32
+   |
+LL |     let bar: fn() -> u8 = || { b };
+   |                                ^ `b` captured here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/closure-no-fn-4.rs b/src/test/ui/closures/closure-no-fn-4.rs
new file mode 100644
index 0000000..275bff6
--- /dev/null
+++ b/src/test/ui/closures/closure-no-fn-4.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let b = 2;
+    let _: fn(usize) -> usize = match true {
+        true => |a| a + 1,
+        false => |a| a - b,
+        //~^ ERROR `match` arms have incompatible types
+    };
+}
diff --git a/src/test/ui/closures/closure-no-fn-4.stderr b/src/test/ui/closures/closure-no-fn-4.stderr
new file mode 100644
index 0000000..89798ec
--- /dev/null
+++ b/src/test/ui/closures/closure-no-fn-4.stderr
@@ -0,0 +1,24 @@
+error[E0308]: `match` arms have incompatible types
+  --> $DIR/closure-no-fn-4.rs:5:18
+   |
+LL |       let _: fn(usize) -> usize = match true {
+   |  _________________________________-
+LL | |         true => |a| a + 1,
+   | |                 --------- this is found to be of type `fn(usize) -> usize`
+LL | |         false => |a| a - b,
+   | |                  ^^^^^^^^^ expected fn pointer, found closure
+LL | |
+LL | |     };
+   | |_____- `match` arms have incompatible types
+   |
+   = note: expected fn pointer `fn(usize) -> usize`
+                 found closure `[closure@$DIR/closure-no-fn-4.rs:5:18: 5:27]`
+note: closures can only be coerced to `fn` types if they do not capture any variables
+  --> $DIR/closure-no-fn-4.rs:5:26
+   |
+LL |         false => |a| a - b,
+   |                          ^ `b` captured here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/closures/closure-no-fn-5.rs b/src/test/ui/closures/closure-no-fn-5.rs
new file mode 100644
index 0000000..43e3e97
--- /dev/null
+++ b/src/test/ui/closures/closure-no-fn-5.rs
@@ -0,0 +1,12 @@
+// When providing diagnostics about not being able to coerce a capturing-closure
+// to fn type, we want to report only upto 4 captures.
+
+fn main() {
+    let a = 0u8;
+    let b = 0u8;
+    let c = 0u8;
+    let d = 0u8;
+    let e = 0u8;
+    let bar: fn() -> u8 = || { a; b; c; d; e };
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/closures/closure-no-fn-5.stderr b/src/test/ui/closures/closure-no-fn-5.stderr
new file mode 100644
index 0000000..1f373f1
--- /dev/null
+++ b/src/test/ui/closures/closure-no-fn-5.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+  --> $DIR/closure-no-fn-5.rs:10:27
+   |
+LL |     let bar: fn() -> u8 = || { a; b; c; d; e };
+   |              ----------   ^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found closure
+   |              |
+   |              expected due to this
+   |
+   = note: expected fn pointer `fn() -> u8`
+                 found closure `[closure@$DIR/closure-no-fn-5.rs:10:27: 10:47]`
+note: closures can only be coerced to `fn` types if they do not capture any variables
+  --> $DIR/closure-no-fn-5.rs:10:32
+   |
+LL |     let bar: fn() -> u8 = || { a; b; c; d; e };
+   |                                ^  ^  ^  ^ `d` captured here
+   |                                |  |  |
+   |                                |  |  `c` captured here
+   |                                |  `b` captured here
+   |                                `a` captured here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/closures/closure-reform-bad.stderr b/src/test/ui/closures/closure-reform-bad.stderr
index 77c8c7a..3781387 100644
--- a/src/test/ui/closures/closure-reform-bad.stderr
+++ b/src/test/ui/closures/closure-reform-bad.stderr
@@ -8,6 +8,11 @@
    |
    = note: expected fn pointer `for<'r> fn(&'r str)`
                  found closure `[closure@$DIR/closure-reform-bad.rs:10:13: 10:50]`
+note: closures can only be coerced to `fn` types if they do not capture any variables
+  --> $DIR/closure-reform-bad.rs:10:43
+   |
+LL |     let f = |s: &str| println!("{}{}", s, string);
+   |                                           ^^^^^^ `string` captured here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/block-arg-call-as.rs b/src/test/ui/closures/old-closure-arg-call-as.rs
similarity index 100%
rename from src/test/ui/block-arg-call-as.rs
rename to src/test/ui/closures/old-closure-arg-call-as.rs
diff --git a/src/test/ui/block-arg.rs b/src/test/ui/closures/old-closure-arg.rs
similarity index 100%
rename from src/test/ui/block-arg.rs
rename to src/test/ui/closures/old-closure-arg.rs
diff --git a/src/test/ui/block-explicit-types.rs b/src/test/ui/closures/old-closure-explicit-types.rs
similarity index 100%
rename from src/test/ui/block-explicit-types.rs
rename to src/test/ui/closures/old-closure-explicit-types.rs
diff --git a/src/test/ui/block-expr-precedence.rs b/src/test/ui/closures/old-closure-expr-precedence.rs
similarity index 100%
rename from src/test/ui/block-expr-precedence.rs
rename to src/test/ui/closures/old-closure-expr-precedence.rs
diff --git a/src/test/ui/block-expr-precedence.stderr b/src/test/ui/closures/old-closure-expr-precedence.stderr
similarity index 82%
rename from src/test/ui/block-expr-precedence.stderr
rename to src/test/ui/closures/old-closure-expr-precedence.stderr
index c28980b..fabece1 100644
--- a/src/test/ui/block-expr-precedence.stderr
+++ b/src/test/ui/closures/old-closure-expr-precedence.stderr
@@ -1,5 +1,5 @@
 warning: unnecessary trailing semicolons
-  --> $DIR/block-expr-precedence.rs:60:21
+  --> $DIR/old-closure-expr-precedence.rs:60:21
    |
 LL |   if (true) { 12; };;; -num;
    |                     ^^ help: remove these semicolons
diff --git a/src/test/ui/block-expression-remove-semicolon.fixed b/src/test/ui/closures/old-closure-expression-remove-semicolon.fixed
similarity index 100%
rename from src/test/ui/block-expression-remove-semicolon.fixed
rename to src/test/ui/closures/old-closure-expression-remove-semicolon.fixed
diff --git a/src/test/ui/block-expression-remove-semicolon.rs b/src/test/ui/closures/old-closure-expression-remove-semicolon.rs
similarity index 100%
rename from src/test/ui/block-expression-remove-semicolon.rs
rename to src/test/ui/closures/old-closure-expression-remove-semicolon.rs
diff --git a/src/test/ui/block-expression-remove-semicolon.stderr b/src/test/ui/closures/old-closure-expression-remove-semicolon.stderr
similarity index 84%
rename from src/test/ui/block-expression-remove-semicolon.stderr
rename to src/test/ui/closures/old-closure-expression-remove-semicolon.stderr
index 74dc4d5..ab7983d 100644
--- a/src/test/ui/block-expression-remove-semicolon.stderr
+++ b/src/test/ui/closures/old-closure-expression-remove-semicolon.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/block-expression-remove-semicolon.rs:8:19
+  --> $DIR/old-closure-expression-remove-semicolon.rs:8:19
    |
 LL |       let _x: i32 = {
    |  ___________________^
diff --git a/src/test/ui/block-fn-coerce.rs b/src/test/ui/closures/old-closure-fn-coerce.rs
similarity index 100%
rename from src/test/ui/block-fn-coerce.rs
rename to src/test/ui/closures/old-closure-fn-coerce.rs
diff --git a/src/test/ui/block-iter-1.rs b/src/test/ui/closures/old-closure-iter-1.rs
similarity index 100%
rename from src/test/ui/block-iter-1.rs
rename to src/test/ui/closures/old-closure-iter-1.rs
diff --git a/src/test/ui/block-iter-2.rs b/src/test/ui/closures/old-closure-iter-2.rs
similarity index 100%
rename from src/test/ui/block-iter-2.rs
rename to src/test/ui/closures/old-closure-iter-2.rs
diff --git a/src/test/ui/closures/print/closure-print-verbose.stderr b/src/test/ui/closures/print/closure-print-verbose.stderr
index 9e07137..d19b07a 100644
--- a/src/test/ui/closures/print/closure-print-verbose.stderr
+++ b/src/test/ui/closures/print/closure-print-verbose.stderr
@@ -8,6 +8,11 @@
    |
    = note: expected fn pointer `fn(u8) -> u8`
                  found closure `[main::{closure#0} closure_substs=(unavailable)]`
+note: closures can only be coerced to `fn` types if they do not capture any variables
+  --> $DIR/closure-print-verbose.rs:10:39
+   |
+LL |     let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
+   |                                       ^ `a` captured here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/tab_3.stderr b/src/test/ui/codemap_tests/tab_3.stderr
index 958d54b..e067dbb 100644
--- a/src/test/ui/codemap_tests/tab_3.stderr
+++ b/src/test/ui/codemap_tests/tab_3.stderr
@@ -9,7 +9,7 @@
 LL |         println!("{:?}", some_vec);
    |                          ^^^^^^^^ value borrowed here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `some_vec`
+note: this function takes ownership of the receiver `self`, which moves `some_vec`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
diff --git a/src/test/ui/command/command-current-dir.rs b/src/test/ui/command/command-current-dir.rs
new file mode 100644
index 0000000..91d8e4f
--- /dev/null
+++ b/src/test/ui/command/command-current-dir.rs
@@ -0,0 +1,49 @@
+// run-pass
+// ignore-emscripten no processes
+// ignore-sgx no processes
+
+use std::env;
+use std::fs;
+use std::path::Path;
+use std::process::Command;
+
+fn main() {
+    // Checks the behavior of current_dir when used with a relative exe path.
+    let me = env::current_exe().unwrap();
+    if matches!(env::args().skip(1).next().as_deref(), Some("current-dir")) {
+        let cwd = env::current_dir().unwrap();
+        assert_eq!(cwd.file_name().unwrap(), "bar");
+        std::process::exit(0);
+    }
+    let exe = me.file_name().unwrap();
+    let cwd = me.parent().unwrap();
+    eprintln!("cwd={:?}", cwd);
+    // Change directory to where the exectuable is located, since this test
+    // fundamentally needs to use relative paths. In some cases (like
+    // remote-test-server), the current_dir can be somewhere else, so make
+    // sure it is something we can use. We assume we can write to this
+    // directory.
+    env::set_current_dir(&cwd).unwrap();
+    let foo = cwd.join("foo");
+    let bar = cwd.join("bar");
+    fs::create_dir_all(&foo).unwrap();
+    fs::create_dir_all(&bar).unwrap();
+    fs::copy(&me, foo.join(exe)).unwrap();
+
+    // Unfortunately this is inconsistent based on the platform, see
+    // https://github.com/rust-lang/rust/issues/37868. On Windows,
+    // it is relative *before* changing the directory, and on Unix
+    // it is *after* changing the directory.
+    let relative_exe = if cfg!(windows) {
+        Path::new("foo").join(exe)
+    } else {
+        Path::new("../foo").join(exe)
+    };
+
+    let status = Command::new(relative_exe)
+        .arg("current-dir")
+        .current_dir("bar")
+        .status()
+        .unwrap();
+    assert!(status.success());
+}
diff --git a/src/test/ui/const-generics/arg-in-pat-1.rs b/src/test/ui/const-generics/arg-in-pat-1.rs
new file mode 100644
index 0000000..8255508
--- /dev/null
+++ b/src/test/ui/const-generics/arg-in-pat-1.rs
@@ -0,0 +1,23 @@
+// check-pass
+enum ConstGenericEnum<const N: usize> {
+    Foo([i32; N]),
+    Bar,
+}
+
+fn foo<const N: usize>(val: &ConstGenericEnum<N>) {
+    if let ConstGenericEnum::<N>::Foo(field, ..) = val {}
+}
+
+fn bar<const N: usize>(val: &ConstGenericEnum<N>) {
+    match val {
+        ConstGenericEnum::<N>::Foo(field, ..) => (),
+        ConstGenericEnum::<N>::Bar => (),
+    }
+}
+
+fn main() {
+    match ConstGenericEnum::Bar {
+        ConstGenericEnum::<3>::Foo(field, ..) => (),
+        ConstGenericEnum::<3>::Bar => (),
+    }
+}
diff --git a/src/test/ui/const-generics/arg-in-pat-2.rs b/src/test/ui/const-generics/arg-in-pat-2.rs
new file mode 100644
index 0000000..dc9e722
--- /dev/null
+++ b/src/test/ui/const-generics/arg-in-pat-2.rs
@@ -0,0 +1,10 @@
+// check-pass
+enum Generic<const N: usize> {
+    Variant,
+}
+
+fn main() {
+    match todo!() {
+        Generic::<0usize>::Variant => todo!()
+    }
+}
diff --git a/src/test/ui/const-generics/arg-in-pat-3.rs b/src/test/ui/const-generics/arg-in-pat-3.rs
new file mode 100644
index 0000000..24626a3
--- /dev/null
+++ b/src/test/ui/const-generics/arg-in-pat-3.rs
@@ -0,0 +1,43 @@
+// check-pass
+struct Foo<const N: usize>;
+
+fn bindingp() {
+    match Foo {
+        mut x @ Foo::<3> => {
+            let ref mut _x @ Foo::<3> = x;
+        }
+    }
+}
+
+struct Bar<const N: usize> {
+    field: Foo<N>,
+}
+
+fn structp() {
+    match todo!() {
+        Bar::<3> {
+            field: Foo::<3>,
+        } => (),
+    }
+}
+
+struct Baz<const N: usize>(Foo<N>);
+
+fn tuplestructp() {
+    match Baz(Foo) {
+        Baz::<3>(Foo::<3>) => (),
+    }
+}
+
+impl<const N: usize> Baz<N> {
+    const ASSOC: usize = 3;
+}
+
+fn pathp() {
+    match 3 {
+        Baz::<3>::ASSOC => (),
+        _ => (),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr
index 7af2310..8f6e568 100644
--- a/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr
+++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr
@@ -23,7 +23,7 @@
    |                     ^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/const-generics/const-param-before-other-params.min.stderr b/src/test/ui/const-generics/const-param-before-other-params.min.stderr
index 1e49588..a9349ce 100644
--- a/src/test/ui/const-generics/const-param-before-other-params.min.stderr
+++ b/src/test/ui/const-generics/const-param-before-other-params.min.stderr
@@ -17,7 +17,7 @@
    |                 ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-before-other-params.rs:10:17
@@ -26,7 +26,7 @@
    |                 ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr b/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr
index 5d3c8f7..48d33a7 100644
--- a/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr
+++ b/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr
@@ -35,7 +35,7 @@
    |                   ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:15:15
@@ -44,7 +44,7 @@
    |               ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:23:15
@@ -53,7 +53,7 @@
    |               ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:27:17
@@ -62,7 +62,7 @@
    |                 ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:18:21
@@ -71,7 +71,7 @@
    |                     ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr b/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr
index d63bc23..9804363 100644
--- a/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr
+++ b/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr
@@ -17,7 +17,7 @@
    |                                               ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `[u8; _]` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-type-depends-on-const-param.rs:15:35
@@ -26,7 +26,7 @@
    |                                   ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/const-generics/defaults/complex-unord-param.min.stderr b/src/test/ui/const-generics/defaults/complex-unord-param.min.stderr
index cec56d7..8e8d26a 100644
--- a/src/test/ui/const-generics/defaults/complex-unord-param.min.stderr
+++ b/src/test/ui/const-generics/defaults/complex-unord-param.min.stderr
@@ -2,7 +2,7 @@
   --> $DIR/complex-unord-param.rs:8:41
    |
 LL | struct NestedArrays<'a, const N: usize, A: 'a, const M: usize, T:'a =u32> {
-   |                    ---------------------^----------------------^--------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, A: 'a, T: 'a, const N: usize, const M: usize>`
+   |                    ---------------------^----------------------^--------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, A: 'a, T: 'a = u32, const N: usize, const M: usize>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr
index 98352ad..c4a666a 100644
--- a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr
+++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr
@@ -2,13 +2,13 @@
   --> $DIR/intermixed-lifetime.rs:6:28
    |
 LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
-   |           -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T>`
+   |           -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>`
 
 error: lifetime parameters must be declared prior to type parameters
   --> $DIR/intermixed-lifetime.rs:10:37
    |
 LL | struct Bar<const N: usize, T = u32, 'a>(&'a (), T);
-   |           --------------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T>`
+   |           --------------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr
index 532f6d7..69a4909 100644
--- a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr
+++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr
@@ -2,25 +2,25 @@
   --> $DIR/intermixed-lifetime.rs:6:28
    |
 LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
-   |           -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>`
+   |           -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
 
 error: type parameters must be declared prior to const parameters
   --> $DIR/intermixed-lifetime.rs:6:32
    |
 LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
-   |           ---------------------^------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>`
+   |           ---------------------^------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
 
 error: lifetime parameters must be declared prior to const parameters
   --> $DIR/intermixed-lifetime.rs:10:37
    |
 LL | struct Bar<const N: usize, T = u32, 'a>(&'a (), T);
-   |           --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>`
+   |           --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
 
 error: type parameters must be declared prior to const parameters
   --> $DIR/intermixed-lifetime.rs:10:28
    |
 LL | struct Bar<const N: usize, T = u32, 'a>(&'a (), T);
-   |           -----------------^----------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>`
+   |           -----------------^----------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/const-generics/defaults/needs-feature.min.stderr b/src/test/ui/const-generics/defaults/needs-feature.min.stderr
index 86d6173..a400620 100644
--- a/src/test/ui/const-generics/defaults/needs-feature.min.stderr
+++ b/src/test/ui/const-generics/defaults/needs-feature.min.stderr
@@ -2,7 +2,7 @@
   --> $DIR/needs-feature.rs:9:26
    |
 LL | struct A<const N: usize, T=u32>(T);
-   |         -----------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<T, const N: usize>`
+   |         -----------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<T = u32, const N: usize>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/defaults/needs-feature.none.stderr b/src/test/ui/const-generics/defaults/needs-feature.none.stderr
index 86d6173..a400620 100644
--- a/src/test/ui/const-generics/defaults/needs-feature.none.stderr
+++ b/src/test/ui/const-generics/defaults/needs-feature.none.stderr
@@ -2,7 +2,7 @@
   --> $DIR/needs-feature.rs:9:26
    |
 LL | struct A<const N: usize, T=u32>(T);
-   |         -----------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<T, const N: usize>`
+   |         -----------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<T = u32, const N: usize>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr b/src/test/ui/const-generics/defaults/simple-defaults.min.stderr
index 01fb421..0746c64 100644
--- a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr
+++ b/src/test/ui/const-generics/defaults/simple-defaults.min.stderr
@@ -2,7 +2,7 @@
   --> $DIR/simple-defaults.rs:8:40
    |
 LL | struct FixedOutput<'a, const N: usize, T=u32> {
-   |                   ---------------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>`
+   |                   ---------------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/different_byref.min.stderr b/src/test/ui/const-generics/different_byref.min.stderr
index 05720d1..93874fb 100644
--- a/src/test/ui/const-generics/different_byref.min.stderr
+++ b/src/test/ui/const-generics/different_byref.min.stderr
@@ -5,7 +5,7 @@
    |                       ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr
index 3912cf5..80eac99 100644
--- a/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr
+++ b/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr
@@ -5,7 +5,7 @@
    |                   ^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `C` is forbidden as the type of a const generic parameter
   --> $DIR/forbid-non-structural_match-types.rs:14:19
@@ -14,7 +14,7 @@
    |                   ^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
   --> $DIR/forbid-non-structural_match-types.rs:14:19
diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr b/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr
index 9c8359b..dd7e634 100644
--- a/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr
+++ b/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr
@@ -1,14 +1,34 @@
-error[E0107]: wrong number of const arguments: expected 2, found 1
+error[E0107]: this function takes 2 const arguments but only 1 const argument was supplied
   --> $DIR/incorrect-number-of-const-args.rs:11:5
    |
 LL |     foo::<0>();
-   |     ^^^^^^^^ expected 2 const arguments
+   |     ^^^   - supplied 1 const argument
+   |     |
+   |     expected 2 const arguments
+   |
+note: function defined here, with 2 const parameters: `X`, `Y`
+  --> $DIR/incorrect-number-of-const-args.rs:6:4
+   |
+LL | fn foo<const X: usize, const Y: usize>() -> usize {
+   |    ^^^       -               -
+help: add missing const argument
+   |
+LL |     foo::<0, Y>();
+   |            ^^^
 
-error[E0107]: wrong number of const arguments: expected 2, found 3
-  --> $DIR/incorrect-number-of-const-args.rs:12:17
+error[E0107]: this function takes 2 const arguments but 3 const arguments were supplied
+  --> $DIR/incorrect-number-of-const-args.rs:14:5
    |
 LL |     foo::<0, 0, 0>();
-   |                 ^ unexpected const argument
+   |     ^^^       --- help: remove this const argument
+   |     |
+   |     expected 2 const arguments
+   |
+note: function defined here, with 2 const parameters: `X`, `Y`
+  --> $DIR/incorrect-number-of-const-args.rs:6:4
+   |
+LL | fn foo<const X: usize, const Y: usize>() -> usize {
+   |    ^^^       -               -
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr b/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr
index 9c8359b..dd7e634 100644
--- a/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr
+++ b/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr
@@ -1,14 +1,34 @@
-error[E0107]: wrong number of const arguments: expected 2, found 1
+error[E0107]: this function takes 2 const arguments but only 1 const argument was supplied
   --> $DIR/incorrect-number-of-const-args.rs:11:5
    |
 LL |     foo::<0>();
-   |     ^^^^^^^^ expected 2 const arguments
+   |     ^^^   - supplied 1 const argument
+   |     |
+   |     expected 2 const arguments
+   |
+note: function defined here, with 2 const parameters: `X`, `Y`
+  --> $DIR/incorrect-number-of-const-args.rs:6:4
+   |
+LL | fn foo<const X: usize, const Y: usize>() -> usize {
+   |    ^^^       -               -
+help: add missing const argument
+   |
+LL |     foo::<0, Y>();
+   |            ^^^
 
-error[E0107]: wrong number of const arguments: expected 2, found 3
-  --> $DIR/incorrect-number-of-const-args.rs:12:17
+error[E0107]: this function takes 2 const arguments but 3 const arguments were supplied
+  --> $DIR/incorrect-number-of-const-args.rs:14:5
    |
 LL |     foo::<0, 0, 0>();
-   |                 ^ unexpected const argument
+   |     ^^^       --- help: remove this const argument
+   |     |
+   |     expected 2 const arguments
+   |
+note: function defined here, with 2 const parameters: `X`, `Y`
+  --> $DIR/incorrect-number-of-const-args.rs:6:4
+   |
+LL | fn foo<const X: usize, const Y: usize>() -> usize {
+   |    ^^^       -               -
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.rs b/src/test/ui/const-generics/incorrect-number-of-const-args.rs
index 3c4290d..3114e71 100644
--- a/src/test/ui/const-generics/incorrect-number-of-const-args.rs
+++ b/src/test/ui/const-generics/incorrect-number-of-const-args.rs
@@ -8,6 +8,9 @@
 }
 
 fn main() {
-    foo::<0>(); //~ ERROR wrong number of const arguments: expected 2, found 1
-    foo::<0, 0, 0>(); //~ ERROR wrong number of const arguments: expected 2, found 3
+    foo::<0>();
+    //~^ ERROR this function takes 2 const arguments but only 1 const argument was supplied
+
+    foo::<0, 0, 0>();
+    //~^ ERROR this function takes 2 const arguments but 3 const arguments were supplied
 }
diff --git a/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr b/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr
index 4c2aaef..8701d54 100644
--- a/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr
+++ b/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr
@@ -14,7 +14,7 @@
    |                      ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.rs b/src/test/ui/const-generics/invalid-const-arg-for-type-param.rs
index b069cd8..b67a1f1 100644
--- a/src/test/ui/const-generics/invalid-const-arg-for-type-param.rs
+++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.rs
@@ -3,7 +3,12 @@
 struct S;
 
 fn main() {
-    let _: u32 = 5i32.try_into::<32>().unwrap(); //~ ERROR wrong number of const arguments
-    S.f::<0>(); //~ ERROR no method named `f`
-    S::<0>; //~ ERROR  wrong number of const arguments
+    let _: u32 = 5i32.try_into::<32>().unwrap();
+    //~^ ERROR this associated function takes 0 const arguments but 1 const argument was supplied
+
+    S.f::<0>();
+    //~^ ERROR no method named `f`
+
+    S::<0>;
+    //~^ ERROR this struct takes 0 const arguments but 1 const argument was supplied
 }
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 19e7d20..a75da91 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
@@ -1,11 +1,19 @@
-error[E0107]: wrong number of const arguments: expected 0, found 1
-  --> $DIR/invalid-const-arg-for-type-param.rs:6:34
+error[E0107]: this associated function takes 0 const arguments but 1 const argument was supplied
+  --> $DIR/invalid-const-arg-for-type-param.rs:6:23
    |
 LL |     let _: u32 = 5i32.try_into::<32>().unwrap();
-   |                                  ^^ unexpected const argument
+   |                       ^^^^^^^^------ help: remove these generics
+   |                       |
+   |                       expected 0 const arguments
+   |
+note: associated function defined here, with 0 const parameters
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn try_into(self) -> Result<T, Self::Error>;
+   |        ^^^^^^^^
 
 error[E0599]: no method named `f` found for struct `S` in the current scope
-  --> $DIR/invalid-const-arg-for-type-param.rs:7:7
+  --> $DIR/invalid-const-arg-for-type-param.rs:9:7
    |
 LL | struct S;
    | --------- method `f` not found for this
@@ -13,11 +21,19 @@
 LL |     S.f::<0>();
    |       ^ method not found in `S`
 
-error[E0107]: wrong number of const arguments: expected 0, found 1
-  --> $DIR/invalid-const-arg-for-type-param.rs:8:9
+error[E0107]: this struct takes 0 const arguments but 1 const argument was supplied
+  --> $DIR/invalid-const-arg-for-type-param.rs:12:5
    |
 LL |     S::<0>;
-   |         ^ unexpected const argument
+   |     ^----- help: remove these generics
+   |     |
+   |     expected 0 const arguments
+   |
+note: struct defined here, with 0 const parameters
+  --> $DIR/invalid-const-arg-for-type-param.rs:3:8
+   |
+LL | struct S;
+   |        ^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/const-generics/invalid-constant-in-args.rs b/src/test/ui/const-generics/invalid-constant-in-args.rs
index 0bd9cbf..7419d4a 100644
--- a/src/test/ui/const-generics/invalid-constant-in-args.rs
+++ b/src/test/ui/const-generics/invalid-constant-in-args.rs
@@ -2,5 +2,5 @@
 
 fn main() {
     let _: Cell<&str, "a"> = Cell::new("");
-    //~^ ERROR wrong number of generic arguments
+    //~^ ERROR this struct takes 1 generic argument but 2 generic arguments were supplied
 }
diff --git a/src/test/ui/const-generics/invalid-constant-in-args.stderr b/src/test/ui/const-generics/invalid-constant-in-args.stderr
index 9b8a5d1..57c1af3 100644
--- a/src/test/ui/const-generics/invalid-constant-in-args.stderr
+++ b/src/test/ui/const-generics/invalid-constant-in-args.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of generic arguments: expected 1, found 2
-  --> $DIR/invalid-constant-in-args.rs:4:23
+error[E0107]: this struct takes 1 generic argument but 2 generic arguments were supplied
+  --> $DIR/invalid-constant-in-args.rs:4:12
    |
 LL |     let _: Cell<&str, "a"> = Cell::new("");
-   |                       ^^^ unexpected const argument
+   |            ^^^^     ----- help: remove this generic argument
+   |            |
+   |            expected 1 generic argument
+   |
+note: struct defined here, with 1 generic parameter: `T`
+  --> $SRC_DIR/core/src/cell.rs:LL:COL
+   |
+LL | pub struct Cell<T: ?Sized> {
+   |            ^^^^ -
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr
index b6c6e6f..e96b9e7 100644
--- a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr
+++ b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr
@@ -5,7 +5,7 @@
    |                         ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-73899.rs b/src/test/ui/const-generics/issue-73899.rs
similarity index 100%
rename from src/test/ui/issues/issue-73899.rs
rename to src/test/ui/const-generics/issue-73899.rs
diff --git a/src/test/ui/issues/issue-75763.rs b/src/test/ui/const-generics/issue-75763.rs
similarity index 100%
rename from src/test/ui/issues/issue-75763.rs
rename to src/test/ui/const-generics/issue-75763.rs
diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr b/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr
index a0aee48..5c9387d 100644
--- a/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr
@@ -5,7 +5,7 @@
    |                 ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-62878.min.stderr b/src/test/ui/const-generics/issues/issue-62878.min.stderr
index 920d7e4..e4a71fe 100644
--- a/src/test/ui/const-generics/issues/issue-62878.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-62878.min.stderr
@@ -11,7 +11,7 @@
    |                                 ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr
index 543e4b2..2fb38ad 100644
--- a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr
@@ -5,7 +5,7 @@
    |                  ^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
   --> $DIR/issue-63322-forbid-dyn.rs:9:18
diff --git a/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr b/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr
index 2de8ada..4782b1d 100644
--- a/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr
@@ -5,7 +5,7 @@
    |                       ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-68615-array.min.stderr b/src/test/ui/const-generics/issues/issue-68615-array.min.stderr
index 0d17b04..d0c190b 100644
--- a/src/test/ui/const-generics/issues/issue-68615-array.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-68615-array.min.stderr
@@ -5,7 +5,7 @@
    |                     ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-71169.min.stderr b/src/test/ui/const-generics/issues/issue-71169.min.stderr
index 68ac474..1c6e08a 100644
--- a/src/test/ui/const-generics/issues/issue-71169.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-71169.min.stderr
@@ -11,7 +11,7 @@
    |                                      ^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/issues/issue-73491.min.stderr b/src/test/ui/const-generics/issues/issue-73491.min.stderr
index aeab9e2..c8f2e0d 100644
--- a/src/test/ui/const-generics/issues/issue-73491.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-73491.min.stderr
@@ -5,7 +5,7 @@
    |                   ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-74101.min.stderr b/src/test/ui/const-generics/issues/issue-74101.min.stderr
index 6561183..a7f0ecf0 100644
--- a/src/test/ui/const-generics/issues/issue-74101.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-74101.min.stderr
@@ -5,7 +5,7 @@
    |                  ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `[u8; _]` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74101.rs:9:21
@@ -14,7 +14,7 @@
    |                     ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/issues/issue-74255.min.stderr b/src/test/ui/const-generics/issues/issue-74255.min.stderr
index 2b6aa7d..62ad439 100644
--- a/src/test/ui/const-generics/issues/issue-74255.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-74255.min.stderr
@@ -5,7 +5,7 @@
    |                               ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-74950.min.stderr b/src/test/ui/const-generics/issues/issue-74950.min.stderr
index 27393d3..4e640ff 100644
--- a/src/test/ui/const-generics/issues/issue-74950.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-74950.min.stderr
@@ -5,7 +5,7 @@
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:17:23
@@ -14,7 +14,7 @@
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:17:23
@@ -23,7 +23,7 @@
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:17:23
@@ -32,7 +32,7 @@
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:17:23
@@ -41,7 +41,7 @@
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/const-generics/issues/issue-75047.min.stderr b/src/test/ui/const-generics/issues/issue-75047.min.stderr
index 4ab90dd..3c1c3ea 100644
--- a/src/test/ui/const-generics/issues/issue-75047.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-75047.min.stderr
@@ -5,7 +5,7 @@
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-76595.rs b/src/test/ui/const-generics/issues/issue-76595.rs
index 04c0190..d95d675 100644
--- a/src/test/ui/const-generics/issues/issue-76595.rs
+++ b/src/test/ui/const-generics/issues/issue-76595.rs
@@ -13,5 +13,5 @@
 
 fn main() {
     test::<2>();
-    //~^ ERROR wrong number of generic arguments
+    //~^ ERROR this function takes 2 generic arguments but only 1 generic argument was supplied
 }
diff --git a/src/test/ui/const-generics/issues/issue-76595.stderr b/src/test/ui/const-generics/issues/issue-76595.stderr
index 1e37f9d..9d95e5a 100644
--- a/src/test/ui/const-generics/issues/issue-76595.stderr
+++ b/src/test/ui/const-generics/issues/issue-76595.stderr
@@ -1,8 +1,20 @@
-error[E0107]: wrong number of generic arguments: expected 2, found 1
+error[E0107]: this function takes 2 generic arguments but only 1 generic argument was supplied
   --> $DIR/issue-76595.rs:15:5
    |
 LL |     test::<2>();
-   |     ^^^^^^^^^ expected 2 generic arguments
+   |     ^^^^   - supplied 1 generic argument
+   |     |
+   |     expected 2 generic arguments
+   |
+note: function defined here, with 2 generic parameters: `T`, `P`
+  --> $DIR/issue-76595.rs:10:4
+   |
+LL | fn test<T, const P: usize>() where Bool<{core::mem::size_of::<T>() > 4}>: True {
+   |    ^^^^ -        -
+help: add missing generic argument
+   |
+LL |     test::<2, P>();
+   |             ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/late-bound-vars/in_closure.rs b/src/test/ui/const-generics/late-bound-vars/in_closure.rs
new file mode 100644
index 0000000..0aaeaff
--- /dev/null
+++ b/src/test/ui/const-generics/late-bound-vars/in_closure.rs
@@ -0,0 +1,18 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+const fn inner<'a>() -> usize where &'a (): Sized {
+    3
+}
+
+fn test<'a>() {
+    let _ = || {
+        let _: [u8; inner::<'a>()];
+        let _ = [0; inner::<'a>()];
+    };
+}
+
+fn main() {
+    test();
+}
diff --git a/src/test/ui/const-generics/late-bound-vars/simple.rs b/src/test/ui/const-generics/late-bound-vars/simple.rs
new file mode 100644
index 0000000..2c411a3
--- /dev/null
+++ b/src/test/ui/const-generics/late-bound-vars/simple.rs
@@ -0,0 +1,16 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+const fn inner<'a>() -> usize where &'a (): Sized {
+    3
+}
+
+fn test<'a>() {
+    let _: [u8; inner::<'a>()];
+    let _ = [0; inner::<'a>()];
+}
+
+fn main() {
+    test();
+}
diff --git a/src/test/ui/const-generics/min_const_generics/complex-types.stderr b/src/test/ui/const-generics/min_const_generics/complex-types.stderr
index 20d498f..a658a7b 100644
--- a/src/test/ui/const-generics/min_const_generics/complex-types.stderr
+++ b/src/test/ui/const-generics/min_const_generics/complex-types.stderr
@@ -5,7 +5,7 @@
    |                     ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:6:21
@@ -14,7 +14,7 @@
    |                     ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `No` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:11:21
@@ -23,7 +23,7 @@
    |                     ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:14:21
@@ -32,7 +32,7 @@
    |                     ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `!` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:17:21
@@ -41,7 +41,7 @@
    |                     ^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:20:19
@@ -50,7 +50,7 @@
    |                   ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:23:20
@@ -59,7 +59,7 @@
    |                    ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/const-generics/min_const_generics/default_function_param.rs b/src/test/ui/const-generics/min_const_generics/default_function_param.rs
index d7918a7..5b0a42a 100644
--- a/src/test/ui/const-generics/min_const_generics/default_function_param.rs
+++ b/src/test/ui/const-generics/min_const_generics/default_function_param.rs
@@ -1,4 +1,4 @@
 fn foo<const SIZE: usize = 5>() {}
-                      //~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=`
+//~^ ERROR default values for const generic parameters are experimental
 
 fn main() {}
diff --git a/src/test/ui/const-generics/min_const_generics/default_function_param.stderr b/src/test/ui/const-generics/min_const_generics/default_function_param.stderr
index 8eb796d..31b5ad5 100644
--- a/src/test/ui/const-generics/min_const_generics/default_function_param.stderr
+++ b/src/test/ui/const-generics/min_const_generics/default_function_param.stderr
@@ -1,8 +1,12 @@
-error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=`
+error[E0658]: default values for const generic parameters are experimental
   --> $DIR/default_function_param.rs:1:26
    |
 LL | fn foo<const SIZE: usize = 5>() {}
-   |                          ^ expected one of 7 possible tokens
+   |                          ^^^
+   |
+   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+   = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/const-generics/min_const_generics/default_trait_param.rs b/src/test/ui/const-generics/min_const_generics/default_trait_param.rs
index c8003ad..14bac47 100644
--- a/src/test/ui/const-generics/min_const_generics/default_trait_param.rs
+++ b/src/test/ui/const-generics/min_const_generics/default_trait_param.rs
@@ -1,4 +1,4 @@
 trait Foo<const KIND: bool = true> {}
-                        //~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=`
+//~^ ERROR default values for const generic parameters are experimental
 
 fn main() {}
diff --git a/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr b/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr
index 6d112ef..5617b35 100644
--- a/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr
+++ b/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr
@@ -1,8 +1,12 @@
-error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=`
+error[E0658]: default values for const generic parameters are experimental
   --> $DIR/default_trait_param.rs:1:28
    |
 LL | trait Foo<const KIND: bool = true> {}
-   |                            ^ expected one of 7 possible tokens
+   |                            ^^^^^^
+   |
+   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+   = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr b/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr
index 05939b0..647ef54 100644
--- a/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr
+++ b/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr
@@ -5,7 +5,7 @@
    |               ^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr b/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr
index 8724c7e..d612e0c 100644
--- a/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr
+++ b/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr
@@ -5,7 +5,7 @@
    |                       ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/nested-type.min.stderr b/src/test/ui/const-generics/nested-type.min.stderr
index dabb3f2..6defd39 100644
--- a/src/test/ui/const-generics/nested-type.min.stderr
+++ b/src/test/ui/const-generics/nested-type.min.stderr
@@ -12,7 +12,7 @@
    | |__^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
   --> $DIR/nested-type.rs:15:5
diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
index 845c611..a85e2a2 100644
--- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
+++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
@@ -7,7 +7,7 @@
 //[full]~^ ERROR constant values inside of type parameter defaults
 //[min]~^^ ERROR generic parameters may not be used in const operations
 
-// FIXME(const_generics:defaults): We still don't know how to we deal with type defaults.
+// FIXME(const_generics_defaults): We still don't know how to deal with type defaults.
 struct Bar<T = [u8; N], const N: usize>(T);
 //~^ ERROR constant values inside of type parameter defaults
 //~| ERROR type parameters with a default
diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr b/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr
index 13d0b21..166a35e 100644
--- a/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr
+++ b/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr
@@ -5,7 +5,7 @@
    |                             ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static [u8]` is forbidden as the type of a const generic parameter
   --> $DIR/slice-const-param-mismatch.rs:9:28
@@ -14,7 +14,7 @@
    |                            ^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/slice-const-param.min.stderr b/src/test/ui/const-generics/slice-const-param.min.stderr
index 821c6e3..ed39a0c 100644
--- a/src/test/ui/const-generics/slice-const-param.min.stderr
+++ b/src/test/ui/const-generics/slice-const-param.min.stderr
@@ -5,7 +5,7 @@
    |                                        ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static [u8]` is forbidden as the type of a const generic parameter
   --> $DIR/slice-const-param.rs:12:41
@@ -14,7 +14,7 @@
    |                                         ^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/std/const-generics-range.min.stderr b/src/test/ui/const-generics/std/const-generics-range.min.stderr
index d7d2a84..86e6159 100644
--- a/src/test/ui/const-generics/std/const-generics-range.min.stderr
+++ b/src/test/ui/const-generics/std/const-generics-range.min.stderr
@@ -5,7 +5,7 @@
    |                        ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `RangeFrom<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:12:28
@@ -14,7 +14,7 @@
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `RangeFull` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:17:28
@@ -23,7 +23,7 @@
    |                            ^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `RangeInclusive<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:23:33
@@ -32,7 +32,7 @@
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `RangeTo<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:28:26
@@ -41,7 +41,7 @@
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `RangeToInclusive<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:33:35
@@ -50,7 +50,7 @@
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/const-generics/suggest_const_for_array.rs b/src/test/ui/const-generics/suggest_const_for_array.rs
new file mode 100644
index 0000000..f3e5a31
--- /dev/null
+++ b/src/test/ui/const-generics/suggest_const_for_array.rs
@@ -0,0 +1,10 @@
+#![crate_type = "lib"]
+
+fn example<const N: usize>() {}
+
+fn other() {
+  example::<[usize; 3]>();
+  //~^ ERROR type provided when a const
+  example::<[usize; 4+5]>();
+  //~^ ERROR type provided when a const
+}
diff --git a/src/test/ui/const-generics/suggest_const_for_array.stderr b/src/test/ui/const-generics/suggest_const_for_array.stderr
new file mode 100644
index 0000000..a617bf2
--- /dev/null
+++ b/src/test/ui/const-generics/suggest_const_for_array.stderr
@@ -0,0 +1,15 @@
+error[E0747]: type provided when a constant was expected
+  --> $DIR/suggest_const_for_array.rs:6:13
+   |
+LL |   example::<[usize; 3]>();
+   |             ^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 3 }`
+
+error[E0747]: type provided when a constant was expected
+  --> $DIR/suggest_const_for_array.rs:8:13
+   |
+LL |   example::<[usize; 4+5]>();
+   |             ^^^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 4+5 }`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0747`.
diff --git a/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr b/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr
index 92f5d81..f3516d1 100644
--- a/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr
+++ b/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr
@@ -5,7 +5,7 @@
    |                        ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static str` is forbidden as the type of a const generic parameter
   --> $DIR/issue-71348.rs:18:25
@@ -14,7 +14,7 @@
    |                         ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const_prop/ice-assert-fail-div-by-zero.rs b/src/test/ui/const_prop/ice-assert-fail-div-by-zero.rs
index d19cf00..2afbf34 100644
--- a/src/test/ui/const_prop/ice-assert-fail-div-by-zero.rs
+++ b/src/test/ui/const_prop/ice-assert-fail-div-by-zero.rs
@@ -1,6 +1,8 @@
 // check-pass
 
-// compile-flags: --crate-type lib
+// need to emit MIR, because const prop (which emits `unconditional_panic`) only runs if
+// the `optimized_mir` query is run, which it isn't in check-only mode.
+// compile-flags: --crate-type lib --emit=mir,link
 
 #![warn(unconditional_panic)]
 
diff --git a/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr b/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr
index 276fb71..865c69c 100644
--- a/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr
+++ b/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr
@@ -1,11 +1,11 @@
 warning: this operation will panic at runtime
-  --> $DIR/ice-assert-fail-div-by-zero.rs:11:5
+  --> $DIR/ice-assert-fail-div-by-zero.rs:13:5
    |
 LL |     f.0 / 0;
    |     ^^^^^^^ attempt to divide `_` by zero
    |
 note: the lint level is defined here
-  --> $DIR/ice-assert-fail-div-by-zero.rs:5:9
+  --> $DIR/ice-assert-fail-div-by-zero.rs:7:9
    |
 LL | #![warn(unconditional_panic)]
    |         ^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/constructor-lifetime-args.rs b/src/test/ui/constructor-lifetime-args.rs
index 6af5f6d..d038269 100644
--- a/src/test/ui/constructor-lifetime-args.rs
+++ b/src/test/ui/constructor-lifetime-args.rs
@@ -15,12 +15,12 @@
 fn main() {
     S(&0, &0); // OK
     S::<'static>(&0, &0);
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
+    //~^ ERROR this struct takes 2 lifetime arguments but only 1 lifetime argument was supplied
     S::<'static, 'static, 'static>(&0, &0);
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
+    //~^ ERROR this struct takes 2 lifetime arguments but 3 lifetime arguments were supplied
     E::V(&0); // OK
     E::V::<'static>(&0);
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
+    //~^ ERROR this enum takes 2 lifetime arguments but only 1 lifetime argument was supplied
     E::V::<'static, 'static, 'static>(&0);
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
+    //~^ ERROR this enum takes 2 lifetime arguments but 3 lifetime arguments were supplied
 }
diff --git a/src/test/ui/constructor-lifetime-args.stderr b/src/test/ui/constructor-lifetime-args.stderr
index ec8ed92..378b076 100644
--- a/src/test/ui/constructor-lifetime-args.stderr
+++ b/src/test/ui/constructor-lifetime-args.stderr
@@ -1,26 +1,66 @@
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this struct takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/constructor-lifetime-args.rs:17:5
    |
 LL |     S::<'static>(&0, &0);
-   |     ^^^^^^^^^^^^ expected 2 lifetime arguments
+   |     ^   ------- supplied 1 lifetime argument
+   |     |
+   |     expected 2 lifetime arguments
+   |
+note: struct defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/constructor-lifetime-args.rs:9:8
+   |
+LL | struct S<'a, 'b>(&'a u8, &'b u8);
+   |        ^ --  --
+help: add missing lifetime argument
+   |
+LL |     S::<'static, 'b>(&0, &0);
+   |                ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 3
-  --> $DIR/constructor-lifetime-args.rs:19:27
+error[E0107]: this struct takes 2 lifetime arguments but 3 lifetime arguments were supplied
+  --> $DIR/constructor-lifetime-args.rs:19:5
    |
 LL |     S::<'static, 'static, 'static>(&0, &0);
-   |                           ^^^^^^^ unexpected lifetime argument
+   |     ^                   --------- help: remove this lifetime argument
+   |     |
+   |     expected 2 lifetime arguments
+   |
+note: struct defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/constructor-lifetime-args.rs:9:8
+   |
+LL | struct S<'a, 'b>(&'a u8, &'b u8);
+   |        ^ --  --
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/constructor-lifetime-args.rs:22:5
+error[E0107]: this enum takes 2 lifetime arguments but only 1 lifetime argument was supplied
+  --> $DIR/constructor-lifetime-args.rs:22:8
    |
 LL |     E::V::<'static>(&0);
-   |     ^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |        ^   ------- supplied 1 lifetime argument
+   |        |
+   |        expected 2 lifetime arguments
+   |
+note: enum defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/constructor-lifetime-args.rs:10:6
+   |
+LL | enum E<'a, 'b> {
+   |      ^ --  --
+help: add missing lifetime argument
+   |
+LL |     E::V::<'static, 'b>(&0);
+   |                   ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 3
-  --> $DIR/constructor-lifetime-args.rs:24:30
+error[E0107]: this enum takes 2 lifetime arguments but 3 lifetime arguments were supplied
+  --> $DIR/constructor-lifetime-args.rs:24:8
    |
 LL |     E::V::<'static, 'static, 'static>(&0);
-   |                              ^^^^^^^ unexpected lifetime argument
+   |        ^                   --------- help: remove this lifetime argument
+   |        |
+   |        expected 2 lifetime arguments
+   |
+note: enum defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/constructor-lifetime-args.rs:10:6
+   |
+LL | enum E<'a, 'b> {
+   |      ^ --  --
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/consts/auxiliary/cci_const.rs b/src/test/ui/consts/auxiliary/cci_const.rs
index af6a5ad8..c83b3f4 100644
--- a/src/test/ui/consts/auxiliary/cci_const.rs
+++ b/src/test/ui/consts/auxiliary/cci_const.rs
@@ -1,4 +1,4 @@
-pub extern fn bar() {
+pub extern "C" fn bar() {
 }
 
 pub const foopy: &'static str = "hi there";
diff --git a/src/test/ui/consts/auxiliary/issue-63226.rs b/src/test/ui/consts/auxiliary/issue-63226.rs
index 39cc01a..2dc9539 100644
--- a/src/test/ui/consts/auxiliary/issue-63226.rs
+++ b/src/test/ui/consts/auxiliary/issue-63226.rs
@@ -1,5 +1,5 @@
 pub struct VTable{
-    state:extern fn(),
+    state:extern "C" fn(),
 }
 
 impl VTable{
@@ -11,4 +11,4 @@
         &VTable{state};
 }
 
-extern fn state() {}
+extern "C" fn state() {}
diff --git a/src/test/ui/check_const-feature-gated.rs b/src/test/ui/consts/check_const-feature-gated.rs
similarity index 100%
rename from src/test/ui/check_const-feature-gated.rs
rename to src/test/ui/consts/check_const-feature-gated.rs
diff --git a/src/test/ui/consts/const-address-of-interior-mut.stderr b/src/test/ui/consts/const-address-of-interior-mut.stderr
index f15174c..9312075 100644
--- a/src/test/ui/consts/const-address-of-interior-mut.stderr
+++ b/src/test/ui/consts/const-address-of-interior-mut.stderr
@@ -1,27 +1,39 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/const-address-of-interior-mut.rs:5:39
    |
 LL | const A: () = { let x = Cell::new(2); &raw const x; };
    |                                       ^^^^^^^^^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
 
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/const-address-of-interior-mut.rs:7:40
    |
 LL | static B: () = { let x = Cell::new(2); &raw const x; };
    |                                        ^^^^^^^^^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
 
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/const-address-of-interior-mut.rs:9:44
    |
 LL | static mut C: () = { let x = Cell::new(2); &raw const x; };
    |                                            ^^^^^^^^^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
 
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/const-address-of-interior-mut.rs:13:13
    |
 LL |     let y = &raw const x;
    |             ^^^^^^^^^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0492`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-cast.rs b/src/test/ui/consts/const-cast.rs
index 0d8609e..abeb241 100644
--- a/src/test/ui/consts/const-cast.rs
+++ b/src/test/ui/consts/const-cast.rs
@@ -7,7 +7,7 @@
 
 unsafe impl Sync for TestStruct {}
 
-extern fn foo() {}
+extern "C" fn foo() {}
 const x: extern "C" fn() = foo;
 static y: TestStruct = TestStruct { x: x as *const u8 };
 
diff --git a/src/test/ui/consts/const-eval/extern_fat_pointer.rs b/src/test/ui/consts/const-eval/extern_fat_pointer.rs
index f210d1a..d91d078 100644
--- a/src/test/ui/consts/const-eval/extern_fat_pointer.rs
+++ b/src/test/ui/consts/const-eval/extern_fat_pointer.rs
@@ -2,7 +2,7 @@
 
 #![feature(extern_types)]
 
-extern {
+extern "C" {
     type Opaque;
 }
 
diff --git a/src/test/ui/consts/const-eval/issue-49296.stderr b/src/test/ui/consts/const-eval/issue-49296.stderr
index 798f130..9363ffb 100644
--- a/src/test/ui/consts/const-eval/issue-49296.stderr
+++ b/src/test/ui/consts/const-eval/issue-49296.stderr
@@ -4,7 +4,7 @@
 LL | const X: u64 = *wat(42);
    | ---------------^^^^^^^^-
    |                |
-   |                pointer to alloc2 was dereferenced after this allocation got freed
+   |                pointer to alloc1 was dereferenced after this allocation got freed
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr
index afd8a4b..39a568d 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.stderr
+++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr
@@ -7,13 +7,13 @@
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: any use of this value will cause an error
-  --> $DIR/ub-nonnull.rs:18:29
+  --> $DIR/ub-nonnull.rs:18:30
    |
 LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
 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 alloc10 which has size 1
+   | |                              ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
 LL | |     mem::transmute(out_of_bounds_ptr)
 LL | | } };
    | |____-
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
index 3e148af..bcd05b4 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
@@ -95,22 +95,26 @@
 
 // # trait object
 // bad trait object
+#[warn(const_err)]
 const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) };
-//~^ ERROR it is undefined behavior to use this value
+//~^ WARN any use of this value will cause an error [const_err]
 // bad trait object
+#[warn(const_err)]
 const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
-//~^ ERROR it is undefined behavior to use this value
+//~^ WARN any use of this value will cause an error [const_err]
 // bad trait object
+#[warn(const_err)]
 const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) };
-//~^ ERROR it is undefined behavior to use this value
+//~^ WARN any use of this value will cause an error [const_err]
 const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
 //~^ ERROR it is undefined behavior to use this value
 const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
 //~^ ERROR it is undefined behavior to use this value
 const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
 //~^ ERROR it is undefined behavior to use this value
+#[warn(const_err)]
 const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: &dyn Trait = unsafe { mem::transmute((&92u8, &[&42u8; 8])) };
-//~^ ERROR it is undefined behavior to use this value
+//~^ WARN any use of this value will cause an error [const_err]
 
 // bad data *inside* the trait object
 const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr
index b750910..ec5d465 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr
@@ -134,32 +134,50 @@
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:98:1
+warning: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:99:55
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable
+   | ------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                                       |
+   |                                                       memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N
    |
-   = 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.
+note: the lint level is defined here
+  --> $DIR/ub-wide-ptr.rs:98:8
+   |
+LL | #[warn(const_err)]
+   |        ^^^^^^^^^
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:101:1
+warning: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:103:55
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable
+   | ------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                                       |
+   |                                                       memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N
    |
-   = 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.
+note: the lint level is defined here
+  --> $DIR/ub-wide-ptr.rs:102:8
+   |
+LL | #[warn(const_err)]
+   |        ^^^^^^^^^
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:104:1
+warning: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:107:51
    |
 LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer
+   | --------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                                   |
+   |                                                   unable to turn bytes into a pointer
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+note: the lint level is defined here
+  --> $DIR/ub-wide-ptr.rs:106:8
+   |
+LL | #[warn(const_err)]
+   |        ^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:106:1
+  --> $DIR/ub-wide-ptr.rs:109:1
    |
 LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned vtable pointer in wide pointer
@@ -167,7 +185,7 @@
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:108:1
+  --> $DIR/ub-wide-ptr.rs:111:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
@@ -175,23 +193,29 @@
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:110:1
+  --> $DIR/ub-wide-ptr.rs:113:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:112:1
+warning: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:116:63
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: &dyn Trait = unsafe { mem::transmute((&92u8, &[&42u8; 8])) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
+   | --------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                                               |
+   |                                                               "pointer-to-integer cast" needs an rfc before being allowed inside constants
    |
-   = 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.
+note: the lint level is defined here
+  --> $DIR/ub-wide-ptr.rs:115:8
+   |
+LL | #[warn(const_err)]
+   |        ^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:116:1
+  --> $DIR/ub-wide-ptr.rs:120:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .<deref>.<dyn-downcast>, but expected a boolean
@@ -199,7 +223,7 @@
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:120:1
+  --> $DIR/ub-wide-ptr.rs:124:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer
@@ -207,7 +231,7 @@
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:122:1
+  --> $DIR/ub-wide-ptr.rs:126:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable
@@ -215,17 +239,17 @@
    = 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]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:128:5
+  --> $DIR/ub-wide-ptr.rs:132:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inbounds test failed: 0x0 is not a valid pointer
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:132:5
+  --> $DIR/ub-wide-ptr.rs:136:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N
 
-error: aborting due to 28 previous errors
+error: aborting due to 24 previous errors; 4 warnings emitted
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs
index e18e0a8..ee07dfa 100644
--- a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs
+++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs
@@ -4,16 +4,16 @@
     fn regular_in_block();
 }
 
-const extern fn bar() {
+const extern "C" fn bar() {
     unsafe {
         regular_in_block();
         //~^ ERROR: calls in constant functions
     }
 }
 
-extern fn regular() {}
+extern "C" fn regular() {}
 
-const extern fn foo() {
+const extern "C" fn foo() {
     unsafe {
         regular();
         //~^ ERROR: calls in constant functions
diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs
index 645a957..76380eb 100644
--- a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs
+++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs
@@ -1,10 +1,10 @@
 #![feature(const_extern_fn)]
 
-const extern fn unsize(x: &[u8; 3]) -> &[u8] { x }
+const extern "C" fn unsize(x: &[u8; 3]) -> &[u8] { x }
 const unsafe extern "C" fn closure() -> fn() { || {} }
 //~^ ERROR function pointer
 //~| ERROR function pointer cast
-const unsafe extern fn use_float() { 1.0 + 1.0; }
+const unsafe extern "C" fn use_float() { 1.0 + 1.0; }
 //~^ ERROR floating point arithmetic
 const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
 //~^ ERROR casting pointers to integers
diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr
index 694e229..80d234b 100644
--- a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr
+++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr
@@ -17,10 +17,10 @@
    = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
 
 error[E0658]: floating point arithmetic is not allowed in constant functions
-  --> $DIR/const-extern-fn-min-const-fn.rs:7:38
+  --> $DIR/const-extern-fn-min-const-fn.rs:7:42
    |
-LL | const unsafe extern fn use_float() { 1.0 + 1.0; }
-   |                                      ^^^^^^^^^
+LL | const unsafe extern "C" fn use_float() { 1.0 + 1.0; }
+   |                                          ^^^^^^^^^
    |
    = note: see issue #57241 <https://github.com/rust-lang/rust/issues/57241> for more information
    = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable
diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs
index cab175b..71e6c2c 100644
--- a/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs
+++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs
@@ -1,6 +1,6 @@
 #![feature(const_extern_fn)]
 
-const unsafe extern fn foo() -> usize { 5 }
+const unsafe extern "C" fn foo() -> usize { 5 }
 
 fn main() {
     let a: [u8; foo()];
diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn.rs
index 1dc0f83..2ce2eaf 100644
--- a/src/test/ui/consts/const-extern-fn/const-extern-fn.rs
+++ b/src/test/ui/consts/const-extern-fn/const-extern-fn.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![feature(const_extern_fn)]
 
-const extern fn foo1(val: u8) -> u8 {
+const extern "C" fn foo1(val: u8) -> u8 {
     val + 1
 }
 
@@ -9,7 +9,7 @@
     val + 1
 }
 
-const unsafe extern fn bar1(val: bool) -> bool {
+const unsafe extern "C" fn bar1(val: bool) -> bool {
     !val
 }
 
@@ -28,8 +28,8 @@
     assert!(bar1_res);
     assert_eq!(bar1_res, bar2_res);
 
-    let _foo1_cast: extern fn(u8) -> u8 = foo1;
-    let _foo2_cast: extern fn(u8) -> u8 = foo2;
-    let _bar1_cast: unsafe extern fn(bool) -> bool = bar1;
-    let _bar2_cast: unsafe extern fn(bool) -> bool = bar2;
+    let _foo1_cast: extern "C" fn(u8) -> u8 = foo1;
+    let _foo2_cast: extern "C" fn(u8) -> u8 = foo2;
+    let _bar1_cast: unsafe extern "C" fn(bool) -> bool = bar1;
+    let _bar2_cast: unsafe extern "C" fn(bool) -> bool = bar2;
 }
diff --git a/src/test/ui/consts/const-extern-function.rs b/src/test/ui/consts/const-extern-function.rs
index cfcf99b..01f487a 100644
--- a/src/test/ui/consts/const-extern-function.rs
+++ b/src/test/ui/consts/const-extern-function.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![allow(non_upper_case_globals)]
 
-extern fn foopy() {}
+extern "C" fn foopy() {}
 
 static f: extern "C" fn() = foopy;
 static s: S = S { f: foopy };
diff --git a/src/test/ui/consts/const-multi-ref.rs b/src/test/ui/consts/const-multi-ref.rs
index 18645ef..7e0f1a8 100644
--- a/src/test/ui/consts/const-multi-ref.rs
+++ b/src/test/ui/consts/const-multi-ref.rs
@@ -13,7 +13,7 @@
 
 const _: std::cell::Cell<i32> = {
     let mut a = std::cell::Cell::new(5);
-    let p = &a; //~ ERROR cannot borrow a constant which may contain interior mutability
+    let p = &a; //~ ERROR borrowed element may contain interior mutability
 
     let reborrow = {p};
     let pp = &reborrow;
diff --git a/src/test/ui/consts/const-multi-ref.stderr b/src/test/ui/consts/const-multi-ref.stderr
index 9a7914b..c0a320d 100644
--- a/src/test/ui/consts/const-multi-ref.stderr
+++ b/src/test/ui/consts/const-multi-ref.stderr
@@ -4,13 +4,16 @@
 LL |     let p = &mut a;
    |             ^^^^^^ `&mut` is only allowed in `const fn`
 
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/const-multi-ref.rs:16:13
    |
 LL |     let p = &a;
    |             ^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0492, E0764.
-For more information about an error, try `rustc --explain E0492`.
+Some errors have detailed explanations: E0658, E0764.
+For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs
index 96a8a84..09c7d55 100644
--- a/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs
+++ b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs
@@ -2,9 +2,9 @@
 #![feature(core_intrinsics)]
 #![feature(const_size_of_val, const_align_of_val)]
 
-use std::intrinsics::{size_of_val, min_align_of_val};
+use std::intrinsics::{min_align_of_val, size_of_val};
 
-extern {
+extern "C" {
     type Opaque;
 }
 
diff --git a/src/test/ui/const-suggest-feature.rs b/src/test/ui/consts/const-suggest-feature.rs
similarity index 100%
rename from src/test/ui/const-suggest-feature.rs
rename to src/test/ui/consts/const-suggest-feature.rs
diff --git a/src/test/ui/const-suggest-feature.stderr b/src/test/ui/consts/const-suggest-feature.stderr
similarity index 100%
rename from src/test/ui/const-suggest-feature.stderr
rename to src/test/ui/consts/const-suggest-feature.stderr
diff --git a/src/test/ui/issues/issue-17718-borrow-interior.rs b/src/test/ui/consts/issue-17718-borrow-interior.rs
similarity index 100%
rename from src/test/ui/issues/issue-17718-borrow-interior.rs
rename to src/test/ui/consts/issue-17718-borrow-interior.rs
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.rs b/src/test/ui/consts/issue-17718-const-bad-values.rs
similarity index 100%
rename from src/test/ui/issues/issue-17718-const-bad-values.rs
rename to src/test/ui/consts/issue-17718-const-bad-values.rs
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.stderr b/src/test/ui/consts/issue-17718-const-bad-values.stderr
similarity index 100%
rename from src/test/ui/issues/issue-17718-const-bad-values.stderr
rename to src/test/ui/consts/issue-17718-const-bad-values.stderr
diff --git a/src/test/ui/consts/issue-17718-const-borrow.rs b/src/test/ui/consts/issue-17718-const-borrow.rs
new file mode 100644
index 0000000..89316db
--- /dev/null
+++ b/src/test/ui/consts/issue-17718-const-borrow.rs
@@ -0,0 +1,14 @@
+use std::cell::UnsafeCell;
+
+const A: UnsafeCell<usize> = UnsafeCell::new(1);
+const B: &'static UnsafeCell<usize> = &A;
+//~^ ERROR: cannot refer to interior mutable
+
+struct C { a: UnsafeCell<usize> }
+const D: C = C { a: UnsafeCell::new(1) };
+const E: &'static UnsafeCell<usize> = &D.a;
+//~^ ERROR: cannot refer to interior mutable
+const F: &'static C = &D;
+//~^ ERROR: cannot refer to interior mutable
+
+fn main() {}
diff --git a/src/test/ui/consts/issue-17718-const-borrow.stderr b/src/test/ui/consts/issue-17718-const-borrow.stderr
new file mode 100644
index 0000000..e3ff6c9
--- /dev/null
+++ b/src/test/ui/consts/issue-17718-const-borrow.stderr
@@ -0,0 +1,21 @@
+error[E0492]: constants cannot refer to interior mutable data
+  --> $DIR/issue-17718-const-borrow.rs:4:39
+   |
+LL | const B: &'static UnsafeCell<usize> = &A;
+   |                                       ^^ this borrow of an interior mutable value may end up in the final value
+
+error[E0492]: constants cannot refer to interior mutable data
+  --> $DIR/issue-17718-const-borrow.rs:9:39
+   |
+LL | const E: &'static UnsafeCell<usize> = &D.a;
+   |                                       ^^^^ this borrow of an interior mutable value may end up in the final value
+
+error[E0492]: constants cannot refer to interior mutable data
+  --> $DIR/issue-17718-const-borrow.rs:11:23
+   |
+LL | const F: &'static C = &D;
+   |                       ^^ this borrow of an interior mutable value may end up in the final value
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0492`.
diff --git a/src/test/ui/issues/issue-21562.rs b/src/test/ui/consts/issue-21562.rs
similarity index 100%
rename from src/test/ui/issues/issue-21562.rs
rename to src/test/ui/consts/issue-21562.rs
diff --git a/src/test/ui/issues/issue-21721.rs b/src/test/ui/consts/issue-21721.rs
similarity index 100%
rename from src/test/ui/issues/issue-21721.rs
rename to src/test/ui/consts/issue-21721.rs
diff --git a/src/test/ui/issues/issue-27890.rs b/src/test/ui/consts/issue-27890.rs
similarity index 100%
rename from src/test/ui/issues/issue-27890.rs
rename to src/test/ui/consts/issue-27890.rs
diff --git a/src/test/ui/issues/issue-28113.rs b/src/test/ui/consts/issue-28113.rs
similarity index 100%
rename from src/test/ui/issues/issue-28113.rs
rename to src/test/ui/consts/issue-28113.rs
diff --git a/src/test/ui/issues/issue-28113.stderr b/src/test/ui/consts/issue-28113.stderr
similarity index 100%
rename from src/test/ui/issues/issue-28113.stderr
rename to src/test/ui/consts/issue-28113.stderr
diff --git a/src/test/ui/issues/issue-29914-2.rs b/src/test/ui/consts/issue-29914-2.rs
similarity index 100%
rename from src/test/ui/issues/issue-29914-2.rs
rename to src/test/ui/consts/issue-29914-2.rs
diff --git a/src/test/ui/issues/issue-29914-3.rs b/src/test/ui/consts/issue-29914-3.rs
similarity index 100%
rename from src/test/ui/issues/issue-29914-3.rs
rename to src/test/ui/consts/issue-29914-3.rs
diff --git a/src/test/ui/issues/issue-29914.rs b/src/test/ui/consts/issue-29914.rs
similarity index 100%
rename from src/test/ui/issues/issue-29914.rs
rename to src/test/ui/consts/issue-29914.rs
diff --git a/src/test/ui/issues/issue-29927-1.rs b/src/test/ui/consts/issue-29927-1.rs
similarity index 100%
rename from src/test/ui/issues/issue-29927-1.rs
rename to src/test/ui/consts/issue-29927-1.rs
diff --git a/src/test/ui/issues/issue-29927.rs b/src/test/ui/consts/issue-29927.rs
similarity index 100%
rename from src/test/ui/issues/issue-29927.rs
rename to src/test/ui/consts/issue-29927.rs
diff --git a/src/test/ui/issues/issue-32829-2.rs b/src/test/ui/consts/issue-32829-2.rs
similarity index 100%
rename from src/test/ui/issues/issue-32829-2.rs
rename to src/test/ui/consts/issue-32829-2.rs
diff --git a/src/test/ui/issues/issue-32829-2.stderr b/src/test/ui/consts/issue-32829-2.stderr
similarity index 100%
rename from src/test/ui/issues/issue-32829-2.stderr
rename to src/test/ui/consts/issue-32829-2.stderr
diff --git a/src/test/ui/issues/issue-36163.rs b/src/test/ui/consts/issue-36163.rs
similarity index 100%
rename from src/test/ui/issues/issue-36163.rs
rename to src/test/ui/consts/issue-36163.rs
diff --git a/src/test/ui/issues/issue-36163.stderr b/src/test/ui/consts/issue-36163.stderr
similarity index 100%
rename from src/test/ui/issues/issue-36163.stderr
rename to src/test/ui/consts/issue-36163.stderr
diff --git a/src/test/ui/issues/issue-43105.rs b/src/test/ui/consts/issue-43105.rs
similarity index 100%
rename from src/test/ui/issues/issue-43105.rs
rename to src/test/ui/consts/issue-43105.rs
diff --git a/src/test/ui/issues/issue-43105.stderr b/src/test/ui/consts/issue-43105.stderr
similarity index 100%
rename from src/test/ui/issues/issue-43105.stderr
rename to src/test/ui/consts/issue-43105.stderr
diff --git a/src/test/ui/issues/issue-47789.rs b/src/test/ui/consts/issue-47789.rs
similarity index 100%
rename from src/test/ui/issues/issue-47789.rs
rename to src/test/ui/consts/issue-47789.rs
diff --git a/src/test/ui/issues/issue-52023-array-size-pointer-cast.rs b/src/test/ui/consts/issue-52023-array-size-pointer-cast.rs
similarity index 100%
rename from src/test/ui/issues/issue-52023-array-size-pointer-cast.rs
rename to src/test/ui/consts/issue-52023-array-size-pointer-cast.rs
diff --git a/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr b/src/test/ui/consts/issue-52023-array-size-pointer-cast.stderr
similarity index 100%
rename from src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr
rename to src/test/ui/consts/issue-52023-array-size-pointer-cast.stderr
diff --git a/src/test/ui/issues/issue-58435-ice-with-assoc-const.rs b/src/test/ui/consts/issue-58435-ice-with-assoc-const.rs
similarity index 100%
rename from src/test/ui/issues/issue-58435-ice-with-assoc-const.rs
rename to src/test/ui/consts/issue-58435-ice-with-assoc-const.rs
diff --git a/src/test/ui/issues/issue-6991.rs b/src/test/ui/consts/issue-6991.rs
similarity index 100%
rename from src/test/ui/issues/issue-6991.rs
rename to src/test/ui/consts/issue-6991.rs
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr
index b65e50e..14eeabb 100644
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr
@@ -35,11 +35,11 @@
    |         ^^^^^^
 
 warning: any use of this value will cause an error
-  --> $DIR/const_refers_to_static_cross_crate.rs:26:14
+  --> $DIR/const_refers_to_static_cross_crate.rs:26:15
    |
 LL | / const U8_MUT2: &u8 = {
 LL | |     unsafe { &(*static_cross_crate::ZERO_REF)[0] }
-   | |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
+   | |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
 LL | |
 LL | |
 LL | | };
diff --git a/src/test/ui/consts/partial_qualif.rs b/src/test/ui/consts/partial_qualif.rs
index 32c68e6..7c28b8b 100644
--- a/src/test/ui/consts/partial_qualif.rs
+++ b/src/test/ui/consts/partial_qualif.rs
@@ -3,7 +3,7 @@
 const FOO: &(Cell<usize>, bool) = {
     let mut a = (Cell::new(0), false);
     a.1 = true; // sets `qualif(a)` to `qualif(a) | qualif(true)`
-    &{a} //~ ERROR cannot borrow a constant which may contain interior mutability
+    &{a} //~ ERROR cannot refer to interior mutable
 };
 
 fn main() {}
diff --git a/src/test/ui/consts/partial_qualif.stderr b/src/test/ui/consts/partial_qualif.stderr
index 221e449..32c25be 100644
--- a/src/test/ui/consts/partial_qualif.stderr
+++ b/src/test/ui/consts/partial_qualif.stderr
@@ -1,8 +1,8 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0492]: constants cannot refer to interior mutable data
   --> $DIR/partial_qualif.rs:6:5
    |
 LL |     &{a}
-   |     ^^^^
+   |     ^^^^ this borrow of an interior mutable value may end up in the final value
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/promotion.rs b/src/test/ui/consts/promotion.rs
index e6f5c3d..b6e7127 100644
--- a/src/test/ui/consts/promotion.rs
+++ b/src/test/ui/consts/promotion.rs
@@ -4,12 +4,23 @@
 
 fn foo(_: &'static [&'static str]) {}
 fn bar(_: &'static [&'static str; 3]) {}
-fn baz_i32(_: &'static i32) {}
-fn baz_u32(_: &'static u32) {}
+const fn baz_i32(_: &'static i32) {}
+const fn baz_u32(_: &'static u32) {}
+
+const fn fail() -> i32 { 1/0 }
+const C: i32 = {
+    // Promoted that fails to evaluate in dead code -- this must work
+    // (for backwards compatibility reasons).
+    if false {
+        baz_i32(&fail());
+    }
+    42
+};
 
 fn main() {
     foo(&["a", "b", "c"]);
     bar(&["d", "e", "f"]);
+    assert_eq!(C, 42);
 
     // make sure that these do not cause trouble despite overflowing
     baz_u32(&(0-1));
diff --git a/src/test/ui/consts/ptr_comparisons.rs b/src/test/ui/consts/ptr_comparisons.rs
index be998c8..595ed30 100644
--- a/src/test/ui/consts/ptr_comparisons.rs
+++ b/src/test/ui/consts/ptr_comparisons.rs
@@ -66,6 +66,7 @@
 //~^ NOTE
     unsafe { std::ptr::raw_const!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
 //~^ ERROR any use of this value will cause an error
+//~| NOTE
 
 const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
 //~^ ERROR any use of this value will cause an error
diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr
index 63faae2..49511b8 100644
--- a/src/test/ui/consts/ptr_comparisons.stderr
+++ b/src/test/ui/consts/ptr_comparisons.stderr
@@ -16,19 +16,17 @@
    = note: `#[deny(const_err)]` on by default
 
 error: any use of this value will cause an error
-  --> $DIR/ptr_comparisons.rs:67:14
+  --> $DIR/ptr_comparisons.rs:67:35
    |
 LL | / const _: *const u8 =
 LL | |
 LL | |     unsafe { std::ptr::raw_const!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
-   | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
-   |                |
-   |                memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD
-   |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   | |___________________________________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^___-
+   |                                     |
+   |                                     memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD
 
 error: any use of this value will cause an error
-  --> $DIR/ptr_comparisons.rs:70:27
+  --> $DIR/ptr_comparisons.rs:71:27
    |
 LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
    | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -36,7 +34,7 @@
    |                           "pointer-to-integer cast" needs an rfc before being allowed inside constants
 
 error: any use of this value will cause an error
-  --> $DIR/ptr_comparisons.rs:75:27
+  --> $DIR/ptr_comparisons.rs:76:27
    |
 LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
    | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
diff --git a/src/test/ui/consts/qualif_overwrite.rs b/src/test/ui/consts/qualif_overwrite.rs
index 430eea3..aae4e41 100644
--- a/src/test/ui/consts/qualif_overwrite.rs
+++ b/src/test/ui/consts/qualif_overwrite.rs
@@ -7,7 +7,7 @@
 const FOO: &Option<Cell<usize>> = {
     let mut a = Some(Cell::new(0));
     a = None; // sets `qualif(a)` to `qualif(a) | qualif(None)`
-    &{a} //~ ERROR cannot borrow a constant which may contain interior mutability
+    &{a} //~ ERROR cannot refer to interior mutable
 };
 
 fn main() {}
diff --git a/src/test/ui/consts/qualif_overwrite.stderr b/src/test/ui/consts/qualif_overwrite.stderr
index fbaae71..86a669c 100644
--- a/src/test/ui/consts/qualif_overwrite.stderr
+++ b/src/test/ui/consts/qualif_overwrite.stderr
@@ -1,8 +1,8 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0492]: constants cannot refer to interior mutable data
   --> $DIR/qualif_overwrite.rs:10:5
    |
 LL |     &{a}
-   |     ^^^^
+   |     ^^^^ this borrow of an interior mutable value may end up in the final value
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/qualif_overwrite_2.rs b/src/test/ui/consts/qualif_overwrite_2.rs
index fa79b5c..1819d9a 100644
--- a/src/test/ui/consts/qualif_overwrite_2.rs
+++ b/src/test/ui/consts/qualif_overwrite_2.rs
@@ -5,7 +5,7 @@
 const FOO: &Option<Cell<usize>> = {
     let mut a = (Some(Cell::new(0)),);
     a.0 = None; // sets `qualif(a)` to `qualif(a) | qualif(None)`
-    &{a.0} //~ ERROR cannot borrow a constant which may contain interior mutability
+    &{a.0} //~ ERROR cannot refer to interior mutable
 };
 
 fn main() {}
diff --git a/src/test/ui/consts/qualif_overwrite_2.stderr b/src/test/ui/consts/qualif_overwrite_2.stderr
index a393c4e..9eb123d 100644
--- a/src/test/ui/consts/qualif_overwrite_2.stderr
+++ b/src/test/ui/consts/qualif_overwrite_2.stderr
@@ -1,8 +1,8 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0492]: constants cannot refer to interior mutable data
   --> $DIR/qualif_overwrite_2.rs:8:5
    |
 LL |     &{a.0}
-   |     ^^^^^^
+   |     ^^^^^^ this borrow of an interior mutable value may end up in the final value
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rustc-args-required-const.rs b/src/test/ui/consts/rustc-args-required-const.rs
similarity index 100%
rename from src/test/ui/rustc-args-required-const.rs
rename to src/test/ui/consts/rustc-args-required-const.rs
diff --git a/src/test/ui/rustc-args-required-const.stderr b/src/test/ui/consts/rustc-args-required-const.stderr
similarity index 100%
rename from src/test/ui/rustc-args-required-const.stderr
rename to src/test/ui/consts/rustc-args-required-const.stderr
diff --git a/src/test/ui/consts/std/cell.rs b/src/test/ui/consts/std/cell.rs
index cf6c0f2..f1ef541 100644
--- a/src/test/ui/consts/std/cell.rs
+++ b/src/test/ui/consts/std/cell.rs
@@ -1,18 +1,31 @@
+#![feature(const_refs_to_cell)]
+
 use std::cell::*;
 
-// not ok, because this would create a silent constant with interior mutability.
-// the rules could be relaxed in the future
+// not ok, because this creates a dangling pointer, just like `let x = Cell::new(42).as_ptr()` would
 static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr());
-//~^ ERROR cannot borrow a constant which may contain interior mutability
+//~^ ERROR encountered dangling pointer
+const FOO_CONST: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr());
+//~^ ERROR encountered dangling pointer
 
+// Ok, these are just base values and it is the `Wrap` author's job to uphold `Send` and `Sync`
+// invariants, since they used `unsafe impl`.
 static FOO3: Wrap<Cell<u32>> = Wrap(Cell::new(42));
-// ok
+const FOO3_CONST: Wrap<Cell<u32>> = Wrap(Cell::new(42));
+
+// ok, we are referring to the memory of another static item.
 static FOO4: Wrap<*mut u32> = Wrap(FOO3.0.as_ptr());
 
-// not ok, because the `as_ptr` call takes a reference to a type with interior mutability
-// which is not allowed in constants
+// not ok, the use of a constant here is equivalent to an inline declaration of the value, so
+// its memory will get freed before the constant is finished evaluating, thus creating a dangling
+// pointer. This would happen exactly the same at runtime.
+const FOO4_CONST: Wrap<*mut u32> = Wrap(FOO3_CONST.0.as_ptr());
+//~^ ERROR encountered dangling pointer
+
+// not ok, because the `as_ptr` call takes a reference to a temporary that will get freed
+// before the constant is finished evaluating.
 const FOO2: *mut u32 = Cell::new(42).as_ptr();
-//~^ ERROR cannot borrow a constant which may contain interior mutability
+//~^ ERROR encountered dangling pointer
 
 struct IMSafeTrustMe(UnsafeCell<u32>);
 unsafe impl Send for IMSafeTrustMe {}
@@ -21,10 +34,13 @@
 static BAR: IMSafeTrustMe = IMSafeTrustMe(UnsafeCell::new(5));
 
 
+
 struct Wrap<T>(T);
 unsafe impl<T> Send for Wrap<T> {}
 unsafe impl<T> Sync for Wrap<T> {}
 
 static BAR_PTR: Wrap<*mut u32> = Wrap(BAR.0.get());
 
+const fn fst_ref<T, U>(x: &(T, U)) -> &T { &x.0 }
+
 fn main() {}
diff --git a/src/test/ui/consts/std/cell.stderr b/src/test/ui/consts/std/cell.stderr
index f75aadf..355c326 100644
--- a/src/test/ui/consts/std/cell.stderr
+++ b/src/test/ui/consts/std/cell.stderr
@@ -1,15 +1,26 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
-  --> $DIR/cell.rs:5:35
+error: encountered dangling pointer in final constant
+  --> $DIR/cell.rs:6:1
    |
 LL | static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr());
-   |                                   ^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
-  --> $DIR/cell.rs:14:24
+error: encountered dangling pointer in final constant
+  --> $DIR/cell.rs:8:1
+   |
+LL | const FOO_CONST: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr());
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: encountered dangling pointer in final constant
+  --> $DIR/cell.rs:22:1
+   |
+LL | const FOO4_CONST: Wrap<*mut u32> = Wrap(FOO3_CONST.0.as_ptr());
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: encountered dangling pointer in final constant
+  --> $DIR/cell.rs:27:1
    |
 LL | const FOO2: *mut u32 = Cell::new(42).as_ptr();
-   |                        ^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0492`.
diff --git a/src/test/ui/cross-crate/auxiliary/cci_const.rs b/src/test/ui/cross-crate/auxiliary/cci_const.rs
index af6a5ad8..c83b3f4 100644
--- a/src/test/ui/cross-crate/auxiliary/cci_const.rs
+++ b/src/test/ui/cross-crate/auxiliary/cci_const.rs
@@ -1,4 +1,4 @@
-pub extern fn bar() {
+pub extern "C" fn bar() {
 }
 
 pub const foopy: &'static str = "hi there";
diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr
index 0e7174e..c270593 100644
--- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr
+++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr
@@ -31,6 +31,15 @@
 ...
 LL |     TupleStruct(_) = TupleStruct(1, 2);
    |     ^^^^^^^^^^^^^^ expected 2 fields, found 1
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |     TupleStruct(_, _) = TupleStruct(1, 2);
+   |                  ^^^
+help: use `..` to ignore all fields
+   |
+LL |     TupleStruct(..) = TupleStruct(1, 2);
+   |                 ^^
 
 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
   --> $DIR/tuple_struct_destructure_fail.rs:34:5
@@ -49,6 +58,15 @@
 ...
 LL |     Enum::SingleVariant(_) = Enum::SingleVariant(1, 2);
    |     ^^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 1
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |     Enum::SingleVariant(_, _) = Enum::SingleVariant(1, 2);
+   |                          ^^^
+help: use `..` to ignore all fields
+   |
+LL |     Enum::SingleVariant(..) = Enum::SingleVariant(1, 2);
+   |                         ^^
 
 error[E0070]: invalid left-hand side of assignment
   --> $DIR/tuple_struct_destructure_fail.rs:40:12
diff --git a/src/test/ui/doc-alias-crate-level.rs b/src/test/ui/doc-alias-crate-level.rs
index 9b596ec..c7783aa 100644
--- a/src/test/ui/doc-alias-crate-level.rs
+++ b/src/test/ui/doc-alias-crate-level.rs
@@ -1,7 +1,5 @@
 // compile-flags: -Zdeduplicate-diagnostics=no
 
-#![feature(doc_alias)]
-
 #![crate_type = "lib"]
 
 #![doc(alias = "not working!")] //~ ERROR
diff --git a/src/test/ui/doc-alias-crate-level.stderr b/src/test/ui/doc-alias-crate-level.stderr
index b6437fa..c046751 100644
--- a/src/test/ui/doc-alias-crate-level.stderr
+++ b/src/test/ui/doc-alias-crate-level.stderr
@@ -1,11 +1,11 @@
 error: '\'' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/doc-alias-crate-level.rs:9:15
+  --> $DIR/doc-alias-crate-level.rs:7:15
    |
 LL | #[doc(alias = "shouldn't work!")]
    |               ^^^^^^^^^^^^^^^^^
 
 error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute
-  --> $DIR/doc-alias-crate-level.rs:7:8
+  --> $DIR/doc-alias-crate-level.rs:5:8
    |
 LL | #![doc(alias = "not working!")]
    |        ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/doc-alias-same-name.rs b/src/test/ui/doc-alias-same-name.rs
new file mode 100644
index 0000000..da97c26
--- /dev/null
+++ b/src/test/ui/doc-alias-same-name.rs
@@ -0,0 +1,4 @@
+#![crate_type = "lib"]
+
+#[doc(alias = "Foo")] //~ ERROR
+pub struct Foo;
diff --git a/src/test/ui/doc-alias-same-name.stderr b/src/test/ui/doc-alias-same-name.stderr
new file mode 100644
index 0000000..5ba09a2
--- /dev/null
+++ b/src/test/ui/doc-alias-same-name.stderr
@@ -0,0 +1,8 @@
+error: `#[doc(alias = "...")]` is the same as the item's name
+  --> $DIR/doc-alias-same-name.rs:3:7
+   |
+LL | #[doc(alias = "Foo")]
+   |       ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/auxiliary/issue-10028.rs b/src/test/ui/drop/auxiliary/issue-10028.rs
similarity index 100%
rename from src/test/ui/issues/auxiliary/issue-10028.rs
rename to src/test/ui/drop/auxiliary/issue-10028.rs
diff --git a/src/test/ui/issues/issue-10028.rs b/src/test/ui/drop/issue-10028.rs
similarity index 100%
rename from src/test/ui/issues/issue-10028.rs
rename to src/test/ui/drop/issue-10028.rs
diff --git a/src/test/ui/issues/issue-30018-nopanic.rs b/src/test/ui/drop/issue-30018-nopanic.rs
similarity index 100%
rename from src/test/ui/issues/issue-30018-nopanic.rs
rename to src/test/ui/drop/issue-30018-nopanic.rs
diff --git a/src/test/ui/issues/issue-28498-ugeh-with-lifetime-param.rs b/src/test/ui/dropck/issue-28498-ugeh-with-lifetime-param.rs
similarity index 100%
rename from src/test/ui/issues/issue-28498-ugeh-with-lifetime-param.rs
rename to src/test/ui/dropck/issue-28498-ugeh-with-lifetime-param.rs
diff --git a/src/test/ui/issues/issue-28498-ugeh-with-trait-bound.rs b/src/test/ui/dropck/issue-28498-ugeh-with-trait-bound.rs
similarity index 100%
rename from src/test/ui/issues/issue-28498-ugeh-with-trait-bound.rs
rename to src/test/ui/dropck/issue-28498-ugeh-with-trait-bound.rs
diff --git a/src/test/ui/issues/issue-29844.rs b/src/test/ui/dropck/issue-29844.rs
similarity index 100%
rename from src/test/ui/issues/issue-29844.rs
rename to src/test/ui/dropck/issue-29844.rs
diff --git a/src/test/ui/duplicate/dupe-symbols-2.rs b/src/test/ui/duplicate/dupe-symbols-2.rs
index d9edd77..e303a79 100644
--- a/src/test/ui/duplicate/dupe-symbols-2.rs
+++ b/src/test/ui/duplicate/dupe-symbols-2.rs
@@ -6,13 +6,13 @@
 
 pub mod a {
     #[no_mangle]
-    pub extern fn fail() {
+    pub extern "C" fn fail() {
     }
 }
 
 pub mod b {
     #[no_mangle]
-    pub extern fn fail() {
+    pub extern "C" fn fail() {
     //~^ symbol `fail` is already defined
     }
 }
diff --git a/src/test/ui/duplicate/dupe-symbols-2.stderr b/src/test/ui/duplicate/dupe-symbols-2.stderr
index 1b29edf..b132eae 100644
--- a/src/test/ui/duplicate/dupe-symbols-2.stderr
+++ b/src/test/ui/duplicate/dupe-symbols-2.stderr
@@ -1,8 +1,8 @@
 error: symbol `fail` is already defined
   --> $DIR/dupe-symbols-2.rs:15:5
    |
-LL |     pub extern fn fail() {
-   |     ^^^^^^^^^^^^^^^^^^^^
+LL |     pub extern "C" fn fail() {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/editions/async-block-2015.rs b/src/test/ui/editions/async-block-2015.rs
index 985606a..92eae9e 100644
--- a/src/test/ui/editions/async-block-2015.rs
+++ b/src/test/ui/editions/async-block-2015.rs
@@ -1,13 +1,13 @@
 async fn foo() {
-//~^ ERROR `async fn` is not permitted in the 2015 edition
-//~| NOTE to use `async fn`, switch to Rust 2018
+//~^ ERROR `async fn` is not permitted in Rust 2015
+//~| NOTE to use `async fn`, switch to Rust 2018 or later
 //~| HELP set `edition = "2018"` in `Cargo.toml`
 //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
 
     let x = async {};
     //~^ ERROR cannot find struct, variant or union type `async` in this scope
-    //~| NOTE `async` blocks are only allowed in the 2018 edition
-    let y = async { //~ NOTE `async` blocks are only allowed in the 2018 edition
+    //~| NOTE `async` blocks are only allowed in Rust 2018 or later
+    let y = async { //~ NOTE `async` blocks are only allowed in Rust 2018 or later
         let x = 42;
         //~^ ERROR expected identifier, found keyword `let`
         //~| NOTE expected identifier, found keyword
@@ -15,7 +15,7 @@
         //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
         42
     };
-    let z = async { //~ NOTE `async` blocks are only allowed in the 2018 edition
+    let z = async { //~ NOTE `async` blocks are only allowed in Rust 2018 or later
         42
         //~^ ERROR expected identifier, found `42`
         //~| NOTE expected identifier
diff --git a/src/test/ui/editions/async-block-2015.stderr b/src/test/ui/editions/async-block-2015.stderr
index 8e5e5d8..e42747c 100644
--- a/src/test/ui/editions/async-block-2015.stderr
+++ b/src/test/ui/editions/async-block-2015.stderr
@@ -1,8 +1,8 @@
-error[E0670]: `async fn` is not permitted in the 2015 edition
+error[E0670]: `async fn` is not permitted in Rust 2015
   --> $DIR/async-block-2015.rs:1:1
    |
 LL | async fn foo() {
-   | ^^^^^ to use `async fn`, switch to Rust 2018
+   | ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
@@ -11,7 +11,7 @@
   --> $DIR/async-block-2015.rs:11:9
    |
 LL |     let y = async {
-   |             ----- `async` blocks are only allowed in the 2018 edition
+   |             ----- `async` blocks are only allowed in Rust 2018 or later
 LL |         let x = 42;
    |         ^^^ expected identifier, found keyword
    |
@@ -22,7 +22,7 @@
   --> $DIR/async-block-2015.rs:19:9
    |
 LL |     let z = async {
-   |             ----- `async` blocks are only allowed in the 2018 edition
+   |             ----- `async` blocks are only allowed in Rust 2018 or later
 LL |         42
    |         ^^ expected identifier
    |
@@ -33,7 +33,7 @@
   --> $DIR/async-block-2015.rs:7:13
    |
 LL |     let x = async {};
-   |             ^^^^^ `async` blocks are only allowed in the 2018 edition
+   |             ^^^^^ `async` blocks are only allowed in Rust 2018 or later
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/empty/empty-linkname.rs b/src/test/ui/empty/empty-linkname.rs
index 79895ab..b641233 100644
--- a/src/test/ui/empty/empty-linkname.rs
+++ b/src/test/ui/empty/empty-linkname.rs
@@ -1,5 +1,4 @@
 #[link(name = "")] //~ ERROR: given with empty name
-extern {
-}
+extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-43398.rs b/src/test/ui/enum-discriminant/issue-43398.rs
similarity index 100%
rename from src/test/ui/issues/issue-43398.rs
rename to src/test/ui/enum-discriminant/issue-43398.rs
diff --git a/src/test/ui/issues/issue-43398.stderr b/src/test/ui/enum-discriminant/issue-43398.stderr
similarity index 100%
rename from src/test/ui/issues/issue-43398.stderr
rename to src/test/ui/enum-discriminant/issue-43398.stderr
diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr
index a361009..832eba6 100644
--- a/src/test/ui/error-codes/E0023.stderr
+++ b/src/test/ui/error-codes/E0023.stderr
@@ -6,6 +6,11 @@
 ...
 LL |         Fruit::Apple(a) => {},
    |         ^^^^^^^^^^^^^^^ expected 2 fields, found 1
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         Fruit::Apple(a, _) => {},
+   |                       ^^^
 
 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
   --> $DIR/E0023.rs:12:9
@@ -34,7 +39,7 @@
 LL |         Fruit::Orange(a, b) => {},
    |         ^^^^^^^^^^^^^^^^^^^ expected 1 field, found 2
    |
-help: missing parenthesis
+help: missing parentheses
    |
 LL |         Fruit::Orange((a, b)) => {},
    |                       ^    ^
@@ -48,7 +53,7 @@
 LL |         Fruit::Banana() => {},
    |         ^^^^^^^^^^^^^^^ expected 1 field, found 0
    |
-help: missing parenthesis
+help: missing parentheses
    |
 LL |         Fruit::Banana(()) => {},
    |                      ^  ^
diff --git a/src/test/ui/error-codes/E0044.rs b/src/test/ui/error-codes/E0044.rs
index 9eee9c3..d9cdaf8 100644
--- a/src/test/ui/error-codes/E0044.rs
+++ b/src/test/ui/error-codes/E0044.rs
@@ -1,9 +1,8 @@
-extern {
+extern "C" {
     fn sqrt<T>(f: T) -> T;
-    //~^ ERROR foreign items may not have type parameters [E0044]
-    //~| HELP replace the type parameters with concrete types
-    //~| NOTE can't have type parameters
+//~^ ERROR foreign items may not have type parameters [E0044]
+//~| HELP replace the type parameters with concrete types
+//~| NOTE can't have type parameters
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/error-codes/E0107.rs b/src/test/ui/error-codes/E0107.rs
index 35173dc..c3dde72 100644
--- a/src/test/ui/error-codes/E0107.rs
+++ b/src/test/ui/error-codes/E0107.rs
@@ -9,15 +9,16 @@
 
 struct Baz<'a, 'b, 'c> {
     buzz: Buzz<'a>,
-    //~^ ERROR E0107
-    //~| expected 2 lifetime arguments
+    //~^ ERROR this struct takes 2 lifetime arguments but only 1 lifetime argument was supplied
+    //~| HELP add missing lifetime argument
+
     bar: Bar<'a>,
-    //~^ ERROR E0107
-    //~| unexpected lifetime argument
+    //~^ ERROR this enum takes 0 lifetime arguments but 1 lifetime argument was supplied
+    //~| HELP remove these generics
+
     foo2: Foo<'a, 'b, 'c>,
-    //~^ ERROR E0107
-    //~| unexpected lifetime argument
-    //~| unexpected lifetime argument
+    //~^ ERROR this struct takes 1 lifetime argument but 3 lifetime arguments were supplied
+    //~| HELP remove these lifetime arguments
 }
 
 fn main() {}
diff --git a/src/test/ui/error-codes/E0107.stderr b/src/test/ui/error-codes/E0107.stderr
index 486810a..30a2768 100644
--- a/src/test/ui/error-codes/E0107.stderr
+++ b/src/test/ui/error-codes/E0107.stderr
@@ -1,22 +1,48 @@
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this struct takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/E0107.rs:11:11
    |
 LL |     buzz: Buzz<'a>,
-   |           ^^^^^^^^ expected 2 lifetime arguments
+   |           ^^^^ -- supplied 1 lifetime argument
+   |           |
+   |           expected 2 lifetime arguments
+   |
+note: struct defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/E0107.rs:2:8
+   |
+LL | struct Buzz<'a, 'b>(&'a str, &'b str);
+   |        ^^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     buzz: Buzz<'a, 'b>,
+   |                  ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 0, found 1
-  --> $DIR/E0107.rs:14:14
+error[E0107]: this enum takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/E0107.rs:15:10
    |
 LL |     bar: Bar<'a>,
-   |              ^^ unexpected lifetime argument
+   |          ^^^---- help: remove these generics
+   |          |
+   |          expected 0 lifetime arguments
+   |
+note: enum defined here, with 0 lifetime parameters
+  --> $DIR/E0107.rs:4:6
+   |
+LL | enum Bar {
+   |      ^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 1, found 3
-  --> $DIR/E0107.rs:17:19
+error[E0107]: this struct takes 1 lifetime argument but 3 lifetime arguments were supplied
+  --> $DIR/E0107.rs:19:11
    |
 LL |     foo2: Foo<'a, 'b, 'c>,
-   |                   ^^  ^^ unexpected lifetime argument
-   |                   |
-   |                   unexpected lifetime argument
+   |           ^^^   -------- help: remove these lifetime arguments
+   |           |
+   |           expected 1 lifetime argument
+   |
+note: struct defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/E0107.rs:1:8
+   |
+LL | struct Foo<'a>(&'a str);
+   |        ^^^ --
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/error-codes/E0130.rs b/src/test/ui/error-codes/E0130.rs
index 1ac546b..d523507 100644
--- a/src/test/ui/error-codes/E0130.rs
+++ b/src/test/ui/error-codes/E0130.rs
@@ -1,7 +1,6 @@
-extern {
+extern "C" {
     fn foo((a, b): (u32, u32));
-    //~^ ERROR E0130
+//~^ ERROR E0130
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/error-codes/E0435.fixed b/src/test/ui/error-codes/E0435.fixed
new file mode 100644
index 0000000..fdf896d
--- /dev/null
+++ b/src/test/ui/error-codes/E0435.fixed
@@ -0,0 +1,6 @@
+// run-rustfix
+fn main () {
+    #[allow(non_upper_case_globals)]
+    const foo: usize = 42;
+    let _: [u8; foo]; //~ ERROR E0435
+}
diff --git a/src/test/ui/error-codes/E0435.rs b/src/test/ui/error-codes/E0435.rs
index 620dd30..d9354ef 100644
--- a/src/test/ui/error-codes/E0435.rs
+++ b/src/test/ui/error-codes/E0435.rs
@@ -1,4 +1,6 @@
+// run-rustfix
 fn main () {
-    let foo = 42u32;
+    #[allow(non_upper_case_globals)]
+    let foo: usize = 42;
     let _: [u8; foo]; //~ ERROR E0435
 }
diff --git a/src/test/ui/error-codes/E0435.stderr b/src/test/ui/error-codes/E0435.stderr
index 349aa0d..fc08fad 100644
--- a/src/test/ui/error-codes/E0435.stderr
+++ b/src/test/ui/error-codes/E0435.stderr
@@ -1,6 +1,8 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/E0435.rs:3:17
+  --> $DIR/E0435.rs:5:17
    |
+LL |     let foo: usize = 42;
+   |     ------- help: consider using `const` instead of `let`: `const foo`
 LL |     let _: [u8; foo];
    |                 ^^^ non-constant value
 
diff --git a/src/test/ui/error-codes/E0454.rs b/src/test/ui/error-codes/E0454.rs
index d62210c..ff54783 100644
--- a/src/test/ui/error-codes/E0454.rs
+++ b/src/test/ui/error-codes/E0454.rs
@@ -1,4 +1,4 @@
-#[link(name = "")] extern {}
+#[link(name = "")] extern "C" {}
 //~^ ERROR E0454
 
 fn main() {
diff --git a/src/test/ui/error-codes/E0454.stderr b/src/test/ui/error-codes/E0454.stderr
index 4991626..6b62bef 100644
--- a/src/test/ui/error-codes/E0454.stderr
+++ b/src/test/ui/error-codes/E0454.stderr
@@ -1,7 +1,7 @@
 error[E0454]: `#[link(name = "")]` given with empty name
   --> $DIR/E0454.rs:1:1
    |
-LL | #[link(name = "")] extern {}
+LL | #[link(name = "")] extern "C" {}
    | ^^^^^^^^^^^^^^^^^^ empty name given
 
 error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0458.rs b/src/test/ui/error-codes/E0458.rs
index 3d23035..35e7e84 100644
--- a/src/test/ui/error-codes/E0458.rs
+++ b/src/test/ui/error-codes/E0458.rs
@@ -1,5 +1,5 @@
-#[link(kind = "wonderful_unicorn")] extern {} //~ ERROR E0458
-                                              //~| ERROR E0459
+#[link(kind = "wonderful_unicorn")] extern "C" {} //~ ERROR E0458
+                                                  //~| ERROR E0459
 
 fn main() {
 }
diff --git a/src/test/ui/error-codes/E0458.stderr b/src/test/ui/error-codes/E0458.stderr
index 51f7764..0f2fec0 100644
--- a/src/test/ui/error-codes/E0458.stderr
+++ b/src/test/ui/error-codes/E0458.stderr
@@ -1,7 +1,7 @@
 error[E0458]: unknown kind: `wonderful_unicorn`
   --> $DIR/E0458.rs:1:8
    |
-LL | #[link(kind = "wonderful_unicorn")] extern {}
+LL | #[link(kind = "wonderful_unicorn")] extern "C" {}
    | -------^^^^^^^^^^^^^^^^^^^^^^^^^^--
    |        |
    |        unknown kind
@@ -9,7 +9,7 @@
 error[E0459]: `#[link(...)]` specified without `name = "foo"`
   --> $DIR/E0458.rs:1:1
    |
-LL | #[link(kind = "wonderful_unicorn")] extern {}
+LL | #[link(kind = "wonderful_unicorn")] extern "C" {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/error-codes/E0459.rs b/src/test/ui/error-codes/E0459.rs
index 80a2fd3..c56d8f0 100644
--- a/src/test/ui/error-codes/E0459.rs
+++ b/src/test/ui/error-codes/E0459.rs
@@ -1,4 +1,4 @@
-#[link(kind = "dylib")] extern {} //~ ERROR E0459
+#[link(kind = "dylib")] extern "C" {} //~ ERROR E0459
 
 fn main() {
 }
diff --git a/src/test/ui/error-codes/E0459.stderr b/src/test/ui/error-codes/E0459.stderr
index c618fea..4e0d51e 100644
--- a/src/test/ui/error-codes/E0459.stderr
+++ b/src/test/ui/error-codes/E0459.stderr
@@ -1,7 +1,7 @@
 error[E0459]: `#[link(...)]` specified without `name = "foo"`
   --> $DIR/E0459.rs:1:1
    |
-LL | #[link(kind = "dylib")] extern {}
+LL | #[link(kind = "dylib")] extern "C" {}
    | ^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument
 
 error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0492.rs b/src/test/ui/error-codes/E0492.rs
index 2de4c12..2c735fc 100644
--- a/src/test/ui/error-codes/E0492.rs
+++ b/src/test/ui/error-codes/E0492.rs
@@ -1,7 +1,10 @@
 use std::sync::atomic::AtomicUsize;
 
 const A: AtomicUsize = AtomicUsize::new(0);
-static B: &'static AtomicUsize = &A; //~ ERROR E0492
+const B: &'static AtomicUsize = &A; //~ ERROR E0492
+static C: &'static AtomicUsize = &A; //~ ERROR E0492
+
+const NONE: &'static Option<AtomicUsize> = &None;
 
 fn main() {
 }
diff --git a/src/test/ui/error-codes/E0492.stderr b/src/test/ui/error-codes/E0492.stderr
index 5f337dd..557c977 100644
--- a/src/test/ui/error-codes/E0492.stderr
+++ b/src/test/ui/error-codes/E0492.stderr
@@ -1,9 +1,17 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
-  --> $DIR/E0492.rs:4:34
+error[E0492]: constants cannot refer to interior mutable data
+  --> $DIR/E0492.rs:4:33
    |
-LL | static B: &'static AtomicUsize = &A;
-   |                                  ^^
+LL | const B: &'static AtomicUsize = &A;
+   |                                 ^^ this borrow of an interior mutable value may end up in the final value
 
-error: aborting due to previous error
+error[E0492]: statics cannot refer to interior mutable data
+  --> $DIR/E0492.rs:5:34
+   |
+LL | static C: &'static AtomicUsize = &A;
+   |                                  ^^ this borrow of an interior mutable value may end up in the final value
+   |
+   = help: to fix this, the value can be extracted to a separate `static` item and then referenced
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0492`.
diff --git a/src/test/ui/error-codes/E0617.rs b/src/test/ui/error-codes/E0617.rs
index c832e09..b71ba0e 100644
--- a/src/test/ui/error-codes/E0617.rs
+++ b/src/test/ui/error-codes/E0617.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     fn printf(c: *const i8, ...);
 }
 
diff --git a/src/test/ui/extern/auxiliary/extern-take-value.rs b/src/test/ui/extern/auxiliary/extern-take-value.rs
index 869e794..56256aa 100644
--- a/src/test/ui/extern/auxiliary/extern-take-value.rs
+++ b/src/test/ui/extern/auxiliary/extern-take-value.rs
@@ -1,5 +1,5 @@
-pub extern fn f() -> i32 { 1 }
-pub extern fn g() -> i32 { 2 }
+pub extern "C" fn f() -> i32 { 1 }
+pub extern "C" fn g() -> i32 { 2 }
 
-pub fn get_f() -> extern fn() -> i32 { f }
-pub fn get_g() -> extern fn() -> i32 { g }
+pub fn get_f() -> extern "C" fn() -> i32 { f }
+pub fn get_g() -> extern "C" fn() -> i32 { g }
diff --git a/src/test/ui/extern/auxiliary/extern_calling_convention.rs b/src/test/ui/extern/auxiliary/extern_calling_convention.rs
index 968b1a2..e24cf9f 100644
--- a/src/test/ui/extern/auxiliary/extern_calling_convention.rs
+++ b/src/test/ui/extern/auxiliary/extern_calling_convention.rs
@@ -15,7 +15,7 @@
 
 #[inline(never)]
 #[cfg(not(target_arch = "x86_64"))]
-pub extern fn foo(a: isize, b: isize, c: isize, d: isize) {
+pub extern "C" fn foo(a: isize, b: isize, c: isize, d: isize) {
     assert_eq!(a, 1);
     assert_eq!(b, 2);
     assert_eq!(c, 3);
diff --git a/src/test/ui/extern/extern-1.rs b/src/test/ui/extern/extern-1.rs
index eb9aabc..66e5605 100644
--- a/src/test/ui/extern/extern-1.rs
+++ b/src/test/ui/extern/extern-1.rs
@@ -2,7 +2,7 @@
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
-extern fn f() {
+extern "C" fn f() {
 }
 
 pub fn main() {
diff --git a/src/test/ui/extern/extern-compare-with-return-type.rs b/src/test/ui/extern/extern-compare-with-return-type.rs
index 6c9ed37..1ddfc77 100644
--- a/src/test/ui/extern/extern-compare-with-return-type.rs
+++ b/src/test/ui/extern/extern-compare-with-return-type.rs
@@ -2,23 +2,24 @@
 // Tests that we can compare various kinds of extern fn signatures.
 #![allow(non_camel_case_types)]
 
-extern fn voidret1() {}
-extern fn voidret2() {}
+// `dbg!()` differentiates these functions to ensure they won't be merged.
+extern "C" fn voidret1() { dbg!() }
+extern "C" fn voidret2() { dbg!() }
 
-extern fn uintret() -> usize { 22 }
+extern "C" fn uintret() -> usize { 22 }
 
-extern fn uintvoidret(_x: usize) {}
+extern "C" fn uintvoidret(_x: usize) {}
 
-extern fn uintuintuintuintret(x: usize, y: usize, z: usize) -> usize { x+y+z }
-type uintuintuintuintret = extern fn(usize,usize,usize) -> usize;
+extern "C" fn uintuintuintuintret(x: usize, y: usize, z: usize) -> usize { x+y+z }
+type uintuintuintuintret = extern "C" fn(usize,usize,usize) -> usize;
 
 pub fn main() {
-    assert!(voidret1 as extern fn() == voidret1 as extern fn());
-    assert!(voidret1 as extern fn() != voidret2 as extern fn());
+    assert!(voidret1 as extern "C" fn() == voidret1 as extern "C" fn());
+    assert!(voidret1 as extern "C" fn() != voidret2 as extern "C" fn());
 
-    assert!(uintret as extern fn() -> usize == uintret as extern fn() -> usize);
+    assert!(uintret as extern "C" fn() -> usize == uintret as extern "C" fn() -> usize);
 
-    assert!(uintvoidret as extern fn(usize) == uintvoidret as extern fn(usize));
+    assert!(uintvoidret as extern "C" fn(usize) == uintvoidret as extern "C" fn(usize));
 
     assert!(uintuintuintuintret as uintuintuintuintret ==
             uintuintuintuintret as uintuintuintuintret);
diff --git a/src/test/ui/extern/extern-main-fn.rs b/src/test/ui/extern/extern-main-fn.rs
index ddf2e13..bb1468a 100644
--- a/src/test/ui/extern/extern-main-fn.rs
+++ b/src/test/ui/extern/extern-main-fn.rs
@@ -1 +1 @@
-extern fn main() {} //~ ERROR: `main` function has wrong type [E0580]
+extern "C" fn main() {} //~ ERROR: `main` function has wrong type [E0580]
diff --git a/src/test/ui/extern/extern-main-fn.stderr b/src/test/ui/extern/extern-main-fn.stderr
index 9c99498..136c957 100644
--- a/src/test/ui/extern/extern-main-fn.stderr
+++ b/src/test/ui/extern/extern-main-fn.stderr
@@ -1,8 +1,8 @@
 error[E0580]: `main` function has wrong type
   --> $DIR/extern-main-fn.rs:1:1
    |
-LL | extern fn main() {}
-   | ^^^^^^^^^^^^^^^^ expected "Rust" fn, found "C" fn
+LL | extern "C" fn main() {}
+   | ^^^^^^^^^^^^^^^^^^^^ expected "Rust" fn, found "C" fn
    |
    = note: expected fn pointer `fn()`
               found fn pointer `extern "C" fn()`
diff --git a/src/test/ui/extern/extern-methods.rs b/src/test/ui/extern/extern-methods.rs
index 3c3e229..97559a6 100644
--- a/src/test/ui/extern/extern-methods.rs
+++ b/src/test/ui/extern/extern-methods.rs
@@ -5,7 +5,7 @@
 
 trait A {
     extern "fastcall" fn test1(i: i32);
-    extern fn test2(i: i32);
+    extern "C" fn test2(i: i32);
 }
 
 struct S;
@@ -19,7 +19,7 @@
     extern "fastcall" fn test1(i: i32) {
         assert_eq!(i, 1);
     }
-    extern fn test2(i: i32) {
+    extern "C" fn test2(i: i32) {
         assert_eq!(i, 2);
     }
 }
diff --git a/src/test/ui/extern/extern-pub.rs b/src/test/ui/extern/extern-pub.rs
index c97e04b..0b95045 100644
--- a/src/test/ui/extern/extern-pub.rs
+++ b/src/test/ui/extern/extern-pub.rs
@@ -1,9 +1,8 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
-extern {
+extern "C" {
     pub fn free(p: *const u8);
 }
 
-pub fn main() {
-}
+pub fn main() {}
diff --git a/src/test/ui/extern/extern-rust.rs b/src/test/ui/extern/extern-rust.rs
index 0cb1902..7cea8be 100644
--- a/src/test/ui/extern/extern-rust.rs
+++ b/src/test/ui/extern/extern-rust.rs
@@ -5,7 +5,7 @@
 pub struct Foo(u32);
 
 // ICE trigger, bad handling of differing types between rust and external ABIs
-pub extern fn bar() -> Foo {
+pub extern "C" fn bar() -> Foo {
     Foo(0)
 }
 
diff --git a/src/test/ui/extern/extern-types-distinct-types.rs b/src/test/ui/extern/extern-types-distinct-types.rs
index 000ba54..4da049b 100644
--- a/src/test/ui/extern/extern-types-distinct-types.rs
+++ b/src/test/ui/extern/extern-types-distinct-types.rs
@@ -1,6 +1,6 @@
 #![feature(extern_types)]
 
-extern {
+extern "C" {
     type A;
     type B;
 }
@@ -9,4 +9,4 @@
     r //~ ERROR mismatched types
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/extern/extern-types-manual-sync-send.rs b/src/test/ui/extern/extern-types-manual-sync-send.rs
index ec63e5d..87eb3f6 100644
--- a/src/test/ui/extern/extern-types-manual-sync-send.rs
+++ b/src/test/ui/extern/extern-types-manual-sync-send.rs
@@ -3,15 +3,15 @@
 
 #![feature(extern_types)]
 
-extern {
+extern "C" {
     type A;
 }
 
-unsafe impl Sync for A { }
-unsafe impl Send for A { }
+unsafe impl Sync for A {}
+unsafe impl Send for A {}
 
-fn assert_sync<T: ?Sized + Sync>() { }
-fn assert_send<T: ?Sized + Send>() { }
+fn assert_sync<T: ?Sized + Sync>() {}
+fn assert_send<T: ?Sized + Send>() {}
 
 fn main() {
     assert_sync::<A>();
diff --git a/src/test/ui/extern/extern-types-not-sync-send.rs b/src/test/ui/extern/extern-types-not-sync-send.rs
index 3af8b9b..ba82cac 100644
--- a/src/test/ui/extern/extern-types-not-sync-send.rs
+++ b/src/test/ui/extern/extern-types-not-sync-send.rs
@@ -2,12 +2,12 @@
 
 #![feature(extern_types)]
 
-extern {
+extern "C" {
     type A;
 }
 
-fn assert_sync<T: ?Sized + Sync>() { }
-fn assert_send<T: ?Sized + Send>() { }
+fn assert_sync<T: ?Sized + Sync>() {}
+fn assert_send<T: ?Sized + Send>() {}
 
 fn main() {
     assert_sync::<A>();
diff --git a/src/test/ui/extern/extern-types-not-sync-send.stderr b/src/test/ui/extern/extern-types-not-sync-send.stderr
index dc9810c..547116f 100644
--- a/src/test/ui/extern/extern-types-not-sync-send.stderr
+++ b/src/test/ui/extern/extern-types-not-sync-send.stderr
@@ -1,7 +1,7 @@
 error[E0277]: `A` cannot be shared between threads safely
   --> $DIR/extern-types-not-sync-send.rs:13:19
    |
-LL | fn assert_sync<T: ?Sized + Sync>() { }
+LL | fn assert_sync<T: ?Sized + Sync>() {}
    |                            ---- required by this bound in `assert_sync`
 ...
 LL |     assert_sync::<A>();
@@ -12,7 +12,7 @@
 error[E0277]: `A` cannot be sent between threads safely
   --> $DIR/extern-types-not-sync-send.rs:16:19
    |
-LL | fn assert_send<T: ?Sized + Send>() { }
+LL | fn assert_send<T: ?Sized + Send>() {}
    |                            ---- required by this bound in `assert_send`
 ...
 LL |     assert_send::<A>();
diff --git a/src/test/ui/extern/extern-types-pointer-cast.rs b/src/test/ui/extern/extern-types-pointer-cast.rs
index a4ebd3c..de6955b 100644
--- a/src/test/ui/extern/extern-types-pointer-cast.rs
+++ b/src/test/ui/extern/extern-types-pointer-cast.rs
@@ -2,10 +2,9 @@
 #![allow(dead_code)]
 // Test that pointers to extern types can be cast from/to usize,
 // despite being !Sized.
-
 #![feature(extern_types)]
 
-extern {
+extern "C" {
     type A;
 }
 
diff --git a/src/test/ui/extern/extern-types-size_of_val.rs b/src/test/ui/extern/extern-types-size_of_val.rs
index 1c96560..3b02ea2 100644
--- a/src/test/ui/extern/extern-types-size_of_val.rs
+++ b/src/test/ui/extern/extern-types-size_of_val.rs
@@ -1,16 +1,14 @@
 // run-pass
 #![feature(extern_types)]
 
-use std::mem::{size_of_val, align_of_val};
+use std::mem::{align_of_val, size_of_val};
 
-extern {
+extern "C" {
     type A;
 }
 
 fn main() {
-    let x: &A = unsafe {
-        &*(1usize as *const A)
-    };
+    let x: &A = unsafe { &*(1usize as *const A) };
 
     assert_eq!(size_of_val(x), 0);
     assert_eq!(align_of_val(x), 1);
diff --git a/src/test/ui/extern/extern-types-thin-pointer.rs b/src/test/ui/extern/extern-types-thin-pointer.rs
index 83c35f7..b85fc48 100644
--- a/src/test/ui/extern/extern-types-thin-pointer.rs
+++ b/src/test/ui/extern/extern-types-thin-pointer.rs
@@ -2,12 +2,11 @@
 #![allow(dead_code)]
 // Test that pointers and references to extern types are thin, ie they have the same size and
 // alignment as a pointer to ().
-
 #![feature(extern_types)]
 
 use std::mem::{align_of, size_of};
 
-extern {
+extern "C" {
     type A;
 }
 
diff --git a/src/test/ui/extern/extern-types-trait-impl.rs b/src/test/ui/extern/extern-types-trait-impl.rs
index 6cce6c7..656101e 100644
--- a/src/test/ui/extern/extern-types-trait-impl.rs
+++ b/src/test/ui/extern/extern-types-trait-impl.rs
@@ -1,22 +1,21 @@
 // run-pass
 #![allow(dead_code)]
 // Test that traits can be implemented for extern types.
-
 #![feature(extern_types)]
 
-extern {
+extern "C" {
     type A;
 }
 
 trait Foo {
-    fn foo(&self) { }
+    fn foo(&self) {}
 }
 
 impl Foo for A {
-    fn foo(&self) { }
+    fn foo(&self) {}
 }
 
-fn assert_foo<T: ?Sized + Foo>() { }
+fn assert_foo<T: ?Sized + Foo>() {}
 
 fn use_foo<T: ?Sized + Foo>(x: &dyn Foo) {
     x.foo();
diff --git a/src/test/ui/extern/extern-types-unsized.rs b/src/test/ui/extern/extern-types-unsized.rs
index a296ae0..94a222a 100644
--- a/src/test/ui/extern/extern-types-unsized.rs
+++ b/src/test/ui/extern/extern-types-unsized.rs
@@ -2,7 +2,7 @@
 
 #![feature(extern_types)]
 
-extern {
+extern "C" {
     type A;
 }
 
@@ -16,7 +16,7 @@
     tail: T,
 }
 
-fn assert_sized<T>() { }
+fn assert_sized<T>() {}
 
 fn main() {
     assert_sized::<A>();
diff --git a/src/test/ui/extern/extern-types-unsized.stderr b/src/test/ui/extern/extern-types-unsized.stderr
index fba919c..278db45 100644
--- a/src/test/ui/extern/extern-types-unsized.stderr
+++ b/src/test/ui/extern/extern-types-unsized.stderr
@@ -1,7 +1,7 @@
 error[E0277]: the size for values of type `A` cannot be known at compilation time
   --> $DIR/extern-types-unsized.rs:22:20
    |
-LL | fn assert_sized<T>() { }
+LL | fn assert_sized<T>() {}
    |                 - required by this bound in `assert_sized`
 ...
 LL |     assert_sized::<A>();
@@ -10,13 +10,13 @@
    = help: the trait `Sized` is not implemented for `A`
 help: consider relaxing the implicit `Sized` restriction
    |
-LL | fn assert_sized<T: ?Sized>() { }
+LL | fn assert_sized<T: ?Sized>() {}
    |                  ^^^^^^^^
 
 error[E0277]: the size for values of type `A` cannot be known at compilation time
   --> $DIR/extern-types-unsized.rs:25:5
    |
-LL | fn assert_sized<T>() { }
+LL | fn assert_sized<T>() {}
    |                 - required by this bound in `assert_sized`
 ...
 LL |     assert_sized::<Foo>();
@@ -26,13 +26,13 @@
    = note: required because it appears within the type `Foo`
 help: consider relaxing the implicit `Sized` restriction
    |
-LL | fn assert_sized<T: ?Sized>() { }
+LL | fn assert_sized<T: ?Sized>() {}
    |                  ^^^^^^^^
 
 error[E0277]: the size for values of type `A` cannot be known at compilation time
   --> $DIR/extern-types-unsized.rs:28:5
    |
-LL | fn assert_sized<T>() { }
+LL | fn assert_sized<T>() {}
    |                 - required by this bound in `assert_sized`
 ...
 LL |     assert_sized::<Bar<A>>();
@@ -42,13 +42,13 @@
    = note: required because it appears within the type `Bar<A>`
 help: consider relaxing the implicit `Sized` restriction
    |
-LL | fn assert_sized<T: ?Sized>() { }
+LL | fn assert_sized<T: ?Sized>() {}
    |                  ^^^^^^^^
 
 error[E0277]: the size for values of type `A` cannot be known at compilation time
   --> $DIR/extern-types-unsized.rs:31:5
    |
-LL | fn assert_sized<T>() { }
+LL | fn assert_sized<T>() {}
    |                 - required by this bound in `assert_sized`
 ...
 LL |     assert_sized::<Bar<Bar<A>>>();
@@ -59,7 +59,7 @@
    = note: required because it appears within the type `Bar<Bar<A>>`
 help: consider relaxing the implicit `Sized` restriction
    |
-LL | fn assert_sized<T: ?Sized>() { }
+LL | fn assert_sized<T: ?Sized>() {}
    |                  ^^^^^^^^
 
 error: aborting due to 4 previous errors
diff --git a/src/test/ui/extern/extern-wrong-value-type.rs b/src/test/ui/extern/extern-wrong-value-type.rs
index a4d7b00..337865e 100644
--- a/src/test/ui/extern/extern-wrong-value-type.rs
+++ b/src/test/ui/extern/extern-wrong-value-type.rs
@@ -1,4 +1,4 @@
-extern fn f() {
+extern "C" fn f() {
 }
 
 fn is_fn<F>(_: F) where F: Fn() {}
diff --git a/src/test/ui/issues/issue-10025.rs b/src/test/ui/extern/issue-10025.rs
similarity index 99%
rename from src/test/ui/issues/issue-10025.rs
rename to src/test/ui/extern/issue-10025.rs
index 193d7ee..4439b46 100644
--- a/src/test/ui/issues/issue-10025.rs
+++ b/src/test/ui/extern/issue-10025.rs
@@ -1,6 +1,6 @@
 // run-pass
-#![allow(dead_code)]
 // pretty-expanded FIXME #23616
+#![allow(dead_code)]
 
 unsafe extern fn foo() {}
 unsafe extern "C" fn bar() {}
diff --git a/src/test/ui/extern/issue-36122-accessing-externed-dst.rs b/src/test/ui/extern/issue-36122-accessing-externed-dst.rs
index 22229db..5f886ff 100644
--- a/src/test/ui/extern/issue-36122-accessing-externed-dst.rs
+++ b/src/test/ui/extern/issue-36122-accessing-externed-dst.rs
@@ -1,5 +1,5 @@
 fn main() {
-    extern {
+    extern "C" {
         static symbol: [usize]; //~ ERROR: the size for values of type
     }
     println!("{}", symbol[0]);
diff --git a/src/test/ui/feature-gate/allow-features-empty.rs b/src/test/ui/feature-gates/allow-features-empty.rs
similarity index 100%
rename from src/test/ui/feature-gate/allow-features-empty.rs
rename to src/test/ui/feature-gates/allow-features-empty.rs
diff --git a/src/test/ui/feature-gate/allow-features-empty.stderr b/src/test/ui/feature-gates/allow-features-empty.stderr
similarity index 100%
rename from src/test/ui/feature-gate/allow-features-empty.stderr
rename to src/test/ui/feature-gates/allow-features-empty.stderr
diff --git a/src/test/ui/feature-gate/allow-features.rs b/src/test/ui/feature-gates/allow-features.rs
similarity index 100%
rename from src/test/ui/feature-gate/allow-features.rs
rename to src/test/ui/feature-gates/allow-features.rs
diff --git a/src/test/ui/feature-gate/allow-features.stderr b/src/test/ui/feature-gates/allow-features.stderr
similarity index 100%
rename from src/test/ui/feature-gate/allow-features.stderr
rename to src/test/ui/feature-gates/allow-features.stderr
diff --git a/src/test/ui/feature-gate/duplicate-features.rs b/src/test/ui/feature-gates/duplicate-features.rs
similarity index 100%
rename from src/test/ui/feature-gate/duplicate-features.rs
rename to src/test/ui/feature-gates/duplicate-features.rs
diff --git a/src/test/ui/feature-gate/duplicate-features.stderr b/src/test/ui/feature-gates/duplicate-features.stderr
similarity index 100%
rename from src/test/ui/feature-gate/duplicate-features.stderr
rename to src/test/ui/feature-gates/duplicate-features.stderr
diff --git a/src/test/ui/feature-gate/feature-gate-c_variadic.rs b/src/test/ui/feature-gates/feature-gate-c_variadic.rs
similarity index 100%
rename from src/test/ui/feature-gate/feature-gate-c_variadic.rs
rename to src/test/ui/feature-gates/feature-gate-c_variadic.rs
diff --git a/src/test/ui/feature-gate/feature-gate-c_variadic.stderr b/src/test/ui/feature-gates/feature-gate-c_variadic.stderr
similarity index 100%
rename from src/test/ui/feature-gate/feature-gate-c_variadic.stderr
rename to src/test/ui/feature-gates/feature-gate-c_variadic.stderr
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs
index d44f78d..b600ad2 100644
--- a/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs
@@ -5,10 +5,9 @@
 
 extern crate cfg_target_thread_local;
 
-extern {
+extern "C" {
     #[cfg_attr(target_thread_local, thread_local)]
     //~^ `cfg(target_thread_local)` is experimental and subject to change
-
     static FOO: u32;
 }
 
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.stderr b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
index b2b7e45..ed19109 100644
--- a/src/test/ui/feature-gates/feature-gate-const_generics.stderr
+++ b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
@@ -5,7 +5,7 @@
    |                 ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics_defaults.rs b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.rs
new file mode 100644
index 0000000..5b5ccc8
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.rs
@@ -0,0 +1,9 @@
+#[cfg(FALSE)]
+struct A<const N: usize = 3>;
+//~^ ERROR default values for const generic parameters are experimental
+
+#[cfg(FALSE)]
+fn foo<const B: bool = false>() {}
+//~^ ERROR default values for const generic parameters are experimental
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics_defaults.stderr b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.stderr
new file mode 100644
index 0000000..e2b48d7
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.stderr
@@ -0,0 +1,21 @@
+error[E0658]: default values for const generic parameters are experimental
+  --> $DIR/feature-gate-const_generics_defaults.rs:2:25
+   |
+LL | struct A<const N: usize = 3>;
+   |                         ^^^
+   |
+   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+   = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable
+
+error[E0658]: default values for const generic parameters are experimental
+  --> $DIR/feature-gate-const_generics_defaults.rs:6:22
+   |
+LL | fn foo<const B: bool = false>() {}
+   |                      ^^^^^^^
+   |
+   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+   = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-const_refs_to_cell.rs b/src/test/ui/feature-gates/feature-gate-const_refs_to_cell.rs
new file mode 100644
index 0000000..63159ed
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const_refs_to_cell.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(const_refs_to_cell)]
+
+const FOO: () = {
+    let x = std::cell::Cell::new(42);
+    let y = &x;
+};
+
+fn main() {
+    FOO;
+}
diff --git a/src/test/ui/feature-gates/feature-gate-edition_macro_pats.rs b/src/test/ui/feature-gates/feature-gate-edition_macro_pats.rs
new file mode 100644
index 0000000..bd8a21e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-edition_macro_pats.rs
@@ -0,0 +1,8 @@
+// Feature gate test for `edition_macro_pats` feature.
+
+macro_rules! foo {
+    ($x:pat2018) => {}; //~ERROR `pat2018` and `pat2021` are unstable
+    ($x:pat2021) => {}; //~ERROR `pat2018` and `pat2021` are unstable
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-edition_macro_pats.stderr b/src/test/ui/feature-gates/feature-gate-edition_macro_pats.stderr
new file mode 100644
index 0000000..89bfb23
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-edition_macro_pats.stderr
@@ -0,0 +1,21 @@
+error[E0658]: `pat2018` and `pat2021` are unstable.
+  --> $DIR/feature-gate-edition_macro_pats.rs:4:9
+   |
+LL |     ($x:pat2018) => {};
+   |         ^^^^^^^
+   |
+   = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information
+   = help: add `#![feature(edition_macro_pats)]` to the crate attributes to enable
+
+error[E0658]: `pat2018` and `pat2021` are unstable.
+  --> $DIR/feature-gate-edition_macro_pats.rs:5:9
+   |
+LL |     ($x:pat2021) => {};
+   |         ^^^^^^^
+   |
+   = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information
+   = help: add `#![feature(edition_macro_pats)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-extern_types.rs b/src/test/ui/feature-gates/feature-gate-extern_types.rs
index 6bdc96f..103f8ee 100644
--- a/src/test/ui/feature-gates/feature-gate-extern_types.rs
+++ b/src/test/ui/feature-gates/feature-gate-extern_types.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     type T; //~ ERROR extern types are experimental
 }
 
diff --git a/src/test/ui/feature-gates/feature-gate-ffi_const.rs b/src/test/ui/feature-gates/feature-gate-ffi_const.rs
index 27323b1..9f3d783 100644
--- a/src/test/ui/feature-gates/feature-gate-ffi_const.rs
+++ b/src/test/ui/feature-gates/feature-gate-ffi_const.rs
@@ -1,6 +1,6 @@
 #![crate_type = "lib"]
 
-extern {
+extern "C" {
     #[ffi_const] //~ ERROR the `#[ffi_const]` attribute is an experimental feature
     pub fn foo();
 }
diff --git a/src/test/ui/feature-gates/feature-gate-ffi_pure.rs b/src/test/ui/feature-gates/feature-gate-ffi_pure.rs
index e24a686..b0dfa01 100644
--- a/src/test/ui/feature-gates/feature-gate-ffi_pure.rs
+++ b/src/test/ui/feature-gates/feature-gate-ffi_pure.rs
@@ -1,6 +1,6 @@
 #![crate_type = "lib"]
 
-extern {
+extern "C" {
     #[ffi_pure] //~ ERROR the `#[ffi_pure]` attribute is an experimental feature
     pub fn foo();
 }
diff --git a/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs b/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs
index d118b7f..f354534 100644
--- a/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs
+++ b/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs
@@ -1,6 +1,6 @@
 #![crate_type = "lib"]
 
-extern {
+extern "C" {
     #[ffi_returns_twice] //~ ERROR the `#[ffi_returns_twice]` attribute is an experimental feature
     pub fn foo();
 }
diff --git a/src/test/ui/feature-gate-inline_const.rs b/src/test/ui/feature-gates/feature-gate-inline_const.rs
similarity index 100%
rename from src/test/ui/feature-gate-inline_const.rs
rename to src/test/ui/feature-gates/feature-gate-inline_const.rs
diff --git a/src/test/ui/feature-gate-inline_const.stderr b/src/test/ui/feature-gates/feature-gate-inline_const.stderr
similarity index 100%
rename from src/test/ui/feature-gate-inline_const.stderr
rename to src/test/ui/feature-gates/feature-gate-inline_const.stderr
diff --git a/src/test/ui/feature-gate-isa_attribute.rs b/src/test/ui/feature-gates/feature-gate-isa_attribute.rs
similarity index 100%
rename from src/test/ui/feature-gate-isa_attribute.rs
rename to src/test/ui/feature-gates/feature-gate-isa_attribute.rs
diff --git a/src/test/ui/feature-gate-isa_attribute.stderr b/src/test/ui/feature-gates/feature-gate-isa_attribute.stderr
similarity index 100%
rename from src/test/ui/feature-gate-isa_attribute.stderr
rename to src/test/ui/feature-gates/feature-gate-isa_attribute.stderr
diff --git a/src/test/ui/feature-gates/feature-gate-link_args.rs b/src/test/ui/feature-gates/feature-gate-link_args.rs
index 49948da..e1c651f 100644
--- a/src/test/ui/feature-gates/feature-gate-link_args.rs
+++ b/src/test/ui/feature-gates/feature-gate-link_args.rs
@@ -5,13 +5,12 @@
 // sidestep warning (which is correct, but misleading for
 // purposes of this test)
 #![allow(unused_attributes)]
-
 #![link_args = "-l unexpected_use_as_inner_attr_on_mod"]
 //~^ ERROR the `link_args` attribute is experimental
 
 #[link_args = "-l expected_use_case"]
 //~^ ERROR the `link_args` attribute is experimental
-extern {}
+extern "C" {}
 
 #[link_args = "-l unexected_use_on_non_extern_item"]
 //~^ ERROR: the `link_args` attribute is experimental
diff --git a/src/test/ui/feature-gates/feature-gate-link_args.stderr b/src/test/ui/feature-gates/feature-gate-link_args.stderr
index c75f762..ae4918f 100644
--- a/src/test/ui/feature-gates/feature-gate-link_args.stderr
+++ b/src/test/ui/feature-gates/feature-gate-link_args.stderr
@@ -1,5 +1,5 @@
 error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead
-  --> $DIR/feature-gate-link_args.rs:12:1
+  --> $DIR/feature-gate-link_args.rs:11:1
    |
 LL | #[link_args = "-l expected_use_case"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@
    = help: add `#![feature(link_args)]` to the crate attributes to enable
 
 error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead
-  --> $DIR/feature-gate-link_args.rs:16:1
+  --> $DIR/feature-gate-link_args.rs:15:1
    |
 LL | #[link_args = "-l unexected_use_on_non_extern_item"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,7 @@
    = help: add `#![feature(link_args)]` to the crate attributes to enable
 
 error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead
-  --> $DIR/feature-gate-link_args.rs:9:1
+  --> $DIR/feature-gate-link_args.rs:8:1
    |
 LL | #![link_args = "-l unexpected_use_as_inner_attr_on_mod"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/feature-gates/feature-gate-link_cfg.rs b/src/test/ui/feature-gates/feature-gate-link_cfg.rs
index 27ec2e9..d30ee3b 100644
--- a/src/test/ui/feature-gates/feature-gate-link_cfg.rs
+++ b/src/test/ui/feature-gates/feature-gate-link_cfg.rs
@@ -1,5 +1,5 @@
 #[link(name = "foo", cfg(foo))]
 //~^ ERROR: is unstable
-extern {}
+extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.rs b/src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.rs
index 1c7f331..7391ea9 100644
--- a/src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.rs
+++ b/src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.rs
@@ -1,8 +1,7 @@
-extern {
+extern "C" {
     #[link_name = "llvm.sqrt.f32"]
     fn sqrt(x: f32) -> f32;
-    //~^ ERROR linking to LLVM intrinsics is experimental
+//~^ ERROR linking to LLVM intrinsics is experimental
 }
 
-fn main(){
-}
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-linkage.rs b/src/test/ui/feature-gates/feature-gate-linkage.rs
index 70f33cc..15b8d44 100644
--- a/src/test/ui/feature-gates/feature-gate-linkage.rs
+++ b/src/test/ui/feature-gates/feature-gate-linkage.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     #[linkage = "extern_weak"] static foo: isize;
     //~^ ERROR: the `linkage` attribute is experimental and not portable
 }
diff --git a/src/test/ui/feature-gates/feature-gate-non_ascii_idents.rs b/src/test/ui/feature-gates/feature-gate-non_ascii_idents.rs
index 11ff540..5cc04ad 100644
--- a/src/test/ui/feature-gates/feature-gate-non_ascii_idents.rs
+++ b/src/test/ui/feature-gates/feature-gate-non_ascii_idents.rs
@@ -26,7 +26,7 @@
     }
 }
 
-extern {
+extern "C" {
     fn qüx();  //~ ERROR non-ascii idents
 }
 
diff --git a/src/test/ui/feature-gate-optimize_attribute.rs b/src/test/ui/feature-gates/feature-gate-optimize_attribute.rs
similarity index 100%
rename from src/test/ui/feature-gate-optimize_attribute.rs
rename to src/test/ui/feature-gates/feature-gate-optimize_attribute.rs
diff --git a/src/test/ui/feature-gate-optimize_attribute.stderr b/src/test/ui/feature-gates/feature-gate-optimize_attribute.stderr
similarity index 100%
rename from src/test/ui/feature-gate-optimize_attribute.stderr
rename to src/test/ui/feature-gates/feature-gate-optimize_attribute.stderr
diff --git a/src/test/ui/feature-gates/feature-gate-simd-ffi.rs b/src/test/ui/feature-gates/feature-gate-simd-ffi.rs
index 0425e39..abffa4a 100644
--- a/src/test/ui/feature-gates/feature-gate-simd-ffi.rs
+++ b/src/test/ui/feature-gates/feature-gate-simd-ffi.rs
@@ -5,7 +5,7 @@
 #[derive(Copy, Clone)]
 struct LocalSimd(u8, u8);
 
-extern {
+extern "C" {
     fn baz() -> LocalSimd; //~ ERROR use of SIMD type
     fn qux(x: LocalSimd); //~ ERROR use of SIMD type
 }
diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs b/src/test/ui/feature-gates/feature-gate-static-nobundle-2.rs
similarity index 100%
rename from src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs
rename to src/test/ui/feature-gates/feature-gate-static-nobundle-2.rs
diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr b/src/test/ui/feature-gates/feature-gate-static-nobundle-2.stderr
similarity index 100%
rename from src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr
rename to src/test/ui/feature-gates/feature-gate-static-nobundle-2.stderr
diff --git a/src/test/ui/feature-gates/feature-gate-static-nobundle.rs b/src/test/ui/feature-gates/feature-gate-static-nobundle.rs
index 644b1f9..05c52f9 100644
--- a/src/test/ui/feature-gates/feature-gate-static-nobundle.rs
+++ b/src/test/ui/feature-gates/feature-gate-static-nobundle.rs
@@ -1,5 +1,5 @@
-#[link(name="foo", kind="static-nobundle")]
+#[link(name = "foo", kind = "static-nobundle")]
 //~^ ERROR: kind="static-nobundle" is unstable
-extern {}
+extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr b/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr
index 773ad8f..3a3c86c 100644
--- a/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr
+++ b/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr
@@ -1,8 +1,8 @@
 error[E0658]: kind="static-nobundle" is unstable
   --> $DIR/feature-gate-static-nobundle.rs:1:1
    |
-LL | #[link(name="foo", kind="static-nobundle")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[link(name = "foo", kind = "static-nobundle")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #37403 <https://github.com/rust-lang/rust/issues/37403> for more information
    = help: add `#![feature(static_nobundle)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs b/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs
index 20c443b..cd348de 100644
--- a/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs
+++ b/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs
@@ -3,12 +3,12 @@
 
 #![crate_type = "lib"]
 
-extern {
-// CHECK: Function Attrs: nounwind
-// CHECK-NEXT: declare void @extern_fn
+extern "C" {
+    // CHECK: Function Attrs: nounwind
+    // CHECK-NEXT: declare void @extern_fn
     fn extern_fn();
-// CHECK-NOT: Function Attrs: nounwind
-// CHECK: declare void @unwinding_extern_fn
+    // CHECK-NOT: Function Attrs: nounwind
+    // CHECK: declare void @unwinding_extern_fn
     #[unwind(allowed)] //~ ERROR the `#[unwind]` attribute is an experimental feature
     fn unwinding_extern_fn();
 }
diff --git a/src/test/ui/feature-gated-feature-in-macro-arg.rs b/src/test/ui/feature-gates/feature-gated-feature-in-macro-arg.rs
similarity index 100%
rename from src/test/ui/feature-gated-feature-in-macro-arg.rs
rename to src/test/ui/feature-gates/feature-gated-feature-in-macro-arg.rs
diff --git a/src/test/ui/feature-gated-feature-in-macro-arg.stderr b/src/test/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr
similarity index 100%
rename from src/test/ui/feature-gated-feature-in-macro-arg.stderr
rename to src/test/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs b/src/test/ui/feature-gates/issue-43106-gating-of-bench.rs
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-bench.rs
rename to src/test/ui/feature-gates/issue-43106-gating-of-bench.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-bench.stderr
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr
rename to src/test/ui/feature-gates/issue-43106-gating-of-bench.stderr
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs-error.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs-error.rs
rename to src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs-error.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs-error.stderr
rename to src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
similarity index 99%
rename from src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
rename to src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
index aba6c08..21f4052 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
@@ -536,7 +536,7 @@
     //~^ WARN attribute should be applied to a foreign function or static [unused_attributes]
     //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
     //~| HELP try `#[link(name = "1900")]` instead
-    extern { }
+    extern "C" { }
     //~^ NOTE not a foreign function or static
 
     mod inner { #![link_name="1900"] }
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
similarity index 99%
rename from src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
rename to src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
index ef9c9ef..c908d25 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
@@ -173,12 +173,6 @@
    |            ^^^^^
 
 warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:438:1
-   |
-LL | #[macro_escape]
-   | ^^^^^^^^^^^^^^^
-
-warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:441:17
    |
 LL |     mod inner { #![macro_escape] }
@@ -186,6 +180,12 @@
    |
    = help: try an outer attribute: `#[macro_use]`
 
+warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:438:1
+   |
+LL | #[macro_escape]
+   | ^^^^^^^^^^^^^^^
+
 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:228:17
    |
@@ -403,8 +403,8 @@
 LL |     #[link_name = "1900"]
    |     ^^^^^^^^^^^^^^^^^^^^^
 ...
-LL |     extern { }
-   |     ---------- not a foreign function or static
+LL |     extern "C" { }
+   |     -------------- not a foreign function or static
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 help: try `#[link(name = "1900")]` instead
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.rs b/src/test/ui/feature-gates/issue-43106-gating-of-deprecated.rs
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-deprecated.rs
rename to src/test/ui/feature-gates/issue-43106-gating-of-deprecated.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs b/src/test/ui/feature-gates/issue-43106-gating-of-derive-2.rs
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs
rename to src/test/ui/feature-gates/issue-43106-gating-of-derive-2.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-derive-2.stderr
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr
rename to src/test/ui/feature-gates/issue-43106-gating-of-derive-2.stderr
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs b/src/test/ui/feature-gates/issue-43106-gating-of-derive.rs
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-derive.rs
rename to src/test/ui/feature-gates/issue-43106-gating-of-derive.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-derive.stderr
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr
rename to src/test/ui/feature-gates/issue-43106-gating-of-derive.stderr
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs b/src/test/ui/feature-gates/issue-43106-gating-of-macro_escape.rs
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs
rename to src/test/ui/feature-gates/issue-43106-gating-of-macro_escape.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-macro_escape.stderr
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr
rename to src/test/ui/feature-gates/issue-43106-gating-of-macro_escape.stderr
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.rs b/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.rs
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-macro_use.rs
rename to src/test/ui/feature-gates/issue-43106-gating-of-macro_use.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr
similarity index 99%
rename from src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr
rename to src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr
index 52a682e..7f6d608 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr
@@ -1,8 +1,8 @@
 error: arguments to `macro_use` are not allowed here
-  --> $DIR/issue-43106-gating-of-macro_use.rs:6:1
+  --> $DIR/issue-43106-gating-of-macro_use.rs:12:17
    |
-LL | #![macro_use(my_macro)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
+LL |     mod inner { #![macro_use(my_macro)] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: arguments to `macro_use` are not allowed here
   --> $DIR/issue-43106-gating-of-macro_use.rs:9:1
@@ -11,10 +11,10 @@
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 error: arguments to `macro_use` are not allowed here
-  --> $DIR/issue-43106-gating-of-macro_use.rs:12:17
+  --> $DIR/issue-43106-gating-of-macro_use.rs:6:1
    |
-LL |     mod inner { #![macro_use(my_macro)] }
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![macro_use(my_macro)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: malformed `macro_use` attribute input
   --> $DIR/issue-43106-gating-of-macro_use.rs:15:5
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.rs b/src/test/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.rs
rename to src/test/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr
rename to src/test/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs b/src/test/ui/feature-gates/issue-43106-gating-of-rustc_deprecated.rs
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs
rename to src/test/ui/feature-gates/issue-43106-gating-of-rustc_deprecated.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-rustc_deprecated.stderr
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
rename to src/test/ui/feature-gates/issue-43106-gating-of-rustc_deprecated.stderr
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs b/src/test/ui/feature-gates/issue-43106-gating-of-stable.rs
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-stable.rs
rename to src/test/ui/feature-gates/issue-43106-gating-of-stable.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-stable.stderr
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
rename to src/test/ui/feature-gates/issue-43106-gating-of-stable.stderr
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.rs b/src/test/ui/feature-gates/issue-43106-gating-of-test.rs
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-test.rs
rename to src/test/ui/feature-gates/issue-43106-gating-of-test.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-test.stderr
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-test.stderr
rename to src/test/ui/feature-gates/issue-43106-gating-of-test.stderr
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs b/src/test/ui/feature-gates/issue-43106-gating-of-unstable.rs
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs
rename to src/test/ui/feature-gates/issue-43106-gating-of-unstable.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-unstable.stderr
similarity index 100%
rename from src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
rename to src/test/ui/feature-gates/issue-43106-gating-of-unstable.stderr
diff --git a/src/test/ui/feature-gate/issue-49983-see-issue-0.rs b/src/test/ui/feature-gates/issue-49983-see-issue-0.rs
similarity index 100%
rename from src/test/ui/feature-gate/issue-49983-see-issue-0.rs
rename to src/test/ui/feature-gates/issue-49983-see-issue-0.rs
diff --git a/src/test/ui/feature-gate/issue-49983-see-issue-0.stderr b/src/test/ui/feature-gates/issue-49983-see-issue-0.stderr
similarity index 100%
rename from src/test/ui/feature-gate/issue-49983-see-issue-0.stderr
rename to src/test/ui/feature-gates/issue-49983-see-issue-0.stderr
diff --git a/src/test/ui/feature-gate/rustc-private.rs b/src/test/ui/feature-gates/rustc-private.rs
similarity index 100%
rename from src/test/ui/feature-gate/rustc-private.rs
rename to src/test/ui/feature-gates/rustc-private.rs
diff --git a/src/test/ui/feature-gate/rustc-private.stderr b/src/test/ui/feature-gates/rustc-private.stderr
similarity index 100%
rename from src/test/ui/feature-gate/rustc-private.stderr
rename to src/test/ui/feature-gates/rustc-private.stderr
diff --git a/src/test/ui/feature-gate/stability-attribute-consistency.rs b/src/test/ui/feature-gates/stability-attribute-consistency.rs
similarity index 100%
rename from src/test/ui/feature-gate/stability-attribute-consistency.rs
rename to src/test/ui/feature-gates/stability-attribute-consistency.rs
diff --git a/src/test/ui/feature-gate/stability-attribute-consistency.stderr b/src/test/ui/feature-gates/stability-attribute-consistency.stderr
similarity index 100%
rename from src/test/ui/feature-gate/stability-attribute-consistency.stderr
rename to src/test/ui/feature-gates/stability-attribute-consistency.stderr
diff --git a/src/test/ui/trace_macros-gate.rs b/src/test/ui/feature-gates/trace_macros-gate.rs
similarity index 100%
rename from src/test/ui/trace_macros-gate.rs
rename to src/test/ui/feature-gates/trace_macros-gate.rs
diff --git a/src/test/ui/trace_macros-gate.stderr b/src/test/ui/feature-gates/trace_macros-gate.stderr
similarity index 100%
rename from src/test/ui/trace_macros-gate.stderr
rename to src/test/ui/feature-gates/trace_macros-gate.stderr
diff --git a/src/test/ui/feature-gate/unknown-feature.rs b/src/test/ui/feature-gates/unknown-feature.rs
similarity index 100%
rename from src/test/ui/feature-gate/unknown-feature.rs
rename to src/test/ui/feature-gates/unknown-feature.rs
diff --git a/src/test/ui/feature-gate/unknown-feature.stderr b/src/test/ui/feature-gates/unknown-feature.stderr
similarity index 100%
rename from src/test/ui/feature-gate/unknown-feature.stderr
rename to src/test/ui/feature-gates/unknown-feature.stderr
diff --git a/src/test/ui/feature-gate/unstable-attribute-allow-issue-0.rs b/src/test/ui/feature-gates/unstable-attribute-allow-issue-0.rs
similarity index 100%
rename from src/test/ui/feature-gate/unstable-attribute-allow-issue-0.rs
rename to src/test/ui/feature-gates/unstable-attribute-allow-issue-0.rs
diff --git a/src/test/ui/feature-gate/unstable-attribute-allow-issue-0.stderr b/src/test/ui/feature-gates/unstable-attribute-allow-issue-0.stderr
similarity index 100%
rename from src/test/ui/feature-gate/unstable-attribute-allow-issue-0.stderr
rename to src/test/ui/feature-gates/unstable-attribute-allow-issue-0.stderr
diff --git a/src/test/ui/ffi_const2.rs b/src/test/ui/ffi_const2.rs
index 4bd9637..82fe8a9 100644
--- a/src/test/ui/ffi_const2.rs
+++ b/src/test/ui/ffi_const2.rs
@@ -1,6 +1,6 @@
 #![feature(ffi_const, ffi_pure)]
 
-extern {
+extern "C" {
     #[ffi_pure] //~ ERROR `#[ffi_const]` function cannot be `#[ffi_pure]`
     #[ffi_const]
     pub fn baz();
diff --git a/src/test/ui/foreign-unsafe-fn-called.rs b/src/test/ui/foreign-unsafe-fn-called.rs
index 9352efa..abbe462 100644
--- a/src/test/ui/foreign-unsafe-fn-called.rs
+++ b/src/test/ui/foreign-unsafe-fn-called.rs
@@ -1,5 +1,5 @@
 mod test {
-    extern {
+    extern "C" {
         pub fn free();
     }
 }
diff --git a/src/test/ui/foreign/foreign-fn-linkname.rs b/src/test/ui/foreign/foreign-fn-linkname.rs
index 1f04815..f6d8205 100644
--- a/src/test/ui/foreign/foreign-fn-linkname.rs
+++ b/src/test/ui/foreign/foreign-fn-linkname.rs
@@ -10,7 +10,7 @@
 mod mlibc {
     use libc::{c_char, size_t};
 
-    extern {
+    extern "C" {
         #[link_name = "strlen"]
         pub fn my_strlen(str: *const c_char) -> size_t;
     }
@@ -19,9 +19,7 @@
 fn strlen(str: String) -> usize {
     // C string is terminated with a zero
     let s = CString::new(str).unwrap();
-    unsafe {
-        mlibc::my_strlen(s.as_ptr()) as usize
-    }
+    unsafe { mlibc::my_strlen(s.as_ptr()) as usize }
 }
 
 pub fn main() {
diff --git a/src/test/ui/foreign/foreign-int-types.rs b/src/test/ui/foreign/foreign-int-types.rs
index 6629657..2d01d32 100644
--- a/src/test/ui/foreign/foreign-int-types.rs
+++ b/src/test/ui/foreign/foreign-int-types.rs
@@ -3,11 +3,10 @@
 #![allow(dead_code)]
 
 mod xx {
-    extern {
+    extern "C" {
         pub fn strlen(str: *const u8) -> usize;
         pub fn foo(x: isize, y: usize);
     }
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/foreign/foreign-mod-unused-const.rs b/src/test/ui/foreign/foreign-mod-unused-const.rs
index d9efbe0..7d79c30 100644
--- a/src/test/ui/foreign/foreign-mod-unused-const.rs
+++ b/src/test/ui/foreign/foreign-mod-unused-const.rs
@@ -3,10 +3,9 @@
 // pretty-expanded FIXME #23616
 
 mod foo {
-    extern {
+    extern "C" {
         pub static errno: u32;
     }
 }
 
-pub fn main() {
-}
+pub fn main() {}
diff --git a/src/test/ui/foreign/foreign2.rs b/src/test/ui/foreign/foreign2.rs
index c1ab577..df431f2 100644
--- a/src/test/ui/foreign/foreign2.rs
+++ b/src/test/ui/foreign/foreign2.rs
@@ -2,29 +2,28 @@
 #![allow(dead_code)]
 // ignore-wasm32-bare no libc to test ffi with
 // pretty-expanded FIXME #23616
-
 #![feature(rustc_private)]
 
 extern crate libc;
 
 mod bar {
-    extern {}
+    extern "C" {}
 }
 
 mod zed {
-    extern {}
+    extern "C" {}
 }
 
 mod mlibc {
     use libc::{c_int, c_void, size_t, ssize_t};
 
-    extern {
+    extern "C" {
         pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t;
     }
 }
 
 mod baz {
-    extern {}
+    extern "C" {}
 }
 
-pub fn main() { }
+pub fn main() {}
diff --git a/src/test/ui/functions-closures/auxiliary/fn-abi.rs b/src/test/ui/functions-closures/auxiliary/fn-abi.rs
index 25c9e1b..ace9fbd 100644
--- a/src/test/ui/functions-closures/auxiliary/fn-abi.rs
+++ b/src/test/ui/functions-closures/auxiliary/fn-abi.rs
@@ -1,2 +1,2 @@
 #[no_mangle]
-pub extern fn foo() {}
+pub extern "C" fn foo() {}
diff --git a/src/test/ui/functions-closures/fn-abi.rs b/src/test/ui/functions-closures/fn-abi.rs
index 900af9c..ac3a4be 100644
--- a/src/test/ui/functions-closures/fn-abi.rs
+++ b/src/test/ui/functions-closures/fn-abi.rs
@@ -7,12 +7,12 @@
 
 extern crate fn_abi;
 
-extern {
+extern "C" {
     fn foo();
 }
 
 pub fn main() {
     // Will only type check if the type of _p and the decl of foo use the
     // same ABI
-    let _p: unsafe extern fn() = foo;
+    let _p: unsafe extern "C" fn() = foo;
 }
diff --git a/src/test/ui/generator/auxiliary/metadata-sufficient-for-layout.rs b/src/test/ui/generator/auxiliary/metadata-sufficient-for-layout.rs
new file mode 100644
index 0000000..207c273
--- /dev/null
+++ b/src/test/ui/generator/auxiliary/metadata-sufficient-for-layout.rs
@@ -0,0 +1,11 @@
+// compile-flags: --emit metadata
+#![feature(generators, generator_trait)]
+
+use std::marker::Unpin;
+use std::ops::Generator;
+
+pub fn g() -> impl Generator<(), Yield = (), Return = ()> {
+    || {
+        yield;
+    }
+}
diff --git a/src/test/ui/generator/layout-error.rs b/src/test/ui/generator/layout-error.rs
new file mode 100644
index 0000000..0598672
--- /dev/null
+++ b/src/test/ui/generator/layout-error.rs
@@ -0,0 +1,28 @@
+// Verifies that computing a layout of a generator tainted by type errors
+// doesn't ICE. Regression test for #80998.
+//
+// edition:2018
+
+#![feature(type_alias_impl_trait)]
+use std::future::Future;
+
+pub struct Task<F: Future>(F);
+impl<F: Future> Task<F> {
+    fn new() -> Self {
+        todo!()
+    }
+    fn spawn(&self, _: impl FnOnce() -> F) {
+        todo!()
+    }
+}
+
+fn main() {
+    async fn cb() {
+        let a = Foo; //~ ERROR cannot find value `Foo` in this scope
+    }
+
+    type F = impl Future;
+    // Check that statics are inhabited computes they layout.
+    static POOL: Task<F> = Task::new();
+    Task::spawn(&POOL, || cb());
+}
diff --git a/src/test/ui/generator/layout-error.stderr b/src/test/ui/generator/layout-error.stderr
new file mode 100644
index 0000000..b1a258f
--- /dev/null
+++ b/src/test/ui/generator/layout-error.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `Foo` in this scope
+  --> $DIR/layout-error.rs:21:17
+   |
+LL |         let a = Foo;
+   |                 ^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/generator/metadata-sufficient-for-layout.rs b/src/test/ui/generator/metadata-sufficient-for-layout.rs
new file mode 100644
index 0000000..9c82359
--- /dev/null
+++ b/src/test/ui/generator/metadata-sufficient-for-layout.rs
@@ -0,0 +1,23 @@
+// Check that the layout of a generator is available when auxiliary crate
+// is compiled with --emit metadata.
+//
+// Regression test for #80998.
+//
+// aux-build:metadata-sufficient-for-layout.rs
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+#![feature(generator_trait)]
+
+extern crate metadata_sufficient_for_layout;
+
+use std::ops::Generator;
+
+type F = impl Generator<(), Yield = (), Return = ()>;
+
+// Static queries the layout of the generator.
+static A: Option<F> = None;
+
+fn f() -> F { metadata_sufficient_for_layout::g() }
+
+fn main() {}
diff --git a/src/test/ui/generator/resume-arg-late-bound.stderr b/src/test/ui/generator/resume-arg-late-bound.stderr
index dc086416..63411b5 100644
--- a/src/test/ui/generator/resume-arg-late-bound.stderr
+++ b/src/test/ui/generator/resume-arg-late-bound.stderr
@@ -2,19 +2,47 @@
   --> $DIR/resume-arg-late-bound.rs:15:5
    |
 LL |     test(gen);
-   |     ^^^^ one type is more general than the other
+   |     ^^^^ lifetime mismatch
    |
    = note: expected type `for<'a> Generator<&'a mut bool>`
               found type `Generator<&mut bool>`
+note: the required lifetime does not necessarily outlive the anonymous lifetime #1 defined on the body at 11:15
+  --> $DIR/resume-arg-late-bound.rs:11:15
+   |
+LL |       let gen = |arg: &mut bool| {
+   |  _______________^
+LL | |         yield ();
+LL | |         *arg = true;
+LL | |     };
+   | |_____^
+note: the lifetime requirement is introduced here
+  --> $DIR/resume-arg-late-bound.rs:8:17
+   |
+LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {}
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/resume-arg-late-bound.rs:15:5
    |
 LL |     test(gen);
-   |     ^^^^ one type is more general than the other
+   |     ^^^^ lifetime mismatch
    |
    = note: expected type `for<'a> Generator<&'a mut bool>`
               found type `Generator<&mut bool>`
+note: the anonymous lifetime #1 defined on the body at 11:15 doesn't meet the lifetime requirements
+  --> $DIR/resume-arg-late-bound.rs:11:15
+   |
+LL |       let gen = |arg: &mut bool| {
+   |  _______________^
+LL | |         yield ();
+LL | |         *arg = true;
+LL | |     };
+   | |_____^
+note: the lifetime requirement is introduced here
+  --> $DIR/resume-arg-late-bound.rs:8:17
+   |
+LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {}
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind.rs b/src/test/ui/generic-associated-types/parameter_number_and_kind.rs
index f4d09fc..9d7ef88 100644
--- a/src/test/ui/generic-associated-types/parameter_number_and_kind.rs
+++ b/src/test/ui/generic-associated-types/parameter_number_and_kind.rs
@@ -11,10 +11,10 @@
     // Test parameters in default values
     type FOk<T> = Self::E<'static, T>;
     type FErr1 = Self::E<'static, 'static>;
-    //~^ ERROR wrong number of lifetime arguments: expected 1, found 2
-    //~| ERROR wrong number of type arguments: expected 1, found 0
+    //~^ ERROR this associated type takes 1 lifetime argument but 2 lifetime arguments were supplied
+    //~| ERROR this associated type takes 1 type argument but 0 type arguments were supplied
     type FErr2<T> = Self::E<'static, T, u32>;
-    //~^ ERROR wrong number of type arguments: expected 1, found 2
+    //~^ ERROR this associated type takes 1 type argument but 2 type arguments were supplied
 }
 
 fn main() {}
diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr b/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr
index ed090e3..d021889 100644
--- a/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr
+++ b/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr
@@ -1,20 +1,46 @@
-error[E0107]: wrong number of lifetime arguments: expected 1, found 2
-  --> $DIR/parameter_number_and_kind.rs:13:35
+error[E0107]: this associated type takes 1 lifetime argument but 2 lifetime arguments were supplied
+  --> $DIR/parameter_number_and_kind.rs:13:24
    |
 LL |     type FErr1 = Self::E<'static, 'static>;
-   |                                   ^^^^^^^ unexpected lifetime argument
+   |                        ^        --------- help: remove this lifetime argument
+   |                        |
+   |                        expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/parameter_number_and_kind.rs:10:10
+   |
+LL |     type E<'a, T>;
+   |          ^ --
 
-error[E0107]: wrong number of type arguments: expected 1, found 0
-  --> $DIR/parameter_number_and_kind.rs:13:18
+error[E0107]: this associated type takes 1 type argument but 0 type arguments were supplied
+  --> $DIR/parameter_number_and_kind.rs:13:24
    |
 LL |     type FErr1 = Self::E<'static, 'static>;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument
+   |                        ^ expected 1 type argument
+   |
+note: associated type defined here, with 1 type parameter: `T`
+  --> $DIR/parameter_number_and_kind.rs:10:10
+   |
+LL |     type E<'a, T>;
+   |          ^     -
+help: add missing type argument
+   |
+LL |     type FErr1 = Self::E<'static, 'static, T>;
+   |                                          ^^^
 
-error[E0107]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/parameter_number_and_kind.rs:16:41
+error[E0107]: this associated type takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/parameter_number_and_kind.rs:16:27
    |
 LL |     type FErr2<T> = Self::E<'static, T, u32>;
-   |                                         ^^^ unexpected type argument
+   |                           ^           ----- help: remove this type argument
+   |                           |
+   |                           expected 1 type argument
+   |
+note: associated type defined here, with 1 type parameter: `T`
+  --> $DIR/parameter_number_and_kind.rs:10:10
+   |
+LL |     type E<'a, T>;
+   |          ^     -
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/generics/generic-arg-mismatch-recover.rs b/src/test/ui/generics/generic-arg-mismatch-recover.rs
index 3e5e2e6..0e0d1da 100644
--- a/src/test/ui/generics/generic-arg-mismatch-recover.rs
+++ b/src/test/ui/generics/generic-arg-mismatch-recover.rs
@@ -3,8 +3,10 @@
 struct Bar<'a>(&'a ());
 
 fn main() {
-    Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arguments
+    Foo::<'static, 'static, ()>(&0);
+    //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
 
-    Bar::<'static, 'static, ()>(&()); //~ ERROR wrong number of lifetime arguments
-    //~^ ERROR wrong number of type arguments
+    Bar::<'static, 'static, ()>(&());
+    //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+    //~| ERROR this struct takes 0 type arguments but 1 type argument was supplied
 }
diff --git a/src/test/ui/generics/generic-arg-mismatch-recover.stderr b/src/test/ui/generics/generic-arg-mismatch-recover.stderr
index 99adb35..ca73b82 100644
--- a/src/test/ui/generics/generic-arg-mismatch-recover.stderr
+++ b/src/test/ui/generics/generic-arg-mismatch-recover.stderr
@@ -1,20 +1,44 @@
-error[E0107]: wrong number of lifetime arguments: expected 1, found 2
-  --> $DIR/generic-arg-mismatch-recover.rs:6:20
+error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+  --> $DIR/generic-arg-mismatch-recover.rs:6:5
    |
 LL |     Foo::<'static, 'static, ()>(&0);
-   |                    ^^^^^^^ unexpected lifetime argument
+   |     ^^^            --------- help: remove this lifetime argument
+   |     |
+   |     expected 1 lifetime argument
+   |
+note: struct defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/generic-arg-mismatch-recover.rs:1:8
+   |
+LL | struct Foo<'a, T: 'a>(&'a T);
+   |        ^^^ --
 
-error[E0107]: wrong number of lifetime arguments: expected 1, found 2
-  --> $DIR/generic-arg-mismatch-recover.rs:8:20
+error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+  --> $DIR/generic-arg-mismatch-recover.rs:9:5
    |
 LL |     Bar::<'static, 'static, ()>(&());
-   |                    ^^^^^^^ unexpected lifetime argument
+   |     ^^^            --------- help: remove this lifetime argument
+   |     |
+   |     expected 1 lifetime argument
+   |
+note: struct defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/generic-arg-mismatch-recover.rs:3:8
+   |
+LL | struct Bar<'a>(&'a ());
+   |        ^^^ --
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/generic-arg-mismatch-recover.rs:8:29
+error[E0107]: this struct takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/generic-arg-mismatch-recover.rs:9:5
    |
 LL |     Bar::<'static, 'static, ()>(&());
-   |                             ^^ unexpected type argument
+   |     ^^^                   ---- help: remove this type argument
+   |     |
+   |     expected 0 type arguments
+   |
+note: struct defined here, with 0 type parameters
+  --> $DIR/generic-arg-mismatch-recover.rs:3:8
+   |
+LL | struct Bar<'a>(&'a ());
+   |        ^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/generics/generic-extern-lifetime.rs b/src/test/ui/generics/generic-extern-lifetime.rs
index 22bcd44..c427448 100644
--- a/src/test/ui/generics/generic-extern-lifetime.rs
+++ b/src/test/ui/generics/generic-extern-lifetime.rs
@@ -1,15 +1,15 @@
 // Test to make sure the names of the lifetimes are correctly resolved
 // in extern blocks.
 
-extern {
-   pub fn life<'a>(x:&'a i32);
-   pub fn life2<'b>(x:&'a i32, y:&'b i32); //~ ERROR use of undeclared lifetime name `'a`
-   pub fn life3<'a>(x:&'a i32, y:&i32) -> &'a i32;
-   pub fn life4<'b>(x: for<'c> fn(&'a i32)); //~ ERROR use of undeclared lifetime name `'a`
-   pub fn life5<'b>(x: for<'c> fn(&'b i32));
-   pub fn life6<'b>(x: for<'c> fn(&'c i32));
-   pub fn life7<'b>() -> for<'c> fn(&'a i32); //~ ERROR use of undeclared lifetime name `'a`
-   pub fn life8<'b>() -> for<'c> fn(&'b i32);
-   pub fn life9<'b>() -> for<'c> fn(&'c i32);
+extern "C" {
+    pub fn life<'a>(x: &'a i32);
+    pub fn life2<'b>(x: &'a i32, y: &'b i32); //~ ERROR use of undeclared lifetime name `'a`
+    pub fn life3<'a>(x: &'a i32, y: &i32) -> &'a i32;
+    pub fn life4<'b>(x: for<'c> fn(&'a i32)); //~ ERROR use of undeclared lifetime name `'a`
+    pub fn life5<'b>(x: for<'c> fn(&'b i32));
+    pub fn life6<'b>(x: for<'c> fn(&'c i32));
+    pub fn life7<'b>() -> for<'c> fn(&'a i32); //~ ERROR use of undeclared lifetime name `'a`
+    pub fn life8<'b>() -> for<'c> fn(&'b i32);
+    pub fn life9<'b>() -> for<'c> fn(&'c i32);
 }
 fn main() {}
diff --git a/src/test/ui/generics/generic-extern-lifetime.stderr b/src/test/ui/generics/generic-extern-lifetime.stderr
index 72951ae..3c9ed7a 100644
--- a/src/test/ui/generics/generic-extern-lifetime.stderr
+++ b/src/test/ui/generics/generic-extern-lifetime.stderr
@@ -1,32 +1,32 @@
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/generic-extern-lifetime.rs:6:24
+  --> $DIR/generic-extern-lifetime.rs:6:26
    |
-LL |    pub fn life2<'b>(x:&'a i32, y:&'b i32);
-   |                        ^^ undeclared lifetime
+LL |     pub fn life2<'b>(x: &'a i32, y: &'b i32);
+   |                          ^^ undeclared lifetime
 
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/generic-extern-lifetime.rs:8:36
+  --> $DIR/generic-extern-lifetime.rs:8:37
    |
-LL |    pub fn life4<'b>(x: for<'c> fn(&'a i32));
-   |                                    ^^ undeclared lifetime
+LL |     pub fn life4<'b>(x: for<'c> fn(&'a i32));
+   |                                     ^^ undeclared lifetime
    |
    = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
 help: consider making the type lifetime-generic with a new `'a` lifetime
    |
-LL |    pub fn life4<'b>(x: for<'c, 'a> fn(&'a i32));
-   |                              ^^^^
+LL |     pub fn life4<'b>(x: for<'c, 'a> fn(&'a i32));
+   |                               ^^^^
 
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/generic-extern-lifetime.rs:11:38
+  --> $DIR/generic-extern-lifetime.rs:11:39
    |
-LL |    pub fn life7<'b>() -> for<'c> fn(&'a i32);
-   |                                      ^^ undeclared lifetime
+LL |     pub fn life7<'b>() -> for<'c> fn(&'a i32);
+   |                                       ^^ undeclared lifetime
    |
    = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
 help: consider making the type lifetime-generic with a new `'a` lifetime
    |
-LL |    pub fn life7<'b>() -> for<'c, 'a> fn(&'a i32);
-   |                                ^^^^
+LL |     pub fn life7<'b>() -> for<'c, 'a> fn(&'a i32);
+   |                                 ^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/generics/generic-extern.rs b/src/test/ui/generics/generic-extern.rs
index e52a885..3690d6f 100644
--- a/src/test/ui/generics/generic-extern.rs
+++ b/src/test/ui/generics/generic-extern.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     fn foo<T>(); //~ ERROR foreign items may not have type parameters
 }
 
diff --git a/src/test/ui/generics/generic-impl-less-params-with-defaults.rs b/src/test/ui/generics/generic-impl-less-params-with-defaults.rs
index abbf640..01964f6 100644
--- a/src/test/ui/generics/generic-impl-less-params-with-defaults.rs
+++ b/src/test/ui/generics/generic-impl-less-params-with-defaults.rs
@@ -9,5 +9,5 @@
 
 fn main() {
     Foo::<isize>::new();
-    //~^ ERROR wrong number of type arguments
+    //~^ ERROR this struct takes at least 2 type arguments but only 1 type argument was supplied
 }
diff --git a/src/test/ui/generics/generic-impl-less-params-with-defaults.stderr b/src/test/ui/generics/generic-impl-less-params-with-defaults.stderr
index 22b00e1..a8a1787 100644
--- a/src/test/ui/generics/generic-impl-less-params-with-defaults.stderr
+++ b/src/test/ui/generics/generic-impl-less-params-with-defaults.stderr
@@ -1,8 +1,20 @@
-error[E0107]: wrong number of type arguments: expected at least 2, found 1
+error[E0107]: this struct takes at least 2 type arguments but only 1 type argument was supplied
   --> $DIR/generic-impl-less-params-with-defaults.rs:11:5
    |
 LL |     Foo::<isize>::new();
-   |     ^^^^^^^^^^^^^^^^^ expected at least 2 type arguments
+   |     ^^^   ----- supplied 1 type argument
+   |     |
+   |     expected at least 2 type arguments
+   |
+note: struct defined here, with at least 2 type parameters: `A`, `B`
+  --> $DIR/generic-impl-less-params-with-defaults.rs:3:8
+   |
+LL | struct Foo<A, B, C = (A, B)>(
+   |        ^^^ -  -
+help: add missing type argument
+   |
+LL |     Foo::<isize, B>::new();
+   |                ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generics/generic-impl-more-params-with-defaults.rs b/src/test/ui/generics/generic-impl-more-params-with-defaults.rs
index a14fb70..24c41a9 100644
--- a/src/test/ui/generics/generic-impl-more-params-with-defaults.rs
+++ b/src/test/ui/generics/generic-impl-more-params-with-defaults.rs
@@ -11,5 +11,5 @@
 
 fn main() {
     Vec::<isize, Heap, bool>::new();
-    //~^ ERROR wrong number of type arguments
+    //~^ ERROR this struct takes at most 2 type arguments but 3 type arguments were supplied
 }
diff --git a/src/test/ui/generics/generic-impl-more-params-with-defaults.stderr b/src/test/ui/generics/generic-impl-more-params-with-defaults.stderr
index 380e920..8ba86af 100644
--- a/src/test/ui/generics/generic-impl-more-params-with-defaults.stderr
+++ b/src/test/ui/generics/generic-impl-more-params-with-defaults.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of type arguments: expected at most 2, found 3
-  --> $DIR/generic-impl-more-params-with-defaults.rs:13:24
+error[E0107]: this struct takes at most 2 type arguments but 3 type arguments were supplied
+  --> $DIR/generic-impl-more-params-with-defaults.rs:13:5
    |
 LL |     Vec::<isize, Heap, bool>::new();
-   |                        ^^^^ unexpected type argument
+   |     ^^^              ------ help: remove this type argument
+   |     |
+   |     expected at most 2 type arguments
+   |
+note: struct defined here, with at most 2 type parameters: `T`, `A`
+  --> $DIR/generic-impl-more-params-with-defaults.rs:5:8
+   |
+LL | struct Vec<T, A = Heap>(
+   |        ^^^ -  -
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generics/generic-no-mangle.fixed b/src/test/ui/generics/generic-no-mangle.fixed
index 72f9af0..207d8a9 100644
--- a/src/test/ui/generics/generic-no-mangle.fixed
+++ b/src/test/ui/generics/generic-no-mangle.fixed
@@ -6,7 +6,7 @@
 pub fn foo<T>() {} //~ ERROR functions generic over types or consts must be mangled
 
 
-pub extern fn bar<T>() {} //~ ERROR functions generic over types or consts must be mangled
+pub extern "C" fn bar<T>() {} //~ ERROR functions generic over types or consts must be mangled
 
 #[no_mangle]
 pub fn baz(x: &i32) -> &i32 { x }
diff --git a/src/test/ui/generics/generic-no-mangle.rs b/src/test/ui/generics/generic-no-mangle.rs
index 08d631e..146896c 100644
--- a/src/test/ui/generics/generic-no-mangle.rs
+++ b/src/test/ui/generics/generic-no-mangle.rs
@@ -6,7 +6,7 @@
 pub fn foo<T>() {} //~ ERROR functions generic over types or consts must be mangled
 
 #[no_mangle]
-pub extern fn bar<T>() {} //~ ERROR functions generic over types or consts must be mangled
+pub extern "C" fn bar<T>() {} //~ ERROR functions generic over types or consts must be mangled
 
 #[no_mangle]
 pub fn baz(x: &i32) -> &i32 { x }
diff --git a/src/test/ui/generics/generic-no-mangle.stderr b/src/test/ui/generics/generic-no-mangle.stderr
index e8e6d9d..b437417 100644
--- a/src/test/ui/generics/generic-no-mangle.stderr
+++ b/src/test/ui/generics/generic-no-mangle.stderr
@@ -17,8 +17,8 @@
    |
 LL | #[no_mangle]
    | ------------ help: remove this attribute
-LL | pub extern fn bar<T>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | pub extern "C" fn bar<T>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generics/generic-type-less-params-with-defaults.rs b/src/test/ui/generics/generic-type-less-params-with-defaults.rs
index 3aa0339..6b877ab 100644
--- a/src/test/ui/generics/generic-type-less-params-with-defaults.rs
+++ b/src/test/ui/generics/generic-type-less-params-with-defaults.rs
@@ -7,5 +7,5 @@
 
 fn main() {
     let _: Vec;
-    //~^ ERROR wrong number of type arguments: expected at least 1, found 0 [E0107]
+    //~^ ERROR missing generics for struct `Vec`
 }
diff --git a/src/test/ui/generics/generic-type-less-params-with-defaults.stderr b/src/test/ui/generics/generic-type-less-params-with-defaults.stderr
index a4cc832..93f7a24 100644
--- a/src/test/ui/generics/generic-type-less-params-with-defaults.stderr
+++ b/src/test/ui/generics/generic-type-less-params-with-defaults.stderr
@@ -1,8 +1,18 @@
-error[E0107]: wrong number of type arguments: expected at least 1, found 0
+error[E0107]: missing generics for struct `Vec`
   --> $DIR/generic-type-less-params-with-defaults.rs:9:12
    |
 LL |     let _: Vec;
    |            ^^^ expected at least 1 type argument
+   |
+note: struct defined here, with at least 1 type parameter: `T`
+  --> $DIR/generic-type-less-params-with-defaults.rs:5:8
+   |
+LL | struct Vec<T, A = Heap>(
+   |        ^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL |     let _: Vec<T>;
+   |               ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generics/generic-type-more-params-with-defaults.rs b/src/test/ui/generics/generic-type-more-params-with-defaults.rs
index 2713f08..c421774 100644
--- a/src/test/ui/generics/generic-type-more-params-with-defaults.rs
+++ b/src/test/ui/generics/generic-type-more-params-with-defaults.rs
@@ -7,5 +7,5 @@
 
 fn main() {
     let _: Vec<isize, Heap, bool>;
-    //~^ ERROR wrong number of type arguments: expected at most 2, found 3 [E0107]
+    //~^ ERROR this struct takes at most 2 type arguments but 3 type arguments were supplied
 }
diff --git a/src/test/ui/generics/generic-type-more-params-with-defaults.stderr b/src/test/ui/generics/generic-type-more-params-with-defaults.stderr
index cc296b5..e331481 100644
--- a/src/test/ui/generics/generic-type-more-params-with-defaults.stderr
+++ b/src/test/ui/generics/generic-type-more-params-with-defaults.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of type arguments: expected at most 2, found 3
-  --> $DIR/generic-type-more-params-with-defaults.rs:9:29
+error[E0107]: this struct takes at most 2 type arguments but 3 type arguments were supplied
+  --> $DIR/generic-type-more-params-with-defaults.rs:9:12
    |
 LL |     let _: Vec<isize, Heap, bool>;
-   |                             ^^^^ unexpected type argument
+   |            ^^^            ------ help: remove this type argument
+   |            |
+   |            expected at most 2 type arguments
+   |
+note: struct defined here, with at most 2 type parameters: `T`, `A`
+  --> $DIR/generic-type-more-params-with-defaults.rs:5:8
+   |
+LL | struct Vec<T, A = Heap>(
+   |        ^^^ -  -
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-2936.rs b/src/test/ui/generics/issue-2936.rs
similarity index 100%
rename from src/test/ui/issues/issue-2936.rs
rename to src/test/ui/generics/issue-2936.rs
diff --git a/src/test/ui/generics/wrong-number-of-args.rs b/src/test/ui/generics/wrong-number-of-args.rs
new file mode 100644
index 0000000..6b99865
--- /dev/null
+++ b/src/test/ui/generics/wrong-number-of-args.rs
@@ -0,0 +1,161 @@
+mod no_generics {
+    struct Ty;
+
+    type A = Ty;
+
+    type B = Ty<'static>;
+    //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+    //~| HELP remove these generics
+
+    type C = Ty<'static, usize>;
+    //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+    //~| ERROR this struct takes 0 type arguments but 1 type argument was supplied
+    //~| HELP remove this lifetime argument
+    //~| HELP remove this type argument
+
+    type D = Ty<'static, usize, { 0 }>;
+    //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+    //~| ERROR this struct takes 0 generic arguments but 2 generic arguments were supplied
+    //~| HELP remove this lifetime argument
+    //~| HELP remove these generic arguments
+}
+
+mod type_and_type {
+    struct Ty<A, B>;
+
+    type A = Ty;
+    //~^ ERROR missing generics for struct `type_and_type::Ty`
+    //~| HELP use angle brackets
+
+    type B = Ty<usize>;
+    //~^ ERROR this struct takes 2 type arguments but only 1 type argument was supplied
+    //~| HELP add missing type argument
+
+    type C = Ty<usize, String>;
+
+    type D = Ty<usize, String, char>;
+    //~^ ERROR this struct takes 2 type arguments but 3 type arguments were supplied
+    //~| HELP remove this type argument
+}
+
+mod lifetime_and_type {
+    struct Ty<'a, T>;
+
+    type A = Ty;
+    //~^ ERROR missing generics for struct `lifetime_and_type::Ty`
+    //~| ERROR missing lifetime specifier
+    //~| HELP consider introducing
+    //~| HELP use angle brackets
+
+    type B = Ty<'static>;
+    //~^ ERROR this struct takes 1 type argument but 0 type arguments were supplied
+    //~| HELP add missing type argument
+
+    type C = Ty<usize>;
+    //~^ ERROR missing lifetime specifier
+    //~| HELP consider introducing
+
+    type D = Ty<'static, usize>;
+}
+
+mod type_and_type_and_type {
+    struct Ty<A, B, C = &'static str>;
+
+    type A = Ty;
+    //~^ ERROR missing generics for struct `type_and_type_and_type::Ty`
+    //~| HELP use angle brackets
+
+    type B = Ty<usize>;
+    //~^ ERROR this struct takes at least 2 type arguments but only 1 type argument was supplied
+    //~| HELP add missing type argument
+
+    type C = Ty<usize, String>;
+
+    type D = Ty<usize, String, char>;
+
+    type E = Ty<usize, String, char, f64>;
+    //~^ ERROR this struct takes at most 3 type arguments but 4 type arguments were supplied
+    //~| HELP remove
+}
+
+// Traits have an implicit `Self` type - these tests ensure we don't accidentally return it
+// somewhere in the message
+mod r#trait {
+    trait NonGeneric {
+        //
+    }
+
+    trait GenericLifetime<'a> {
+        //
+    }
+
+    trait GenericType<A> {
+        //
+    }
+
+    type A = Box<dyn NonGeneric<usize>>;
+    //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+    //~| HELP remove
+
+    type B = Box<dyn GenericLifetime>;
+    //~^ ERROR missing lifetime specifier
+    //~| HELP consider introducing
+
+    type C = Box<dyn GenericLifetime<'static, 'static>>;
+    //~^ ERROR this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
+    //~| HELP remove
+
+    type D = Box<dyn GenericType>;
+    //~^ ERROR missing generics for trait `GenericType`
+    //~| HELP use angle brackets
+
+    type E = Box<dyn GenericType<String, usize>>;
+    //~^ ERROR this trait takes 1 type argument but 2 type arguments were supplied
+    //~| HELP remove
+}
+
+mod stdlib {
+    mod hash_map {
+        use std::collections::HashMap;
+
+        type A = HashMap;
+        //~^ ERROR missing generics for struct `HashMap`
+        //~| HELP use angle brackets
+
+        type B = HashMap<String>;
+        //~^ ERROR this struct takes at least 2 type arguments but only 1 type argument was supplied
+        //~| HELP add missing type argument
+
+        type C = HashMap<'static>;
+        //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+        //~| HELP remove these generics
+        //~| ERROR this struct takes at least 2 type arguments but 0 type arguments were supplied
+        //~| HELP add missing type arguments
+
+        type D = HashMap<usize, String, char, f64>;
+        //~^ ERROR this struct takes at most 3 type arguments but 4 type arguments were supplied
+        //~| HELP remove this type argument
+    }
+
+    mod result {
+        type A = Result;
+        //~^ ERROR missing generics for enum `std::result::Result`
+        //~| HELP use angle brackets
+
+        type B = Result<String>;
+        //~^ ERROR this enum takes 2 type arguments but only 1 type argument was supplied
+        //~| HELP add missing type argument
+
+        type C = Result<'static>;
+        //~^ ERROR this enum takes 0 lifetime arguments but 1 lifetime argument was supplied
+        //~| HELP remove these generics
+        //~| ERROR this enum takes 2 type arguments but 0 type arguments were supplied
+        //~| HELP add missing type arguments
+
+        type D = Result<usize, String, char>;
+        //~^ ERROR this enum takes 2 type arguments but 3 type arguments were supplied
+        //~| HELP remove
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr
new file mode 100644
index 0000000..2a34fba
--- /dev/null
+++ b/src/test/ui/generics/wrong-number-of-args.stderr
@@ -0,0 +1,449 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:44:14
+   |
+LL |     type A = Ty;
+   |              ^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type A<'a> = Ty<'a>;
+   |           ^^^^   ^^^^^^
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:54:17
+   |
+LL |     type C = Ty<usize>;
+   |                 ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type C<'a> = Ty<'a, usize>;
+   |           ^^^^      ^^^
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:100:22
+   |
+LL |     type B = Box<dyn GenericLifetime>;
+   |                      ^^^^^^^^^^^^^^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type B<'a> = Box<dyn GenericLifetime<'a>>;
+   |           ^^^^           ^^^^^^^^^^^^^^^^^^^
+
+error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/wrong-number-of-args.rs:6:14
+   |
+LL |     type B = Ty<'static>;
+   |              ^^--------- help: remove these generics
+   |              |
+   |              expected 0 lifetime arguments
+   |
+note: struct defined here, with 0 lifetime parameters
+  --> $DIR/wrong-number-of-args.rs:2:12
+   |
+LL |     struct Ty;
+   |            ^^
+
+error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/wrong-number-of-args.rs:10:14
+   |
+LL |     type C = Ty<'static, usize>;
+   |              ^^ --------- help: remove this lifetime argument
+   |              |
+   |              expected 0 lifetime arguments
+   |
+note: struct defined here, with 0 lifetime parameters
+  --> $DIR/wrong-number-of-args.rs:2:12
+   |
+LL |     struct Ty;
+   |            ^^
+
+error[E0107]: this struct takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/wrong-number-of-args.rs:10:14
+   |
+LL |     type C = Ty<'static, usize>;
+   |              ^^        ------- help: remove this type argument
+   |              |
+   |              expected 0 type arguments
+   |
+note: struct defined here, with 0 type parameters
+  --> $DIR/wrong-number-of-args.rs:2:12
+   |
+LL |     struct Ty;
+   |            ^^
+
+error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/wrong-number-of-args.rs:16:14
+   |
+LL |     type D = Ty<'static, usize, { 0 }>;
+   |              ^^ --------- help: remove this lifetime argument
+   |              |
+   |              expected 0 lifetime arguments
+   |
+note: struct defined here, with 0 lifetime parameters
+  --> $DIR/wrong-number-of-args.rs:2:12
+   |
+LL |     struct Ty;
+   |            ^^
+
+error[E0107]: this struct takes 0 generic arguments but 2 generic arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:16:14
+   |
+LL |     type D = Ty<'static, usize, { 0 }>;
+   |              ^^        -------------- help: remove these generic arguments
+   |              |
+   |              expected 0 generic arguments
+   |
+note: struct defined here, with 0 generic parameters
+  --> $DIR/wrong-number-of-args.rs:2:12
+   |
+LL |     struct Ty;
+   |            ^^
+
+error[E0107]: missing generics for struct `type_and_type::Ty`
+  --> $DIR/wrong-number-of-args.rs:26:14
+   |
+LL |     type A = Ty;
+   |              ^^ expected 2 type arguments
+   |
+note: struct defined here, with 2 type parameters: `A`, `B`
+  --> $DIR/wrong-number-of-args.rs:24:12
+   |
+LL |     struct Ty<A, B>;
+   |            ^^ -  -
+help: use angle brackets to add missing type arguments
+   |
+LL |     type A = Ty<A, B>;
+   |                ^^^^^^
+
+error[E0107]: this struct takes 2 type arguments but only 1 type argument was supplied
+  --> $DIR/wrong-number-of-args.rs:30:14
+   |
+LL |     type B = Ty<usize>;
+   |              ^^ ----- supplied 1 type argument
+   |              |
+   |              expected 2 type arguments
+   |
+note: struct defined here, with 2 type parameters: `A`, `B`
+  --> $DIR/wrong-number-of-args.rs:24:12
+   |
+LL |     struct Ty<A, B>;
+   |            ^^ -  -
+help: add missing type argument
+   |
+LL |     type B = Ty<usize, B>;
+   |                      ^^^
+
+error[E0107]: this struct takes 2 type arguments but 3 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:36:14
+   |
+LL |     type D = Ty<usize, String, char>;
+   |              ^^              ------ help: remove this type argument
+   |              |
+   |              expected 2 type arguments
+   |
+note: struct defined here, with 2 type parameters: `A`, `B`
+  --> $DIR/wrong-number-of-args.rs:24:12
+   |
+LL |     struct Ty<A, B>;
+   |            ^^ -  -
+
+error[E0107]: missing generics for struct `lifetime_and_type::Ty`
+  --> $DIR/wrong-number-of-args.rs:44:14
+   |
+LL |     type A = Ty;
+   |              ^^ expected 1 type argument
+   |
+note: struct defined here, with 1 type parameter: `T`
+  --> $DIR/wrong-number-of-args.rs:42:12
+   |
+LL |     struct Ty<'a, T>;
+   |            ^^     -
+help: use angle brackets to add missing type argument
+   |
+LL |     type A = Ty<T>;
+   |                ^^^
+
+error[E0107]: this struct takes 1 type argument but 0 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:50:14
+   |
+LL |     type B = Ty<'static>;
+   |              ^^ expected 1 type argument
+   |
+note: struct defined here, with 1 type parameter: `T`
+  --> $DIR/wrong-number-of-args.rs:42:12
+   |
+LL |     struct Ty<'a, T>;
+   |            ^^     -
+help: add missing type argument
+   |
+LL |     type B = Ty<'static, T>;
+   |                        ^^^
+
+error[E0107]: missing generics for struct `type_and_type_and_type::Ty`
+  --> $DIR/wrong-number-of-args.rs:64:14
+   |
+LL |     type A = Ty;
+   |              ^^ expected at least 2 type arguments
+   |
+note: struct defined here, with at least 2 type parameters: `A`, `B`
+  --> $DIR/wrong-number-of-args.rs:62:12
+   |
+LL |     struct Ty<A, B, C = &'static str>;
+   |            ^^ -  -
+help: use angle brackets to add missing type arguments
+   |
+LL |     type A = Ty<A, B>;
+   |                ^^^^^^
+
+error[E0107]: this struct takes at least 2 type arguments but only 1 type argument was supplied
+  --> $DIR/wrong-number-of-args.rs:68:14
+   |
+LL |     type B = Ty<usize>;
+   |              ^^ ----- supplied 1 type argument
+   |              |
+   |              expected at least 2 type arguments
+   |
+note: struct defined here, with at least 2 type parameters: `A`, `B`
+  --> $DIR/wrong-number-of-args.rs:62:12
+   |
+LL |     struct Ty<A, B, C = &'static str>;
+   |            ^^ -  -
+help: add missing type argument
+   |
+LL |     type B = Ty<usize, B>;
+   |                      ^^^
+
+error[E0107]: this struct takes at most 3 type arguments but 4 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:76:14
+   |
+LL |     type E = Ty<usize, String, char, f64>;
+   |              ^^                    ----- help: remove this type argument
+   |              |
+   |              expected at most 3 type arguments
+   |
+note: struct defined here, with at most 3 type parameters: `A`, `B`, `C`
+  --> $DIR/wrong-number-of-args.rs:62:12
+   |
+LL |     struct Ty<A, B, C = &'static str>;
+   |            ^^ -  -  -
+
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/wrong-number-of-args.rs:96:22
+   |
+LL |     type A = Box<dyn NonGeneric<usize>>;
+   |                      ^^^^^^^^^^------- help: remove these generics
+   |                      |
+   |                      expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/wrong-number-of-args.rs:84:11
+   |
+LL |     trait NonGeneric {
+   |           ^^^^^^^^^^
+
+error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:104:22
+   |
+LL |     type C = Box<dyn GenericLifetime<'static, 'static>>;
+   |                      ^^^^^^^^^^^^^^^        --------- help: remove this lifetime argument
+   |                      |
+   |                      expected 1 lifetime argument
+   |
+note: trait defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/wrong-number-of-args.rs:88:11
+   |
+LL |     trait GenericLifetime<'a> {
+   |           ^^^^^^^^^^^^^^^ --
+
+error[E0107]: missing generics for trait `GenericType`
+  --> $DIR/wrong-number-of-args.rs:108:22
+   |
+LL |     type D = Box<dyn GenericType>;
+   |                      ^^^^^^^^^^^ expected 1 type argument
+   |
+note: trait defined here, with 1 type parameter: `A`
+  --> $DIR/wrong-number-of-args.rs:92:11
+   |
+LL |     trait GenericType<A> {
+   |           ^^^^^^^^^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL |     type D = Box<dyn GenericType<A>>;
+   |                                 ^^^
+
+error[E0107]: this trait takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:112:22
+   |
+LL |     type E = Box<dyn GenericType<String, usize>>;
+   |                      ^^^^^^^^^^^       ------- help: remove this type argument
+   |                      |
+   |                      expected 1 type argument
+   |
+note: trait defined here, with 1 type parameter: `A`
+  --> $DIR/wrong-number-of-args.rs:92:11
+   |
+LL |     trait GenericType<A> {
+   |           ^^^^^^^^^^^ -
+
+error[E0107]: missing generics for struct `HashMap`
+  --> $DIR/wrong-number-of-args.rs:121:18
+   |
+LL |         type A = HashMap;
+   |                  ^^^^^^^ expected at least 2 type arguments
+   |
+note: struct defined here, with at least 2 type parameters: `K`, `V`
+  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
+   |
+LL | pub struct HashMap<K, V, S = RandomState> {
+   |            ^^^^^^^ -  -
+help: use angle brackets to add missing type arguments
+   |
+LL |         type A = HashMap<K, V>;
+   |                         ^^^^^^
+
+error[E0107]: this struct takes at least 2 type arguments but only 1 type argument was supplied
+  --> $DIR/wrong-number-of-args.rs:125:18
+   |
+LL |         type B = HashMap<String>;
+   |                  ^^^^^^^ ------ supplied 1 type argument
+   |                  |
+   |                  expected at least 2 type arguments
+   |
+note: struct defined here, with at least 2 type parameters: `K`, `V`
+  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
+   |
+LL | pub struct HashMap<K, V, S = RandomState> {
+   |            ^^^^^^^ -  -
+help: add missing type argument
+   |
+LL |         type B = HashMap<String, V>;
+   |                                ^^^
+
+error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/wrong-number-of-args.rs:129:18
+   |
+LL |         type C = HashMap<'static>;
+   |                  ^^^^^^^--------- help: remove these generics
+   |                  |
+   |                  expected 0 lifetime arguments
+   |
+note: struct defined here, with 0 lifetime parameters
+  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
+   |
+LL | pub struct HashMap<K, V, S = RandomState> {
+   |            ^^^^^^^
+
+error[E0107]: this struct takes at least 2 type arguments but 0 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:129:18
+   |
+LL |         type C = HashMap<'static>;
+   |                  ^^^^^^^ expected at least 2 type arguments
+   |
+note: struct defined here, with at least 2 type parameters: `K`, `V`
+  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
+   |
+LL | pub struct HashMap<K, V, S = RandomState> {
+   |            ^^^^^^^ -  -
+help: add missing type arguments
+   |
+LL |         type C = HashMap<'static, K, V>;
+   |                                 ^^^^^^
+
+error[E0107]: this struct takes at most 3 type arguments but 4 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:135:18
+   |
+LL |         type D = HashMap<usize, String, char, f64>;
+   |                  ^^^^^^^                    ----- help: remove this type argument
+   |                  |
+   |                  expected at most 3 type arguments
+   |
+note: struct defined here, with at most 3 type parameters: `K`, `V`, `S`
+  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
+   |
+LL | pub struct HashMap<K, V, S = RandomState> {
+   |            ^^^^^^^ -  -  -
+
+error[E0107]: missing generics for enum `std::result::Result`
+  --> $DIR/wrong-number-of-args.rs:141:18
+   |
+LL |         type A = Result;
+   |                  ^^^^^^ expected 2 type arguments
+   |
+note: enum defined here, with 2 type parameters: `T`, `E`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   |          ^^^^^^ -  -
+help: use angle brackets to add missing type arguments
+   |
+LL |         type A = Result<T, E>;
+   |                        ^^^^^^
+
+error[E0107]: this enum takes 2 type arguments but only 1 type argument was supplied
+  --> $DIR/wrong-number-of-args.rs:145:18
+   |
+LL |         type B = Result<String>;
+   |                  ^^^^^^ ------ supplied 1 type argument
+   |                  |
+   |                  expected 2 type arguments
+   |
+note: enum defined here, with 2 type parameters: `T`, `E`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   |          ^^^^^^ -  -
+help: add missing type argument
+   |
+LL |         type B = Result<String, E>;
+   |                               ^^^
+
+error[E0107]: this enum takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/wrong-number-of-args.rs:149:18
+   |
+LL |         type C = Result<'static>;
+   |                  ^^^^^^--------- help: remove these generics
+   |                  |
+   |                  expected 0 lifetime arguments
+   |
+note: enum defined here, with 0 lifetime parameters
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   |          ^^^^^^
+
+error[E0107]: this enum takes 2 type arguments but 0 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:149:18
+   |
+LL |         type C = Result<'static>;
+   |                  ^^^^^^ expected 2 type arguments
+   |
+note: enum defined here, with 2 type parameters: `T`, `E`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   |          ^^^^^^ -  -
+help: add missing type arguments
+   |
+LL |         type C = Result<'static, T, E>;
+   |                                ^^^^^^
+
+error[E0107]: this enum takes 2 type arguments but 3 type arguments were supplied
+  --> $DIR/wrong-number-of-args.rs:155:18
+   |
+LL |         type D = Result<usize, String, char>;
+   |                  ^^^^^^              ------ help: remove this type argument
+   |                  |
+   |                  expected 2 type arguments
+   |
+note: enum defined here, with 2 type parameters: `T`, `E`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   |          ^^^^^^ -  -
+
+error: aborting due to 30 previous errors
+
+Some errors have detailed explanations: E0106, E0107.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/src/test/ui/hashmap/hashmap-memory.rs b/src/test/ui/hashmap/hashmap-memory.rs
index 3129eb0..2031196 100644
--- a/src/test/ui/hashmap/hashmap-memory.rs
+++ b/src/test/ui/hashmap/hashmap-memory.rs
@@ -23,7 +23,7 @@
 
     pub type putter<'a> = Box<dyn FnMut(String, String) + 'a>;
 
-    pub type mapper = extern fn(String, putter);
+    pub type mapper = extern "C" fn(String, putter);
 
     enum ctrl_proto { find_reducer(Vec<u8>, Sender<isize>), mapper_done, }
 
diff --git a/src/test/ui/hello2021.rs b/src/test/ui/hello2021.rs
new file mode 100644
index 0000000..738f151
--- /dev/null
+++ b/src/test/ui/hello2021.rs
@@ -0,0 +1,7 @@
+// run-pass
+// edition:2021
+// compile-flags: -Zunstable-options
+
+fn main() {
+    println!("hello, 2021");
+}
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
index 1ceb0c9..ed810d4 100644
--- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
@@ -2,19 +2,39 @@
   --> $DIR/hrtb-perfect-forwarding.rs:46:5
    |
 LL |     foo_hrtb_bar_not(&mut t);
-   |     ^^^^^^^^^^^^^^^^ one type is more general than the other
+   |     ^^^^^^^^^^^^^^^^ lifetime mismatch
    |
    = note: expected type `Bar<&'a isize>`
               found type `Bar<&'b isize>`
+note: the required lifetime does not necessarily outlive the lifetime `'b` as defined on the function body at 39:21
+  --> $DIR/hrtb-perfect-forwarding.rs:39:21
+   |
+LL | fn foo_hrtb_bar_not<'b,T>(mut t: T)
+   |                     ^^
+note: the lifetime requirement is introduced here
+  --> $DIR/hrtb-perfect-forwarding.rs:40:15
+   |
+LL |     where T : for<'a> Foo<&'a isize> + Bar<&'b isize>
+   |               ^^^^^^^^^^^^^^^^^^^^^^
 
 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
+   |     ^^^^^^^^^^^^^^^^ lifetime mismatch
    |
    = note: expected type `Bar<&'a isize>`
               found type `Bar<&'b isize>`
+note: the lifetime `'b` as defined on the function body at 39:21 doesn't meet the lifetime requirements
+  --> $DIR/hrtb-perfect-forwarding.rs:39:21
+   |
+LL | fn foo_hrtb_bar_not<'b,T>(mut t: T)
+   |                     ^^
+note: the lifetime requirement is introduced here
+  --> $DIR/hrtb-perfect-forwarding.rs:40:15
+   |
+LL |     where T : for<'a> Foo<&'a isize> + Bar<&'b isize>
+   |               ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/hygiene/traits-in-scope.rs b/src/test/ui/hygiene/traits-in-scope.rs
new file mode 100644
index 0000000..548bb22
--- /dev/null
+++ b/src/test/ui/hygiene/traits-in-scope.rs
@@ -0,0 +1,53 @@
+// Macros with def-site hygiene still bring traits into scope.
+// It is not clear whether this is desirable behavior or not.
+// It is also not clear how to prevent it if it is not desirable.
+
+// check-pass
+
+#![feature(decl_macro)]
+#![feature(trait_alias)]
+
+mod traits {
+    pub trait Trait1 {
+        fn simple_import(&self) {}
+    }
+    pub trait Trait2 {
+        fn renamed_import(&self) {}
+    }
+    pub trait Trait3 {
+        fn underscore_import(&self) {}
+    }
+    pub trait Trait4 {
+        fn trait_alias(&self) {}
+    }
+
+    impl Trait1 for () {}
+    impl Trait2 for () {}
+    impl Trait3 for () {}
+    impl Trait4 for () {}
+}
+
+macro m1() {
+    use traits::Trait1;
+}
+macro m2() {
+    use traits::Trait2 as Alias;
+}
+macro m3() {
+    use traits::Trait3 as _;
+}
+macro m4() {
+    trait Alias = traits::Trait4;
+}
+
+fn main() {
+    m1!();
+    m2!();
+    m3!();
+    m4!();
+
+    ().simple_import();
+    ().renamed_import();
+    ().underscore_import();
+    ().trait_alias();
+}
diff --git a/src/test/ui/impl-trait/bindings.stderr b/src/test/ui/impl-trait/bindings.stderr
index e983fde..4da49f4 100644
--- a/src/test/ui/impl-trait/bindings.stderr
+++ b/src/test/ui/impl-trait/bindings.stderr
@@ -2,25 +2,33 @@
   --> $DIR/bindings.rs:5:29
    |
 LL |     const foo: impl Clone = x;
-   |                             ^ non-constant value
+   |     ---------               ^ non-constant value
+   |     |
+   |     help: consider using `let` instead of `const`: `let foo`
 
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/bindings.rs:11:33
    |
 LL |         const foo: impl Clone = x;
-   |                                 ^ non-constant value
+   |         ---------               ^ non-constant value
+   |         |
+   |         help: consider using `let` instead of `const`: `let foo`
 
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/bindings.rs:18:33
    |
 LL |         const foo: impl Clone = x;
-   |                                 ^ non-constant value
+   |         ---------               ^ non-constant value
+   |         |
+   |         help: consider using `let` instead of `const`: `let foo`
 
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/bindings.rs:25:33
    |
 LL |         const foo: impl Clone = x;
-   |                                 ^ non-constant value
+   |         ---------               ^ non-constant value
+   |         |
+   |         help: consider using `let` instead of `const`: `let foo`
 
 warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/bindings.rs:1:12
diff --git a/src/test/ui/nested_impl_trait.rs b/src/test/ui/impl-trait/nested_impl_trait.rs
similarity index 100%
rename from src/test/ui/nested_impl_trait.rs
rename to src/test/ui/impl-trait/nested_impl_trait.rs
diff --git a/src/test/ui/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr
similarity index 100%
rename from src/test/ui/nested_impl_trait.stderr
rename to src/test/ui/impl-trait/nested_impl_trait.stderr
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
similarity index 100%
rename from src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs
rename to src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
similarity index 100%
rename from src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
rename to src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
diff --git a/src/test/ui/imports/glob-resolve1.rs b/src/test/ui/imports/glob-resolve1.rs
index 32660fd..904b771 100644
--- a/src/test/ui/imports/glob-resolve1.rs
+++ b/src/test/ui/imports/glob-resolve1.rs
@@ -5,11 +5,15 @@
 mod bar {
     use self::fpriv as import;
     fn fpriv() {}
-    extern {
+    extern "C" {
         fn epriv();
     }
-    enum A { A1 }
-    pub enum B { B1 }
+    enum A {
+        A1,
+    }
+    pub enum B {
+        B1,
+    }
 
     struct C;
 
diff --git a/src/test/ui/imports/glob-resolve1.stderr b/src/test/ui/imports/glob-resolve1.stderr
index cd128c1..7629ced 100644
--- a/src/test/ui/imports/glob-resolve1.stderr
+++ b/src/test/ui/imports/glob-resolve1.stderr
@@ -1,5 +1,5 @@
 error[E0425]: cannot find function `fpriv` in this scope
-  --> $DIR/glob-resolve1.rs:22:5
+  --> $DIR/glob-resolve1.rs:26:5
    |
 LL |     fpriv();
    |     ^^^^^ not found in this scope
@@ -10,7 +10,7 @@
    |
 
 error[E0425]: cannot find function `epriv` in this scope
-  --> $DIR/glob-resolve1.rs:23:5
+  --> $DIR/glob-resolve1.rs:27:5
    |
 LL |     epriv();
    |     ^^^^^ not found in this scope
@@ -21,23 +21,25 @@
    |
 
 error[E0423]: expected value, found enum `B`
-  --> $DIR/glob-resolve1.rs:24:5
+  --> $DIR/glob-resolve1.rs:28:5
    |
 LL |     B;
    |     ^
    |
 note: the enum is defined here
-  --> $DIR/glob-resolve1.rs:12:5
+  --> $DIR/glob-resolve1.rs:14:5
    |
-LL |     pub enum B { B1 }
-   |     ^^^^^^^^^^^^^^^^^
+LL | /     pub enum B {
+LL | |         B1,
+LL | |     }
+   | |_____^
 help: you might have meant to use the following enum variant
    |
 LL |     B::B1;
    |     ^^^^^
 
 error[E0425]: cannot find value `C` in this scope
-  --> $DIR/glob-resolve1.rs:25:5
+  --> $DIR/glob-resolve1.rs:29:5
    |
 LL |     C;
    |     ^ not found in this scope
@@ -48,7 +50,7 @@
    |
 
 error[E0425]: cannot find function `import` in this scope
-  --> $DIR/glob-resolve1.rs:26:5
+  --> $DIR/glob-resolve1.rs:30:5
    |
 LL |     import();
    |     ^^^^^^ not found in this scope
@@ -59,9 +61,9 @@
    |
 
 error[E0412]: cannot find type `A` in this scope
-  --> $DIR/glob-resolve1.rs:28:11
+  --> $DIR/glob-resolve1.rs:32:11
    |
-LL |     pub enum B { B1 }
+LL |     pub enum B {
    |     ---------- similarly named enum `B` defined here
 ...
 LL |     foo::<A>();
@@ -77,9 +79,9 @@
    |
 
 error[E0412]: cannot find type `C` in this scope
-  --> $DIR/glob-resolve1.rs:29:11
+  --> $DIR/glob-resolve1.rs:33:11
    |
-LL |     pub enum B { B1 }
+LL |     pub enum B {
    |     ---------- similarly named enum `B` defined here
 ...
 LL |     foo::<C>();
@@ -95,9 +97,9 @@
    |
 
 error[E0412]: cannot find type `D` in this scope
-  --> $DIR/glob-resolve1.rs:30:11
+  --> $DIR/glob-resolve1.rs:34:11
    |
-LL |     pub enum B { B1 }
+LL |     pub enum B {
    |     ---------- similarly named enum `B` defined here
 ...
 LL |     foo::<D>();
diff --git a/src/test/ui/issues/issue-26873-onefile.rs b/src/test/ui/imports/issue-26873-onefile.rs
similarity index 100%
rename from src/test/ui/issues/issue-26873-onefile.rs
rename to src/test/ui/imports/issue-26873-onefile.rs
diff --git a/src/test/ui/issues/issue-32119.rs b/src/test/ui/imports/issue-32119.rs
similarity index 100%
rename from src/test/ui/issues/issue-32119.rs
rename to src/test/ui/imports/issue-32119.rs
diff --git a/src/test/ui/issues/issue-32222.rs b/src/test/ui/imports/issue-32222.rs
similarity index 100%
rename from src/test/ui/issues/issue-32222.rs
rename to src/test/ui/imports/issue-32222.rs
diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr
index 2f630c2..2875cef 100644
--- a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr
+++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr
@@ -13,7 +13,9 @@
 LL |     let fut = async {
    |         --- consider giving `fut` the explicit type `impl Future`, with the type parameters specified
 LL |         make_unit()?;
-   |                    ^ cannot infer type
+   |                    ^ cannot infer type of error for `?` operator
+   |
+   = note: `?` implicitly converts the error value into a type implementing `From<std::io::Error>`
 
 error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/inference/cannot-infer-async.stderr b/src/test/ui/inference/cannot-infer-async.stderr
index 92a9045..282bc13 100644
--- a/src/test/ui/inference/cannot-infer-async.stderr
+++ b/src/test/ui/inference/cannot-infer-async.stderr
@@ -4,7 +4,9 @@
 LL |     let fut = async {
    |         --- consider giving `fut` a type
 LL |         make_unit()?;
-   |                    ^ cannot infer type
+   |                    ^ cannot infer type of error for `?` operator
+   |
+   = note: `?` implicitly converts the error value into a type implementing `From<std::io::Error>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/inference/cannot-infer-closure-circular.rs b/src/test/ui/inference/cannot-infer-closure-circular.rs
new file mode 100644
index 0000000..a3b9571
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-closure-circular.rs
@@ -0,0 +1,14 @@
+fn main() {
+    // Below we call the closure with its own return as the argument, unifying
+    // its inferred input and return types. We want to make sure that the generated
+    // error handles this gracefully, and in particular doesn't generate an extra
+    // note about the `?` operator in the closure body, which isn't relevant to
+    // the inference.
+    let x = |r| {
+        //~^ ERROR type annotations needed
+        let v = r?;
+        Ok(v)
+    };
+
+    let _ = x(x(Ok(())));
+}
diff --git a/src/test/ui/inference/cannot-infer-closure-circular.stderr b/src/test/ui/inference/cannot-infer-closure-circular.stderr
new file mode 100644
index 0000000..5efb400
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-closure-circular.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed for `std::result::Result<(), E>`
+  --> $DIR/cannot-infer-closure-circular.rs:7:14
+   |
+LL |     let x = |r| {
+   |              ^ consider giving this closure parameter the explicit type `std::result::Result<(), E>`, with the type parameters specified
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/inference/cannot-infer-closure.stderr b/src/test/ui/inference/cannot-infer-closure.stderr
index d5366e4..475ed00 100644
--- a/src/test/ui/inference/cannot-infer-closure.stderr
+++ b/src/test/ui/inference/cannot-infer-closure.stderr
@@ -2,8 +2,9 @@
   --> $DIR/cannot-infer-closure.rs:3:15
    |
 LL |         Err(a)?;
-   |               ^ cannot infer type
+   |               ^ cannot infer type of error for `?` operator
    |
+   = note: `?` implicitly converts the error value into a type implementing `From<()>`
 help: give this closure an explicit return type without `_` placeholders
    |
 LL |     let x = |a: (), b: ()| -> std::result::Result<(), _> {
diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.rs b/src/test/ui/inference/cannot-infer-partial-try-return.rs
new file mode 100644
index 0000000..e1058e9
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-partial-try-return.rs
@@ -0,0 +1,22 @@
+struct QualifiedError<E>(E);
+
+impl<E, T> From<E> for QualifiedError<T>
+where
+    E: std::error::Error,
+    T: From<E>,
+{
+    fn from(e: E) -> QualifiedError<T> {
+        QualifiedError(e.into())
+    }
+}
+
+fn infallible() -> Result<(), std::convert::Infallible> {
+    Ok(())
+}
+
+fn main() {
+    let x = || -> Result<_, QualifiedError<_>> {
+        infallible()?; //~ERROR type annotations needed
+        Ok(())
+    };
+}
diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.stderr b/src/test/ui/inference/cannot-infer-partial-try-return.stderr
new file mode 100644
index 0000000..a64503fa
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-partial-try-return.stderr
@@ -0,0 +1,15 @@
+error[E0282]: type annotations needed for the closure `fn() -> std::result::Result<(), QualifiedError<_>>`
+  --> $DIR/cannot-infer-partial-try-return.rs:19:9
+   |
+LL |         infallible()?;
+   |         ^^^^^^^^^^^^^ cannot infer type of error for `?` operator
+   |
+   = note: `?` implicitly converts the error value into `QualifiedError<_>` using its implementation of `From<Infallible>`
+help: give this closure an explicit return type without `_` placeholders
+   |
+LL |     let x = || -> std::result::Result<(), QualifiedError<_>> {
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/intrinsics/intrinsic-move-val-cleanups.rs b/src/test/ui/intrinsics/intrinsic-move-val-cleanups.rs
deleted file mode 100644
index 9804c42..0000000
--- a/src/test/ui/intrinsics/intrinsic-move-val-cleanups.rs
+++ /dev/null
@@ -1,191 +0,0 @@
-// run-pass
-#![allow(unused_braces)]
-#![allow(unused_unsafe)]
-#![allow(unreachable_code)]
-// ignore-emscripten no threads support
-#![allow(stable_features)]
-
-// This test is checking that the move_val_init intrinsic is
-// respecting cleanups for both of its argument expressions.
-//
-// In other words, if either DEST or SOURCE in
-//
-//   `intrinsics::move_val_init(DEST, SOURCE)
-//
-// introduce temporaries that require cleanup, and SOURCE panics, then
-// make sure the cleanups still occur.
-
-#![feature(core_intrinsics, sync_poison)]
-
-use std::cell::RefCell;
-use std::intrinsics;
-use std::sync::{Arc, LockResult, Mutex, MutexGuard};
-use std::thread;
-
-type LogEntry = (&'static str, i32);
-type Guarded = RefCell<Vec<LogEntry>>;
-#[derive(Clone)]
-struct Log(Arc<Mutex<Guarded>>);
-struct Acquired<'a>(MutexGuard<'a, Guarded>);
-type LogState = (MutexWas, &'static [LogEntry]);
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-enum MutexWas { Poisoned, NotPoisoned }
-
-impl Log {
-    fn lock(&self) -> LockResult<MutexGuard<RefCell<Vec<LogEntry>>>> { self.0.lock() }
-    fn acquire(&self) -> Acquired { Acquired(self.0.lock().unwrap()) }
-}
-
-impl<'a> Acquired<'a> {
-    fn log(&self, s: &'static str, i: i32) { self.0.borrow_mut().push((s, i)); }
-}
-
-const TEST1_EXPECT: LogState = (MutexWas::NotPoisoned,
-                                &[("double-check non-poisoning path", 1)
-                                  ]);
-
-fn test1(log: Log) {
-    {
-        let acq = log.acquire();
-        acq.log("double-check non-poisoning path", 1);
-    }
-    panic!("every test ends in a panic");
-}
-
-const TEST2_EXPECT: LogState = (MutexWas::Poisoned,
-                                &[("double-check poisoning path", 1),
-                                  ("and multiple log entries", 2),
-                                  ]);
-fn test2(log: Log) {
-    let acq = log.acquire();
-    acq.log("double-check poisoning path", 1);
-    acq.log("and multiple log entries", 2);
-    panic!("every test ends in a panic");
-}
-
-struct LogOnDrop<'a>(&'a Acquired<'a>, &'static str, i32);
-impl<'a> Drop for LogOnDrop<'a> {
-    fn drop(&mut self) {
-        self.0.log(self.1, self.2);
-    }
-}
-
-const TEST3_EXPECT: LogState = (MutexWas::Poisoned,
-                                &[("double-check destructors can log", 1),
-                                  ("drop d2", 2),
-                                  ("drop d1", 3),
-                                  ]);
-fn test3(log: Log) {
-    let acq = log.acquire();
-    acq.log("double-check destructors can log", 1);
-    let _d1 = LogOnDrop(&acq, "drop d1", 3);
-    let _d2 = LogOnDrop(&acq, "drop d2", 2);
-    panic!("every test ends in a panic");
-}
-
-// The *real* tests of panic-handling for move_val_init intrinsic
-// start here.
-
-const TEST4_EXPECT: LogState = (MutexWas::Poisoned,
-                                &[("neither arg panics", 1),
-                                  ("drop temp LOD", 2),
-                                  ("drop temp LOD", 3),
-                                  ("drop dest_b", 4),
-                                  ("drop dest_a", 5),
-                                  ]);
-fn test4(log: Log) {
-    let acq = log.acquire();
-    acq.log("neither arg panics", 1);
-    let mut dest_a = LogOnDrop(&acq, "a will be overwritten, not dropped", 0);
-    let mut dest_b = LogOnDrop(&acq, "b will be overwritten, not dropped", 0);
-    unsafe {
-        intrinsics::move_val_init({ LogOnDrop(&acq, "drop temp LOD", 2); &mut dest_a },
-                                  LogOnDrop(&acq, "drop dest_a", 5));
-        intrinsics::move_val_init(&mut dest_b, { LogOnDrop(&acq, "drop temp LOD", 3);
-                                                 LogOnDrop(&acq, "drop dest_b", 4) });
-    }
-    panic!("every test ends in a panic");
-}
-
-
-// Check that move_val_init(PANIC, SOURCE_EXPR) never evaluates SOURCE_EXPR
-const TEST5_EXPECT: LogState = (MutexWas::Poisoned,
-                                &[("first arg panics", 1),
-                                  ("drop orig dest_a", 2),
-                                  ]);
-fn test5(log: Log) {
-    let acq = log.acquire();
-    acq.log("first arg panics", 1);
-    let mut _dest_a = LogOnDrop(&acq, "drop orig dest_a", 2);
-    unsafe {
-        intrinsics::move_val_init({ panic!("every test ends in a panic") },
-                                  LogOnDrop(&acq, "we never get here", 0));
-    }
-}
-
-// Check that move_val_init(DEST_EXPR, PANIC) cleans up temps from DEST_EXPR.
-const TEST6_EXPECT: LogState = (MutexWas::Poisoned,
-                                &[("second arg panics", 1),
-                                  ("drop temp LOD", 2),
-                                  ("drop orig dest_a", 3),
-                                  ]);
-fn test6(log: Log) {
-    let acq = log.acquire();
-    acq.log("second arg panics", 1);
-    let mut dest_a = LogOnDrop(&acq, "drop orig dest_a", 3);
-    unsafe {
-        intrinsics::move_val_init({ LogOnDrop(&acq, "drop temp LOD", 2); &mut dest_a },
-                                  { panic!("every test ends in a panic"); });
-    }
-}
-
-// Check that move_val_init(DEST_EXPR, COMPLEX_PANIC) cleans up temps from COMPLEX_PANIC.
-const TEST7_EXPECT: LogState = (MutexWas::Poisoned,
-                                &[("second arg panics", 1),
-                                  ("drop temp LOD", 2),
-                                  ("drop temp LOD", 3),
-                                  ("drop orig dest_a", 4),
-                                  ]);
-fn test7(log: Log) {
-    let acq = log.acquire();
-    acq.log("second arg panics", 1);
-    let mut dest_a = LogOnDrop(&acq, "drop orig dest_a", 4);
-    unsafe {
-        intrinsics::move_val_init({ LogOnDrop(&acq, "drop temp LOD", 2); &mut dest_a },
-                                  { LogOnDrop(&acq, "drop temp LOD", 3);
-                                    panic!("every test ends in a panic"); });
-    }
-}
-
-const TEST_SUITE: &'static [(&'static str, fn (Log), LogState)] =
-    &[("test1", test1, TEST1_EXPECT),
-      ("test2", test2, TEST2_EXPECT),
-      ("test3", test3, TEST3_EXPECT),
-      ("test4", test4, TEST4_EXPECT),
-      ("test5", test5, TEST5_EXPECT),
-      ("test6", test6, TEST6_EXPECT),
-      ("test7", test7, TEST7_EXPECT),
-      ];
-
-fn main() {
-    for &(name, test, expect) in TEST_SUITE {
-        let log = Log(Arc::new(Mutex::new(RefCell::new(Vec::new()))));
-        let ret = { let log = log.clone(); thread::spawn(move || test(log)).join() };
-        assert!(ret.is_err(), "{} must end with panic", name);
-        {
-            let l = log.lock();
-            match l {
-                Ok(acq) => {
-                    assert_eq!((MutexWas::NotPoisoned, &acq.borrow()[..]), expect);
-                    println!("{} (unpoisoned) log: {:?}", name, *acq);
-                }
-                Err(e) => {
-                    let acq = e.into_inner();
-                    assert_eq!((MutexWas::Poisoned, &acq.borrow()[..]), expect);
-                    println!("{} (poisoned) log: {:?}", name, *acq);
-                }
-            }
-        }
-    }
-}
diff --git a/src/test/ui/intrinsics/intrinsic-move-val.rs b/src/test/ui/intrinsics/intrinsic-move-val.rs
deleted file mode 100644
index b672f1e..0000000
--- a/src/test/ui/intrinsics/intrinsic-move-val.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-// run-pass
-
-#![feature(box_syntax)]
-#![feature(intrinsics)]
-
-mod rusti {
-    extern "rust-intrinsic" {
-        pub fn move_val_init<T>(dst: *mut T, src: T);
-    }
-}
-
-pub fn main() {
-    unsafe {
-        // sanity check
-        check_drops_state(0, None);
-
-        let mut x: Option<Box<D>> = Some(box D(1));
-        assert_eq!(x.as_ref().unwrap().0, 1);
-
-        // A normal overwrite, to demonstrate `check_drops_state`.
-        x = Some(box D(2));
-
-        // At this point, one destructor has run, because the
-        // overwrite of `x` drops its initial value.
-        check_drops_state(1, Some(1));
-
-        let mut y: Option<Box<D>> = std::mem::zeroed();
-
-        // An initial binding does not overwrite anything.
-        check_drops_state(1, Some(1));
-
-        // Since `y` has been initialized via the `init` intrinsic, it
-        // would be unsound to directly overwrite its value via normal
-        // assignment.
-        //
-        // The code currently generated by the compiler is overly
-        // accepting, however, in that it will check if `y` is itself
-        // null and thus avoid the unsound action of attempting to
-        // free null. In other words, if we were to do a normal
-        // assignment like `y = box D(4);` here, it probably would not
-        // crash today. But the plan is that it may well crash in the
-        // future, (I believe).
-
-        // `x` is moved here; the manner in which this is tracked by the
-        // compiler is hidden.
-        rusti::move_val_init(&mut y, x);
-
-        // But what we *can* observe is how many times the destructor
-        // for `D` is invoked, and what the last value we saw was
-        // during such a destructor call. We do so after the end of
-        // this scope.
-
-        assert_eq!(y.as_ref().unwrap().0, 2);
-        y.as_mut().unwrap().0 = 3;
-        assert_eq!(y.as_ref().unwrap().0, 3);
-
-        check_drops_state(1, Some(1));
-    }
-
-    check_drops_state(2, Some(3));
-}
-
-static mut NUM_DROPS: i32 = 0;
-static mut LAST_DROPPED: Option<i32> = None;
-
-fn check_drops_state(num_drops: i32, last_dropped: Option<i32>) {
-    unsafe {
-        assert_eq!(NUM_DROPS, num_drops);
-        assert_eq!(LAST_DROPPED, last_dropped);
-    }
-}
-
-struct D(i32);
-impl Drop for D {
-    fn drop(&mut self) {
-        unsafe {
-            NUM_DROPS += 1;
-            LAST_DROPPED = Some(self.0);
-        }
-    }
-}
diff --git a/src/test/ui/issues/auxiliary/issue-10031-aux.rs b/src/test/ui/issues/auxiliary/issue-10031-aux.rs
deleted file mode 100644
index e2abeb9..0000000
--- a/src/test/ui/issues/auxiliary/issue-10031-aux.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub struct Wrap<A>(pub A);
diff --git a/src/test/ui/issues/auxiliary/issue-13620-1.rs b/src/test/ui/issues/auxiliary/issue-13620-1.rs
index 1442c0c..a77aa5a 100644
--- a/src/test/ui/issues/auxiliary/issue-13620-1.rs
+++ b/src/test/ui/issues/auxiliary/issue-13620-1.rs
@@ -1,8 +1,8 @@
 pub struct Foo {
-    pub foo: extern fn()
+    pub foo: extern "C" fn()
 }
 
-extern fn the_foo() {}
+extern "C" fn the_foo() {}
 
 pub const FOO: Foo = Foo {
     foo: the_foo
diff --git a/src/test/ui/issues/auxiliary/issue-15562.rs b/src/test/ui/issues/auxiliary/issue-15562.rs
index d5afaaa..6ff26b4 100644
--- a/src/test/ui/issues/auxiliary/issue-15562.rs
+++ b/src/test/ui/issues/auxiliary/issue-15562.rs
@@ -1,5 +1,5 @@
 #![crate_type = "lib"]
 
-extern {
+extern "C" {
     pub fn transmute();
 }
diff --git a/src/test/ui/issues/auxiliary/issue-16725.rs b/src/test/ui/issues/auxiliary/issue-16725.rs
index b75b5e2..9f9abd5 100644
--- a/src/test/ui/issues/auxiliary/issue-16725.rs
+++ b/src/test/ui/issues/auxiliary/issue-16725.rs
@@ -1,3 +1,3 @@
-extern {
+extern "C" {
     fn bar();
 }
diff --git a/src/test/ui/issues/auxiliary/issue-25185-1.rs b/src/test/ui/issues/auxiliary/issue-25185-1.rs
index 77a4787..e957be9 100644
--- a/src/test/ui/issues/auxiliary/issue-25185-1.rs
+++ b/src/test/ui/issues/auxiliary/issue-25185-1.rs
@@ -3,6 +3,6 @@
 #![crate_type = "rlib"]
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     pub fn rust_dbg_extern_identity_u32(u: u32) -> u32;
 }
diff --git a/src/test/ui/issues/issue-10031.rs b/src/test/ui/issues/issue-10031.rs
deleted file mode 100644
index 136df05..0000000
--- a/src/test/ui/issues/issue-10031.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// run-pass
-// aux-build:issue-10031-aux.rs
-// pretty-expanded FIXME #23616
-
-extern crate issue_10031_aux;
-
-pub fn main() {
-    let _ = issue_10031_aux::Wrap(());
-}
diff --git a/src/test/ui/issues/issue-10764.rs b/src/test/ui/issues/issue-10764.rs
index 8fa3607..bb915f5 100644
--- a/src/test/ui/issues/issue-10764.rs
+++ b/src/test/ui/issues/issue-10764.rs
@@ -1,5 +1,5 @@
 fn f(_: extern "Rust" fn()) {}
-extern fn bar() {}
+extern "C" fn bar() {}
 
 fn main() { f(bar) }
 //~^ ERROR mismatched types
diff --git a/src/test/ui/issues/issue-10877.rs b/src/test/ui/issues/issue-10877.rs
index b57929b..15a3831 100644
--- a/src/test/ui/issues/issue-10877.rs
+++ b/src/test/ui/issues/issue-10877.rs
@@ -1,12 +1,14 @@
-struct Foo { x: isize }
-extern {
+struct Foo {
+    x: isize,
+}
+extern "C" {
     fn foo(1: ());
     //~^ ERROR: patterns aren't allowed in foreign function declarations
     fn bar((): isize);
     //~^ ERROR: patterns aren't allowed in foreign function declarations
     fn baz(Foo { x }: isize);
     //~^ ERROR: patterns aren't allowed in foreign function declarations
-    fn qux((x,y): ());
+    fn qux((x, y): ());
     //~^ ERROR: patterns aren't allowed in foreign function declarations
     fn this_is_actually_ok(a: usize);
     fn and_so_is_this(_: usize);
diff --git a/src/test/ui/issues/issue-10877.stderr b/src/test/ui/issues/issue-10877.stderr
index 0f9dc21..bd3797c 100644
--- a/src/test/ui/issues/issue-10877.stderr
+++ b/src/test/ui/issues/issue-10877.stderr
@@ -1,26 +1,26 @@
 error[E0130]: patterns aren't allowed in foreign function declarations
-  --> $DIR/issue-10877.rs:3:12
+  --> $DIR/issue-10877.rs:5:12
    |
 LL |     fn foo(1: ());
    |            ^ pattern not allowed in foreign function
 
 error[E0130]: patterns aren't allowed in foreign function declarations
-  --> $DIR/issue-10877.rs:5:12
+  --> $DIR/issue-10877.rs:7:12
    |
 LL |     fn bar((): isize);
    |            ^^ pattern not allowed in foreign function
 
 error[E0130]: patterns aren't allowed in foreign function declarations
-  --> $DIR/issue-10877.rs:7:12
+  --> $DIR/issue-10877.rs:9:12
    |
 LL |     fn baz(Foo { x }: isize);
    |            ^^^^^^^^^ pattern not allowed in foreign function
 
 error[E0130]: patterns aren't allowed in foreign function declarations
-  --> $DIR/issue-10877.rs:9:12
+  --> $DIR/issue-10877.rs:11:12
    |
-LL |     fn qux((x,y): ());
-   |            ^^^^^ pattern not allowed in foreign function
+LL |     fn qux((x, y): ());
+   |            ^^^^^^ pattern not allowed in foreign function
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-1251.rs b/src/test/ui/issues/issue-1251.rs
index 7f25c9a..c2c047c 100644
--- a/src/test/ui/issues/issue-1251.rs
+++ b/src/test/ui/issues/issue-1251.rs
@@ -3,15 +3,14 @@
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 // ignore-wasm32-bare no libc to test ffi with
-
 #![feature(rustc_private)]
 
 mod rustrt {
     extern crate libc;
 
-    extern {
+    extern "C" {
         pub fn rust_get_test_int() -> libc::intptr_t;
     }
 }
 
-pub fn main() { }
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-13033.stderr b/src/test/ui/issues/issue-13033.stderr
index a8473c8..57447fa 100644
--- a/src/test/ui/issues/issue-13033.stderr
+++ b/src/test/ui/issues/issue-13033.stderr
@@ -5,14 +5,13 @@
    |                              ------------ type in trait
 ...
 LL |     fn bar(&mut self, other: &dyn Foo) {}
-   |                              ^^^^^^^^ types differ in mutability
+   |                              ^^^^^^^^
+   |                              |
+   |                              types differ in mutability
+   |                              help: consider changing the mutability to match the trait: `&mut dyn Foo`
    |
    = note: expected fn pointer `fn(&mut Baz, &mut dyn Foo)`
               found fn pointer `fn(&mut Baz, &dyn Foo)`
-help: consider change the type to match the mutability in trait
-   |
-LL |     fn bar(&mut self, other: &mut dyn Foo) {}
-   |                              ^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-14091.stderr b/src/test/ui/issues/issue-14091.stderr
index 7db4734..fc49cc6 100644
--- a/src/test/ui/issues/issue-14091.stderr
+++ b/src/test/ui/issues/issue-14091.stderr
@@ -3,6 +3,8 @@
    |
 LL |     assert!(1,1);
    |     ^^^^^^^^^^^^^ expected `bool`, found integer
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-14092.rs b/src/test/ui/issues/issue-14092.rs
index 3cfaa20..67c2a42 100644
--- a/src/test/ui/issues/issue-14092.rs
+++ b/src/test/ui/issues/issue-14092.rs
@@ -1,4 +1,4 @@
 fn fn1(0: Box) {}
-        //~^ ERROR wrong number of type arguments: expected at least 1, found 0 [E0107]
+//~^ ERROR missing generics for struct `Box`
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-14092.stderr b/src/test/ui/issues/issue-14092.stderr
index b749c44..5cacce7 100644
--- a/src/test/ui/issues/issue-14092.stderr
+++ b/src/test/ui/issues/issue-14092.stderr
@@ -1,8 +1,20 @@
-error[E0107]: wrong number of type arguments: expected at least 1, found 0
+error[E0107]: missing generics for struct `Box`
   --> $DIR/issue-14092.rs:1:11
    |
 LL | fn fn1(0: Box) {}
    |           ^^^ expected at least 1 type argument
+   |
+note: struct defined here, with at least 1 type parameter: `T`
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+   |
+LL | pub struct Box<
+   |            ^^^
+LL |     T: ?Sized,
+   |     -
+help: use angle brackets to add missing type argument
+   |
+LL | fn fn1(0: Box<T>) {}
+   |              ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-14227.rs b/src/test/ui/issues/issue-14227.rs
index d80eefc..a1fde14 100644
--- a/src/test/ui/issues/issue-14227.rs
+++ b/src/test/ui/issues/issue-14227.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     pub static symbol: u32;
 }
 static CRASH: u32 = symbol;
diff --git a/src/test/ui/issues/issue-15487.rs b/src/test/ui/issues/issue-15487.rs
index 17b16a6..34ac53b 100644
--- a/src/test/ui/issues/issue-15487.rs
+++ b/src/test/ui/issues/issue-15487.rs
@@ -3,12 +3,11 @@
 // ignore-windows
 // ignore-wasm32-bare no libs to link
 // ignore-sgx no libs to link
-
 #![feature(link_args)]
 
-#[link_args="-lc  -lm"]
-#[link_args=" -lc"]
-#[link_args="-lc "]
-extern {}
+#[link_args = "-lc  -lm"]
+#[link_args = " -lc"]
+#[link_args = "-lc "]
+extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-15562.rs b/src/test/ui/issues/issue-15562.rs
index b37ba81..dc0ecd3 100644
--- a/src/test/ui/issues/issue-15562.rs
+++ b/src/test/ui/issues/issue-15562.rs
@@ -16,4 +16,4 @@
 // The above extern is NOT `extern "rust-intrinsic"` and thus
 // means it'll try to find a corresponding symbol to link to.
 #[no_mangle]
-pub extern fn transmute() {}
+pub extern "C" fn transmute() {}
diff --git a/src/test/ui/issues/issue-15881-model-lexer-dotdotdot.rs b/src/test/ui/issues/issue-15881-model-lexer-dotdotdot.rs
deleted file mode 100644
index dee7f25..0000000
--- a/src/test/ui/issues/issue-15881-model-lexer-dotdotdot.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-// run-pass
-#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620
-#![allow(ellipsis_inclusive_range_patterns)]
-
-// regression test for the model lexer handling the DOTDOTDOT syntax (#15877)
-
-
-pub fn main() {
-    match 5_usize {
-      1_usize...5_usize => {}
-      _ => panic!("should match range"),
-    }
-    match 5_usize {
-      6_usize...7_usize => panic!("shouldn't match range"),
-      _ => {}
-    }
-    match 5_usize {
-      1_usize => panic!("should match non-first range"),
-      2_usize...6_usize => {}
-      _ => panic!("math is broken")
-    }
-    match 'c' {
-      'a'...'z' => {}
-      _ => panic!("should support char ranges")
-    }
-    match -3_isize {
-      -7...5 => {}
-      _ => panic!("should match signed range")
-    }
-    match 3.0f64 {
-      1.0...5.0 => {}
-      _ => panic!("should match float range")
-    }
-    match -1.5f64 {
-      -3.6...3.6 => {}
-      _ => panic!("should match negative float range")
-    }
-}
diff --git a/src/test/ui/issues/issue-16149.rs b/src/test/ui/issues/issue-16149.rs
index 7f0cad9..51b6072 100644
--- a/src/test/ui/issues/issue-16149.rs
+++ b/src/test/ui/issues/issue-16149.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     static externalValue: isize;
 }
 
@@ -6,6 +6,6 @@
     let boolValue = match 42 {
         externalValue => true,
         //~^ ERROR match bindings cannot shadow statics
-        _ => false
+        _ => false,
     };
 }
diff --git a/src/test/ui/issues/issue-16250.rs b/src/test/ui/issues/issue-16250.rs
index a3c6751..436e2a6 100644
--- a/src/test/ui/issues/issue-16250.rs
+++ b/src/test/ui/issues/issue-16250.rs
@@ -2,9 +2,8 @@
 
 pub struct Foo;
 
-extern {
+extern "C" {
     pub fn foo(x: (Foo)); //~ ERROR `extern` block uses type `Foo`
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/issues/issue-16538.rs b/src/test/ui/issues/issue-16538.rs
index 54d9a73..7d6eefa 100644
--- a/src/test/ui/issues/issue-16538.rs
+++ b/src/test/ui/issues/issue-16538.rs
@@ -1,6 +1,6 @@
 mod Y {
     pub type X = usize;
-    extern {
+    extern "C" {
         pub static x: *const usize;
     }
     pub fn foo(value: *const X) -> *const X {
diff --git a/src/test/ui/issues/issue-16939.stderr b/src/test/ui/issues/issue-16939.stderr
index 103f56f..8e42370 100644
--- a/src/test/ui/issues/issue-16939.stderr
+++ b/src/test/ui/issues/issue-16939.stderr
@@ -5,6 +5,12 @@
    |         ^ - supplied 1 argument
    |         |
    |         expected 0 arguments
+   |
+note: associated function defined here
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL |     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
+   |                           ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17718-const-borrow.rs b/src/test/ui/issues/issue-17718-const-borrow.rs
deleted file mode 100644
index 8a31bd0..0000000
--- a/src/test/ui/issues/issue-17718-const-borrow.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use std::cell::UnsafeCell;
-
-const A: UnsafeCell<usize> = UnsafeCell::new(1);
-const B: &'static UnsafeCell<usize> = &A;
-//~^ ERROR: cannot borrow a constant which may contain interior mutability
-
-struct C { a: UnsafeCell<usize> }
-const D: C = C { a: UnsafeCell::new(1) };
-const E: &'static UnsafeCell<usize> = &D.a;
-//~^ ERROR: cannot borrow a constant which may contain interior mutability
-const F: &'static C = &D;
-//~^ ERROR: cannot borrow a constant which may contain interior mutability
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-17718-const-borrow.stderr b/src/test/ui/issues/issue-17718-const-borrow.stderr
deleted file mode 100644
index b433004..0000000
--- a/src/test/ui/issues/issue-17718-const-borrow.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
-  --> $DIR/issue-17718-const-borrow.rs:4:39
-   |
-LL | const B: &'static UnsafeCell<usize> = &A;
-   |                                       ^^
-
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
-  --> $DIR/issue-17718-const-borrow.rs:9:39
-   |
-LL | const E: &'static UnsafeCell<usize> = &D.a;
-   |                                       ^^^^
-
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
-  --> $DIR/issue-17718-const-borrow.rs:11:23
-   |
-LL | const F: &'static C = &D;
-   |                       ^^
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0492`.
diff --git a/src/test/ui/issues/issue-18423.rs b/src/test/ui/issues/issue-18423.rs
index c072e6b..a81b32f 100644
--- a/src/test/ui/issues/issue-18423.rs
+++ b/src/test/ui/issues/issue-18423.rs
@@ -1,8 +1,8 @@
 // Test that `Box` cannot be used with a lifetime argument.
 
 struct Foo<'a> {
-    x: Box<'a, isize> //~ ERROR wrong number of lifetime arguments
+    x: Box<'a, isize>
+    //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
 }
 
-pub fn main() {
-}
+fn main() { }
diff --git a/src/test/ui/issues/issue-18423.stderr b/src/test/ui/issues/issue-18423.stderr
index 141fd27..f900623 100644
--- a/src/test/ui/issues/issue-18423.stderr
+++ b/src/test/ui/issues/issue-18423.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of lifetime arguments: expected 0, found 1
-  --> $DIR/issue-18423.rs:4:12
+error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/issue-18423.rs:4:8
    |
 LL |     x: Box<'a, isize>
-   |            ^^ unexpected lifetime argument
+   |        ^^^ ---- help: remove this lifetime argument
+   |        |
+   |        expected 0 lifetime arguments
+   |
+note: struct defined here, with 0 lifetime parameters
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+   |
+LL | pub struct Box<
+   |            ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-1866.rs b/src/test/ui/issues/issue-1866.rs
index 9f8a3a8..caac0c5 100644
--- a/src/test/ui/issues/issue-1866.rs
+++ b/src/test/ui/issues/issue-1866.rs
@@ -9,7 +9,7 @@
     pub type rust_task = usize;
     pub mod rustrt {
         use super::rust_task;
-        extern {
+        extern "C" {
             pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
         }
     }
@@ -19,11 +19,11 @@
     pub type rust_task = bool;
     pub mod rustrt {
         use super::rust_task;
-        extern {
+        extern "C" {
             pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
-            //~^ WARN `rust_task_is_unwinding` redeclared with a different signature
+        //~^ WARN `rust_task_is_unwinding` redeclared with a different signature
         }
     }
 }
 
-pub fn main() { }
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-18804/auxiliary/lib.rs b/src/test/ui/issues/issue-18804/auxiliary/lib.rs
index ae27dd5..e29d482 100644
--- a/src/test/ui/issues/issue-18804/auxiliary/lib.rs
+++ b/src/test/ui/issues/issue-18804/auxiliary/lib.rs
@@ -1,10 +1,10 @@
 #![crate_type = "rlib"]
 #![feature(linkage)]
 
-pub fn foo<T>() -> *const() {
-    extern {
+pub fn foo<T>() -> *const () {
+    extern "C" {
         #[linkage = "extern_weak"]
-        static FOO: *const();
+        static FOO: *const ();
     }
     unsafe { FOO }
 }
diff --git a/src/test/ui/issues/issue-20313-rpass.rs b/src/test/ui/issues/issue-20313-rpass.rs
index 0935204..591f365 100644
--- a/src/test/ui/issues/issue-20313-rpass.rs
+++ b/src/test/ui/issues/issue-20313-rpass.rs
@@ -1,13 +1,11 @@
 // run-pass
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
-
 #![feature(link_llvm_intrinsics)]
 
-extern {
+extern "C" {
     #[link_name = "llvm.sqrt.f32"]
     fn sqrt(x: f32) -> f32;
 }
 
-fn main(){
-}
+fn main() {}
diff --git a/src/test/ui/issues/issue-20313.rs b/src/test/ui/issues/issue-20313.rs
index 4149ab4..a72af65 100644
--- a/src/test/ui/issues/issue-20313.rs
+++ b/src/test/ui/issues/issue-20313.rs
@@ -1,7 +1,6 @@
-extern {
+extern "C" {
     #[link_name = "llvm.sqrt.f32"]
     fn sqrt(x: f32) -> f32; //~ ERROR linking to LLVM intrinsics is experimental
 }
 
-fn main(){
-}
+fn main() {}
diff --git a/src/test/ui/issues/issue-2214.rs b/src/test/ui/issues/issue-2214.rs
index 52ab29f..1994c35 100644
--- a/src/test/ui/issues/issue-2214.rs
+++ b/src/test/ui/issues/issue-2214.rs
@@ -5,13 +5,11 @@
 
 extern crate libc;
 
-use std::mem;
 use libc::{c_double, c_int};
+use std::mem;
 
 fn to_c_int(v: &mut isize) -> &mut c_int {
-    unsafe {
-        mem::transmute_copy(&v)
-    }
+    unsafe { mem::transmute_copy(&v) }
 }
 
 fn lgamma(n: c_double, value: &mut isize) -> c_double {
@@ -23,21 +21,21 @@
 mod m {
     use libc::{c_double, c_int};
 
-    extern {
+    extern "C" {
         #[cfg(all(unix, not(target_os = "vxworks")))]
         #[link_name="lgamma_r"]
         pub fn lgamma(n: c_double, sign: &mut c_int) -> c_double;
         #[cfg(windows)]
-        #[link_name="lgamma"]
+        #[link_name = "lgamma"]
         pub fn lgamma(n: c_double, sign: &mut c_int) -> c_double;
         #[cfg(target_os = "vxworks")]
-        #[link_name="lgamma"]
+        #[link_name = "lgamma"]
         pub fn lgamma(n: c_double, sign: &mut c_int) -> c_double;
     }
 }
 
 pub fn main() {
-  let mut y: isize = 5;
-  let x: &mut isize = &mut y;
-  assert_eq!(lgamma(1.0 as c_double, x), 0.0 as c_double);
+    let mut y: isize = 5;
+    let x: &mut isize = &mut y;
+    assert_eq!(lgamma(1.0 as c_double, x), 0.0 as c_double);
 }
diff --git a/src/test/ui/issues/issue-23024.rs b/src/test/ui/issues/issue-23024.rs
index ddeb516..e92273b 100644
--- a/src/test/ui/issues/issue-23024.rs
+++ b/src/test/ui/issues/issue-23024.rs
@@ -8,6 +8,6 @@
     vfnfer.push(box h);
     println!("{:?}",(vfnfer[0] as dyn Fn)(3));
     //~^ ERROR the precise format of `Fn`-family traits'
-    //~| ERROR wrong number of type arguments: expected 1, found 0 [E0107]
+    //~| ERROR missing generics for trait `Fn`
     //~| ERROR the value of the associated type `Output` (from trait `FnOnce`)
 }
diff --git a/src/test/ui/issues/issue-23024.stderr b/src/test/ui/issues/issue-23024.stderr
index fdb68ff..1b87609 100644
--- a/src/test/ui/issues/issue-23024.stderr
+++ b/src/test/ui/issues/issue-23024.stderr
@@ -7,11 +7,21 @@
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0107]: wrong number of type arguments: expected 1, found 0
+error[E0107]: missing generics for trait `Fn`
   --> $DIR/issue-23024.rs:9:39
    |
 LL |     println!("{:?}",(vfnfer[0] as dyn Fn)(3));
    |                                       ^^ expected 1 type argument
+   |
+note: trait defined here, with 1 type parameter: `Args`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   |           ^^ ----
+help: use angle brackets to add missing type argument
+   |
+LL |     println!("{:?}",(vfnfer[0] as dyn Fn<Args>)(3));
+   |                                         ^^^^^^
 
 error[E0191]: the value of the associated type `Output` (from trait `FnOnce`) must be specified
   --> $DIR/issue-23024.rs:9:39
diff --git a/src/test/ui/issues/issue-26217.stderr b/src/test/ui/issues/issue-26217.stderr
index b162553..f5c641b 100644
--- a/src/test/ui/issues/issue-26217.stderr
+++ b/src/test/ui/issues/issue-26217.stderr
@@ -3,8 +3,6 @@
    |
 LL |     foo::<&'a i32>();
    |     ^^^^^^^^^^^^^^
-   |
-   = note: type must outlive any other region
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-26997.rs b/src/test/ui/issues/issue-26997.rs
index fcabd1d..3653e62 100644
--- a/src/test/ui/issues/issue-26997.rs
+++ b/src/test/ui/issues/issue-26997.rs
@@ -7,7 +7,7 @@
 
 impl Foo {
     #[allow(improper_ctypes_definitions)]
-    pub extern fn foo_new() -> Foo {
+    pub extern "C" fn foo_new() -> Foo {
         Foo { x: 21, y: 33 }
     }
 }
diff --git a/src/test/ui/issues/issue-27433.fixed b/src/test/ui/issues/issue-27433.fixed
new file mode 100644
index 0000000..ce31f6b
--- /dev/null
+++ b/src/test/ui/issues/issue-27433.fixed
@@ -0,0 +1,7 @@
+// run-rustfix
+fn main() {
+    let foo = 42u32;
+    #[allow(unused_variables, non_snake_case)]
+    let FOO : u32 = foo;
+                   //~^ ERROR attempt to use a non-constant value in a constant
+}
diff --git a/src/test/ui/issues/issue-27433.rs b/src/test/ui/issues/issue-27433.rs
index 156ae68..01411a5 100644
--- a/src/test/ui/issues/issue-27433.rs
+++ b/src/test/ui/issues/issue-27433.rs
@@ -1,5 +1,7 @@
+// run-rustfix
 fn main() {
     let foo = 42u32;
+    #[allow(unused_variables, non_snake_case)]
     const FOO : u32 = foo;
                    //~^ ERROR attempt to use a non-constant value in a constant
 }
diff --git a/src/test/ui/issues/issue-27433.stderr b/src/test/ui/issues/issue-27433.stderr
index e232d17..da751a6 100644
--- a/src/test/ui/issues/issue-27433.stderr
+++ b/src/test/ui/issues/issue-27433.stderr
@@ -1,8 +1,10 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/issue-27433.rs:3:23
+  --> $DIR/issue-27433.rs:5:23
    |
 LL |     const FOO : u32 = foo;
-   |                       ^^^ non-constant value
+   |     ---------         ^^^ non-constant value
+   |     |
+   |     help: consider using `let` instead of `const`: `let FOO`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-28324.rs b/src/test/ui/issues/issue-28324.rs
index bb48508..f74726e 100644
--- a/src/test/ui/issues/issue-28324.rs
+++ b/src/test/ui/issues/issue-28324.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     static error_message_count: u32;
 }
 
diff --git a/src/test/ui/issues/issue-28472.rs b/src/test/ui/issues/issue-28472.rs
index 17d74ea..6db1f9a 100644
--- a/src/test/ui/issues/issue-28472.rs
+++ b/src/test/ui/issues/issue-28472.rs
@@ -1,6 +1,6 @@
 // Check that the visibility modifier is included in the span of foreign items.
 
-extern {
+extern "C" {
   fn foo();
 
   pub //~ ERROR the name `foo` is defined multiple times
diff --git a/src/test/ui/issues/issue-28600.rs b/src/test/ui/issues/issue-28600.rs
index 297519b..52db0d5 100644
--- a/src/test/ui/issues/issue-28600.rs
+++ b/src/test/ui/issues/issue-28600.rs
@@ -7,7 +7,7 @@
     #[allow(dead_code)]
     #[allow(unused_variables)]
     #[allow(improper_ctypes_definitions)]
-    pub extern fn test(val: &str) {
+    pub extern "C" fn test(val: &str) {
 
     }
 }
diff --git a/src/test/ui/issues/issue-28676.rs b/src/test/ui/issues/issue-28676.rs
deleted file mode 100644
index 2b83478..0000000
--- a/src/test/ui/issues/issue-28676.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-#![allow(improper_ctypes)]
-
-// ignore-wasm32-bare no libc to test ffi with
-
-#[derive(Copy, Clone)]
-pub struct Quad { a: u64, b: u64, c: u64, d: u64 }
-
-mod rustrt {
-    use super::Quad;
-
-    #[link(name = "rust_test_helpers", kind = "static")]
-    extern {
-        pub fn get_c_many_params(_: *const (), _: *const (),
-                                 _: *const (), _: *const (), f: Quad) -> u64;
-    }
-}
-
-fn test() {
-    unsafe {
-        let null = std::ptr::null();
-        let q = Quad {
-            a: 1,
-            b: 2,
-            c: 3,
-            d: 4
-        };
-        assert_eq!(rustrt::get_c_many_params(null, null, null, null, q), q.c);
-    }
-}
-
-pub fn main() {
-    test();
-}
diff --git a/src/test/ui/issues/issue-3044.stderr b/src/test/ui/issues/issue-3044.stderr
index d2c0106..b93aead 100644
--- a/src/test/ui/issues/issue-3044.stderr
+++ b/src/test/ui/issues/issue-3044.stderr
@@ -7,6 +7,12 @@
    | |                       expected 2 arguments
 LL | |     });
    | |_____- supplied 1 argument
+   |
+note: associated function defined here
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn fold<B, F>(mut self, init: B, mut f: F) -> B
+   |        ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3214.rs b/src/test/ui/issues/issue-3214.rs
index 030677c..9bb164f 100644
--- a/src/test/ui/issues/issue-3214.rs
+++ b/src/test/ui/issues/issue-3214.rs
@@ -6,7 +6,7 @@
     }
 
     impl<T> Drop for Foo<T> {
-        //~^ ERROR wrong number of type arguments
+        //~^ ERROR this struct takes 0 type arguments but 1 type argument was supplied
         //~| ERROR the type parameter `T` is not constrained by the impl trait, self type, or predicates
         fn drop(&mut self) {}
     }
diff --git a/src/test/ui/issues/issue-3214.stderr b/src/test/ui/issues/issue-3214.stderr
index 30bc6cb..c226892 100644
--- a/src/test/ui/issues/issue-3214.stderr
+++ b/src/test/ui/issues/issue-3214.stderr
@@ -9,11 +9,19 @@
 LL |         x: T,
    |            ^ use of generic parameter from outer function
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/issue-3214.rs:8:26
+error[E0107]: this struct takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/issue-3214.rs:8:22
    |
 LL |     impl<T> Drop for Foo<T> {
-   |                          ^ unexpected type argument
+   |                      ^^^--- help: remove these generics
+   |                      |
+   |                      expected 0 type arguments
+   |
+note: struct defined here, with 0 type parameters
+  --> $DIR/issue-3214.rs:4:12
+   |
+LL |     struct Foo {
+   |            ^^^
 
 error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
   --> $DIR/issue-3214.rs:8:10
diff --git a/src/test/ui/issues/issue-32201.rs b/src/test/ui/issues/issue-32201.rs
index e22c160..f27bb1c 100644
--- a/src/test/ui/issues/issue-32201.rs
+++ b/src/test/ui/issues/issue-32201.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     fn foo(a: i32, ...);
 }
 
diff --git a/src/test/ui/issues/issue-34721.stderr b/src/test/ui/issues/issue-34721.stderr
index b4cc1a0..b14faff 100644
--- a/src/test/ui/issues/issue-34721.stderr
+++ b/src/test/ui/issues/issue-34721.stderr
@@ -13,7 +13,7 @@
 LL |         x.zero()
    |         ^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
+note: this function takes ownership of the receiver `self`, which moves `x`
   --> $DIR/issue-34721.rs:4:13
    |
 LL |     fn zero(self) -> Self;
diff --git a/src/test/ui/issues/issue-3521-2.fixed b/src/test/ui/issues/issue-3521-2.fixed
new file mode 100644
index 0000000..140c24b
--- /dev/null
+++ b/src/test/ui/issues/issue-3521-2.fixed
@@ -0,0 +1,9 @@
+// run-rustfix
+fn main() {
+    let foo = 100;
+
+    let y: isize = foo + 1;
+    //~^ ERROR attempt to use a non-constant value in a constant
+
+    println!("{}", y);
+}
diff --git a/src/test/ui/issues/issue-3521-2.rs b/src/test/ui/issues/issue-3521-2.rs
index 871394f..f66efec 100644
--- a/src/test/ui/issues/issue-3521-2.rs
+++ b/src/test/ui/issues/issue-3521-2.rs
@@ -1,3 +1,4 @@
+// run-rustfix
 fn main() {
     let foo = 100;
 
diff --git a/src/test/ui/issues/issue-3521-2.stderr b/src/test/ui/issues/issue-3521-2.stderr
index d54bbbc..84c7a9e 100644
--- a/src/test/ui/issues/issue-3521-2.stderr
+++ b/src/test/ui/issues/issue-3521-2.stderr
@@ -1,8 +1,10 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/issue-3521-2.rs:4:23
+  --> $DIR/issue-3521-2.rs:5:23
    |
 LL |     static y: isize = foo + 1;
-   |                       ^^^ non-constant value
+   |     --------          ^^^ non-constant value
+   |     |
+   |     help: consider using `let` instead of `static`: `let y`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3521.fixed b/src/test/ui/issues/issue-3521.fixed
new file mode 100644
index 0000000..f76106d
--- /dev/null
+++ b/src/test/ui/issues/issue-3521.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+fn main() {
+    #[allow(non_upper_case_globals)]
+    const foo: isize = 100;
+
+    #[derive(Debug)]
+    enum Stuff {
+        Bar = foo
+        //~^ ERROR attempt to use a non-constant value in a constant
+    }
+
+    println!("{:?}", Stuff::Bar);
+}
diff --git a/src/test/ui/issues/issue-3521.rs b/src/test/ui/issues/issue-3521.rs
index 9e72dd2..c425a22 100644
--- a/src/test/ui/issues/issue-3521.rs
+++ b/src/test/ui/issues/issue-3521.rs
@@ -1,5 +1,7 @@
+// run-rustfix
 fn main() {
-    let foo = 100;
+    #[allow(non_upper_case_globals)]
+    let foo: isize = 100;
 
     #[derive(Debug)]
     enum Stuff {
diff --git a/src/test/ui/issues/issue-3521.stderr b/src/test/ui/issues/issue-3521.stderr
index ae19987..aa42772 100644
--- a/src/test/ui/issues/issue-3521.stderr
+++ b/src/test/ui/issues/issue-3521.stderr
@@ -1,6 +1,9 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/issue-3521.rs:6:15
+  --> $DIR/issue-3521.rs:8:15
    |
+LL |     let foo: isize = 100;
+   |     ------- help: consider using `const` instead of `let`: `const foo`
+...
 LL |         Bar = foo
    |               ^^^ non-constant value
 
diff --git a/src/test/ui/issues/issue-3656.rs b/src/test/ui/issues/issue-3656.rs
index 17ff6b9..4a9f943 100644
--- a/src/test/ui/issues/issue-3656.rs
+++ b/src/test/ui/issues/issue-3656.rs
@@ -1,14 +1,12 @@
 // run-pass
 #![allow(dead_code)]
 #![allow(improper_ctypes)]
-
 // Issue #3656
 // Incorrect struct size computation in the FFI, because of not taking
 // the alignment of elements into account.
 
 // pretty-expanded FIXME #23616
 // ignore-wasm32-bare no libc to test with
-
 #![feature(rustc_private)]
 
 extern crate libc;
@@ -21,10 +19,9 @@
     salt_size: u32,
 }
 
-extern {
+extern "C" {
     // Bogus signature, just need to test if it compiles.
     pub fn malloc(data: KEYGEN);
 }
 
-pub fn main() {
-}
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-3668-2.fixed b/src/test/ui/issues/issue-3668-2.fixed
new file mode 100644
index 0000000..a95781c
--- /dev/null
+++ b/src/test/ui/issues/issue-3668-2.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+#![allow(unused_variables, dead_code)]
+fn f(x:isize) {
+    let child: isize = x + 1;
+    //~^ ERROR attempt to use a non-constant value in a constant
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3668-2.rs b/src/test/ui/issues/issue-3668-2.rs
index 525f6f5..8aa0897 100644
--- a/src/test/ui/issues/issue-3668-2.rs
+++ b/src/test/ui/issues/issue-3668-2.rs
@@ -1,3 +1,5 @@
+// run-rustfix
+#![allow(unused_variables, dead_code)]
 fn f(x:isize) {
     static child: isize = x + 1;
     //~^ ERROR attempt to use a non-constant value in a constant
diff --git a/src/test/ui/issues/issue-3668-2.stderr b/src/test/ui/issues/issue-3668-2.stderr
index d6a6e83..ba96510 100644
--- a/src/test/ui/issues/issue-3668-2.stderr
+++ b/src/test/ui/issues/issue-3668-2.stderr
@@ -1,8 +1,10 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/issue-3668-2.rs:2:27
+  --> $DIR/issue-3668-2.rs:4:27
    |
 LL |     static child: isize = x + 1;
-   |                           ^ non-constant value
+   |     ------------          ^ non-constant value
+   |     |
+   |     help: consider using `let` instead of `static`: `let child`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3668.stderr b/src/test/ui/issues/issue-3668.stderr
index 98cd363..edc4997 100644
--- a/src/test/ui/issues/issue-3668.stderr
+++ b/src/test/ui/issues/issue-3668.stderr
@@ -2,7 +2,9 @@
   --> $DIR/issue-3668.rs:8:34
    |
 LL |        static childVal: Box<P> = self.child.get();
-   |                                  ^^^^ non-constant value
+   |        ---------------           ^^^^ non-constant value
+   |        |
+   |        help: consider using `let` instead of `static`: `let childVal`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-42060.stderr b/src/test/ui/issues/issue-42060.stderr
index 72408c7..effcbe4 100644
--- a/src/test/ui/issues/issue-42060.stderr
+++ b/src/test/ui/issues/issue-42060.stderr
@@ -1,12 +1,16 @@
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/issue-42060.rs:3:23
    |
+LL |     let thing = ();
+   |     --------- help: consider using `const` instead of `let`: `const thing`
 LL |     let other: typeof(thing) = thing;
    |                       ^^^^^ non-constant value
 
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/issue-42060.rs:9:13
    |
+LL |     let q = 1;
+   |     ----- help: consider using `const` instead of `let`: `const q`
 LL |     <typeof(q)>::N
    |             ^ non-constant value
 
diff --git a/src/test/ui/issues/issue-43925.rs b/src/test/ui/issues/issue-43925.rs
index 1f3bee3..73d1792 100644
--- a/src/test/ui/issues/issue-43925.rs
+++ b/src/test/ui/issues/issue-43925.rs
@@ -1,4 +1,4 @@
-#[link(name="foo", cfg("rlib"))] //~ ERROR invalid argument for `cfg(..)`
-extern {}
+#[link(name = "foo", cfg("rlib"))] //~ ERROR invalid argument for `cfg(..)`
+extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-43925.stderr b/src/test/ui/issues/issue-43925.stderr
index 739ace1..7bf64dc 100644
--- a/src/test/ui/issues/issue-43925.stderr
+++ b/src/test/ui/issues/issue-43925.stderr
@@ -1,8 +1,8 @@
 error: invalid argument for `cfg(..)`
-  --> $DIR/issue-43925.rs:1:24
+  --> $DIR/issue-43925.rs:1:26
    |
-LL | #[link(name="foo", cfg("rlib"))]
-   |                        ^^^^^^
+LL | #[link(name = "foo", cfg("rlib"))]
+   |                          ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-43926.rs b/src/test/ui/issues/issue-43926.rs
index c56a796..0171c12 100644
--- a/src/test/ui/issues/issue-43926.rs
+++ b/src/test/ui/issues/issue-43926.rs
@@ -1,4 +1,4 @@
-#[link(name="foo", cfg())] //~ ERROR `cfg()` must have an argument
-extern {}
+#[link(name = "foo", cfg())] //~ ERROR `cfg()` must have an argument
+extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-43926.stderr b/src/test/ui/issues/issue-43926.stderr
index d9d6b3a..d83e9bd 100644
--- a/src/test/ui/issues/issue-43926.stderr
+++ b/src/test/ui/issues/issue-43926.stderr
@@ -1,8 +1,8 @@
 error: `cfg()` must have an argument
-  --> $DIR/issue-43926.rs:1:20
+  --> $DIR/issue-43926.rs:1:22
    |
-LL | #[link(name="foo", cfg())]
-   |                    ^^^^^
+LL | #[link(name = "foo", cfg())]
+   |                      ^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-44239.fixed b/src/test/ui/issues/issue-44239.fixed
new file mode 100644
index 0000000..e6c29ce
--- /dev/null
+++ b/src/test/ui/issues/issue-44239.fixed
@@ -0,0 +1,11 @@
+// run-rustfix
+#![allow(dead_code, non_upper_case_globals)]
+fn main() {
+    const n: usize = 0;
+
+    struct Foo;
+    impl Foo {
+        const N: usize = n;
+        //~^ ERROR attempt to use a non-constant value
+    }
+}
diff --git a/src/test/ui/issues/issue-44239.rs b/src/test/ui/issues/issue-44239.rs
index 99a865f..482ed19 100644
--- a/src/test/ui/issues/issue-44239.rs
+++ b/src/test/ui/issues/issue-44239.rs
@@ -1,5 +1,7 @@
+// run-rustfix
+#![allow(dead_code, non_upper_case_globals)]
 fn main() {
-    let n = 0;
+    let n: usize = 0;
 
     struct Foo;
     impl Foo {
diff --git a/src/test/ui/issues/issue-44239.stderr b/src/test/ui/issues/issue-44239.stderr
index bc5a6a0..2a245c9 100644
--- a/src/test/ui/issues/issue-44239.stderr
+++ b/src/test/ui/issues/issue-44239.stderr
@@ -1,6 +1,9 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/issue-44239.rs:6:26
+  --> $DIR/issue-44239.rs:8:26
    |
+LL |     let n: usize = 0;
+   |     ----- help: consider using `const` instead of `let`: `const n`
+...
 LL |         const N: usize = n;
    |                          ^ non-constant value
 
diff --git a/src/test/ui/issues/issue-51907.rs b/src/test/ui/issues/issue-51907.rs
index 52d26d0..9378f43 100644
--- a/src/test/ui/issues/issue-51907.rs
+++ b/src/test/ui/issues/issue-51907.rs
@@ -1,15 +1,15 @@
 // run-pass
 trait Foo {
-    extern fn borrow(&self);
-    extern fn take(self: Box<Self>);
+    extern "C" fn borrow(&self);
+    extern "C" fn take(self: Box<Self>);
 }
 
 struct Bar;
 impl Foo for Bar {
     #[allow(improper_ctypes_definitions)]
-    extern fn borrow(&self) {}
+    extern "C" fn borrow(&self) {}
     #[allow(improper_ctypes_definitions)]
-    extern fn take(self: Box<Self>) {}
+    extern "C" fn take(self: Box<Self>) {}
 }
 
 fn main() {
diff --git a/src/test/ui/issues/issue-53251.rs b/src/test/ui/issues/issue-53251.rs
index b5d5514..309b980 100644
--- a/src/test/ui/issues/issue-53251.rs
+++ b/src/test/ui/issues/issue-53251.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-linelength
+
 struct S;
 
 impl S {
@@ -9,8 +11,8 @@
         $(
             fn $n() {
                 S::f::<i64>();
-                //~^ ERROR wrong number of type arguments
-                //~| ERROR wrong number of type arguments
+                //~^ ERROR this associated function takes 0 type arguments but 1 type argument was supplied
+                //~| ERROR this associated function takes 0 type arguments but 1 type argument was supplied
             }
         )*
     }
@@ -18,4 +20,4 @@
 
 impl_add!(a b);
 
-fn main() {}
+fn main() { }
diff --git a/src/test/ui/issues/issue-53251.stderr b/src/test/ui/issues/issue-53251.stderr
index cd5030f..5d1a6d4 100644
--- a/src/test/ui/issues/issue-53251.stderr
+++ b/src/test/ui/issues/issue-53251.stderr
@@ -1,23 +1,37 @@
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/issue-53251.rs:11:24
+error[E0107]: this associated function takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/issue-53251.rs:13:20
    |
 LL |                 S::f::<i64>();
-   |                        ^^^ unexpected type argument
+   |                    ^------- help: remove these generics
+   |                    |
+   |                    expected 0 type arguments
 ...
 LL | impl_add!(a b);
    | --------------- in this macro invocation
    |
+note: associated function defined here, with 0 type parameters
+  --> $DIR/issue-53251.rs:6:8
+   |
+LL |     fn f() {}
+   |        ^
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/issue-53251.rs:11:24
+error[E0107]: this associated function takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/issue-53251.rs:13:20
    |
 LL |                 S::f::<i64>();
-   |                        ^^^ unexpected type argument
+   |                    ^------- help: remove these generics
+   |                    |
+   |                    expected 0 type arguments
 ...
 LL | impl_add!(a b);
    | --------------- in this macro invocation
    |
+note: associated function defined here, with 0 type parameters
+  --> $DIR/issue-53251.rs:6:8
+   |
+LL |     fn f() {}
+   |        ^
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-57843.stderr b/src/test/ui/issues/issue-57843.stderr
index 01edb95..7699e97 100644
--- a/src/test/ui/issues/issue-57843.stderr
+++ b/src/test/ui/issues/issue-57843.stderr
@@ -6,6 +6,11 @@
    |
    = note: expected type `FnOnce<(&'a bool,)>`
               found type `FnOnce<(&bool,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57843.rs:23:18
+   |
+LL |     Foo(Box::new(|_| ()));
+   |                  ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-5791.rs b/src/test/ui/issues/issue-5791.rs
index d9be272..3544160 100644
--- a/src/test/ui/issues/issue-5791.rs
+++ b/src/test/ui/issues/issue-5791.rs
@@ -3,7 +3,7 @@
 #![warn(clashing_extern_declarations)]
 // pretty-expanded FIXME #23616
 
-extern {
+extern "C" {
     #[link_name = "malloc"]
     fn malloc1(len: i32) -> *const u8;
     #[link_name = "malloc"]
@@ -11,4 +11,4 @@
     fn malloc2(len: i32, foo: i32) -> *const u8;
 }
 
-pub fn main () {}
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-60622.rs b/src/test/ui/issues/issue-60622.rs
index d6a0189..1d9bd2d 100644
--- a/src/test/ui/issues/issue-60622.rs
+++ b/src/test/ui/issues/issue-60622.rs
@@ -11,8 +11,8 @@
 fn run_wild<T>(b: &Borked) {
     b.a::<'_, T>();
     //~^ ERROR cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-    //~^^ ERROR wrong number of type arguments: expected 0, found 1
-    //~^^^ WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    //~| ERROR this associated function takes 0 type arguments but 1 type argument was supplied
+    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-60622.stderr b/src/test/ui/issues/issue-60622.stderr
index 79cb6cf..47f2f18 100644
--- a/src/test/ui/issues/issue-60622.stderr
+++ b/src/test/ui/issues/issue-60622.stderr
@@ -16,11 +16,19 @@
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/issue-60622.rs:12:15
+error[E0107]: this associated function takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/issue-60622.rs:12:7
    |
 LL |     b.a::<'_, T>();
-   |               ^ unexpected type argument
+   |       ^     --- help: remove this type argument
+   |       |
+   |       expected 0 type arguments
+   |
+note: associated function defined here, with 0 type parameters
+  --> $DIR/issue-60622.rs:8:8
+   |
+LL |     fn a(&self) {}
+   |        ^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-61108.stderr b/src/test/ui/issues/issue-61108.stderr
index d6c289c..fb242f7 100644
--- a/src/test/ui/issues/issue-61108.stderr
+++ b/src/test/ui/issues/issue-61108.stderr
@@ -12,7 +12,7 @@
 LL |     bad_letters.push('s');
    |     ^^^^^^^^^^^ value borrowed here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `bad_letters`
+note: this function takes ownership of the receiver `self`, which moves `bad_letters`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
diff --git a/src/test/ui/issues/issue-64559.stderr b/src/test/ui/issues/issue-64559.stderr
index 5b97e21..e0da3fd 100644
--- a/src/test/ui/issues/issue-64559.stderr
+++ b/src/test/ui/issues/issue-64559.stderr
@@ -13,7 +13,7 @@
    |                    |
    |                    value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `orig`
+note: this function takes ownership of the receiver `self`, which moves `orig`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
diff --git a/src/test/ui/issues/issue-6470.rs b/src/test/ui/issues/issue-6470.rs
index 0c86a64..8c6192a 100644
--- a/src/test/ui/issues/issue-6470.rs
+++ b/src/test/ui/issues/issue-6470.rs
@@ -1,7 +1,6 @@
 // build-pass
 #![allow(dead_code)]
 #![allow(improper_ctypes)]
-
 // pretty-expanded FIXME #23616
 #![allow(non_snake_case)]
 
@@ -10,9 +9,9 @@
         v: isize,
     }
 
-    extern {
+    extern "C" {
         pub fn foo(v: *const Foo) -> Foo;
     }
 }
 
-pub fn main() { }
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr
index 0a9c868..a1e8ec1 100644
--- a/src/test/ui/issues/issue-72574-2.stderr
+++ b/src/test/ui/issues/issue-72574-2.stderr
@@ -26,6 +26,11 @@
 ...
 LL |         Binder(_a, _x @ ..) => {}
    |         ^^^^^^^^^^^^^^^^^^^ expected 3 fields, found 2
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         Binder(_a, _x @ .., _) => {}
+   |                           ^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-80512-param-reordering-with-defaults.rs b/src/test/ui/issues/issue-80512-param-reordering-with-defaults.rs
new file mode 100644
index 0000000..fe3e4fb
--- /dev/null
+++ b/src/test/ui/issues/issue-80512-param-reordering-with-defaults.rs
@@ -0,0 +1,4 @@
+#![crate_type = "lib"]
+
+struct S<T = (), 'a>(&'a T);
+//~^ ERROR lifetime parameters must be declared prior to type parameters
diff --git a/src/test/ui/issues/issue-80512-param-reordering-with-defaults.stderr b/src/test/ui/issues/issue-80512-param-reordering-with-defaults.stderr
new file mode 100644
index 0000000..a1e9a90
--- /dev/null
+++ b/src/test/ui/issues/issue-80512-param-reordering-with-defaults.stderr
@@ -0,0 +1,8 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/issue-80512-param-reordering-with-defaults.rs:3:18
+   |
+LL | struct S<T = (), 'a>(&'a T);
+   |         ---------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = ()>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-80607.rs b/src/test/ui/issues/issue-80607.rs
new file mode 100644
index 0000000..63f4df3
--- /dev/null
+++ b/src/test/ui/issues/issue-80607.rs
@@ -0,0 +1,10 @@
+// This tests makes sure the diagnostics print the offending enum variant, not just the type.
+pub enum Enum {
+    V1(i32),
+}
+
+pub fn foo(x: i32) -> Enum {
+    Enum::V1 { x } //~ ERROR `Enum::V1` has no field named `x`
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-80607.stderr b/src/test/ui/issues/issue-80607.stderr
new file mode 100644
index 0000000..5375478
--- /dev/null
+++ b/src/test/ui/issues/issue-80607.stderr
@@ -0,0 +1,14 @@
+error[E0559]: variant `Enum::V1` has no field named `x`
+  --> $DIR/issue-80607.rs:7:16
+   |
+LL |     V1(i32),
+   |     -- `Enum::V1` defined here
+...
+LL |     Enum::V1 { x }
+   |     --------   ^ field does not exist
+   |     |
+   |     `Enum::V1` is a tuple variant, use the appropriate syntax: `Enum::V1(/* fields */)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0559`.
diff --git a/src/test/ui/lifetimes/issue-79187-2.nll.stderr b/src/test/ui/lifetimes/issue-79187-2.nll.stderr
new file mode 100644
index 0000000..4970c57
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-79187-2.nll.stderr
@@ -0,0 +1,44 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-79187-2.rs:9:24
+   |
+LL |     take_foo(|a: &i32| a);
+   |                  -   - ^ returning this value requires that `'1` must outlive `'2`
+   |                  |   |
+   |                  |   return type of closure is &'2 i32
+   |                  let's call the lifetime of this reference `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-79187-2.rs:10:34
+   |
+LL |     take_foo(|a: &i32| -> &i32 { a });
+   |                  -        -      ^ returning this value requires that `'1` must outlive `'2`
+   |                  |        |
+   |                  |        let's call the lifetime of this reference `'2`
+   |                  let's call the lifetime of this reference `'1`
+
+error: higher-ranked subtype error
+  --> $DIR/issue-79187-2.rs:8:5
+   |
+LL |     take_foo(|a| a);
+   |     ^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-79187-2.rs:8:5
+   |
+LL |     take_foo(|a| a);
+   |     ^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-79187-2.rs:9:5
+   |
+LL |     take_foo(|a: &i32| a);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-79187-2.rs:10:5
+   |
+LL |     take_foo(|a: &i32| -> &i32 { a });
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/lifetimes/issue-79187-2.rs b/src/test/ui/lifetimes/issue-79187-2.rs
new file mode 100644
index 0000000..29d108f
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-79187-2.rs
@@ -0,0 +1,23 @@
+trait Foo {}
+
+impl<F> Foo for F where F: Fn(&i32) -> &i32 {}
+
+fn take_foo(_: impl Foo) {}
+
+fn main() {
+    take_foo(|a| a); //~ ERROR mismatched types
+    take_foo(|a: &i32| a); //~ ERROR mismatched types
+    take_foo(|a: &i32| -> &i32 { a }); //~ ERROR mismatched types
+
+    // OK
+    take_foo(identity(|a| a));
+    take_foo(identity(|a: &i32| a));
+    take_foo(identity(|a: &i32| -> &i32 { a }));
+
+    fn identity<F>(t: F) -> F
+    where
+        F: Fn(&i32) -> &i32,
+    {
+        t
+    }
+}
diff --git a/src/test/ui/lifetimes/issue-79187-2.stderr b/src/test/ui/lifetimes/issue-79187-2.stderr
new file mode 100644
index 0000000..a156c74
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-79187-2.stderr
@@ -0,0 +1,60 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-79187-2.rs:8:5
+   |
+LL |     take_foo(|a| a);
+   |     ^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `for<'r> Fn<(&'r i32,)>`
+              found type `Fn<(&i32,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-79187-2.rs:8:14
+   |
+LL |     take_foo(|a| a);
+   |              ^^^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-79187-2.rs:5:21
+   |
+LL | fn take_foo(_: impl Foo) {}
+   |                     ^^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-79187-2.rs:9:5
+   |
+LL |     take_foo(|a: &i32| a);
+   |     ^^^^^^^^ lifetime mismatch
+   |
+   = note: expected reference `&i32`
+              found reference `&i32`
+note: the anonymous lifetime #1 defined on the body at 9:14 doesn't meet the lifetime requirements
+  --> $DIR/issue-79187-2.rs:9:14
+   |
+LL |     take_foo(|a: &i32| a);
+   |              ^^^^^^^^^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-79187-2.rs:5:21
+   |
+LL | fn take_foo(_: impl Foo) {}
+   |                     ^^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-79187-2.rs:10:5
+   |
+LL |     take_foo(|a: &i32| -> &i32 { a });
+   |     ^^^^^^^^ lifetime mismatch
+   |
+   = note: expected reference `&i32`
+              found reference `&i32`
+note: the anonymous lifetime #1 defined on the body at 10:14 doesn't meet the lifetime requirements
+  --> $DIR/issue-79187-2.rs:10:14
+   |
+LL |     take_foo(|a: &i32| -> &i32 { a });
+   |              ^^^^^^^^^^^^^^^^^^^^^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-79187-2.rs:5:21
+   |
+LL | fn take_foo(_: impl Foo) {}
+   |                     ^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lifetimes/issue-79187.nll.stderr b/src/test/ui/lifetimes/issue-79187.nll.stderr
new file mode 100644
index 0000000..aa8809d
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-79187.nll.stderr
@@ -0,0 +1,14 @@
+error: higher-ranked subtype error
+  --> $DIR/issue-79187.rs:5:5
+   |
+LL |     thing(f);
+   |     ^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-79187.rs:5:5
+   |
+LL |     thing(f);
+   |     ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lifetimes/issue-79187.rs b/src/test/ui/lifetimes/issue-79187.rs
new file mode 100644
index 0000000..bf331d8
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-79187.rs
@@ -0,0 +1,6 @@
+fn thing(x: impl FnOnce(&u32)) {}
+
+fn main() {
+    let f = |_| ();
+    thing(f); //~ERROR mismatched types
+}
diff --git a/src/test/ui/lifetimes/issue-79187.stderr b/src/test/ui/lifetimes/issue-79187.stderr
new file mode 100644
index 0000000..63f501e
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-79187.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-79187.rs:5:5
+   |
+LL |     thing(f);
+   |     ^^^^^ lifetime mismatch
+   |
+   = note: expected type `FnOnce<(&u32,)>`
+              found type `FnOnce<(&u32,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-79187.rs:4:13
+   |
+LL |     let f = |_| ();
+   |             ^^^^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-79187.rs:1:18
+   |
+LL | fn thing(x: impl FnOnce(&u32)) {}
+   |                  ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr b/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr
index 13b6a7b..c646912 100644
--- a/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr
@@ -28,9 +28,6 @@
 ...
 LL |             x = 1;
    |             ^^^^^ cannot assign twice to immutable variable
-LL |         } else {
-LL |             x = 2;
-   |             ----- first assignment to `x`
 
 error[E0384]: cannot assign twice to immutable variable `x`
   --> $DIR/liveness-assign-imm-local-notes.rs:32:13
@@ -38,6 +35,9 @@
 LL |     let x;
    |         - help: make this binding mutable: `mut x`
 ...
+LL |             x = 1;
+   |             ----- first assignment to `x`
+LL |         } else {
 LL |             x = 2;
    |             ^^^^^ cannot assign twice to immutable variable
 
diff --git a/src/test/ui/link-cfg-works.rs b/src/test/ui/link-cfg-works.rs
index fe1b569..254091f 100644
--- a/src/test/ui/link-cfg-works.rs
+++ b/src/test/ui/link-cfg-works.rs
@@ -4,10 +4,10 @@
 
 #![feature(link_cfg)]
 
-extern crate link_cfg_works_transitive_rlib;
 extern crate link_cfg_works_transitive_dylib;
+extern crate link_cfg_works_transitive_rlib;
 
 #[link(name = "foo", cfg(foo))]
-extern {}
+extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/linkage-attr/auxiliary/def_colliding_external.rs b/src/test/ui/linkage-attr/auxiliary/def_colliding_external.rs
index bbbfc48..60b55b3 100644
--- a/src/test/ui/linkage-attr/auxiliary/def_colliding_external.rs
+++ b/src/test/ui/linkage-attr/auxiliary/def_colliding_external.rs
@@ -1,7 +1,7 @@
 #![feature(linkage)]
 #![crate_type = "lib"]
 
-extern {
-    #[linkage="external"]
+extern "C" {
+    #[linkage = "external"]
     pub static collision: *const i32;
 }
diff --git a/src/test/ui/linkage-attr/invalid-link-args.rs b/src/test/ui/linkage-attr/invalid-link-args.rs
index 5eb1c63..7418691 100644
--- a/src/test/ui/linkage-attr/invalid-link-args.rs
+++ b/src/test/ui/linkage-attr/invalid-link-args.rs
@@ -9,6 +9,6 @@
 #![feature(link_args)]
 
 #[link_args = "aFdEfSeVEEE"]
-extern {}
+extern "C" {}
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs
index 1e50696..b712f32 100644
--- a/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs
+++ b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs
@@ -3,8 +3,8 @@
 #![feature(linkage)]
 
 mod dep1 {
-    extern {
-        #[linkage="external"]
+    extern "C" {
+        #[linkage = "external"]
         #[no_mangle]
         pub static collision: *const i32; //~ ERROR symbol `collision` is already defined
     }
@@ -20,6 +20,6 @@
 
 fn main() {
     unsafe {
-       println!("{:p}", &dep1::collision);
+        println!("{:p}", &dep1::collision);
     }
 }
diff --git a/src/test/ui/linkage-attr/linkage2.rs b/src/test/ui/linkage-attr/linkage2.rs
index 41e7819..a7be198 100644
--- a/src/test/ui/linkage-attr/linkage2.rs
+++ b/src/test/ui/linkage-attr/linkage2.rs
@@ -7,9 +7,10 @@
 
 #![feature(linkage)]
 
-extern {
-    #[linkage = "extern_weak"] static foo: i32;
-    //~^ ERROR: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
+extern "C" {
+    #[linkage = "extern_weak"]
+    static foo: i32;
+//~^ ERROR: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
 }
 
 fn main() {
diff --git a/src/test/ui/linkage-attr/linkage2.stderr b/src/test/ui/linkage-attr/linkage2.stderr
index 72ee3fb..6ffe071 100644
--- a/src/test/ui/linkage-attr/linkage2.stderr
+++ b/src/test/ui/linkage-attr/linkage2.stderr
@@ -1,8 +1,8 @@
 error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
-  --> $DIR/linkage2.rs:11:32
+  --> $DIR/linkage2.rs:12:5
    |
-LL |     #[linkage = "extern_weak"] static foo: i32;
-   |                                ^^^^^^^^^^^^^^^^
+LL |     static foo: i32;
+   |     ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/linkage-attr/linkage3.rs b/src/test/ui/linkage-attr/linkage3.rs
index e91dbf6..112eb1d 100644
--- a/src/test/ui/linkage-attr/linkage3.rs
+++ b/src/test/ui/linkage-attr/linkage3.rs
@@ -6,9 +6,10 @@
 
 #![feature(linkage)]
 
-extern {
-    #[linkage = "foo"] static foo: *const i32;
-    //~^ ERROR: invalid linkage specified
+extern "C" {
+    #[linkage = "foo"]
+    static foo: *const i32;
+//~^ ERROR: invalid linkage specified
 }
 
 fn main() {
diff --git a/src/test/ui/linkage-attr/linkage3.stderr b/src/test/ui/linkage-attr/linkage3.stderr
index 5a0833f..0cbac28 100644
--- a/src/test/ui/linkage-attr/linkage3.stderr
+++ b/src/test/ui/linkage-attr/linkage3.stderr
@@ -1,8 +1,8 @@
 error: invalid linkage specified
-  --> $DIR/linkage3.rs:10:24
+  --> $DIR/linkage3.rs:11:5
    |
-LL |     #[linkage = "foo"] static foo: *const i32;
-   |                        ^^^^^^^^^^^^^^^^^^^^^^^
+LL |     static foo: *const i32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/linkage1.rs b/src/test/ui/linkage1.rs
index bda4da5..deab7a2 100644
--- a/src/test/ui/linkage1.rs
+++ b/src/test/ui/linkage1.rs
@@ -9,7 +9,7 @@
 
 extern crate linkage1 as other;
 
-extern {
+extern "C" {
     #[linkage = "extern_weak"]
     static foo: *const isize;
     #[linkage = "extern_weak"]
diff --git a/src/test/ui/lint/clashing-extern-fn-wasm.rs b/src/test/ui/lint/clashing-extern-fn-wasm.rs
new file mode 100644
index 0000000..eeb2b8e
--- /dev/null
+++ b/src/test/ui/lint/clashing-extern-fn-wasm.rs
@@ -0,0 +1,21 @@
+// check-pass
+#![crate_type = "lib"]
+
+#[cfg(target_arch = "wasm32")]
+mod wasm_non_clash {
+    mod a {
+        #[link(wasm_import_module = "a")]
+        extern "C" {
+            pub fn foo();
+        }
+    }
+
+    mod b {
+        #[link(wasm_import_module = "b")]
+        extern "C" {
+            pub fn foo() -> usize;
+            // #79581: These declarations shouldn't clash because foreign fn names are mangled
+            // on wasm32.
+        }
+    }
+}
diff --git a/src/test/ui/lint/dead-code/leading-underscore.rs b/src/test/ui/lint/dead-code/leading-underscore.rs
index 1b6e03a..d358296 100644
--- a/src/test/ui/lint/dead-code/leading-underscore.rs
+++ b/src/test/ui/lint/dead-code/leading-underscore.rs
@@ -8,7 +8,7 @@
 fn _foo() {}
 
 struct _Y {
-    _z: usize
+    _z: usize,
 }
 
 enum _Z {}
@@ -23,7 +23,7 @@
     fn _qux() {}
 }
 
-extern {
+extern "C" {
     #[link_name = "abort"]
     fn _abort() -> !;
 }
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.rs b/src/test/ui/lint/dead-code/lint-dead-code-3.rs
index fe3c392..7f39f79 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-3.rs
+++ b/src/test/ui/lint/dead-code/lint-dead-code-3.rs
@@ -7,7 +7,7 @@
 
 
 pub use extern_foo as x;
-extern {
+extern "C" {
     pub fn extern_foo();
 }
 
@@ -47,7 +47,7 @@
     // `malloc` below, which are also used.
     enum c_void {}
 
-    extern {
+    extern "C" {
         fn free(p: *const c_void);
         fn malloc(size: usize) -> *const c_void;
     }
@@ -58,7 +58,7 @@
 }
 
 enum c_void {} //~ ERROR: enum is never used
-extern {
+extern "C" {
     fn free(p: *const c_void); //~ ERROR: function is never used
 }
 
diff --git a/src/test/ui/expr_attr_paren_order.rs b/src/test/ui/lint/expr_attr_paren_order.rs
similarity index 100%
rename from src/test/ui/expr_attr_paren_order.rs
rename to src/test/ui/lint/expr_attr_paren_order.rs
diff --git a/src/test/ui/expr_attr_paren_order.stderr b/src/test/ui/lint/expr_attr_paren_order.stderr
similarity index 100%
rename from src/test/ui/expr_attr_paren_order.stderr
rename to src/test/ui/lint/expr_attr_paren_order.stderr
diff --git a/src/test/ui/lint/inline-trait-and-foreign-items.rs b/src/test/ui/lint/inline-trait-and-foreign-items.rs
index 8bdefbb..6321b3c 100644
--- a/src/test/ui/lint/inline-trait-and-foreign-items.rs
+++ b/src/test/ui/lint/inline-trait-and-foreign-items.rs
@@ -26,7 +26,7 @@
     type U = impl Trait; //~ ERROR could not find defining uses
 }
 
-extern {
+extern "C" {
     #[inline] //~ ERROR attribute should be applied to function or closure
     static X: u32;
 
diff --git a/src/test/ui/issues/issue-17718-const-naming.rs b/src/test/ui/lint/issue-17718-const-naming.rs
similarity index 100%
rename from src/test/ui/issues/issue-17718-const-naming.rs
rename to src/test/ui/lint/issue-17718-const-naming.rs
diff --git a/src/test/ui/issues/issue-17718-const-naming.stderr b/src/test/ui/lint/issue-17718-const-naming.stderr
similarity index 100%
rename from src/test/ui/issues/issue-17718-const-naming.stderr
rename to src/test/ui/lint/issue-17718-const-naming.stderr
diff --git a/src/test/ui/issues/issue-30302.rs b/src/test/ui/lint/issue-30302.rs
similarity index 100%
rename from src/test/ui/issues/issue-30302.rs
rename to src/test/ui/lint/issue-30302.rs
diff --git a/src/test/ui/issues/issue-30302.stderr b/src/test/ui/lint/issue-30302.stderr
similarity index 100%
rename from src/test/ui/issues/issue-30302.stderr
rename to src/test/ui/lint/issue-30302.stderr
diff --git a/src/test/ui/issues/issue-34798.rs b/src/test/ui/lint/issue-34798.rs
similarity index 100%
rename from src/test/ui/issues/issue-34798.rs
rename to src/test/ui/lint/issue-34798.rs
diff --git a/src/test/ui/lint/lint-ctypes-enum.rs b/src/test/ui/lint/lint-ctypes-enum.rs
index 17cb705..d7f947a 100644
--- a/src/test/ui/lint/lint-ctypes-enum.rs
+++ b/src/test/ui/lint/lint-ctypes-enum.rs
@@ -5,36 +5,57 @@
 
 use std::num;
 
-enum Z { }
-enum U { A }
-enum B { C, D }
-enum T { E, F, G }
+enum Z {}
+enum U {
+    A,
+}
+enum B {
+    C,
+    D,
+}
+enum T {
+    E,
+    F,
+    G,
+}
 
 #[repr(C)]
-enum ReprC { A, B, C }
+enum ReprC {
+    A,
+    B,
+    C,
+}
 
 #[repr(u8)]
-enum U8 { A, B, C }
+enum U8 {
+    A,
+    B,
+    C,
+}
 
 #[repr(isize)]
-enum Isize { A, B, C }
+enum Isize {
+    A,
+    B,
+    C,
+}
 
 #[repr(transparent)]
 struct TransparentStruct<T>(T, std::marker::PhantomData<Z>);
 
 #[repr(transparent)]
 enum TransparentEnum<T> {
-   Variant(T, std::marker::PhantomData<Z>),
+    Variant(T, std::marker::PhantomData<Z>),
 }
 
 #[repr(transparent)]
 union TransparentUnion<T: Copy> {
-   field: T,
+    field: T,
 }
 
 struct Rust<T>(T);
 
-extern {
+extern "C" {
    fn zf(x: Z);
    fn uf(x: U); //~ ERROR `extern` block uses type `U`
    fn bf(x: B); //~ ERROR `extern` block uses type `B`
diff --git a/src/test/ui/lint/lint-ctypes-enum.stderr b/src/test/ui/lint/lint-ctypes-enum.stderr
index 3d02cda..8917d30 100644
--- a/src/test/ui/lint/lint-ctypes-enum.stderr
+++ b/src/test/ui/lint/lint-ctypes-enum.stderr
@@ -1,5 +1,5 @@
 error: `extern` block uses type `U`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:39:13
+  --> $DIR/lint-ctypes-enum.rs:60:13
    |
 LL |    fn uf(x: U);
    |             ^ not FFI-safe
@@ -14,11 +14,13 @@
 note: the type is defined here
   --> $DIR/lint-ctypes-enum.rs:9:1
    |
-LL | enum U { A }
-   | ^^^^^^^^^^^^
+LL | / enum U {
+LL | |     A,
+LL | | }
+   | |_^
 
 error: `extern` block uses type `B`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:40:13
+  --> $DIR/lint-ctypes-enum.rs:61:13
    |
 LL |    fn bf(x: B);
    |             ^ not FFI-safe
@@ -26,13 +28,16 @@
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:10:1
+  --> $DIR/lint-ctypes-enum.rs:12:1
    |
-LL | enum B { C, D }
-   | ^^^^^^^^^^^^^^^
+LL | / enum B {
+LL | |     C,
+LL | |     D,
+LL | | }
+   | |_^
 
 error: `extern` block uses type `T`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:41:13
+  --> $DIR/lint-ctypes-enum.rs:62:13
    |
 LL |    fn tf(x: T);
    |             ^ not FFI-safe
@@ -40,13 +45,17 @@
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:11:1
+  --> $DIR/lint-ctypes-enum.rs:16:1
    |
-LL | enum T { E, F, G }
-   | ^^^^^^^^^^^^^^^^^^
+LL | / enum T {
+LL | |     E,
+LL | |     F,
+LL | |     G,
+LL | | }
+   | |_^
 
 error: `extern` block uses type `Option<Unique<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:48:17
+  --> $DIR/lint-ctypes-enum.rs:69:17
    |
 LL |    fn unique(x: Option<std::ptr::Unique<u8>>);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -55,7 +64,7 @@
    = note: enum has no representation hint
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:54:23
+  --> $DIR/lint-ctypes-enum.rs:75:23
    |
 LL |    fn nonzero_u128(x: Option<num::NonZeroU128>);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -63,7 +72,7 @@
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:61:23
+  --> $DIR/lint-ctypes-enum.rs:82:23
    |
 LL |    fn nonzero_i128(x: Option<num::NonZeroI128>);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -71,7 +80,7 @@
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Option<TransparentUnion<NonZeroU8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:66:28
+  --> $DIR/lint-ctypes-enum.rs:87:28
    |
 LL |    fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -80,7 +89,7 @@
    = note: enum has no representation hint
 
 error: `extern` block uses type `Option<Rust<NonZeroU8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:68:20
+  --> $DIR/lint-ctypes-enum.rs:89:20
    |
 LL |    fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -89,7 +98,7 @@
    = note: enum has no representation hint
 
 error: `extern` block uses type `std::result::Result<(), NonZeroI32>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:69:20
+  --> $DIR/lint-ctypes-enum.rs:90:20
    |
 LL |    fn no_result(x: Result<(), num::NonZeroI32>);
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
diff --git a/src/test/ui/lint/lint-ctypes-fn.rs b/src/test/ui/lint/lint-ctypes-fn.rs
index 170a04e..e69d0da 100644
--- a/src/test/ui/lint/lint-ctypes-fn.rs
+++ b/src/test/ui/lint/lint-ctypes-fn.rs
@@ -27,7 +27,7 @@
 
 pub type RustFn = fn();
 
-pub type RustBadRet = extern fn() -> Box<u32>;
+pub type RustBadRet = extern "C" fn() -> Box<u32>;
 
 pub type CVoidRet = ();
 
@@ -116,7 +116,7 @@
 
 pub extern "C" fn transparent_fn(p: TransparentBadFn) { }
 
-pub extern "C" fn good3(fptr: Option<extern fn()>) { }
+pub extern "C" fn good3(fptr: Option<extern "C" fn()>) { }
 
 pub extern "C" fn good4(aptr: &[u8; 4 as usize]) { }
 
@@ -124,9 +124,9 @@
 
 pub extern "C" fn good6(s: StructWithProjectionAndLifetime) { }
 
-pub extern "C" fn good7(fptr: extern fn() -> ()) { }
+pub extern "C" fn good7(fptr: extern "C" fn() -> ()) { }
 
-pub extern "C" fn good8(fptr: extern fn() -> !) { }
+pub extern "C" fn good8(fptr: extern "C" fn() -> !) { }
 
 pub extern "C" fn good9() -> () { }
 
diff --git a/src/test/ui/lint/lint-ctypes.rs b/src/test/ui/lint/lint-ctypes.rs
index e8a90bc..fabbdcf 100644
--- a/src/test/ui/lint/lint-ctypes.rs
+++ b/src/test/ui/lint/lint-ctypes.rs
@@ -20,7 +20,7 @@
 #[repr(C)]
 pub struct ZeroSize;
 pub type RustFn = fn();
-pub type RustBadRet = extern fn() -> Box<u32>;
+pub type RustBadRet = extern "C" fn() -> Box<u32>;
 pub type CVoidRet = ();
 pub struct Foo;
 #[repr(transparent)]
@@ -43,7 +43,7 @@
 #[repr(C)]
 pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>);
 
-extern {
+extern "C" {
     pub fn ptr_type1(size: *const Foo); //~ ERROR: uses type `Foo`
     pub fn ptr_type2(size: *const Foo); //~ ERROR: uses type `Foo`
     pub fn slice_type(p: &[u32]); //~ ERROR: uses type `[u32]`
@@ -73,12 +73,12 @@
     pub static static_u128_type: u128; //~ ERROR: uses type `u128`
     pub static static_u128_array_type: [u128; 16]; //~ ERROR: uses type `u128`
 
-    pub fn good3(fptr: Option<extern fn()>);
+    pub fn good3(fptr: Option<extern "C" fn()>);
     pub fn good4(aptr: &[u8; 4 as usize]);
     pub fn good5(s: StructWithProjection);
     pub fn good6(s: StructWithProjectionAndLifetime);
-    pub fn good7(fptr: extern fn() -> ());
-    pub fn good8(fptr: extern fn() -> !);
+    pub fn good7(fptr: extern "C" fn() -> ());
+    pub fn good8(fptr: extern "C" fn() -> !);
     pub fn good9() -> ();
     pub fn good10() -> CVoidRet;
     pub fn good11(size: isize);
@@ -96,12 +96,12 @@
 }
 
 #[allow(improper_ctypes)]
-extern {
+extern "C" {
     pub fn good19(_: &String);
 }
 
 #[cfg(not(target_arch = "wasm32"))]
-extern {
+extern "C" {
     pub fn good1(size: *const libc::c_int);
     pub fn good2(size: *const libc::c_uint);
 }
diff --git a/src/test/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs b/src/test/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs
new file mode 100644
index 0000000..8cc4f97
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs
@@ -0,0 +1,19 @@
+#![warn(unused)]
+#![allow(dead_code)]
+#![deny(non_snake_case)]
+
+mod Impl {}
+//~^ ERROR module `Impl` should have a snake case name
+
+fn While() {}
+//~^ ERROR function `While` should have a snake case name
+
+fn main() {
+    let Mod: usize = 0;
+    //~^ ERROR variable `Mod` should have a snake case name
+    //~^^ WARN unused variable: `Mod`
+
+    let Super: usize = 0;
+    //~^ ERROR variable `Super` should have a snake case name
+    //~^^ WARN unused variable: `Super`
+}
diff --git a/src/test/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr b/src/test/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr
new file mode 100644
index 0000000..c179f4a
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr
@@ -0,0 +1,67 @@
+warning: unused variable: `Mod`
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:12:9
+   |
+LL |     let Mod: usize = 0;
+   |         ^^^ help: if this is intentional, prefix it with an underscore: `_Mod`
+   |
+note: the lint level is defined here
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:1:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
+
+warning: unused variable: `Super`
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:16:9
+   |
+LL |     let Super: usize = 0;
+   |         ^^^^^ help: if this is intentional, prefix it with an underscore: `_Super`
+
+error: module `Impl` should have a snake case name
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:5:5
+   |
+LL | mod Impl {}
+   |     ^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:3:9
+   |
+LL | #![deny(non_snake_case)]
+   |         ^^^^^^^^^^^^^^
+help: rename the identifier or convert it to a snake case raw identifier
+   |
+LL | mod r#impl {}
+   |     ^^^^^^
+
+error: function `While` should have a snake case name
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:8:4
+   |
+LL | fn While() {}
+   |    ^^^^^
+   |
+help: rename the identifier or convert it to a snake case raw identifier
+   |
+LL | fn r#while() {}
+   |    ^^^^^^^
+
+error: variable `Mod` should have a snake case name
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:12:9
+   |
+LL |     let Mod: usize = 0;
+   |         ^^^
+   |
+help: rename the identifier or convert it to a snake case raw identifier
+   |
+LL |     let r#mod: usize = 0;
+   |         ^^^^^
+
+error: variable `Super` should have a snake case name
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:16:9
+   |
+LL |     let Super: usize = 0;
+   |         ^^^^^ help: rename the identifier
+   |
+   = note: `super` cannot be used as a raw identifier
+
+error: aborting due to 4 previous errors; 2 warnings emitted
+
diff --git a/src/test/ui/trivial_casts.rs b/src/test/ui/lint/trivial_casts.rs
similarity index 100%
rename from src/test/ui/trivial_casts.rs
rename to src/test/ui/lint/trivial_casts.rs
diff --git a/src/test/ui/trivial_casts.stderr b/src/test/ui/lint/trivial_casts.stderr
similarity index 100%
rename from src/test/ui/trivial_casts.stderr
rename to src/test/ui/lint/trivial_casts.stderr
diff --git a/src/test/ui/lint/unreachable_pub-pub_crate.rs b/src/test/ui/lint/unreachable_pub-pub_crate.rs
index 94f79d6..27c31c2 100644
--- a/src/test/ui/lint/unreachable_pub-pub_crate.rs
+++ b/src/test/ui/lint/unreachable_pub-pub_crate.rs
@@ -41,7 +41,7 @@
     }
     define_empty_struct_with_visibility!(pub, Fluorine);
 
-    extern {
+    extern "C" {
         pub fn catalyze() -> bool; //~ WARNING unreachable_pub
     }
 
diff --git a/src/test/ui/lint/unreachable_pub.rs b/src/test/ui/lint/unreachable_pub.rs
index a4c1497..6bfec0e 100644
--- a/src/test/ui/lint/unreachable_pub.rs
+++ b/src/test/ui/lint/unreachable_pub.rs
@@ -37,7 +37,7 @@
     }
     define_empty_struct_with_visibility!(pub, Fluorine);
 
-    extern {
+    extern "C" {
         pub fn catalyze() -> bool; //~ WARNING unreachable_pub
     }
 
diff --git a/src/test/ui/lint/warn-unused-inline-on-fn-prototypes.rs b/src/test/ui/lint/warn-unused-inline-on-fn-prototypes.rs
index 2109719..4684fe1 100644
--- a/src/test/ui/lint/warn-unused-inline-on-fn-prototypes.rs
+++ b/src/test/ui/lint/warn-unused-inline-on-fn-prototypes.rs
@@ -5,7 +5,7 @@
     fn foo();
 }
 
-extern {
+extern "C" {
     #[inline] //~ ERROR `#[inline]` is ignored on function prototypes
     fn foo();
 }
diff --git a/src/test/ui/inline-asm-bad-constraint.rs b/src/test/ui/llvm-asm/inline-asm-bad-constraint.rs
similarity index 100%
rename from src/test/ui/inline-asm-bad-constraint.rs
rename to src/test/ui/llvm-asm/inline-asm-bad-constraint.rs
diff --git a/src/test/ui/inline-asm-bad-constraint.stderr b/src/test/ui/llvm-asm/inline-asm-bad-constraint.stderr
similarity index 100%
rename from src/test/ui/inline-asm-bad-constraint.stderr
rename to src/test/ui/llvm-asm/inline-asm-bad-constraint.stderr
diff --git a/src/test/ui/inline-asm-bad-operand.rs b/src/test/ui/llvm-asm/inline-asm-bad-operand.rs
similarity index 100%
rename from src/test/ui/inline-asm-bad-operand.rs
rename to src/test/ui/llvm-asm/inline-asm-bad-operand.rs
diff --git a/src/test/ui/inline-asm-bad-operand.stderr b/src/test/ui/llvm-asm/inline-asm-bad-operand.stderr
similarity index 100%
rename from src/test/ui/inline-asm-bad-operand.stderr
rename to src/test/ui/llvm-asm/inline-asm-bad-operand.stderr
diff --git a/src/test/ui/issues/issue-14936.rs b/src/test/ui/llvm-asm/issue-14936.rs
similarity index 100%
rename from src/test/ui/issues/issue-14936.rs
rename to src/test/ui/llvm-asm/issue-14936.rs
diff --git a/src/test/ui/issues/auxiliary/issue-40469.rs b/src/test/ui/macros/auxiliary/issue-40469.rs
similarity index 100%
rename from src/test/ui/issues/auxiliary/issue-40469.rs
rename to src/test/ui/macros/auxiliary/issue-40469.rs
diff --git a/src/test/ui/macros/edition-macro-pats.rs b/src/test/ui/macros/edition-macro-pats.rs
new file mode 100644
index 0000000..ea1f9bf
--- /dev/null
+++ b/src/test/ui/macros/edition-macro-pats.rs
@@ -0,0 +1,14 @@
+// run-pass
+
+#![feature(or_patterns)]
+#![feature(edition_macro_pats)]
+
+macro_rules! foo {
+    (a $x:pat2018) => {};
+    (b $x:pat2021) => {};
+}
+
+fn main() {
+    foo!(a None);
+    foo!(b 1 | 2);
+}
diff --git a/src/test/ui/issues/issue-26322.rs b/src/test/ui/macros/issue-26322.rs
similarity index 100%
rename from src/test/ui/issues/issue-26322.rs
rename to src/test/ui/macros/issue-26322.rs
diff --git a/src/test/ui/issues/issue-40469.rs b/src/test/ui/macros/issue-40469.rs
similarity index 100%
rename from src/test/ui/issues/issue-40469.rs
rename to src/test/ui/macros/issue-40469.rs
diff --git a/src/test/ui/issues/issue-41803.rs b/src/test/ui/macros/issue-41803.rs
similarity index 100%
rename from src/test/ui/issues/issue-41803.rs
rename to src/test/ui/macros/issue-41803.rs
diff --git a/src/test/ui/issues/issue-5060.rs b/src/test/ui/macros/issue-5060.rs
similarity index 100%
rename from src/test/ui/issues/issue-5060.rs
rename to src/test/ui/macros/issue-5060.rs
diff --git a/src/test/ui/macros/macros-in-extern.rs b/src/test/ui/macros/macros-in-extern.rs
index 05002ed..568ae3a8 100644
--- a/src/test/ui/macros/macros-in-extern.rs
+++ b/src/test/ui/macros/macros-in-extern.rs
@@ -10,7 +10,7 @@
 );
 
 macro takes_u32_returns_u32($ident:ident) {
-    fn $ident (arg: u32) -> u32;
+    fn $ident(arg: u32) -> u32;
 }
 
 macro_rules! emits_nothing(
@@ -25,8 +25,14 @@
 );
 
 mod defs {
-    #[no_mangle] extern fn f1() -> u32 { 1 }
-    #[no_mangle] extern fn f2() -> u32 { 2 }
+    #[no_mangle]
+    extern "C" fn f1() -> u32 {
+        1
+    }
+    #[no_mangle]
+    extern "C" fn f2() -> u32 {
+        2
+    }
 }
 
 fn main() {
@@ -37,7 +43,7 @@
 }
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     returns_isize!(rust_get_test_int);
     takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
     emits_nothing!();
diff --git a/src/test/ui/macros/vec-macro-in-pattern.rs b/src/test/ui/macros/vec-macro-in-pattern.rs
new file mode 100644
index 0000000..ce4298b
--- /dev/null
+++ b/src/test/ui/macros/vec-macro-in-pattern.rs
@@ -0,0 +1,10 @@
+// This is a regression test for #61933
+// Verify that the vec![] macro may not be used in patterns
+// and that the resulting diagnostic is actually helpful.
+
+fn main() {
+    match Some(vec![42]) {
+        Some(vec![43]) => {} //~ ERROR arbitrary expressions aren't allowed in patterns
+        _ => {}
+    }
+}
diff --git a/src/test/ui/macros/vec-macro-in-pattern.stderr b/src/test/ui/macros/vec-macro-in-pattern.stderr
new file mode 100644
index 0000000..3dabebf
--- /dev/null
+++ b/src/test/ui/macros/vec-macro-in-pattern.stderr
@@ -0,0 +1,10 @@
+error: arbitrary expressions aren't allowed in patterns
+  --> $DIR/vec-macro-in-pattern.rs:7:14
+   |
+LL |         Some(vec![43]) => {}
+   |              ^^^^^^^^
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr
index c2298d6..3783948 100644
--- a/src/test/ui/match/match-pattern-field-mismatch.stderr
+++ b/src/test/ui/match/match-pattern-field-mismatch.stderr
@@ -6,6 +6,15 @@
 ...
 LL |           Color::Rgb(_, _) => { }
    |           ^^^^^^^^^^^^^^^^ expected 3 fields, found 2
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |           Color::Rgb(_, _, _) => { }
+   |                          ^^^
+help: use `..` to ignore all fields
+   |
+LL |           Color::Rgb(..) => { }
+   |                      ^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/methods/method-call-lifetime-args-fail.rs b/src/test/ui/methods/method-call-lifetime-args-fail.rs
index 938a7f5..8a840ba 100644
--- a/src/test/ui/methods/method-call-lifetime-args-fail.rs
+++ b/src/test/ui/methods/method-call-lifetime-args-fail.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-linelength
+
 struct S;
 
 impl S {
@@ -14,9 +16,9 @@
 fn method_call() {
     S.early(); // OK
     S.early::<'static>();
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
+    //~^ ERROR this associated function takes 2 lifetime arguments but only 1 lifetime argument was supplied
     S.early::<'static, 'static, 'static>();
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
+    //~^ ERROR this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
     let _: &u8 = S.life_and_type::<'static>();
     S.life_and_type::<u8>();
     S.life_and_type::<'static, u8>();
@@ -61,9 +63,9 @@
 
     S::early(S); // OK
     S::early::<'static>(S);
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
+    //~^ ERROR this associated function takes 2 lifetime arguments but only 1 lifetime argument was supplied
     S::early::<'static, 'static, 'static>(S);
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
+    //~^ ERROR this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
     let _: &u8 = S::life_and_type::<'static>(S);
     S::life_and_type::<u8>(S);
     S::life_and_type::<'static, u8>(S);
diff --git a/src/test/ui/methods/method-call-lifetime-args-fail.stderr b/src/test/ui/methods/method-call-lifetime-args-fail.stderr
index 74dab5f..34a2e3d 100644
--- a/src/test/ui/methods/method-call-lifetime-args-fail.stderr
+++ b/src/test/ui/methods/method-call-lifetime-args-fail.stderr
@@ -1,35 +1,43 @@
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/method-call-lifetime-args-fail.rs:16:7
+error[E0107]: this associated function takes 2 lifetime arguments but only 1 lifetime argument was supplied
+  --> $DIR/method-call-lifetime-args-fail.rs:18:7
    |
 LL |     S.early::<'static>();
-   |       ^^^^^ expected 2 lifetime arguments
+   |       ^^^^^   ------- supplied 1 lifetime argument
+   |       |
+   |       expected 2 lifetime arguments
+   |
+note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/method-call-lifetime-args-fail.rs:8:8
+   |
+LL |     fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+   |        ^^^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     S.early::<'static, 'b>();
+   |                      ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 3
-  --> $DIR/method-call-lifetime-args-fail.rs:18:33
+error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
+  --> $DIR/method-call-lifetime-args-fail.rs:20:7
    |
 LL |     S.early::<'static, 'static, 'static>();
-   |                                 ^^^^^^^ unexpected lifetime argument
+   |       ^^^^^                   --------- help: remove this lifetime argument
+   |       |
+   |       expected 2 lifetime arguments
+   |
+note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/method-call-lifetime-args-fail.rs:8:8
+   |
+LL |     fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+   |        ^^^^^ --  --
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:27:15
+  --> $DIR/method-call-lifetime-args-fail.rs:29:15
    |
 LL |     S::late::<'static>(S, &0, &0);
    |               ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:4:13
-   |
-LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
-   |             ^^
-
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:29:15
-   |
-LL |     S::late::<'static, 'static>(S, &0, &0);
-   |               ^^^^^^^
-   |
-note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:4:13
+  --> $DIR/method-call-lifetime-args-fail.rs:6:13
    |
 LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
    |             ^^
@@ -37,59 +45,59 @@
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:31:15
    |
-LL |     S::late::<'static, 'static, 'static>(S, &0, &0);
+LL |     S::late::<'static, 'static>(S, &0, &0);
    |               ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:4:13
+  --> $DIR/method-call-lifetime-args-fail.rs:6:13
    |
 LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
    |             ^^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:34:21
+  --> $DIR/method-call-lifetime-args-fail.rs:33:15
+   |
+LL |     S::late::<'static, 'static, 'static>(S, &0, &0);
+   |               ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:6:13
+   |
+LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+   |             ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:36:21
    |
 LL |     S::late_early::<'static, 'static>(S, &0);
    |                     ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:7:19
+  --> $DIR/method-call-lifetime-args-fail.rs:9:19
    |
 LL |     fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
    |                   ^^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:36:21
+  --> $DIR/method-call-lifetime-args-fail.rs:38:21
    |
 LL |     S::late_early::<'static, 'static, 'static>(S, &0);
    |                     ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:7:19
+  --> $DIR/method-call-lifetime-args-fail.rs:9:19
    |
 LL |     fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
    |                   ^^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:40:24
+  --> $DIR/method-call-lifetime-args-fail.rs:42:24
    |
 LL |     S::late_implicit::<'static>(S, &0, &0);
    |                        ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:5:31
-   |
-LL |     fn late_implicit(self, _: &u8, _: &u8) {}
-   |                               ^
-
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:42:24
-   |
-LL |     S::late_implicit::<'static, 'static>(S, &0, &0);
-   |                        ^^^^^^^
-   |
-note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:5:31
+  --> $DIR/method-call-lifetime-args-fail.rs:7:31
    |
 LL |     fn late_implicit(self, _: &u8, _: &u8) {}
    |                               ^
@@ -97,98 +105,130 @@
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:44:24
    |
-LL |     S::late_implicit::<'static, 'static, 'static>(S, &0, &0);
+LL |     S::late_implicit::<'static, 'static>(S, &0, &0);
    |                        ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:5:31
+  --> $DIR/method-call-lifetime-args-fail.rs:7:31
    |
 LL |     fn late_implicit(self, _: &u8, _: &u8) {}
    |                               ^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:47:30
+  --> $DIR/method-call-lifetime-args-fail.rs:46:24
+   |
+LL |     S::late_implicit::<'static, 'static, 'static>(S, &0, &0);
+   |                        ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:7:31
+   |
+LL |     fn late_implicit(self, _: &u8, _: &u8) {}
+   |                               ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:49:30
    |
 LL |     S::late_implicit_early::<'static, 'static>(S, &0);
    |                              ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:8:41
+  --> $DIR/method-call-lifetime-args-fail.rs:10:41
    |
 LL |     fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
    |                                         ^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:49:30
+  --> $DIR/method-call-lifetime-args-fail.rs:51:30
    |
 LL |     S::late_implicit_early::<'static, 'static, 'static>(S, &0);
    |                              ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:8:41
+  --> $DIR/method-call-lifetime-args-fail.rs:10:41
    |
 LL |     fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
    |                                         ^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:52:35
+  --> $DIR/method-call-lifetime-args-fail.rs:54:35
    |
 LL |     S::late_implicit_self_early::<'static, 'static>(&S);
    |                                   ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:9:37
+  --> $DIR/method-call-lifetime-args-fail.rs:11:37
    |
 LL |     fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
    |                                     ^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:54:35
+  --> $DIR/method-call-lifetime-args-fail.rs:56:35
    |
 LL |     S::late_implicit_self_early::<'static, 'static, 'static>(&S);
    |                                   ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:9:37
+  --> $DIR/method-call-lifetime-args-fail.rs:11:37
    |
 LL |     fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
    |                                     ^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:57:28
+  --> $DIR/method-call-lifetime-args-fail.rs:59:28
    |
 LL |     S::late_unused_early::<'static, 'static>(S);
    |                            ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:10:26
+  --> $DIR/method-call-lifetime-args-fail.rs:12:26
    |
 LL |     fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
    |                          ^^
 
 error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
-  --> $DIR/method-call-lifetime-args-fail.rs:59:28
+  --> $DIR/method-call-lifetime-args-fail.rs:61:28
    |
 LL |     S::late_unused_early::<'static, 'static, 'static>(S);
    |                            ^^^^^^^
    |
 note: the late bound lifetime parameter is introduced here
-  --> $DIR/method-call-lifetime-args-fail.rs:10:26
+  --> $DIR/method-call-lifetime-args-fail.rs:12:26
    |
 LL |     fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
    |                          ^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/method-call-lifetime-args-fail.rs:63:5
+error[E0107]: this associated function takes 2 lifetime arguments but only 1 lifetime argument was supplied
+  --> $DIR/method-call-lifetime-args-fail.rs:65:8
    |
 LL |     S::early::<'static>(S);
-   |     ^^^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |        ^^^^^   ------- supplied 1 lifetime argument
+   |        |
+   |        expected 2 lifetime arguments
+   |
+note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/method-call-lifetime-args-fail.rs:8:8
+   |
+LL |     fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+   |        ^^^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     S::early::<'static, 'b>(S);
+   |                       ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 3
-  --> $DIR/method-call-lifetime-args-fail.rs:65:34
+error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
+  --> $DIR/method-call-lifetime-args-fail.rs:67:8
    |
 LL |     S::early::<'static, 'static, 'static>(S);
-   |                                  ^^^^^^^ unexpected lifetime argument
+   |        ^^^^^                   --------- help: remove this lifetime argument
+   |        |
+   |        expected 2 lifetime arguments
+   |
+note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+  --> $DIR/method-call-lifetime-args-fail.rs:8:8
+   |
+LL |     fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+   |        ^^^^^ --  --
 
 error: aborting due to 18 previous errors
 
diff --git a/src/test/ui/issues/issue-66851.rs b/src/test/ui/mir/issue-66851.rs
similarity index 100%
rename from src/test/ui/issues/issue-66851.rs
rename to src/test/ui/mir/issue-66851.rs
diff --git a/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs b/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs
new file mode 100644
index 0000000..2437155
--- /dev/null
+++ b/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs
@@ -0,0 +1,21 @@
+// Ensures -Zmir-opt-level=2 (specifically, inlining) is not allowed with -Zinstrument-coverage.
+// Regression test for issue #80060.
+//
+// needs-profiler-support
+// build-pass
+// compile-flags: -Zmir-opt-level=2 -Zinstrument-coverage
+#[inline(never)]
+fn foo() {}
+
+pub fn baz() {
+    bar();
+}
+
+#[inline(always)]
+fn bar() {
+    foo();
+}
+
+fn main() {
+    bar();
+}
diff --git a/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr b/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr
new file mode 100644
index 0000000..eb50e50
--- /dev/null
+++ b/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr
@@ -0,0 +1,2 @@
+warning: `-Z mir-opt-level=2` (or any level > 1) enables function inlining, which is incompatible with `-Z instrument-coverage`. Inlining will be disabled.
+
diff --git a/src/test/ui/mir/mir_codegen_calls.rs b/src/test/ui/mir/mir_codegen_calls.rs
index d93a25c..6a5a4da 100644
--- a/src/test/ui/mir/mir_codegen_calls.rs
+++ b/src/test/ui/mir/mir_codegen_calls.rs
@@ -75,7 +75,7 @@
 }
 
 #[allow(improper_ctypes_definitions)]
-extern fn simple_extern(x: u32, y: (u32, u32)) -> u32 {
+extern "C" fn simple_extern(x: u32, y: (u32, u32)) -> u32 {
     x + y.0 * y.1
 }
 
diff --git a/src/test/ui/mir/ssa-analysis-regression-50041.rs b/src/test/ui/mir/ssa-analysis-regression-50041.rs
new file mode 100644
index 0000000..c818f29
--- /dev/null
+++ b/src/test/ui/mir/ssa-analysis-regression-50041.rs
@@ -0,0 +1,34 @@
+// build-pass
+// compile-flags: -Z mir-opt-level=3
+
+#![crate_type="lib"]
+#![feature(lang_items)]
+#![no_std]
+
+#[lang = "owned_box"]
+pub struct Box<T: ?Sized>(*mut T);
+
+impl<T: ?Sized> Drop for Box<T> {
+    fn drop(&mut self) {
+    }
+}
+
+#[lang = "box_free"]
+#[inline(always)]
+unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
+    dealloc(ptr)
+}
+
+#[inline(never)]
+fn dealloc<T: ?Sized>(_: *mut T) {
+}
+
+pub struct Foo<T>(T);
+
+pub fn foo(a: Option<Box<Foo<usize>>>) -> usize {
+    let f = match a {
+        None => Foo(0),
+        Some(vec) => *vec,
+    };
+    f.0
+}
diff --git a/src/test/ui/mismatched_types/E0053.stderr b/src/test/ui/mismatched_types/E0053.stderr
index fef83e6..e0a3ce9 100644
--- a/src/test/ui/mismatched_types/E0053.stderr
+++ b/src/test/ui/mismatched_types/E0053.stderr
@@ -17,14 +17,13 @@
    |            ----- type in trait
 ...
 LL |     fn bar(&mut self) { }
-   |            ^^^^^^^^^ types differ in mutability
+   |            ^^^^^^^^^
+   |            |
+   |            types differ in mutability
+   |            help: consider changing the mutability to match the trait: `&self`
    |
    = note: expected fn pointer `fn(&Bar)`
               found fn pointer `fn(&mut Bar)`
-help: consider change the type to match the mutability in trait
-   |
-LL |     fn bar(&self) { }
-   |            ^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
index 0af44d2..02ba60f 100644
--- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -26,37 +26,77 @@
   --> $DIR/closure-arg-type-mismatch.rs:10:5
    |
 LL |     baz(f);
-   |     ^^^ one type is more general than the other
+   |     ^^^ lifetime mismatch
    |
    = note: expected type `for<'r> Fn<(*mut &'r u32,)>`
               found type `Fn<(*mut &'a u32,)>`
+note: the required lifetime does not necessarily outlive the lifetime `'a` as defined on the function body at 9:10
+  --> $DIR/closure-arg-type-mismatch.rs:9:10
+   |
+LL | fn _test<'a>(f: fn(*mut &'a u32)) {
+   |          ^^
+note: the lifetime requirement is introduced here
+  --> $DIR/closure-arg-type-mismatch.rs:8:11
+   |
+LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
+   |           ^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/closure-arg-type-mismatch.rs:10:5
    |
 LL |     baz(f);
-   |     ^^^ one type is more general than the other
+   |     ^^^ lifetime mismatch
    |
    = note: expected type `FnOnce<(*mut &u32,)>`
               found type `FnOnce<(*mut &'a u32,)>`
+note: the required lifetime does not necessarily outlive the lifetime `'a` as defined on the function body at 9:10
+  --> $DIR/closure-arg-type-mismatch.rs:9:10
+   |
+LL | fn _test<'a>(f: fn(*mut &'a u32)) {
+   |          ^^
+note: the lifetime requirement is introduced here
+  --> $DIR/closure-arg-type-mismatch.rs:8:11
+   |
+LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
+   |           ^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/closure-arg-type-mismatch.rs:10:5
    |
 LL |     baz(f);
-   |     ^^^ one type is more general than the other
+   |     ^^^ lifetime mismatch
    |
    = note: expected type `for<'r> Fn<(*mut &'r u32,)>`
               found type `Fn<(*mut &'a u32,)>`
+note: the lifetime `'a` as defined on the function body at 9:10 doesn't meet the lifetime requirements
+  --> $DIR/closure-arg-type-mismatch.rs:9:10
+   |
+LL | fn _test<'a>(f: fn(*mut &'a u32)) {
+   |          ^^
+note: the lifetime requirement is introduced here
+  --> $DIR/closure-arg-type-mismatch.rs:8:11
+   |
+LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
+   |           ^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/closure-arg-type-mismatch.rs:10:5
    |
 LL |     baz(f);
-   |     ^^^ one type is more general than the other
+   |     ^^^ lifetime mismatch
    |
    = note: expected type `FnOnce<(*mut &u32,)>`
               found type `FnOnce<(*mut &'a u32,)>`
+note: the lifetime `'a` as defined on the function body at 9:10 doesn't meet the lifetime requirements
+  --> $DIR/closure-arg-type-mismatch.rs:9:10
+   |
+LL | fn _test<'a>(f: fn(*mut &'a u32)) {
+   |          ^^
+note: the lifetime requirement is introduced here
+  --> $DIR/closure-arg-type-mismatch.rs:8:11
+   |
+LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
+   |           ^^^^^^^^^^^^^
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr
index 149f505..c41bece 100644
--- a/src/test/ui/mismatched_types/closure-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-mismatch.stderr
@@ -2,10 +2,20 @@
   --> $DIR/closure-mismatch.rs:8:5
    |
 LL |     baz(|_| ());
-   |     ^^^ one type is more general than the other
+   |     ^^^ lifetime mismatch
    |
    = note: expected type `for<'r> Fn<(&'r (),)>`
               found type `Fn<(&(),)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/closure-mismatch.rs:8:9
+   |
+LL |     baz(|_| ());
+   |         ^^^^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/closure-mismatch.rs:5:11
+   |
+LL | fn baz<T: Foo>(_: T) {}
+   |           ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/mismatched_types/issue-26480.rs b/src/test/ui/mismatched_types/issue-26480.rs
index d140e12..8bd26ce 100644
--- a/src/test/ui/mismatched_types/issue-26480.rs
+++ b/src/test/ui/mismatched_types/issue-26480.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     fn write(fildes: i32, buf: *const i8, nbyte: u64) -> i64;
 }
 
diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
index 706e255..264d7cb 100644
--- a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
+++ b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
@@ -11,6 +11,12 @@
    |               ^-- supplied 0 arguments
    |               |
    |               expected 1 argument
+   |
+note: associated function defined here
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL |     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+   |                           ^^^^^^^^
 
 error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/overloaded-calls-bad.rs:31:15
@@ -19,6 +25,12 @@
    |               ^ -------  ------- supplied 2 arguments
    |               |
    |               expected 1 argument
+   |
+note: associated function defined here
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL |     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+   |                           ^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr
index 5735120..1618434 100644
--- a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr
+++ b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr
@@ -17,14 +17,13 @@
    |                            -------- type in trait
 ...
 LL |     fn bar(&mut self, bar: &Bar) { }
-   |                            ^^^^ types differ in mutability
+   |                            ^^^^
+   |                            |
+   |                            types differ in mutability
+   |                            help: consider changing the mutability to match the trait: `&mut Bar`
    |
    = note: expected fn pointer `fn(&mut Bar, &mut Bar)`
               found fn pointer `fn(&mut Bar, &Bar)`
-help: consider change the type to match the mutability in trait
-   |
-LL |     fn bar(&mut self, bar: &mut Bar) { }
-   |                            ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/moves/move-fn-self-receiver.rs b/src/test/ui/moves/move-fn-self-receiver.rs
index 6107f53..946642e 100644
--- a/src/test/ui/moves/move-fn-self-receiver.rs
+++ b/src/test/ui/moves/move-fn-self-receiver.rs
@@ -69,6 +69,11 @@
     let container = Container(vec![]);
     for _val in container.custom_into_iter() {}
     container; //~ ERROR use of moved
+
+    let foo2 = Foo;
+    loop {
+        foo2.use_self(); //~ ERROR use of moved
+    }
 }
 
 fn main() {}
diff --git a/src/test/ui/moves/move-fn-self-receiver.stderr b/src/test/ui/moves/move-fn-self-receiver.stderr
index dd263c1..eca6bb9 100644
--- a/src/test/ui/moves/move-fn-self-receiver.stderr
+++ b/src/test/ui/moves/move-fn-self-receiver.stderr
@@ -6,7 +6,7 @@
 LL |     val.0;
    |     ^^^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `val.0`
+note: this function takes ownership of the receiver `self`, which moves `val.0`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
@@ -23,7 +23,7 @@
 LL |     foo;
    |     ^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `foo`
+note: this function takes ownership of the receiver `self`, which moves `foo`
   --> $DIR/move-fn-self-receiver.rs:13:17
    |
 LL |     fn use_self(self) {}
@@ -49,7 +49,7 @@
 LL |     boxed_foo;
    |     ^^^^^^^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `boxed_foo`
+note: this function takes ownership of the receiver `self`, which moves `boxed_foo`
   --> $DIR/move-fn-self-receiver.rs:14:21
    |
 LL |     fn use_box_self(self: Box<Self>) {}
@@ -65,7 +65,7 @@
 LL |     pin_box_foo;
    |     ^^^^^^^^^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `pin_box_foo`
+note: this function takes ownership of the receiver `self`, which moves `pin_box_foo`
   --> $DIR/move-fn-self-receiver.rs:15:25
    |
 LL |     fn use_pin_box_self(self: Pin<Box<Self>>) {}
@@ -91,7 +91,7 @@
 LL |     rc_foo;
    |     ^^^^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `rc_foo`
+note: this function takes ownership of the receiver `self`, which moves `rc_foo`
   --> $DIR/move-fn-self-receiver.rs:16:20
    |
 LL |     fn use_rc_self(self: Rc<Self>) {}
@@ -146,13 +146,22 @@
 LL |     container;
    |     ^^^^^^^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `container`
+note: this function takes ownership of the receiver `self`, which moves `container`
   --> $DIR/move-fn-self-receiver.rs:23:25
    |
 LL |     fn custom_into_iter(self) -> impl Iterator<Item = bool> {
    |                         ^^^^
 
-error: aborting due to 11 previous errors
+error[E0382]: use of moved value: `foo2`
+  --> $DIR/move-fn-self-receiver.rs:75:9
+   |
+LL |     let foo2 = Foo;
+   |         ---- move occurs because `foo2` has type `Foo`, which does not implement the `Copy` trait
+LL |     loop {
+LL |         foo2.use_self();
+   |         ^^^^ ---------- `foo2` moved due to this method call, in previous iteration of loop
+
+error: aborting due to 12 previous errors
 
 Some errors have detailed explanations: E0382, E0505.
 For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
index 11e9456..3cc8ca2 100644
--- a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
+++ b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
@@ -8,7 +8,7 @@
 LL |     touch(&x[0]);
    |            ^ value borrowed here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
+note: this function takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
diff --git a/src/test/ui/moves/moves-based-on-type-exprs.stderr b/src/test/ui/moves/moves-based-on-type-exprs.stderr
index 46940cf..9bcec36 100644
--- a/src/test/ui/moves/moves-based-on-type-exprs.stderr
+++ b/src/test/ui/moves/moves-based-on-type-exprs.stderr
@@ -108,7 +108,7 @@
 LL |     touch(&x);
    |           ^^ value borrowed here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
+note: this function takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
@@ -124,7 +124,7 @@
 LL |     touch(&x);
    |           ^^ value borrowed here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
+note: this function takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
diff --git a/src/test/ui/issues/issue-10176.rs b/src/test/ui/never_type/issue-10176.rs
similarity index 100%
rename from src/test/ui/issues/issue-10176.rs
rename to src/test/ui/never_type/issue-10176.rs
diff --git a/src/test/ui/issues/issue-10176.stderr b/src/test/ui/never_type/issue-10176.stderr
similarity index 100%
rename from src/test/ui/issues/issue-10176.stderr
rename to src/test/ui/never_type/issue-10176.stderr
diff --git a/src/test/ui/nil-decl-in-foreign.rs b/src/test/ui/nil-decl-in-foreign.rs
index 9842266..f3be948 100644
--- a/src/test/ui/nil-decl-in-foreign.rs
+++ b/src/test/ui/nil-decl-in-foreign.rs
@@ -6,9 +6,9 @@
 // pretty-expanded FIXME #23616
 
 mod libc {
-    extern {
+    extern "C" {
         pub fn printf(x: ());
     }
 }
 
-pub fn main() { }
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-45696-long-live-borrows-in-boxes.rs b/src/test/ui/nll/issue-45696-long-live-borrows-in-boxes.rs
similarity index 100%
rename from src/test/ui/issues/issue-45696-long-live-borrows-in-boxes.rs
rename to src/test/ui/nll/issue-45696-long-live-borrows-in-boxes.rs
diff --git a/src/test/ui/issues/issue-51345-2.rs b/src/test/ui/nll/issue-51345-2.rs
similarity index 100%
rename from src/test/ui/issues/issue-51345-2.rs
rename to src/test/ui/nll/issue-51345-2.rs
diff --git a/src/test/ui/issues/issue-51770.rs b/src/test/ui/nll/issue-51770.rs
similarity index 100%
rename from src/test/ui/issues/issue-51770.rs
rename to src/test/ui/nll/issue-51770.rs
diff --git a/src/test/ui/issues/issue-54943-3.rs b/src/test/ui/nll/issue-54943-3.rs
similarity index 100%
rename from src/test/ui/issues/issue-54943-3.rs
rename to src/test/ui/nll/issue-54943-3.rs
diff --git a/src/test/ui/issues/issue-55511.rs b/src/test/ui/nll/issue-55511.rs
similarity index 100%
rename from src/test/ui/issues/issue-55511.rs
rename to src/test/ui/nll/issue-55511.rs
diff --git a/src/test/ui/issues/issue-55511.stderr b/src/test/ui/nll/issue-55511.stderr
similarity index 100%
rename from src/test/ui/issues/issue-55511.stderr
rename to src/test/ui/nll/issue-55511.stderr
diff --git a/src/test/ui/no-patterns-in-args-2.stderr b/src/test/ui/no-patterns-in-args-2.stderr
index 21f4439..9893234 100644
--- a/src/test/ui/no-patterns-in-args-2.stderr
+++ b/src/test/ui/no-patterns-in-args-2.stderr
@@ -8,7 +8,7 @@
   --> $DIR/no-patterns-in-args-2.rs:4:11
    |
 LL |     fn f1(mut arg: u8);
-   |           ^^^^^^^
+   |           ^^^^^^^ help: remove `mut` from the parameter: `arg`
    |
 note: the lint level is defined here
   --> $DIR/no-patterns-in-args-2.rs:1:9
diff --git a/src/test/ui/no-patterns-in-args.rs b/src/test/ui/no-patterns-in-args.rs
index a774955..54836b0 100644
--- a/src/test/ui/no-patterns-in-args.rs
+++ b/src/test/ui/no-patterns-in-args.rs
@@ -1,10 +1,10 @@
-extern {
+extern "C" {
     fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
     fn f2(&arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
     fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations
     fn g1(arg: u8); // OK
     fn g2(_: u8); // OK
-    // fn g3(u8); // Not yet
+// fn g3(u8); // Not yet
 }
 
 type A1 = fn(mut arg: u8); //~ ERROR patterns aren't allowed in function pointer types
diff --git a/src/test/ui/no_owned_box_lang_item.rs b/src/test/ui/no_owned_box_lang_item.rs
index bef630d..c22b44f 100644
--- a/src/test/ui/no_owned_box_lang_item.rs
+++ b/src/test/ui/no_owned_box_lang_item.rs
@@ -11,6 +11,6 @@
     let x = box 1i32;
 }
 
-#[lang = "eh_personality"] extern fn eh_personality() {}
+#[lang = "eh_personality"] extern "C" fn eh_personality() {}
 #[lang = "eh_catch_typeinfo"] static EH_CATCH_TYPEINFO: u8 = 0;
 #[lang = "panic_impl"] fn panic_impl(panic: &PanicInfo) -> ! { loop {} }
diff --git a/src/test/ui/non-built-in-quote.rs b/src/test/ui/non-built-in-quote.rs
deleted file mode 100644
index 92efa99..0000000
--- a/src/test/ui/non-built-in-quote.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-// pretty-expanded FIXME #23616
-
-macro_rules! quote_tokens { () => (()) }
-
-pub fn main() {
-    quote_tokens!();
-}
diff --git a/src/test/ui/non-constant-expr-for-arr-len.stderr b/src/test/ui/non-constant-expr-for-arr-len.stderr
index b947cb7..d684b8e 100644
--- a/src/test/ui/non-constant-expr-for-arr-len.stderr
+++ b/src/test/ui/non-constant-expr-for-arr-len.stderr
@@ -1,8 +1,10 @@
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/non-constant-expr-for-arr-len.rs:5:22
    |
+LL |     fn bar(n: usize) {
+   |            - this would need to be a `const`
 LL |         let _x = [0; n];
-   |                      ^ non-constant value
+   |                      ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nullable-pointer-size.rs b/src/test/ui/nullable-pointer-size.rs
index 63a106f..0384553 100644
--- a/src/test/ui/nullable-pointer-size.rs
+++ b/src/test/ui/nullable-pointer-size.rs
@@ -31,5 +31,5 @@
 pub fn main() {
     check_type!(&'static isize);
     check_type!(Box<isize>);
-    check_type!(extern fn());
+    check_type!(extern "C" fn());
 }
diff --git a/src/test/ui/issues/issue-8460-const.noopt.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr
similarity index 100%
rename from src/test/ui/issues/issue-8460-const.noopt.stderr
rename to src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr
diff --git a/src/test/ui/issues/issue-8460-const.opt.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr
similarity index 100%
rename from src/test/ui/issues/issue-8460-const.opt.stderr
rename to src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr
diff --git a/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr
similarity index 100%
rename from src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr
rename to src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr
diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/numbers-arithmetic/issue-8460-const.rs
similarity index 100%
rename from src/test/ui/issues/issue-8460-const.rs
rename to src/test/ui/numbers-arithmetic/issue-8460-const.rs
diff --git a/src/test/ui/issues/issue-8460.rs b/src/test/ui/numbers-arithmetic/issue-8460.rs
similarity index 100%
rename from src/test/ui/issues/issue-8460.rs
rename to src/test/ui/numbers-arithmetic/issue-8460.rs
diff --git a/src/test/ui/osx-frameworks.rs b/src/test/ui/osx-frameworks.rs
index 227e07d..31b853e 100644
--- a/src/test/ui/osx-frameworks.rs
+++ b/src/test/ui/osx-frameworks.rs
@@ -1,8 +1,7 @@
 // ignore-macos this is supposed to succeed on osx
 
 #[link(name = "foo", kind = "framework")]
-extern {}
+extern "C" {}
 //~^^ ERROR: native frameworks are only available on macOS
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/overloaded-calls-nontuple.rs b/src/test/ui/overloaded-calls-nontuple.rs
index 76b114c..07d44ff 100644
--- a/src/test/ui/overloaded-calls-nontuple.rs
+++ b/src/test/ui/overloaded-calls-nontuple.rs
@@ -11,13 +11,13 @@
     extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
         self.x + self.y + z
     }
-    //~^^^ ERROR A function with the "rust-call" ABI must take a single non-self argument
+    //~^^^ ERROR functions with the "rust-call" ABI must take a single non-self argument
 }
 
 impl FnOnce<isize> for S {
     type Output = isize;
     extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
-    //~^ ERROR A function with the "rust-call" ABI must take a single non-self argument
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
 }
 
 fn main() {
diff --git a/src/test/ui/overloaded-calls-nontuple.stderr b/src/test/ui/overloaded-calls-nontuple.stderr
index bdadb95..8f299bc 100644
--- a/src/test/ui/overloaded-calls-nontuple.stderr
+++ b/src/test/ui/overloaded-calls-nontuple.stderr
@@ -1,10 +1,10 @@
-error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
   --> $DIR/overloaded-calls-nontuple.rs:11:5
    |
 LL |     extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
   --> $DIR/overloaded-calls-nontuple.rs:19:5
    |
 LL |     extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
diff --git a/src/test/ui/panic-handler/weak-lang-item.stderr b/src/test/ui/panic-handler/weak-lang-item.stderr
index b7c040c..68e3e21 100644
--- a/src/test/ui/panic-handler/weak-lang-item.stderr
+++ b/src/test/ui/panic-handler/weak-lang-item.stderr
@@ -10,10 +10,10 @@
 LL | extern crate core as other_core;
    |
 
-error: `#[panic_handler]` function required, but not found
-
 error: language item required, but not found: `eh_personality`
 
+error: `#[panic_handler]` function required, but not found
+
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/panic-runtime/auxiliary/panic-runtime-abort.rs b/src/test/ui/panic-runtime/auxiliary/panic-runtime-abort.rs
index 433301f..c92015e 100644
--- a/src/test/ui/panic-runtime/auxiliary/panic-runtime-abort.rs
+++ b/src/test/ui/panic-runtime/auxiliary/panic-runtime-abort.rs
@@ -8,10 +8,10 @@
 #![panic_runtime]
 
 #[no_mangle]
-pub extern fn __rust_maybe_catch_panic() {}
+pub extern "C" fn __rust_maybe_catch_panic() {}
 
 #[no_mangle]
-pub extern fn __rust_start_panic() {}
+pub extern "C" fn __rust_start_panic() {}
 
 #[no_mangle]
-pub extern fn rust_eh_personality() {}
+pub extern "C" fn rust_eh_personality() {}
diff --git a/src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind.rs b/src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind.rs
index 97452a3..2f7aed9 100644
--- a/src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind.rs
+++ b/src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind.rs
@@ -8,10 +8,10 @@
 #![panic_runtime]
 
 #[no_mangle]
-pub extern fn __rust_maybe_catch_panic() {}
+pub extern "C" fn __rust_maybe_catch_panic() {}
 
 #[no_mangle]
-pub extern fn __rust_start_panic() {}
+pub extern "C" fn __rust_start_panic() {}
 
 #[no_mangle]
-pub extern fn rust_eh_personality() {}
+pub extern "C" fn rust_eh_personality() {}
diff --git a/src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind2.rs b/src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind2.rs
index 97452a3..2f7aed9 100644
--- a/src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind2.rs
+++ b/src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind2.rs
@@ -8,10 +8,10 @@
 #![panic_runtime]
 
 #[no_mangle]
-pub extern fn __rust_maybe_catch_panic() {}
+pub extern "C" fn __rust_maybe_catch_panic() {}
 
 #[no_mangle]
-pub extern fn __rust_start_panic() {}
+pub extern "C" fn __rust_start_panic() {}
 
 #[no_mangle]
-pub extern fn rust_eh_personality() {}
+pub extern "C" fn rust_eh_personality() {}
diff --git a/src/test/ui/parser/attrs-after-extern-mod.rs b/src/test/ui/parser/attrs-after-extern-mod.rs
index ea899dc..e3f0fa0 100644
--- a/src/test/ui/parser/attrs-after-extern-mod.rs
+++ b/src/test/ui/parser/attrs-after-extern-mod.rs
@@ -2,6 +2,6 @@
 
 fn main() {}
 
-extern {
+extern "C" {
     #[cfg(stage37)] //~ ERROR expected item after attributes
 }
diff --git a/src/test/ui/parser/attrs-after-extern-mod.stderr b/src/test/ui/parser/attrs-after-extern-mod.stderr
index 3862f5c..135d984 100644
--- a/src/test/ui/parser/attrs-after-extern-mod.stderr
+++ b/src/test/ui/parser/attrs-after-extern-mod.stderr
@@ -1,8 +1,8 @@
 error: expected item after attributes
   --> $DIR/attrs-after-extern-mod.rs:6:5
    |
-LL | extern {
-   |        - while parsing this item list starting here
+LL | extern "C" {
+   |            - while parsing this item list starting here
 LL |     #[cfg(stage37)]
    |     ^^^^^^^^^^^^^^^
 LL | }
diff --git a/src/test/ui/issues/auxiliary/issue-21146-inc.rs b/src/test/ui/parser/auxiliary/issue-21146-inc.rs
similarity index 100%
rename from src/test/ui/issues/auxiliary/issue-21146-inc.rs
rename to src/test/ui/parser/auxiliary/issue-21146-inc.rs
diff --git a/src/test/ui/parser/block-no-opening-brace.rs b/src/test/ui/parser/block-no-opening-brace.rs
index e4bb39f..8a65994 100644
--- a/src/test/ui/parser/block-no-opening-brace.rs
+++ b/src/test/ui/parser/block-no-opening-brace.rs
@@ -26,6 +26,6 @@
     }
 
 fn f5() {
-    async //~ ERROR async closures are unstable
+    async
         let x = 0; //~ ERROR expected one of `move`, `|`, or `||`, found keyword `let`
     }
diff --git a/src/test/ui/parser/block-no-opening-brace.stderr b/src/test/ui/parser/block-no-opening-brace.stderr
index a88e4ac..e32c8bd 100644
--- a/src/test/ui/parser/block-no-opening-brace.stderr
+++ b/src/test/ui/parser/block-no-opening-brace.stderr
@@ -39,15 +39,5 @@
 LL |         let x = 0;
    |         ^^^ unexpected token
 
-error[E0658]: async closures are unstable
-  --> $DIR/block-no-opening-brace.rs:29:5
-   |
-LL |     async
-   |     ^^^^^
-   |
-   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
-   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+error: aborting due to 5 previous errors
 
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/can-begin-expr-check.rs b/src/test/ui/parser/can-begin-expr-check.rs
similarity index 100%
rename from src/test/ui/can-begin-expr-check.rs
rename to src/test/ui/parser/can-begin-expr-check.rs
diff --git a/src/test/ui/can-begin-expr-check.stderr b/src/test/ui/parser/can-begin-expr-check.stderr
similarity index 100%
rename from src/test/ui/can-begin-expr-check.stderr
rename to src/test/ui/parser/can-begin-expr-check.stderr
diff --git a/src/test/ui/parser/doc-before-extern-rbrace.rs b/src/test/ui/parser/doc-before-extern-rbrace.rs
index 040206b..515c90e 100644
--- a/src/test/ui/parser/doc-before-extern-rbrace.rs
+++ b/src/test/ui/parser/doc-before-extern-rbrace.rs
@@ -1,6 +1,6 @@
 fn main() {}
 
-extern {
+extern "C" {
     /// hi
     //~^ ERROR found a documentation comment that doesn't document anything
 }
diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs
index 31318ae..547329c 100644
--- a/src/test/ui/parser/duplicate-visibility.rs
+++ b/src/test/ui/parser/duplicate-visibility.rs
@@ -1,6 +1,6 @@
 fn main() {}
 
-extern {
+extern "C" {
     pub pub fn foo();
     //~^ ERROR visibility `pub` is not followed by an item
     //~| ERROR non-item in item list
diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr
index 36b9efd..8d81222 100644
--- a/src/test/ui/parser/duplicate-visibility.stderr
+++ b/src/test/ui/parser/duplicate-visibility.stderr
@@ -9,8 +9,8 @@
 error: non-item in item list
   --> $DIR/duplicate-visibility.rs:4:9
    |
-LL | extern {
-   |        - item list starts here
+LL | extern "C" {
+   |            - item list starts here
 LL |     pub pub fn foo();
    |         ^^^ non-item starts here
 ...
diff --git a/src/test/ui/parser/extern-no-fn.rs b/src/test/ui/parser/extern-no-fn.rs
index d9f35e0..7356860 100644
--- a/src/test/ui/parser/extern-no-fn.rs
+++ b/src/test/ui/parser/extern-no-fn.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     f(); //~ ERROR expected one of `!` or `::`, found `(`
 }
 
diff --git a/src/test/ui/parser/extern-no-fn.stderr b/src/test/ui/parser/extern-no-fn.stderr
index 0151cb4..d9183d5 100644
--- a/src/test/ui/parser/extern-no-fn.stderr
+++ b/src/test/ui/parser/extern-no-fn.stderr
@@ -1,8 +1,8 @@
 error: expected one of `!` or `::`, found `(`
   --> $DIR/extern-no-fn.rs:2:6
    |
-LL | extern {
-   |        - while parsing this item list starting here
+LL | extern "C" {
+   |            - while parsing this item list starting here
 LL |     f();
    |      ^ expected one of `!` or `::`
 LL | }
diff --git a/src/test/ui/parser/fn-body-eq-expr-semi.rs b/src/test/ui/parser/fn-body-eq-expr-semi.rs
index 0944407..7127ba8 100644
--- a/src/test/ui/parser/fn-body-eq-expr-semi.rs
+++ b/src/test/ui/parser/fn-body-eq-expr-semi.rs
@@ -5,7 +5,7 @@
     fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
 }
 
-extern {
+extern "C" {
     fn foo() = 42; //~ ERROR function body cannot be `= expression;`
     //~^ ERROR incorrect function inside `extern` block
     fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
diff --git a/src/test/ui/parser/fn-body-eq-expr-semi.stderr b/src/test/ui/parser/fn-body-eq-expr-semi.stderr
index 739133e..fdc7a94 100644
--- a/src/test/ui/parser/fn-body-eq-expr-semi.stderr
+++ b/src/test/ui/parser/fn-body-eq-expr-semi.stderr
@@ -89,8 +89,8 @@
 error: incorrect function inside `extern` block
   --> $DIR/fn-body-eq-expr-semi.rs:9:8
    |
-LL | extern {
-   | ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+LL | extern "C" {
+   | ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body
 LL |     fn foo() = 42;
    |        ^^^   ----- help: remove the invalid body: `;`
    |        |
@@ -102,8 +102,8 @@
 error: incorrect function inside `extern` block
   --> $DIR/fn-body-eq-expr-semi.rs:11:8
    |
-LL | extern {
-   | ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+LL | extern "C" {
+   | ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body
 ...
 LL |     fn bar() -> u8 = 42;
    |        ^^^         ----- help: remove the invalid body: `;`
diff --git a/src/test/ui/parser/fn-body-optional-semantic-fail.rs b/src/test/ui/parser/fn-body-optional-semantic-fail.rs
index 38def05..12df488 100644
--- a/src/test/ui/parser/fn-body-optional-semantic-fail.rs
+++ b/src/test/ui/parser/fn-body-optional-semantic-fail.rs
@@ -20,7 +20,7 @@
         fn f4() {} // OK.
     }
 
-    extern {
+    extern "C" {
         fn f5(); // OK.
         fn f6() {} //~ ERROR incorrect function inside `extern` block
     }
diff --git a/src/test/ui/parser/fn-body-optional-semantic-fail.stderr b/src/test/ui/parser/fn-body-optional-semantic-fail.stderr
index 23ce98f..14bcd7c 100644
--- a/src/test/ui/parser/fn-body-optional-semantic-fail.stderr
+++ b/src/test/ui/parser/fn-body-optional-semantic-fail.stderr
@@ -25,8 +25,8 @@
 error: incorrect function inside `extern` block
   --> $DIR/fn-body-optional-semantic-fail.rs:25:12
    |
-LL |     extern {
-   |     ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+LL |     extern "C" {
+   |     ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body
 LL |         fn f5(); // OK.
 LL |         fn f6() {}
    |            ^^   -- help: remove the invalid body: `;`
diff --git a/src/test/ui/parser/fn-body-optional-syntactic-pass.rs b/src/test/ui/parser/fn-body-optional-syntactic-pass.rs
index e7991c7..f9dbebf 100644
--- a/src/test/ui/parser/fn-body-optional-syntactic-pass.rs
+++ b/src/test/ui/parser/fn-body-optional-syntactic-pass.rs
@@ -24,8 +24,8 @@
         fn f() {}
     }
 
-    extern {
+    extern "C" {
         fn f();
-        fn f() {}
+        fn f();
     }
 }
diff --git a/src/test/ui/parser/fn-header-semantic-fail.rs b/src/test/ui/parser/fn-header-semantic-fail.rs
index c327667..0bbaeec 100644
--- a/src/test/ui/parser/fn-header-semantic-fail.rs
+++ b/src/test/ui/parser/fn-header-semantic-fail.rs
@@ -47,7 +47,7 @@
         //~^ ERROR functions cannot be both `const` and `async`
     }
 
-    extern {
+    extern "C" {
         async fn fe1(); //~ ERROR functions in `extern` blocks cannot have qualifiers
         unsafe fn fe2(); //~ ERROR functions in `extern` blocks cannot have qualifiers
         const fn fe3(); //~ ERROR functions in `extern` blocks cannot have qualifiers
diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr
index 2f11f95..4fde243 100644
--- a/src/test/ui/parser/fn-header-semantic-fail.stderr
+++ b/src/test/ui/parser/fn-header-semantic-fail.stderr
@@ -105,8 +105,8 @@
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/fn-header-semantic-fail.rs:51:18
    |
-LL |     extern {
-   |     ------ in this `extern` block
+LL |     extern "C" {
+   |     ---------- in this `extern` block
 LL |         async fn fe1();
    |                  ^^^
    |
@@ -118,8 +118,8 @@
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/fn-header-semantic-fail.rs:52:19
    |
-LL |     extern {
-   |     ------ in this `extern` block
+LL |     extern "C" {
+   |     ---------- in this `extern` block
 LL |         async fn fe1();
 LL |         unsafe fn fe2();
    |                   ^^^
@@ -132,8 +132,8 @@
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/fn-header-semantic-fail.rs:53:18
    |
-LL |     extern {
-   |     ------ in this `extern` block
+LL |     extern "C" {
+   |     ---------- in this `extern` block
 ...
 LL |         const fn fe3();
    |                  ^^^
@@ -146,8 +146,8 @@
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/fn-header-semantic-fail.rs:54:23
    |
-LL |     extern {
-   |     ------ in this `extern` block
+LL |     extern "C" {
+   |     ---------- in this `extern` block
 ...
 LL |         extern "C" fn fe4();
    |                       ^^^
@@ -160,8 +160,8 @@
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/fn-header-semantic-fail.rs:55:42
    |
-LL |     extern {
-   |     ------ in this `extern` block
+LL |     extern "C" {
+   |     ---------- in this `extern` block
 ...
 LL |         const async unsafe extern "C" fn fe5();
    |                                          ^^^
diff --git a/src/test/ui/parser/fn-header-syntactic-pass.rs b/src/test/ui/parser/fn-header-syntactic-pass.rs
index 9e44541..68f1f79 100644
--- a/src/test/ui/parser/fn-header-syntactic-pass.rs
+++ b/src/test/ui/parser/fn-header-syntactic-pass.rs
@@ -37,11 +37,11 @@
         const async unsafe extern "C" fn f();
     }
 
-    extern {
-        async fn f();
-        unsafe fn f();
-        const fn f();
-        extern "C" fn f();
-        const async unsafe extern "C" fn f();
+    extern "C" {
+        fn f();
+        fn f();
+        fn f();
+        fn f();
+        fn f();
     }
 }
diff --git a/src/test/ui/parser/foreign-const-semantic-fail.rs b/src/test/ui/parser/foreign-const-semantic-fail.rs
index 82978e6..c9940b7 100644
--- a/src/test/ui/parser/foreign-const-semantic-fail.rs
+++ b/src/test/ui/parser/foreign-const-semantic-fail.rs
@@ -1,6 +1,6 @@
 fn main() {}
 
-extern {
+extern "C" {
     const A: isize;
     //~^ ERROR extern items cannot be `const`
     const B: isize = 42;
diff --git a/src/test/ui/parser/foreign-const-semantic-fail.stderr b/src/test/ui/parser/foreign-const-semantic-fail.stderr
index f529b3a..8dc66c0 100644
--- a/src/test/ui/parser/foreign-const-semantic-fail.stderr
+++ b/src/test/ui/parser/foreign-const-semantic-fail.stderr
@@ -21,8 +21,8 @@
 error: incorrect `static` inside `extern` block
   --> $DIR/foreign-const-semantic-fail.rs:6:11
    |
-LL | extern {
-   | ------ `extern` blocks define existing foreign statics and statics inside of them cannot have a body
+LL | extern "C" {
+   | ---------- `extern` blocks define existing foreign statics and statics inside of them cannot have a body
 ...
 LL |     const B: isize = 42;
    |           ^          -- the invalid body
diff --git a/src/test/ui/parser/foreign-const-syntactic-fail.rs b/src/test/ui/parser/foreign-const-syntactic-fail.rs
index a78f8b1..a6e77f8 100644
--- a/src/test/ui/parser/foreign-const-syntactic-fail.rs
+++ b/src/test/ui/parser/foreign-const-syntactic-fail.rs
@@ -3,7 +3,7 @@
 fn main() {}
 
 #[cfg(FALSE)]
-extern {
+extern "C" {
     const A: isize; //~ ERROR extern items cannot be `const`
     const B: isize = 42; //~ ERROR extern items cannot be `const`
 }
diff --git a/src/test/ui/parser/foreign-static-semantic-fail.rs b/src/test/ui/parser/foreign-static-semantic-fail.rs
index 9abdf33..3d427ed 100644
--- a/src/test/ui/parser/foreign-static-semantic-fail.rs
+++ b/src/test/ui/parser/foreign-static-semantic-fail.rs
@@ -2,7 +2,7 @@
 
 fn main() {}
 
-extern {
+extern "C" {
     static X: u8 = 0; //~ ERROR incorrect `static` inside `extern` block
     static mut Y: u8 = 0; //~ ERROR incorrect `static` inside `extern` block
 }
diff --git a/src/test/ui/parser/foreign-static-semantic-fail.stderr b/src/test/ui/parser/foreign-static-semantic-fail.stderr
index 5942e3a..105508c 100644
--- a/src/test/ui/parser/foreign-static-semantic-fail.stderr
+++ b/src/test/ui/parser/foreign-static-semantic-fail.stderr
@@ -1,8 +1,8 @@
 error: incorrect `static` inside `extern` block
   --> $DIR/foreign-static-semantic-fail.rs:6:12
    |
-LL | extern {
-   | ------ `extern` blocks define existing foreign statics and statics inside of them cannot have a body
+LL | extern "C" {
+   | ---------- `extern` blocks define existing foreign statics and statics inside of them cannot have a body
 LL |     static X: u8 = 0;
    |            ^       - the invalid body
    |            |
@@ -13,8 +13,8 @@
 error: incorrect `static` inside `extern` block
   --> $DIR/foreign-static-semantic-fail.rs:7:16
    |
-LL | extern {
-   | ------ `extern` blocks define existing foreign statics and statics inside of them cannot have a body
+LL | extern "C" {
+   | ---------- `extern` blocks define existing foreign statics and statics inside of them cannot have a body
 LL |     static X: u8 = 0;
 LL |     static mut Y: u8 = 0;
    |                ^       - the invalid body
diff --git a/src/test/ui/parser/foreign-static-syntactic-pass.rs b/src/test/ui/parser/foreign-static-syntactic-pass.rs
index 2c805e8..5994963 100644
--- a/src/test/ui/parser/foreign-static-syntactic-pass.rs
+++ b/src/test/ui/parser/foreign-static-syntactic-pass.rs
@@ -5,7 +5,7 @@
 fn main() {}
 
 #[cfg(FALSE)]
-extern {
-    static X: u8 = 0;
-    static mut Y: u8 = 0;
+extern "C" {
+    static X: u8;
+    static mut Y: u8;
 }
diff --git a/src/test/ui/parser/import-from-path.stderr b/src/test/ui/parser/import-from-path.stderr
index 5842037..93bdf82 100644
--- a/src/test/ui/parser/import-from-path.stderr
+++ b/src/test/ui/parser/import-from-path.stderr
@@ -3,6 +3,8 @@
    |
 LL | use foo::{bar}::baz
    |               ^^ expected `;`
+   |
+   = note: glob-like brace syntax must be last on the path
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/import-from-rename.stderr b/src/test/ui/parser/import-from-rename.stderr
index a966e99..d78f6de 100644
--- a/src/test/ui/parser/import-from-rename.stderr
+++ b/src/test/ui/parser/import-from-rename.stderr
@@ -3,6 +3,8 @@
    |
 LL | use foo::{bar} as baz;
    |                ^^ expected `;`
+   |
+   = note: glob-like brace syntax must be last on the path
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/import-glob-path.stderr b/src/test/ui/parser/import-glob-path.stderr
index ebca2db..a93ef25 100644
--- a/src/test/ui/parser/import-glob-path.stderr
+++ b/src/test/ui/parser/import-glob-path.stderr
@@ -3,6 +3,8 @@
    |
 LL | use foo::*::bar
    |           ^^ expected `;`
+   |
+   = note: the wildcard token must be last on the path
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/import-glob-rename.stderr b/src/test/ui/parser/import-glob-rename.stderr
index 2853873..e1a026b 100644
--- a/src/test/ui/parser/import-glob-rename.stderr
+++ b/src/test/ui/parser/import-glob-rename.stderr
@@ -3,6 +3,8 @@
    |
 LL | use foo::* as baz;
    |            ^^ expected `;`
+   |
+   = note: the wildcard token must be last on the path
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20616-1.rs b/src/test/ui/parser/issue-20616-1.rs
similarity index 100%
rename from src/test/ui/issues/issue-20616-1.rs
rename to src/test/ui/parser/issue-20616-1.rs
diff --git a/src/test/ui/issues/issue-20616-1.stderr b/src/test/ui/parser/issue-20616-1.stderr
similarity index 100%
rename from src/test/ui/issues/issue-20616-1.stderr
rename to src/test/ui/parser/issue-20616-1.stderr
diff --git a/src/test/ui/issues/issue-20616-2.rs b/src/test/ui/parser/issue-20616-2.rs
similarity index 100%
rename from src/test/ui/issues/issue-20616-2.rs
rename to src/test/ui/parser/issue-20616-2.rs
diff --git a/src/test/ui/issues/issue-20616-2.stderr b/src/test/ui/parser/issue-20616-2.stderr
similarity index 100%
rename from src/test/ui/issues/issue-20616-2.stderr
rename to src/test/ui/parser/issue-20616-2.stderr
diff --git a/src/test/ui/issues/issue-21146.rs b/src/test/ui/parser/issue-21146.rs
similarity index 100%
rename from src/test/ui/issues/issue-21146.rs
rename to src/test/ui/parser/issue-21146.rs
diff --git a/src/test/ui/issues/issue-21146.stderr b/src/test/ui/parser/issue-21146.stderr
similarity index 100%
rename from src/test/ui/issues/issue-21146.stderr
rename to src/test/ui/parser/issue-21146.stderr
diff --git a/src/test/ui/issues/issue-34222-1.rs b/src/test/ui/parser/issue-34222-1.rs
similarity index 100%
rename from src/test/ui/issues/issue-34222-1.rs
rename to src/test/ui/parser/issue-34222-1.rs
diff --git a/src/test/ui/issues/issue-34222-1.stderr b/src/test/ui/parser/issue-34222-1.stderr
similarity index 100%
rename from src/test/ui/issues/issue-34222-1.stderr
rename to src/test/ui/parser/issue-34222-1.stderr
diff --git a/src/test/ui/issues/issue-43196.rs b/src/test/ui/parser/issue-43196.rs
similarity index 100%
rename from src/test/ui/issues/issue-43196.rs
rename to src/test/ui/parser/issue-43196.rs
diff --git a/src/test/ui/issues/issue-43196.stderr b/src/test/ui/parser/issue-43196.stderr
similarity index 100%
rename from src/test/ui/issues/issue-43196.stderr
rename to src/test/ui/parser/issue-43196.stderr
diff --git a/src/test/ui/issues/issue-44021.rs b/src/test/ui/parser/issue-44021.rs
similarity index 100%
rename from src/test/ui/issues/issue-44021.rs
rename to src/test/ui/parser/issue-44021.rs
diff --git a/src/test/ui/issues/issue-44021.stderr b/src/test/ui/parser/issue-44021.stderr
similarity index 100%
rename from src/test/ui/issues/issue-44021.stderr
rename to src/test/ui/parser/issue-44021.stderr
diff --git a/src/test/ui/issues/issue-45296.rs b/src/test/ui/parser/issue-45296.rs
similarity index 100%
rename from src/test/ui/issues/issue-45296.rs
rename to src/test/ui/parser/issue-45296.rs
diff --git a/src/test/ui/issues/issue-45296.stderr b/src/test/ui/parser/issue-45296.stderr
similarity index 100%
rename from src/test/ui/issues/issue-45296.stderr
rename to src/test/ui/parser/issue-45296.stderr
diff --git a/src/test/ui/issues/issue-46186.fixed b/src/test/ui/parser/issue-46186.fixed
similarity index 100%
rename from src/test/ui/issues/issue-46186.fixed
rename to src/test/ui/parser/issue-46186.fixed
diff --git a/src/test/ui/issues/issue-46186.rs b/src/test/ui/parser/issue-46186.rs
similarity index 100%
rename from src/test/ui/issues/issue-46186.rs
rename to src/test/ui/parser/issue-46186.rs
diff --git a/src/test/ui/issues/issue-46186.stderr b/src/test/ui/parser/issue-46186.stderr
similarity index 100%
rename from src/test/ui/issues/issue-46186.stderr
rename to src/test/ui/parser/issue-46186.stderr
diff --git a/src/test/ui/issues/issue-51602.rs b/src/test/ui/parser/issue-51602.rs
similarity index 100%
rename from src/test/ui/issues/issue-51602.rs
rename to src/test/ui/parser/issue-51602.rs
diff --git a/src/test/ui/issues/issue-51602.stderr b/src/test/ui/parser/issue-51602.stderr
similarity index 100%
rename from src/test/ui/issues/issue-51602.stderr
rename to src/test/ui/parser/issue-51602.stderr
diff --git a/src/test/ui/issues/issue-52496.rs b/src/test/ui/parser/issue-52496.rs
similarity index 100%
rename from src/test/ui/issues/issue-52496.rs
rename to src/test/ui/parser/issue-52496.rs
diff --git a/src/test/ui/issues/issue-52496.stderr b/src/test/ui/parser/issue-52496.stderr
similarity index 100%
rename from src/test/ui/issues/issue-52496.stderr
rename to src/test/ui/parser/issue-52496.stderr
diff --git a/src/test/ui/issues/issue-58856-2.rs b/src/test/ui/parser/issue-58856-2.rs
similarity index 100%
rename from src/test/ui/issues/issue-58856-2.rs
rename to src/test/ui/parser/issue-58856-2.rs
diff --git a/src/test/ui/issues/issue-58856-2.stderr b/src/test/ui/parser/issue-58856-2.stderr
similarity index 100%
rename from src/test/ui/issues/issue-58856-2.stderr
rename to src/test/ui/parser/issue-58856-2.stderr
diff --git a/src/test/ui/issues/issue-60075.rs b/src/test/ui/parser/issue-60075.rs
similarity index 100%
rename from src/test/ui/issues/issue-60075.rs
rename to src/test/ui/parser/issue-60075.rs
diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/parser/issue-60075.stderr
similarity index 100%
rename from src/test/ui/issues/issue-60075.stderr
rename to src/test/ui/parser/issue-60075.stderr
diff --git a/src/test/ui/issues/issue-62554.rs b/src/test/ui/parser/issue-62554.rs
similarity index 100%
rename from src/test/ui/issues/issue-62554.rs
rename to src/test/ui/parser/issue-62554.rs
diff --git a/src/test/ui/issues/issue-62554.stderr b/src/test/ui/parser/issue-62554.stderr
similarity index 100%
rename from src/test/ui/issues/issue-62554.stderr
rename to src/test/ui/parser/issue-62554.stderr
diff --git a/src/test/ui/issues/issue-66473.rs b/src/test/ui/parser/issue-66473.rs
similarity index 100%
rename from src/test/ui/issues/issue-66473.rs
rename to src/test/ui/parser/issue-66473.rs
Binary files differ
diff --git a/src/test/ui/issues/issue-66473.stderr b/src/test/ui/parser/issue-66473.stderr
similarity index 100%
rename from src/test/ui/issues/issue-66473.stderr
rename to src/test/ui/parser/issue-66473.stderr
Binary files differ
diff --git a/src/test/ui/issues/issue-72253.rs b/src/test/ui/parser/issue-72253.rs
similarity index 100%
rename from src/test/ui/issues/issue-72253.rs
rename to src/test/ui/parser/issue-72253.rs
diff --git a/src/test/ui/issues/issue-72253.stderr b/src/test/ui/parser/issue-72253.stderr
similarity index 100%
rename from src/test/ui/issues/issue-72253.stderr
rename to src/test/ui/parser/issue-72253.stderr
diff --git a/src/test/ui/issues/issue-72373.rs b/src/test/ui/parser/issue-72373.rs
similarity index 100%
rename from src/test/ui/issues/issue-72373.rs
rename to src/test/ui/parser/issue-72373.rs
diff --git a/src/test/ui/issues/issue-72373.stderr b/src/test/ui/parser/issue-72373.stderr
similarity index 100%
rename from src/test/ui/issues/issue-72373.stderr
rename to src/test/ui/parser/issue-72373.stderr
diff --git a/src/test/ui/issues/issue-75599.rs b/src/test/ui/parser/issue-75599.rs
similarity index 100%
rename from src/test/ui/issues/issue-75599.rs
rename to src/test/ui/parser/issue-75599.rs
diff --git a/src/test/ui/issue-76597.fixed b/src/test/ui/parser/issue-76597.fixed
similarity index 100%
rename from src/test/ui/issue-76597.fixed
rename to src/test/ui/parser/issue-76597.fixed
diff --git a/src/test/ui/issue-76597.rs b/src/test/ui/parser/issue-76597.rs
similarity index 100%
rename from src/test/ui/issue-76597.rs
rename to src/test/ui/parser/issue-76597.rs
diff --git a/src/test/ui/issue-76597.stderr b/src/test/ui/parser/issue-76597.stderr
similarity index 100%
rename from src/test/ui/issue-76597.stderr
rename to src/test/ui/parser/issue-76597.stderr
diff --git a/src/test/ui/lifetime_starts_expressions.rs b/src/test/ui/parser/lifetime_starts_expressions.rs
similarity index 100%
rename from src/test/ui/lifetime_starts_expressions.rs
rename to src/test/ui/parser/lifetime_starts_expressions.rs
diff --git a/src/test/ui/lifetime_starts_expressions.stderr b/src/test/ui/parser/lifetime_starts_expressions.stderr
similarity index 100%
rename from src/test/ui/lifetime_starts_expressions.stderr
rename to src/test/ui/parser/lifetime_starts_expressions.stderr
diff --git a/src/test/ui/parser/no-const-fn-in-extern-block.rs b/src/test/ui/parser/no-const-fn-in-extern-block.rs
index 4cae703..1993124 100644
--- a/src/test/ui/parser/no-const-fn-in-extern-block.rs
+++ b/src/test/ui/parser/no-const-fn-in-extern-block.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     const fn foo();
     //~^ ERROR functions in `extern` blocks cannot have qualifiers
     const unsafe fn bar();
diff --git a/src/test/ui/parser/no-const-fn-in-extern-block.stderr b/src/test/ui/parser/no-const-fn-in-extern-block.stderr
index af92f2d..04fc8c8 100644
--- a/src/test/ui/parser/no-const-fn-in-extern-block.stderr
+++ b/src/test/ui/parser/no-const-fn-in-extern-block.stderr
@@ -1,8 +1,8 @@
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/no-const-fn-in-extern-block.rs:2:14
    |
-LL | extern {
-   | ------ in this `extern` block
+LL | extern "C" {
+   | ---------- in this `extern` block
 LL |     const fn foo();
    |              ^^^
    |
@@ -14,8 +14,8 @@
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/no-const-fn-in-extern-block.rs:4:21
    |
-LL | extern {
-   | ------ in this `extern` block
+LL | extern "C" {
+   | ---------- in this `extern` block
 ...
 LL |     const unsafe fn bar();
    |                     ^^^
diff --git a/src/test/ui/parse-assoc-type-lt.rs b/src/test/ui/parser/parse-assoc-type-lt.rs
similarity index 100%
rename from src/test/ui/parse-assoc-type-lt.rs
rename to src/test/ui/parser/parse-assoc-type-lt.rs
diff --git a/src/test/ui/parse-error-correct.rs b/src/test/ui/parser/parse-error-correct.rs
similarity index 100%
rename from src/test/ui/parse-error-correct.rs
rename to src/test/ui/parser/parse-error-correct.rs
diff --git a/src/test/ui/parse-error-correct.stderr b/src/test/ui/parser/parse-error-correct.stderr
similarity index 100%
rename from src/test/ui/parse-error-correct.stderr
rename to src/test/ui/parser/parse-error-correct.stderr
diff --git a/src/test/ui/parse-panic.rs b/src/test/ui/parser/parse-panic.rs
similarity index 100%
rename from src/test/ui/parse-panic.rs
rename to src/test/ui/parser/parse-panic.rs
diff --git a/src/test/ui/parser-recovery-1.rs b/src/test/ui/parser/parser-recovery-1.rs
similarity index 100%
rename from src/test/ui/parser-recovery-1.rs
rename to src/test/ui/parser/parser-recovery-1.rs
diff --git a/src/test/ui/parser-recovery-1.stderr b/src/test/ui/parser/parser-recovery-1.stderr
similarity index 100%
rename from src/test/ui/parser-recovery-1.stderr
rename to src/test/ui/parser/parser-recovery-1.stderr
diff --git a/src/test/ui/parser-recovery-2.rs b/src/test/ui/parser/parser-recovery-2.rs
similarity index 100%
rename from src/test/ui/parser-recovery-2.rs
rename to src/test/ui/parser/parser-recovery-2.rs
diff --git a/src/test/ui/parser-recovery-2.stderr b/src/test/ui/parser/parser-recovery-2.stderr
similarity index 100%
rename from src/test/ui/parser-recovery-2.stderr
rename to src/test/ui/parser/parser-recovery-2.stderr
diff --git a/src/test/ui/parser-unicode-whitespace.rs b/src/test/ui/parser/parser-unicode-whitespace.rs
similarity index 100%
rename from src/test/ui/parser-unicode-whitespace.rs
rename to src/test/ui/parser/parser-unicode-whitespace.rs
diff --git a/src/test/ui/parser/self-param-semantic-fail.rs b/src/test/ui/parser/self-param-semantic-fail.rs
index 5676971..621aab2 100644
--- a/src/test/ui/parser/self-param-semantic-fail.rs
+++ b/src/test/ui/parser/self-param-semantic-fail.rs
@@ -23,7 +23,7 @@
     //~^ ERROR `self` parameter is only allowed in associated functions
 }
 
-extern {
+extern "C" {
     fn f1(self);
     //~^ ERROR `self` parameter is only allowed in associated functions
     fn f2(mut self);
@@ -40,8 +40,8 @@
     fn f7(self: u8);
     //~^ ERROR `self` parameter is only allowed in associated functions
     fn f8(mut self: u8);
-    //~^ ERROR `self` parameter is only allowed in associated functions
-    //~| ERROR patterns aren't allowed in
+//~^ ERROR `self` parameter is only allowed in associated functions
+//~| ERROR patterns aren't allowed in
 }
 
 type X1 = fn(self);
diff --git a/src/test/ui/parser/self-param-syntactic-pass.rs b/src/test/ui/parser/self-param-syntactic-pass.rs
index 9e215e6..d7bb786 100644
--- a/src/test/ui/parser/self-param-syntactic-pass.rs
+++ b/src/test/ui/parser/self-param-syntactic-pass.rs
@@ -18,7 +18,7 @@
 }
 
 #[cfg(FALSE)]
-extern {
+extern "C" {
     fn f(self);
     fn f(mut self);
     fn f(&self);
diff --git a/src/test/ui/parser/unsafe-foreign-mod.rs b/src/test/ui/parser/unsafe-foreign-mod.rs
index 872af95..eab134a 100644
--- a/src/test/ui/parser/unsafe-foreign-mod.rs
+++ b/src/test/ui/parser/unsafe-foreign-mod.rs
@@ -1,7 +1,3 @@
-unsafe extern {
-    //~^ ERROR extern block cannot be declared unsafe
-}
-
 unsafe extern "C" {
     //~^ ERROR extern block cannot be declared unsafe
 }
diff --git a/src/test/ui/parser/unsafe-foreign-mod.stderr b/src/test/ui/parser/unsafe-foreign-mod.stderr
index 5e10988..4acf72c 100644
--- a/src/test/ui/parser/unsafe-foreign-mod.stderr
+++ b/src/test/ui/parser/unsafe-foreign-mod.stderr
@@ -1,14 +1,8 @@
 error: extern block cannot be declared unsafe
   --> $DIR/unsafe-foreign-mod.rs:1:1
    |
-LL | unsafe extern {
-   | ^^^^^^
-
-error: extern block cannot be declared unsafe
-  --> $DIR/unsafe-foreign-mod.rs:5:1
-   |
 LL | unsafe extern "C" {
    | ^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs
index aa85f6d..404f409 100644
--- a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs
+++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs
@@ -20,22 +20,22 @@
 //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
 //~| ERROR `...` must be the last argument of a C-variadic function
 
-extern fn f3_1(x: isize, ...) {}
+extern "C" fn f3_1(x: isize, ...) {}
 //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
 
-extern fn f3_2(...) {}
+extern "C" fn f3_2(...) {}
 //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
 //~| ERROR C-variadic function must be declared with at least one named argument
 
-extern fn f3_3(..., x: isize) {}
+extern "C" fn f3_3(..., x: isize) {}
 //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
 //~| ERROR `...` must be the last argument of a C-variadic function
 
-extern {
+extern "C" {
     fn e_f1(...);
     //~^ ERROR C-variadic function must be declared with at least one named argument
     fn e_f2(..., x: isize);
-    //~^ ERROR `...` must be the last argument of a C-variadic function
+//~^ ERROR `...` must be the last argument of a C-variadic function
 }
 
 struct X;
diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr
index 3f3ddfe..ebfe497 100644
--- a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr
+++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr
@@ -47,34 +47,34 @@
    |                    ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:23:26
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:23:30
    |
-LL | extern fn f3_1(x: isize, ...) {}
-   |                          ^^^
+LL | extern "C" fn f3_1(x: isize, ...) {}
+   |                              ^^^
 
 error: C-variadic function must be declared with at least one named argument
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:26:20
    |
-LL | extern fn f3_2(...) {}
-   |                ^^^
+LL | extern "C" fn f3_2(...) {}
+   |                    ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:26:20
    |
-LL | extern fn f3_2(...) {}
-   |                ^^^
+LL | extern "C" fn f3_2(...) {}
+   |                    ^^^
 
 error: `...` must be the last argument of a C-variadic function
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:30:20
    |
-LL | extern fn f3_3(..., x: isize) {}
-   |                ^^^
+LL | extern "C" fn f3_3(..., x: isize) {}
+   |                    ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:30:20
    |
-LL | extern fn f3_3(..., x: isize) {}
-   |                ^^^
+LL | extern "C" fn f3_3(..., x: isize) {}
+   |                    ^^^
 
 error: C-variadic function must be declared with at least one named argument
   --> $DIR/variadic-ffi-semantic-restrictions.rs:35:13
diff --git a/src/test/ui/issues/issue-12582.rs b/src/test/ui/pattern/issue-12582.rs
similarity index 100%
rename from src/test/ui/issues/issue-12582.rs
rename to src/test/ui/pattern/issue-12582.rs
diff --git a/src/test/ui/issues/issue-14221.rs b/src/test/ui/pattern/issue-14221.rs
similarity index 100%
rename from src/test/ui/issues/issue-14221.rs
rename to src/test/ui/pattern/issue-14221.rs
diff --git a/src/test/ui/issues/issue-14221.stderr b/src/test/ui/pattern/issue-14221.stderr
similarity index 100%
rename from src/test/ui/issues/issue-14221.stderr
rename to src/test/ui/pattern/issue-14221.stderr
diff --git a/src/test/ui/issues/issue-22546.rs b/src/test/ui/pattern/issue-22546.rs
similarity index 100%
rename from src/test/ui/issues/issue-22546.rs
rename to src/test/ui/pattern/issue-22546.rs
diff --git a/src/test/ui/issues/issue-6449.rs b/src/test/ui/pattern/issue-6449.rs
similarity index 100%
rename from src/test/ui/issues/issue-6449.rs
rename to src/test/ui/pattern/issue-6449.rs
diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs b/src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs
similarity index 100%
rename from src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs
rename to src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs
diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
similarity index 81%
rename from src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
rename to src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
index 6e8ea6b..9bdbf0b 100644
--- a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
+++ b/src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
@@ -17,6 +17,15 @@
 ...
 LL |     let P() = U {};
    |         ^^^ expected 1 field, found 0
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |     let P(_) = U {};
+   |           ^
+help: use `..` to ignore all fields
+   |
+LL |     let P(..) = U {};
+   |           ^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/pattern/issue-74539.stderr b/src/test/ui/pattern/issue-74539.stderr
index cbc90b5..f7644c1 100644
--- a/src/test/ui/pattern/issue-74539.stderr
+++ b/src/test/ui/pattern/issue-74539.stderr
@@ -26,6 +26,11 @@
 ...
 LL |         E::A(x @ ..) => {
    |         ^^^^^^^^^^^^ expected 2 fields, found 1
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E::A(x @ .., _) => {
+   |                    ^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/pattern/pat-tuple-underfield.rs b/src/test/ui/pattern/pat-tuple-underfield.rs
new file mode 100644
index 0000000..ed852a4
--- /dev/null
+++ b/src/test/ui/pattern/pat-tuple-underfield.rs
@@ -0,0 +1,55 @@
+struct S(i32, f32);
+enum E {
+    S(i32, f32),
+}
+struct Point4(i32, i32, i32, i32);
+
+fn main() {
+    match S(0, 1.0) {
+        S(x) => {}
+        //~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields
+        //~| HELP use `_` to explicitly ignore each field
+    }
+    match S(0, 1.0) {
+        S(_) => {}
+        //~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields
+        //~| HELP use `_` to explicitly ignore each field
+        //~| HELP use `..` to ignore all fields
+    }
+    match S(0, 1.0) {
+        S() => {}
+        //~^ ERROR this pattern has 0 fields, but the corresponding tuple struct has 2 fields
+        //~| HELP use `_` to explicitly ignore each field
+        //~| HELP use `..` to ignore all fields
+    }
+
+    match E::S(0, 1.0) {
+        E::S(x) => {}
+        //~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields
+        //~| HELP use `_` to explicitly ignore each field
+    }
+    match E::S(0, 1.0) {
+        E::S(_) => {}
+        //~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields
+        //~| HELP use `_` to explicitly ignore each field
+        //~| HELP use `..` to ignore all fields
+    }
+    match E::S(0, 1.0) {
+        E::S() => {}
+        //~^ ERROR this pattern has 0 fields, but the corresponding tuple variant has 2 fields
+        //~| HELP use `_` to explicitly ignore each field
+        //~| HELP use `..` to ignore all fields
+    }
+    match E::S(0, 1.0) {
+        E::S => {}
+        //~^ ERROR expected unit struct, unit variant or constant, found tuple variant `E::S`
+        //~| HELP use the tuple variant pattern syntax instead
+    }
+
+    match Point4(0, 1, 2, 3) {
+        Point4(   a   ,     _    ) => {}
+        //~^ ERROR this pattern has 2 fields, but the corresponding tuple struct has 4 fields
+        //~| HELP use `_` to explicitly ignore each field
+        //~| HELP use `..` to ignore the rest of the fields
+    }
+}
diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr
new file mode 100644
index 0000000..76323d9
--- /dev/null
+++ b/src/test/ui/pattern/pat-tuple-underfield.stderr
@@ -0,0 +1,131 @@
+error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::S`
+  --> $DIR/pat-tuple-underfield.rs:44:9
+   |
+LL |     S(i32, f32),
+   |     ----------- `E::S` defined here
+...
+LL |         E::S => {}
+   |         ^^^^ help: use the tuple variant pattern syntax instead: `E::S(_, _)`
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields
+  --> $DIR/pat-tuple-underfield.rs:9:9
+   |
+LL | struct S(i32, f32);
+   | ------------------- tuple struct defined here
+...
+LL |         S(x) => {}
+   |         ^^^^ expected 2 fields, found 1
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         S(x, _) => {}
+   |            ^^^
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields
+  --> $DIR/pat-tuple-underfield.rs:14:9
+   |
+LL | struct S(i32, f32);
+   | ------------------- tuple struct defined here
+...
+LL |         S(_) => {}
+   |         ^^^^ expected 2 fields, found 1
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         S(_, _) => {}
+   |            ^^^
+help: use `..` to ignore all fields
+   |
+LL |         S(..) => {}
+   |           ^^
+
+error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields
+  --> $DIR/pat-tuple-underfield.rs:20:9
+   |
+LL | struct S(i32, f32);
+   | ------------------- tuple struct defined here
+...
+LL |         S() => {}
+   |         ^^^ expected 2 fields, found 0
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         S(_, _) => {}
+   |           ^^^^
+help: use `..` to ignore all fields
+   |
+LL |         S(..) => {}
+   |           ^^
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
+  --> $DIR/pat-tuple-underfield.rs:27:9
+   |
+LL |     S(i32, f32),
+   |     ----------- tuple variant defined here
+...
+LL |         E::S(x) => {}
+   |         ^^^^^^^ expected 2 fields, found 1
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E::S(x, _) => {}
+   |               ^^^
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
+  --> $DIR/pat-tuple-underfield.rs:32:9
+   |
+LL |     S(i32, f32),
+   |     ----------- tuple variant defined here
+...
+LL |         E::S(_) => {}
+   |         ^^^^^^^ expected 2 fields, found 1
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E::S(_, _) => {}
+   |               ^^^
+help: use `..` to ignore all fields
+   |
+LL |         E::S(..) => {}
+   |              ^^
+
+error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields
+  --> $DIR/pat-tuple-underfield.rs:38:9
+   |
+LL |     S(i32, f32),
+   |     ----------- tuple variant defined here
+...
+LL |         E::S() => {}
+   |         ^^^^^^ expected 2 fields, found 0
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E::S(_, _) => {}
+   |              ^^^^
+help: use `..` to ignore all fields
+   |
+LL |         E::S(..) => {}
+   |              ^^
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 4 fields
+  --> $DIR/pat-tuple-underfield.rs:50:9
+   |
+LL | struct Point4(i32, i32, i32, i32);
+   | ---------------------------------- tuple struct defined here
+...
+LL |         Point4(   a   ,     _    ) => {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 4 fields, found 2
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         Point4(   a   ,     _    , _, _) => {}
+   |                                  ^^^^^^
+help: use `..` to ignore the rest of the fields
+   |
+LL |         Point4(   a   ,     _    , ..) => {}
+   |                                  ^^^^
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0023, E0532.
+For more information about an error, try `rustc --explain E0023`.
diff --git a/src/test/ui/size-and-align.rs b/src/test/ui/pattern/size-and-align.rs
similarity index 100%
rename from src/test/ui/size-and-align.rs
rename to src/test/ui/pattern/size-and-align.rs
diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
index 0fa77fb..2ca774a 100644
--- a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
+++ b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
@@ -6,6 +6,7 @@
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&!`
+   = note: references are always considered inhabited
 
 error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
   --> $DIR/always-inhabited-union-ref.rs:27:11
diff --git a/src/test/ui/pattern/usefulness/auxiliary/empty.rs b/src/test/ui/pattern/usefulness/auxiliary/empty.rs
index 0b0719f..29a03c9 100644
--- a/src/test/ui/pattern/usefulness/auxiliary/empty.rs
+++ b/src/test/ui/pattern/usefulness/auxiliary/empty.rs
@@ -1,2 +1,10 @@
 #![crate_type = "rlib"]
 pub enum EmptyForeignEnum {}
+
+pub struct VisiblyUninhabitedForeignStruct {
+    pub field: EmptyForeignEnum,
+}
+
+pub struct SecretlyUninhabitedForeignStruct {
+    _priv: EmptyForeignEnum,
+}
diff --git a/src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
new file mode 100644
index 0000000..b99386e
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
@@ -0,0 +1,261 @@
+error: unreachable pattern
+  --> $DIR/empty-match.rs:37:9
+   |
+LL |         _ => {},
+   |         ^
+   |
+note: the lint level is defined here
+  --> $DIR/empty-match.rs:8:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-match.rs:40:9
+   |
+LL |         _ if false => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-match.rs:47:9
+   |
+LL |         _ => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-match.rs:50:9
+   |
+LL |         _ if false => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-match.rs:57:9
+   |
+LL |         _ => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-match.rs:60:9
+   |
+LL |         _ if false => {},
+   |         ^
+
+error[E0004]: non-exhaustive patterns: type `u8` is non-empty
+  --> $DIR/empty-match.rs:78:20
+   |
+LL |     match_no_arms!(0u8);
+   |                    ^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u8`
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
+  --> $DIR/empty-match.rs:79:20
+   |
+LL | struct NonEmptyStruct1;
+   | ----------------------- `NonEmptyStruct1` defined here
+...
+LL |     match_no_arms!(NonEmptyStruct1);
+   |                    ^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyStruct1`
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
+  --> $DIR/empty-match.rs:80:20
+   |
+LL | struct NonEmptyStruct2(bool);
+   | ----------------------------- `NonEmptyStruct2` defined here
+...
+LL |     match_no_arms!(NonEmptyStruct2(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyStruct2`
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
+  --> $DIR/empty-match.rs:81:20
+   |
+LL | / union NonEmptyUnion1 {
+LL | |     foo: (),
+LL | | }
+   | |_- `NonEmptyUnion1` defined here
+...
+LL |       match_no_arms!((NonEmptyUnion1 { foo: () }));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyUnion1`
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
+  --> $DIR/empty-match.rs:82:20
+   |
+LL | / union NonEmptyUnion2 {
+LL | |     foo: (),
+LL | |     bar: (),
+LL | | }
+   | |_- `NonEmptyUnion2` defined here
+...
+LL |       match_no_arms!((NonEmptyUnion2 { foo: () }));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyUnion2`
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
+  --> $DIR/empty-match.rs:83:20
+   |
+LL | / enum NonEmptyEnum1 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | | }
+   | |_- `NonEmptyEnum1` defined here
+...
+LL |       match_no_arms!(NonEmptyEnum1::Foo(true));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyEnum1`
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
+  --> $DIR/empty-match.rs:84:20
+   |
+LL | / enum NonEmptyEnum2 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | |     Bar,
+   | |     --- not covered
+LL | | }
+   | |_- `NonEmptyEnum2` defined here
+...
+LL |       match_no_arms!(NonEmptyEnum2::Foo(true));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyEnum2`
+
+error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
+  --> $DIR/empty-match.rs:85:20
+   |
+LL | / enum NonEmptyEnum5 {
+LL | |     V1, V2, V3, V4, V5,
+LL | | }
+   | |_- `NonEmptyEnum5` defined here
+...
+LL |       match_no_arms!(NonEmptyEnum5::V1);
+   |                      ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyEnum5`
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/empty-match.rs:87:24
+   |
+LL |     match_guarded_arm!(0u8);
+   |                        ^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u8`
+
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
+  --> $DIR/empty-match.rs:88:24
+   |
+LL | struct NonEmptyStruct1;
+   | ----------------------- `NonEmptyStruct1` defined here
+...
+LL |     match_guarded_arm!(NonEmptyStruct1);
+   |                        ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyStruct1`
+
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
+  --> $DIR/empty-match.rs:89:24
+   |
+LL | struct NonEmptyStruct2(bool);
+   | ----------------------------- `NonEmptyStruct2` defined here
+...
+LL |     match_guarded_arm!(NonEmptyStruct2(true));
+   |                        ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyStruct2`
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
+  --> $DIR/empty-match.rs:90:24
+   |
+LL | / union NonEmptyUnion1 {
+LL | |     foo: (),
+LL | | }
+   | |_- `NonEmptyUnion1` defined here
+...
+LL |       match_guarded_arm!((NonEmptyUnion1 { foo: () }));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyUnion1`
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
+  --> $DIR/empty-match.rs:91:24
+   |
+LL | / union NonEmptyUnion2 {
+LL | |     foo: (),
+LL | |     bar: (),
+LL | | }
+   | |_- `NonEmptyUnion2` defined here
+...
+LL |       match_guarded_arm!((NonEmptyUnion2 { foo: () }));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyUnion2`
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
+  --> $DIR/empty-match.rs:92:24
+   |
+LL | / enum NonEmptyEnum1 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | | }
+   | |_- `NonEmptyEnum1` defined here
+...
+LL |       match_guarded_arm!(NonEmptyEnum1::Foo(true));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyEnum1`
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
+  --> $DIR/empty-match.rs:93:24
+   |
+LL | / enum NonEmptyEnum2 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | |     Bar,
+   | |     --- not covered
+LL | | }
+   | |_- `NonEmptyEnum2` defined here
+...
+LL |       match_guarded_arm!(NonEmptyEnum2::Foo(true));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyEnum2`
+
+error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
+  --> $DIR/empty-match.rs:94:24
+   |
+LL | / enum NonEmptyEnum5 {
+LL | |     V1, V2, V3, V4, V5,
+LL | | }
+   | |_- `NonEmptyEnum5` defined here
+...
+LL |       match_guarded_arm!(NonEmptyEnum5::V1);
+   |                          ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyEnum5`
+
+error: aborting due to 22 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/empty-match.normal.stderr b/src/test/ui/pattern/usefulness/empty-match.normal.stderr
new file mode 100644
index 0000000..b99386e
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/empty-match.normal.stderr
@@ -0,0 +1,261 @@
+error: unreachable pattern
+  --> $DIR/empty-match.rs:37:9
+   |
+LL |         _ => {},
+   |         ^
+   |
+note: the lint level is defined here
+  --> $DIR/empty-match.rs:8:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-match.rs:40:9
+   |
+LL |         _ if false => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-match.rs:47:9
+   |
+LL |         _ => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-match.rs:50:9
+   |
+LL |         _ if false => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-match.rs:57:9
+   |
+LL |         _ => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-match.rs:60:9
+   |
+LL |         _ if false => {},
+   |         ^
+
+error[E0004]: non-exhaustive patterns: type `u8` is non-empty
+  --> $DIR/empty-match.rs:78:20
+   |
+LL |     match_no_arms!(0u8);
+   |                    ^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u8`
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
+  --> $DIR/empty-match.rs:79:20
+   |
+LL | struct NonEmptyStruct1;
+   | ----------------------- `NonEmptyStruct1` defined here
+...
+LL |     match_no_arms!(NonEmptyStruct1);
+   |                    ^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyStruct1`
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
+  --> $DIR/empty-match.rs:80:20
+   |
+LL | struct NonEmptyStruct2(bool);
+   | ----------------------------- `NonEmptyStruct2` defined here
+...
+LL |     match_no_arms!(NonEmptyStruct2(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyStruct2`
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
+  --> $DIR/empty-match.rs:81:20
+   |
+LL | / union NonEmptyUnion1 {
+LL | |     foo: (),
+LL | | }
+   | |_- `NonEmptyUnion1` defined here
+...
+LL |       match_no_arms!((NonEmptyUnion1 { foo: () }));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyUnion1`
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
+  --> $DIR/empty-match.rs:82:20
+   |
+LL | / union NonEmptyUnion2 {
+LL | |     foo: (),
+LL | |     bar: (),
+LL | | }
+   | |_- `NonEmptyUnion2` defined here
+...
+LL |       match_no_arms!((NonEmptyUnion2 { foo: () }));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyUnion2`
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
+  --> $DIR/empty-match.rs:83:20
+   |
+LL | / enum NonEmptyEnum1 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | | }
+   | |_- `NonEmptyEnum1` defined here
+...
+LL |       match_no_arms!(NonEmptyEnum1::Foo(true));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyEnum1`
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
+  --> $DIR/empty-match.rs:84:20
+   |
+LL | / enum NonEmptyEnum2 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | |     Bar,
+   | |     --- not covered
+LL | | }
+   | |_- `NonEmptyEnum2` defined here
+...
+LL |       match_no_arms!(NonEmptyEnum2::Foo(true));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyEnum2`
+
+error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
+  --> $DIR/empty-match.rs:85:20
+   |
+LL | / enum NonEmptyEnum5 {
+LL | |     V1, V2, V3, V4, V5,
+LL | | }
+   | |_- `NonEmptyEnum5` defined here
+...
+LL |       match_no_arms!(NonEmptyEnum5::V1);
+   |                      ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyEnum5`
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/empty-match.rs:87:24
+   |
+LL |     match_guarded_arm!(0u8);
+   |                        ^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u8`
+
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
+  --> $DIR/empty-match.rs:88:24
+   |
+LL | struct NonEmptyStruct1;
+   | ----------------------- `NonEmptyStruct1` defined here
+...
+LL |     match_guarded_arm!(NonEmptyStruct1);
+   |                        ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyStruct1`
+
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
+  --> $DIR/empty-match.rs:89:24
+   |
+LL | struct NonEmptyStruct2(bool);
+   | ----------------------------- `NonEmptyStruct2` defined here
+...
+LL |     match_guarded_arm!(NonEmptyStruct2(true));
+   |                        ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyStruct2`
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
+  --> $DIR/empty-match.rs:90:24
+   |
+LL | / union NonEmptyUnion1 {
+LL | |     foo: (),
+LL | | }
+   | |_- `NonEmptyUnion1` defined here
+...
+LL |       match_guarded_arm!((NonEmptyUnion1 { foo: () }));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyUnion1`
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
+  --> $DIR/empty-match.rs:91:24
+   |
+LL | / union NonEmptyUnion2 {
+LL | |     foo: (),
+LL | |     bar: (),
+LL | | }
+   | |_- `NonEmptyUnion2` defined here
+...
+LL |       match_guarded_arm!((NonEmptyUnion2 { foo: () }));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyUnion2`
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
+  --> $DIR/empty-match.rs:92:24
+   |
+LL | / enum NonEmptyEnum1 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | | }
+   | |_- `NonEmptyEnum1` defined here
+...
+LL |       match_guarded_arm!(NonEmptyEnum1::Foo(true));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyEnum1`
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
+  --> $DIR/empty-match.rs:93:24
+   |
+LL | / enum NonEmptyEnum2 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | |     Bar,
+   | |     --- not covered
+LL | | }
+   | |_- `NonEmptyEnum2` defined here
+...
+LL |       match_guarded_arm!(NonEmptyEnum2::Foo(true));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyEnum2`
+
+error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
+  --> $DIR/empty-match.rs:94:24
+   |
+LL | / enum NonEmptyEnum5 {
+LL | |     V1, V2, V3, V4, V5,
+LL | | }
+   | |_- `NonEmptyEnum5` defined here
+...
+LL |       match_guarded_arm!(NonEmptyEnum5::V1);
+   |                          ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyEnum5`
+
+error: aborting due to 22 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/empty-match.rs b/src/test/ui/pattern/usefulness/empty-match.rs
new file mode 100644
index 0000000..8110ec0
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/empty-match.rs
@@ -0,0 +1,95 @@
+// aux-build:empty.rs
+// revisions: normal exhaustive_patterns
+//
+// This tests a match with no arms on various types.
+#![feature(never_type)]
+#![feature(never_type_fallback)]
+#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
+#![deny(unreachable_patterns)]
+
+extern crate empty;
+
+enum EmptyEnum {}
+
+struct NonEmptyStruct1;
+struct NonEmptyStruct2(bool);
+union NonEmptyUnion1 {
+    foo: (),
+}
+union NonEmptyUnion2 {
+    foo: (),
+    bar: (),
+}
+enum NonEmptyEnum1 {
+    Foo(bool),
+}
+enum NonEmptyEnum2 {
+    Foo(bool),
+    Bar,
+}
+enum NonEmptyEnum5 {
+    V1, V2, V3, V4, V5,
+}
+
+fn empty_enum(x: EmptyEnum) {
+    match x {} // ok
+    match x {
+        _ => {}, //~ ERROR unreachable pattern
+    }
+    match x {
+        _ if false => {}, //~ ERROR unreachable pattern
+    }
+}
+
+fn empty_foreign_enum(x: empty::EmptyForeignEnum) {
+    match x {} // ok
+    match x {
+        _ => {}, //~ ERROR unreachable pattern
+    }
+    match x {
+        _ if false => {}, //~ ERROR unreachable pattern
+    }
+}
+
+fn never(x: !) {
+    match x {} // ok
+    match x {
+        _ => {}, //~ ERROR unreachable pattern
+    }
+    match x {
+        _ if false => {}, //~ ERROR unreachable pattern
+    }
+}
+
+macro_rules! match_no_arms {
+    ($e:expr) => {
+        match $e {}
+    };
+}
+macro_rules! match_guarded_arm {
+    ($e:expr) => {
+        match $e {
+            _ if false => {}
+        }
+    };
+}
+
+fn main() {
+    match_no_arms!(0u8); //~ ERROR type `u8` is non-empty
+    match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty
+    match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty
+    match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty
+    match_no_arms!((NonEmptyUnion2 { foo: () })); //~ ERROR type `NonEmptyUnion2` is non-empty
+    match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `Foo(_)` not covered
+    match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `Foo(_)` and `Bar` not covered
+    match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `V1`, `V2`, `V3` and 2 more not covered
+
+    match_guarded_arm!(0u8); //~ ERROR `_` not covered
+    match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered
+    match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered
+    match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered
+    match_guarded_arm!((NonEmptyUnion2 { foo: () })); //~ ERROR `NonEmptyUnion2 { .. }` not covered
+    match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `Foo(_)` not covered
+    match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `Foo(_)` and `Bar` not covered
+    match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `V1`, `V2`, `V3` and 2 more not covered
+}
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.rs b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.rs
deleted file mode 100644
index 9292f22..0000000
--- a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-#![feature(exclusive_range_pattern)]
-
-macro_rules! m {
-    ($s:expr, $($t:tt)+) => {
-        match $s { $($t)+ => {} }
-    }
-}
-
-fn main() {
-    match 0usize {
-        //~^ ERROR non-exhaustive patterns
-        0 ..= usize::MAX => {}
-    }
-
-    match 0isize {
-        //~^ ERROR non-exhaustive patterns
-        isize::MIN ..= isize::MAX => {}
-    }
-
-    m!(0usize, 0..=usize::MAX);
-    //~^ ERROR non-exhaustive patterns
-    m!(0usize, 0..5 | 5..=usize::MAX);
-    //~^ ERROR non-exhaustive patterns
-    m!(0usize, 0..usize::MAX | usize::MAX);
-    //~^ ERROR non-exhaustive patterns
-    m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
-    //~^ ERROR non-exhaustive patterns
-
-    m!(0isize, isize::MIN..=isize::MAX);
-    //~^ ERROR non-exhaustive patterns
-    m!(0isize, isize::MIN..5 | 5..=isize::MAX);
-    //~^ ERROR non-exhaustive patterns
-    m!(0isize, isize::MIN..isize::MAX | isize::MAX);
-    //~^ ERROR non-exhaustive patterns
-    m!((0isize, true), (isize::MIN..5, true)
-        | (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false));
-    //~^^ ERROR non-exhaustive patterns
-
-    match 0isize {
-        //~^ ERROR non-exhaustive patterns
-        isize::MIN ..= -1 => {}
-        0 => {}
-        1 ..= isize::MAX => {}
-    }
-
-    match 7usize {}
-    //~^ ERROR non-exhaustive patterns
-}
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.stderr b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr
similarity index 89%
rename from src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.stderr
rename to src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr
index 0b3c651..2563293 100644
--- a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.stderr
+++ b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: type `usize` is non-empty
-  --> $DIR/pointer-sized-int-allow.rs:36:11
+  --> $DIR/pointer-sized-int.rs:48:11
    |
 LL |     match 7usize {}
    |           ^^^^^^
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.stderr b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr
similarity index 91%
rename from src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.stderr
rename to src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr
index 9d566b0..e8ac9f3 100644
--- a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.stderr
+++ b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/pointer-sized-int-deny.rs:10:11
+  --> $DIR/pointer-sized-int.rs:12:11
    |
 LL |     match 0usize {
    |           ^^^^^^ pattern `_` not covered
@@ -10,7 +10,7 @@
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/pointer-sized-int-deny.rs:15:11
+  --> $DIR/pointer-sized-int.rs:17:11
    |
 LL |     match 0isize {
    |           ^^^^^^ pattern `_` not covered
@@ -21,7 +21,7 @@
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/pointer-sized-int-deny.rs:20:8
+  --> $DIR/pointer-sized-int.rs:22:8
    |
 LL |     m!(0usize, 0..=usize::MAX);
    |        ^^^^^^ pattern `_` not covered
@@ -32,7 +32,7 @@
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/pointer-sized-int-deny.rs:22:8
+  --> $DIR/pointer-sized-int.rs:24:8
    |
 LL |     m!(0usize, 0..5 | 5..=usize::MAX);
    |        ^^^^^^ pattern `_` not covered
@@ -43,7 +43,7 @@
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/pointer-sized-int-deny.rs:24:8
+  --> $DIR/pointer-sized-int.rs:26:8
    |
 LL |     m!(0usize, 0..usize::MAX | usize::MAX);
    |        ^^^^^^ pattern `_` not covered
@@ -54,7 +54,7 @@
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
 
 error[E0004]: non-exhaustive patterns: `(_, _)` not covered
-  --> $DIR/pointer-sized-int-deny.rs:26:8
+  --> $DIR/pointer-sized-int.rs:28:8
    |
 LL |     m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
    |        ^^^^^^^^^^^^^^ pattern `(_, _)` not covered
@@ -63,7 +63,7 @@
    = note: the matched value is of type `(usize, bool)`
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/pointer-sized-int-deny.rs:29:8
+  --> $DIR/pointer-sized-int.rs:31:8
    |
 LL |     m!(0isize, isize::MIN..=isize::MAX);
    |        ^^^^^^ pattern `_` not covered
@@ -74,7 +74,7 @@
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/pointer-sized-int-deny.rs:31:8
+  --> $DIR/pointer-sized-int.rs:33:8
    |
 LL |     m!(0isize, isize::MIN..5 | 5..=isize::MAX);
    |        ^^^^^^ pattern `_` not covered
@@ -85,7 +85,7 @@
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/pointer-sized-int-deny.rs:33:8
+  --> $DIR/pointer-sized-int.rs:35:8
    |
 LL |     m!(0isize, isize::MIN..isize::MAX | isize::MAX);
    |        ^^^^^^ pattern `_` not covered
@@ -96,7 +96,7 @@
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
 
 error[E0004]: non-exhaustive patterns: `(_, _)` not covered
-  --> $DIR/pointer-sized-int-deny.rs:35:8
+  --> $DIR/pointer-sized-int.rs:37:8
    |
 LL |     m!((0isize, true), (isize::MIN..5, true)
    |        ^^^^^^^^^^^^^^ pattern `(_, _)` not covered
@@ -105,7 +105,7 @@
    = note: the matched value is of type `(isize, bool)`
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/pointer-sized-int-deny.rs:39:11
+  --> $DIR/pointer-sized-int.rs:41:11
    |
 LL |     match 0isize {
    |           ^^^^^^ pattern `_` not covered
@@ -116,7 +116,7 @@
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
 
 error[E0004]: non-exhaustive patterns: type `usize` is non-empty
-  --> $DIR/pointer-sized-int-deny.rs:46:11
+  --> $DIR/pointer-sized-int.rs:48:11
    |
 LL |     match 7usize {}
    |           ^^^^^^
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.rs b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs
similarity index 60%
rename from src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.rs
rename to src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs
index 6173053..1ed18c2 100644
--- a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.rs
+++ b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs
@@ -1,5 +1,6 @@
-#![feature(precise_pointer_size_matching)]
+// revisions: allow deny
 #![feature(exclusive_range_pattern)]
+#![cfg_attr(allow, feature(precise_pointer_size_matching))]
 
 macro_rules! m {
     ($s:expr, $($t:tt)+) => {
@@ -9,25 +10,36 @@
 
 fn main() {
     match 0usize {
+        //[deny]~^ ERROR non-exhaustive patterns
         0 ..= usize::MAX => {}
     }
 
     match 0isize {
+        //[deny]~^ ERROR non-exhaustive patterns
         isize::MIN ..= isize::MAX => {}
     }
 
     m!(0usize, 0..=usize::MAX);
+    //[deny]~^ ERROR non-exhaustive patterns
     m!(0usize, 0..5 | 5..=usize::MAX);
+    //[deny]~^ ERROR non-exhaustive patterns
     m!(0usize, 0..usize::MAX | usize::MAX);
+    //[deny]~^ ERROR non-exhaustive patterns
     m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
+    //[deny]~^ ERROR non-exhaustive patterns
 
     m!(0isize, isize::MIN..=isize::MAX);
+    //[deny]~^ ERROR non-exhaustive patterns
     m!(0isize, isize::MIN..5 | 5..=isize::MAX);
+    //[deny]~^ ERROR non-exhaustive patterns
     m!(0isize, isize::MIN..isize::MAX | isize::MAX);
+    //[deny]~^ ERROR non-exhaustive patterns
     m!((0isize, true), (isize::MIN..5, true)
         | (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false));
+    //[deny]~^^ ERROR non-exhaustive patterns
 
     match 0isize {
+        //[deny]~^ ERROR non-exhaustive patterns
         isize::MIN ..= -1 => {}
         0 => {}
         1 ..= isize::MAX => {}
diff --git a/src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs b/src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs
new file mode 100644
index 0000000..6c5a331
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs
@@ -0,0 +1,11 @@
+enum A {}
+    //~^ NOTE `A` defined here
+
+fn f(a: &A) {
+    match a {}
+    //~^ ERROR non-exhaustive patterns: type `&A` is non-empty
+    //~| NOTE the matched value is of type `&A`
+    //~| NOTE references are always considered inhabited
+}
+
+fn main() {}
diff --git a/src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr b/src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr
new file mode 100644
index 0000000..e992632
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr
@@ -0,0 +1,16 @@
+error[E0004]: non-exhaustive patterns: type `&A` is non-empty
+  --> $DIR/issue-78123-non-exhaustive-reference.rs:5:11
+   |
+LL | enum A {}
+   | --------- `A` defined here
+...
+LL |     match a {}
+   |           ^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `&A`
+   = note: references are always considered inhabited
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs
deleted file mode 100644
index c5c3a21..0000000
--- a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs
+++ /dev/null
@@ -1,118 +0,0 @@
-// aux-build:empty.rs
-#![feature(never_type)]
-#![feature(never_type_fallback)]
-#![feature(exhaustive_patterns)]
-#![deny(unreachable_patterns)]
-
-extern crate empty;
-
-enum EmptyEnum {}
-
-struct NonEmptyStruct(bool); //~ `NonEmptyStruct` defined here
-union NonEmptyUnion1 { //~ `NonEmptyUnion1` defined here
-    foo: (),
-}
-union NonEmptyUnion2 { //~ `NonEmptyUnion2` defined here
-    foo: (),
-    bar: (),
-}
-enum NonEmptyEnum1 { //~ `NonEmptyEnum1` defined here
-    Foo(bool),
-    //~^ not covered
-    //~| not covered
-}
-enum NonEmptyEnum2 { //~ `NonEmptyEnum2` defined here
-    Foo(bool),
-    //~^ not covered
-    //~| not covered
-    Bar,
-    //~^ not covered
-    //~| not covered
-}
-enum NonEmptyEnum5 { //~ `NonEmptyEnum5` defined here
-    V1, V2, V3, V4, V5,
-}
-
-macro_rules! match_empty {
-    ($e:expr) => {
-        match $e {}
-    };
-}
-macro_rules! match_false {
-    ($e:expr) => {
-        match $e {
-            _ if false => {}
-        }
-    };
-}
-
-fn empty_enum(x: EmptyEnum) {
-    match x {} // ok
-    match x {
-        _ => {}, //~ ERROR unreachable pattern
-    }
-    match x {
-        _ if false => {}, //~ ERROR unreachable pattern
-    }
-}
-
-fn empty_foreign_enum(x: empty::EmptyForeignEnum) {
-    match x {} // ok
-    match x {
-        _ => {}, //~ ERROR unreachable pattern
-    }
-    match x {
-        _ if false => {}, //~ ERROR unreachable pattern
-    }
-}
-
-fn never(x: !) {
-    match x {} // ok
-    match x {
-        _ => {}, //~ ERROR unreachable pattern
-    }
-    match x {
-        _ if false => {}, //~ ERROR unreachable pattern
-    }
-}
-
-fn main() {
-    match None::<!> {
-        None => {}
-        Some(_) => {} //~ ERROR unreachable pattern
-    }
-    match None::<EmptyEnum> {
-        None => {}
-        Some(_) => {} //~ ERROR unreachable pattern
-    }
-
-    match_empty!(0u8);
-    //~^ ERROR type `u8` is non-empty
-    match_empty!(NonEmptyStruct(true));
-    //~^ ERROR type `NonEmptyStruct` is non-empty
-    match_empty!((NonEmptyUnion1 { foo: () }));
-    //~^ ERROR type `NonEmptyUnion1` is non-empty
-    match_empty!((NonEmptyUnion2 { foo: () }));
-    //~^ ERROR type `NonEmptyUnion2` is non-empty
-    match_empty!(NonEmptyEnum1::Foo(true));
-    //~^ ERROR `Foo(_)` not covered
-    match_empty!(NonEmptyEnum2::Foo(true));
-    //~^ ERROR `Foo(_)` and `Bar` not covered
-    match_empty!(NonEmptyEnum5::V1);
-    //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered
-
-    match_false!(0u8);
-    //~^ ERROR `_` not covered
-    match_false!(NonEmptyStruct(true));
-    //~^ ERROR `NonEmptyStruct(_)` not covered
-    match_false!((NonEmptyUnion1 { foo: () }));
-    //~^ ERROR `NonEmptyUnion1 { .. }` not covered
-    match_false!((NonEmptyUnion2 { foo: () }));
-    //~^ ERROR `NonEmptyUnion2 { .. }` not covered
-    match_false!(NonEmptyEnum1::Foo(true));
-    //~^ ERROR `Foo(_)` not covered
-    match_false!(NonEmptyEnum2::Foo(true));
-    //~^ ERROR `Foo(_)` and `Bar` not covered
-    match_false!(NonEmptyEnum5::V1);
-    //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered
-}
diff --git a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr
deleted file mode 100644
index 9d8b5f3..0000000
--- a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr
+++ /dev/null
@@ -1,261 +0,0 @@
-error: unreachable pattern
-  --> $DIR/match-empty-exhaustive_patterns.rs:52:9
-   |
-LL |         _ => {},
-   |         ^
-   |
-note: the lint level is defined here
-  --> $DIR/match-empty-exhaustive_patterns.rs:5:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/match-empty-exhaustive_patterns.rs:55:9
-   |
-LL |         _ if false => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/match-empty-exhaustive_patterns.rs:62:9
-   |
-LL |         _ => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/match-empty-exhaustive_patterns.rs:65:9
-   |
-LL |         _ if false => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/match-empty-exhaustive_patterns.rs:72:9
-   |
-LL |         _ => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/match-empty-exhaustive_patterns.rs:75:9
-   |
-LL |         _ if false => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/match-empty-exhaustive_patterns.rs:82:9
-   |
-LL |         Some(_) => {}
-   |         ^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/match-empty-exhaustive_patterns.rs:86:9
-   |
-LL |         Some(_) => {}
-   |         ^^^^^^^
-
-error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/match-empty-exhaustive_patterns.rs:89:18
-   |
-LL |     match_empty!(0u8);
-   |                  ^^^
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u8`
-
-error[E0004]: non-exhaustive patterns: type `NonEmptyStruct` is non-empty
-  --> $DIR/match-empty-exhaustive_patterns.rs:91:18
-   |
-LL | struct NonEmptyStruct(bool);
-   | ---------------------------- `NonEmptyStruct` defined here
-...
-LL |     match_empty!(NonEmptyStruct(true));
-   |                  ^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyStruct`
-
-error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
-  --> $DIR/match-empty-exhaustive_patterns.rs:93:18
-   |
-LL | / union NonEmptyUnion1 {
-LL | |     foo: (),
-LL | | }
-   | |_- `NonEmptyUnion1` defined here
-...
-LL |       match_empty!((NonEmptyUnion1 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyUnion1`
-
-error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
-  --> $DIR/match-empty-exhaustive_patterns.rs:95:18
-   |
-LL | / union NonEmptyUnion2 {
-LL | |     foo: (),
-LL | |     bar: (),
-LL | | }
-   | |_- `NonEmptyUnion2` defined here
-...
-LL |       match_empty!((NonEmptyUnion2 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyUnion2`
-
-error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:97:18
-   |
-LL | / enum NonEmptyEnum1 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | |
-LL | |
-LL | | }
-   | |_- `NonEmptyEnum1` defined here
-...
-LL |       match_empty!(NonEmptyEnum1::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyEnum1`
-
-error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:99:18
-   |
-LL | / enum NonEmptyEnum2 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | |
-LL | |
-LL | |     Bar,
-   | |     --- not covered
-LL | |
-LL | |
-LL | | }
-   | |_- `NonEmptyEnum2` defined here
-...
-LL |       match_empty!(NonEmptyEnum2::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyEnum2`
-
-error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:101:18
-   |
-LL | / enum NonEmptyEnum5 {
-LL | |     V1, V2, V3, V4, V5,
-LL | | }
-   | |_- `NonEmptyEnum5` defined here
-...
-LL |       match_empty!(NonEmptyEnum5::V1);
-   |                    ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyEnum5`
-
-error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:104:18
-   |
-LL |     match_false!(0u8);
-   |                  ^^^ pattern `_` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u8`
-
-error[E0004]: non-exhaustive patterns: `NonEmptyStruct(_)` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:106:18
-   |
-LL | struct NonEmptyStruct(bool);
-   | ---------------------------- `NonEmptyStruct` defined here
-...
-LL |     match_false!(NonEmptyStruct(true));
-   |                  ^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct(_)` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyStruct`
-
-error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:108:18
-   |
-LL | / union NonEmptyUnion1 {
-LL | |     foo: (),
-LL | | }
-   | |_- `NonEmptyUnion1` defined here
-...
-LL |       match_false!((NonEmptyUnion1 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyUnion1`
-
-error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:110:18
-   |
-LL | / union NonEmptyUnion2 {
-LL | |     foo: (),
-LL | |     bar: (),
-LL | | }
-   | |_- `NonEmptyUnion2` defined here
-...
-LL |       match_false!((NonEmptyUnion2 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyUnion2`
-
-error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:112:18
-   |
-LL | / enum NonEmptyEnum1 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | |
-LL | |
-LL | | }
-   | |_- `NonEmptyEnum1` defined here
-...
-LL |       match_false!(NonEmptyEnum1::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyEnum1`
-
-error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:114:18
-   |
-LL | / enum NonEmptyEnum2 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | |
-LL | |
-LL | |     Bar,
-   | |     --- not covered
-LL | |
-LL | |
-LL | | }
-   | |_- `NonEmptyEnum2` defined here
-...
-LL |       match_false!(NonEmptyEnum2::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyEnum2`
-
-error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:116:18
-   |
-LL | / enum NonEmptyEnum5 {
-LL | |     V1, V2, V3, V4, V5,
-LL | | }
-   | |_- `NonEmptyEnum5` defined here
-...
-LL |       match_false!(NonEmptyEnum5::V1);
-   |                    ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyEnum5`
-
-error: aborting due to 22 previous errors
-
-For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/match-empty.rs b/src/test/ui/pattern/usefulness/match-empty.rs
deleted file mode 100644
index 10ea2a1..0000000
--- a/src/test/ui/pattern/usefulness/match-empty.rs
+++ /dev/null
@@ -1,118 +0,0 @@
-// aux-build:empty.rs
-#![feature(never_type)]
-#![feature(never_type_fallback)]
-#![deny(unreachable_patterns)]
-
-extern crate empty;
-
-enum EmptyEnum {}
-
-struct NonEmptyStruct(bool); //~ `NonEmptyStruct` defined here
-union NonEmptyUnion1 { //~ `NonEmptyUnion1` defined here
-    foo: (),
-}
-union NonEmptyUnion2 { //~ `NonEmptyUnion2` defined here
-    foo: (),
-    bar: (),
-}
-enum NonEmptyEnum1 { //~ `NonEmptyEnum1` defined here
-    Foo(bool),
-    //~^ not covered
-    //~| not covered
-}
-enum NonEmptyEnum2 { //~ `NonEmptyEnum2` defined here
-    Foo(bool),
-    //~^ not covered
-    //~| not covered
-    Bar,
-    //~^ not covered
-    //~| not covered
-}
-enum NonEmptyEnum5 { //~ `NonEmptyEnum5` defined here
-    V1, V2, V3, V4, V5,
-}
-
-macro_rules! match_empty {
-    ($e:expr) => {
-        match $e {}
-    };
-}
-macro_rules! match_false {
-    ($e:expr) => {
-        match $e {
-            _ if false => {}
-        }
-    };
-}
-
-fn empty_enum(x: EmptyEnum) {
-    match x {} // ok
-    match x {
-        _ => {}, //~ ERROR unreachable pattern
-    }
-    match x {
-        _ if false => {}, //~ ERROR unreachable pattern
-    }
-}
-
-fn empty_foreign_enum(x: empty::EmptyForeignEnum) {
-    match x {} // ok
-    match x {
-        _ => {}, //~ ERROR unreachable pattern
-    }
-    match x {
-        _ if false => {}, //~ ERROR unreachable pattern
-    }
-}
-
-fn never(x: !) {
-    match x {} // ok
-    match x {
-        _ => {}, //~ ERROR unreachable pattern
-    }
-    match x {
-        _ if false => {}, //~ ERROR unreachable pattern
-    }
-}
-
-fn main() {
-    // `exhaustive_patterns` is not on, so uninhabited branches are not detected as unreachable.
-    match None::<!> {
-        None => {}
-        Some(_) => {}
-    }
-    match None::<EmptyEnum> {
-        None => {}
-        Some(_) => {}
-    }
-
-    match_empty!(0u8);
-    //~^ ERROR type `u8` is non-empty
-    match_empty!(NonEmptyStruct(true));
-    //~^ ERROR type `NonEmptyStruct` is non-empty
-    match_empty!((NonEmptyUnion1 { foo: () }));
-    //~^ ERROR type `NonEmptyUnion1` is non-empty
-    match_empty!((NonEmptyUnion2 { foo: () }));
-    //~^ ERROR type `NonEmptyUnion2` is non-empty
-    match_empty!(NonEmptyEnum1::Foo(true));
-    //~^ ERROR `Foo(_)` not covered
-    match_empty!(NonEmptyEnum2::Foo(true));
-    //~^ ERROR `Foo(_)` and `Bar` not covered
-    match_empty!(NonEmptyEnum5::V1);
-    //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered
-
-    match_false!(0u8);
-    //~^ ERROR `_` not covered
-    match_false!(NonEmptyStruct(true));
-    //~^ ERROR `NonEmptyStruct(_)` not covered
-    match_false!((NonEmptyUnion1 { foo: () }));
-    //~^ ERROR `NonEmptyUnion1 { .. }` not covered
-    match_false!((NonEmptyUnion2 { foo: () }));
-    //~^ ERROR `NonEmptyUnion2 { .. }` not covered
-    match_false!(NonEmptyEnum1::Foo(true));
-    //~^ ERROR `Foo(_)` not covered
-    match_false!(NonEmptyEnum2::Foo(true));
-    //~^ ERROR `Foo(_)` and `Bar` not covered
-    match_false!(NonEmptyEnum5::V1);
-    //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered
-}
diff --git a/src/test/ui/pattern/usefulness/match-empty.stderr b/src/test/ui/pattern/usefulness/match-empty.stderr
deleted file mode 100644
index 6065c55..0000000
--- a/src/test/ui/pattern/usefulness/match-empty.stderr
+++ /dev/null
@@ -1,249 +0,0 @@
-error: unreachable pattern
-  --> $DIR/match-empty.rs:51:9
-   |
-LL |         _ => {},
-   |         ^
-   |
-note: the lint level is defined here
-  --> $DIR/match-empty.rs:4:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/match-empty.rs:54:9
-   |
-LL |         _ if false => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/match-empty.rs:61:9
-   |
-LL |         _ => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/match-empty.rs:64:9
-   |
-LL |         _ if false => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/match-empty.rs:71:9
-   |
-LL |         _ => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/match-empty.rs:74:9
-   |
-LL |         _ if false => {},
-   |         ^
-
-error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/match-empty.rs:89:18
-   |
-LL |     match_empty!(0u8);
-   |                  ^^^
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u8`
-
-error[E0004]: non-exhaustive patterns: type `NonEmptyStruct` is non-empty
-  --> $DIR/match-empty.rs:91:18
-   |
-LL | struct NonEmptyStruct(bool);
-   | ---------------------------- `NonEmptyStruct` defined here
-...
-LL |     match_empty!(NonEmptyStruct(true));
-   |                  ^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyStruct`
-
-error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
-  --> $DIR/match-empty.rs:93:18
-   |
-LL | / union NonEmptyUnion1 {
-LL | |     foo: (),
-LL | | }
-   | |_- `NonEmptyUnion1` defined here
-...
-LL |       match_empty!((NonEmptyUnion1 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyUnion1`
-
-error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
-  --> $DIR/match-empty.rs:95:18
-   |
-LL | / union NonEmptyUnion2 {
-LL | |     foo: (),
-LL | |     bar: (),
-LL | | }
-   | |_- `NonEmptyUnion2` defined here
-...
-LL |       match_empty!((NonEmptyUnion2 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyUnion2`
-
-error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
-  --> $DIR/match-empty.rs:97:18
-   |
-LL | / enum NonEmptyEnum1 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | |
-LL | |
-LL | | }
-   | |_- `NonEmptyEnum1` defined here
-...
-LL |       match_empty!(NonEmptyEnum1::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyEnum1`
-
-error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
-  --> $DIR/match-empty.rs:99:18
-   |
-LL | / enum NonEmptyEnum2 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | |
-LL | |
-LL | |     Bar,
-   | |     --- not covered
-LL | |
-LL | |
-LL | | }
-   | |_- `NonEmptyEnum2` defined here
-...
-LL |       match_empty!(NonEmptyEnum2::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyEnum2`
-
-error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
-  --> $DIR/match-empty.rs:101:18
-   |
-LL | / enum NonEmptyEnum5 {
-LL | |     V1, V2, V3, V4, V5,
-LL | | }
-   | |_- `NonEmptyEnum5` defined here
-...
-LL |       match_empty!(NonEmptyEnum5::V1);
-   |                    ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyEnum5`
-
-error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/match-empty.rs:104:18
-   |
-LL |     match_false!(0u8);
-   |                  ^^^ pattern `_` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u8`
-
-error[E0004]: non-exhaustive patterns: `NonEmptyStruct(_)` not covered
-  --> $DIR/match-empty.rs:106:18
-   |
-LL | struct NonEmptyStruct(bool);
-   | ---------------------------- `NonEmptyStruct` defined here
-...
-LL |     match_false!(NonEmptyStruct(true));
-   |                  ^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct(_)` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyStruct`
-
-error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
-  --> $DIR/match-empty.rs:108:18
-   |
-LL | / union NonEmptyUnion1 {
-LL | |     foo: (),
-LL | | }
-   | |_- `NonEmptyUnion1` defined here
-...
-LL |       match_false!((NonEmptyUnion1 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyUnion1`
-
-error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
-  --> $DIR/match-empty.rs:110:18
-   |
-LL | / union NonEmptyUnion2 {
-LL | |     foo: (),
-LL | |     bar: (),
-LL | | }
-   | |_- `NonEmptyUnion2` defined here
-...
-LL |       match_false!((NonEmptyUnion2 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyUnion2`
-
-error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
-  --> $DIR/match-empty.rs:112:18
-   |
-LL | / enum NonEmptyEnum1 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | |
-LL | |
-LL | | }
-   | |_- `NonEmptyEnum1` defined here
-...
-LL |       match_false!(NonEmptyEnum1::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyEnum1`
-
-error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
-  --> $DIR/match-empty.rs:114:18
-   |
-LL | / enum NonEmptyEnum2 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | |
-LL | |
-LL | |     Bar,
-   | |     --- not covered
-LL | |
-LL | |
-LL | | }
-   | |_- `NonEmptyEnum2` defined here
-...
-LL |       match_false!(NonEmptyEnum2::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyEnum2`
-
-error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
-  --> $DIR/match-empty.rs:116:18
-   |
-LL | / enum NonEmptyEnum5 {
-LL | |     V1, V2, V3, V4, V5,
-LL | | }
-   | |_- `NonEmptyEnum5` defined here
-...
-LL |       match_false!(NonEmptyEnum5::V1);
-   |                    ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyEnum5`
-
-error: aborting due to 20 previous errors
-
-For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/uninhabited.rs b/src/test/ui/pattern/usefulness/uninhabited.rs
new file mode 100644
index 0000000..77cd0f4
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/uninhabited.rs
@@ -0,0 +1,143 @@
+// check-pass
+// aux-build:empty.rs
+//
+// This tests plays with matching and uninhabited types. This also serves as a test for the
+// `tcx.is_ty_uninhabited_from()` function.
+#![feature(never_type)]
+#![feature(never_type_fallback)]
+#![feature(exhaustive_patterns)]
+#![deny(unreachable_patterns)]
+
+macro_rules! assert_empty {
+    ($ty:ty) => {
+        const _: () = {
+            fn assert_empty(x: $ty) {
+                match x {}
+                match Some(x) {
+                    None => {}
+                }
+            }
+        };
+    };
+}
+macro_rules! assert_non_empty {
+    ($ty:ty) => {
+        const _: () = {
+            fn assert_non_empty(x: $ty) {
+                match x {
+                    _ => {}
+                }
+                match Some(x) {
+                    None => {}
+                    Some(_) => {}
+                }
+            }
+        };
+    };
+}
+
+extern crate empty;
+assert_empty!(empty::EmptyForeignEnum);
+assert_empty!(empty::VisiblyUninhabitedForeignStruct);
+assert_non_empty!(empty::SecretlyUninhabitedForeignStruct);
+
+enum Void {}
+assert_empty!(Void);
+
+enum Enum2 {
+    Foo(Void),
+    Bar(!),
+}
+assert_empty!(Enum2);
+
+enum Enum3 {
+    Foo(Void),
+    Bar {
+        x: u64,
+        y: !,
+    },
+}
+assert_empty!(Enum3);
+
+enum Enum4 {
+    Foo(u64),
+    Bar(!),
+}
+assert_non_empty!(Enum4);
+
+struct Struct1(empty::EmptyForeignEnum);
+assert_empty!(Struct1);
+
+struct Struct2 {
+    x: u64,
+    y: !,
+}
+assert_empty!(Struct2);
+
+union Union {
+    foo: !,
+}
+assert_non_empty!(Union);
+
+assert_empty!((!, String));
+
+assert_non_empty!(&'static !);
+assert_non_empty!(&'static Struct1);
+assert_non_empty!(&'static &'static &'static !);
+
+assert_empty!([!; 1]);
+assert_empty!([Void; 2]);
+assert_non_empty!([!; 0]);
+assert_non_empty!(&'static [!]);
+
+mod visibility {
+    /// This struct can only be seen to be inhabited in modules `b`, `c` or `d`, because otherwise
+    /// the uninhabitedness of both `SecretlyUninhabited` structs is hidden.
+    struct SometimesEmptyStruct {
+        x: a::b::SecretlyUninhabited,
+        y: c::AlsoSecretlyUninhabited,
+    }
+
+    /// This enum can only be seen to be inhabited in module `d`.
+    enum SometimesEmptyEnum {
+        X(c::AlsoSecretlyUninhabited),
+        Y(c::d::VerySecretlyUninhabited),
+    }
+
+    mod a {
+        use super::*;
+        pub mod b {
+            use super::*;
+            pub struct SecretlyUninhabited {
+                _priv: !,
+            }
+            assert_empty!(SometimesEmptyStruct);
+        }
+
+        assert_non_empty!(SometimesEmptyStruct);
+        assert_non_empty!(SometimesEmptyEnum);
+    }
+
+    mod c {
+        use super::*;
+        pub struct AlsoSecretlyUninhabited {
+            _priv: ::Struct1,
+        }
+        assert_empty!(SometimesEmptyStruct);
+        assert_non_empty!(SometimesEmptyEnum);
+
+        pub mod d {
+            use super::*;
+            pub struct VerySecretlyUninhabited {
+                _priv: !,
+            }
+            assert_empty!(SometimesEmptyStruct);
+            assert_empty!(SometimesEmptyEnum);
+        }
+    }
+
+    assert_non_empty!(SometimesEmptyStruct);
+    assert_non_empty!(SometimesEmptyEnum);
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-29161.rs b/src/test/ui/privacy/issue-29161.rs
similarity index 100%
rename from src/test/ui/issues/issue-29161.rs
rename to src/test/ui/privacy/issue-29161.rs
diff --git a/src/test/ui/issues/issue-29161.stderr b/src/test/ui/privacy/issue-29161.stderr
similarity index 100%
rename from src/test/ui/issues/issue-29161.stderr
rename to src/test/ui/privacy/issue-29161.stderr
diff --git a/src/test/ui/issues/issue-30079.rs b/src/test/ui/privacy/issue-30079.rs
similarity index 100%
rename from src/test/ui/issues/issue-30079.rs
rename to src/test/ui/privacy/issue-30079.rs
diff --git a/src/test/ui/issues/issue-30079.stderr b/src/test/ui/privacy/issue-30079.stderr
similarity index 100%
rename from src/test/ui/issues/issue-30079.stderr
rename to src/test/ui/privacy/issue-30079.stderr
diff --git a/src/test/ui/priv-in-bad-locations.rs b/src/test/ui/privacy/priv-in-bad-locations.rs
similarity index 81%
rename from src/test/ui/priv-in-bad-locations.rs
rename to src/test/ui/privacy/priv-in-bad-locations.rs
index b9f5d4c..76af8c6 100644
--- a/src/test/ui/priv-in-bad-locations.rs
+++ b/src/test/ui/privacy/priv-in-bad-locations.rs
@@ -1,4 +1,4 @@
-pub extern { //~ ERROR unnecessary visibility qualifier
+pub extern "C" { //~ ERROR unnecessary visibility qualifier
     pub fn bar();
 }
 
diff --git a/src/test/ui/priv-in-bad-locations.stderr b/src/test/ui/privacy/priv-in-bad-locations.stderr
similarity index 97%
rename from src/test/ui/priv-in-bad-locations.stderr
rename to src/test/ui/privacy/priv-in-bad-locations.stderr
index 713568f..75bd2fe 100644
--- a/src/test/ui/priv-in-bad-locations.stderr
+++ b/src/test/ui/privacy/priv-in-bad-locations.stderr
@@ -1,7 +1,7 @@
 error[E0449]: unnecessary visibility qualifier
   --> $DIR/priv-in-bad-locations.rs:1:1
    |
-LL | pub extern {
+LL | pub extern "C" {
    | ^^^ `pub` not permitted here because it's implied
    |
    = note: place qualifiers on individual foreign items instead
diff --git a/src/test/ui/privacy/privacy1.rs b/src/test/ui/privacy/privacy1.rs
index e28fd13..3c9fa98 100644
--- a/src/test/ui/privacy/privacy1.rs
+++ b/src/test/ui/privacy/privacy1.rs
@@ -61,7 +61,7 @@
         pub fn bar() {}
     }
 
-    extern {
+    extern "C" {
         fn epriv();
         pub fn epub();
     }
diff --git a/src/test/ui/privacy/private-in-public-warn.rs b/src/test/ui/privacy/private-in-public-warn.rs
index 1c8706d..09afa04 100644
--- a/src/test/ui/privacy/private-in-public-warn.rs
+++ b/src/test/ui/privacy/private-in-public-warn.rs
@@ -29,7 +29,7 @@
         fn f2() -> Priv { panic!() } //~ ERROR private type `types::Priv` in public interface
         //~^ WARNING hard error
     }
-    extern {
+    extern "C" {
         pub static ES: Priv; //~ ERROR private type `types::Priv` in public interface
         //~^ WARNING hard error
         pub fn ef1(arg: Priv); //~ ERROR private type `types::Priv` in public interface
diff --git a/src/test/ui/privacy/pub-extern-privacy.rs b/src/test/ui/privacy/pub-extern-privacy.rs
index 832acfb..dbbbe4e 100644
--- a/src/test/ui/privacy/pub-extern-privacy.rs
+++ b/src/test/ui/privacy/pub-extern-privacy.rs
@@ -6,7 +6,7 @@
 use std::mem::transmute;
 
 mod a {
-    extern {
+    extern "C" {
         pub fn free(x: *const u8);
     }
 }
diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs
index 142efb3..5f45f68 100644
--- a/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs
+++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs
@@ -1,5 +1,5 @@
+// edition:2018
 // aux-build:builtin-attrs.rs
-
 #![feature(decl_macro)] //~ ERROR `feature` is ambiguous
 
 extern crate builtin_attrs;
@@ -31,3 +31,7 @@
     Bench;
     NonExistent; //~ ERROR cannot find value `NonExistent` in this scope
 }
+
+use deny as allow;
+#[allow(unused)] //~ ERROR `allow` is ambiguous (built-in attribute vs any other name)
+fn builtin_renamed() {}
diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr
index 276ee1c..dfd60dc 100644
--- a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr
+++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr
@@ -60,6 +60,20 @@
    |     ^^^^^^^^^^^^^^^^
    = help: use `crate::repr` to refer to this attribute macro unambiguously
 
+error[E0659]: `allow` is ambiguous (built-in attribute vs any other name)
+  --> $DIR/ambiguous-builtin-attrs.rs:36:3
+   |
+LL | #[allow(unused)]
+   |   ^^^^^ ambiguous name
+   |
+   = note: `allow` could refer to a built-in attribute
+note: `allow` could also refer to the built-in attribute imported here
+  --> $DIR/ambiguous-builtin-attrs.rs:35:5
+   |
+LL | use deny as allow;
+   |     ^^^^^^^^^^^^^
+   = help: use `crate::allow` to refer to this built-in attribute unambiguously
+
 error[E0659]: `feature` is ambiguous (built-in attribute vs any other name)
   --> $DIR/ambiguous-builtin-attrs.rs:3:4
    |
@@ -80,7 +94,7 @@
 LL | fn non_macro_expanded_location<#[repr(C)] T>() {
    |                                       ^   - not a struct, enum, or union
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0425, E0517, E0659.
 For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout
index 4c08102..5f51368 100644
--- a/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout
+++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout
@@ -1211,141 +1211,141 @@
     Punct {
         ch: '#',
         spacing: Alone,
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 ident: "allow",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Group {
                 delimiter: Parenthesis,
                 stream: TokenStream [
                     Ident {
                         ident: "dead_code",
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                 ],
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
         ],
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Punct {
         ch: '#',
         spacing: Alone,
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 ident: "print_helper",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Group {
                 delimiter: Parenthesis,
                 stream: TokenStream [
                     Ident {
                         ident: "b",
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                 ],
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
         ],
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Punct {
         ch: '#',
         spacing: Alone,
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 ident: "print_helper",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Group {
                 delimiter: Parenthesis,
                 stream: TokenStream [
                     Ident {
                         ident: "a",
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                 ],
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
         ],
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Ident {
         ident: "struct",
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Ident {
         ident: "Foo",
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Punct {
         ch: '<',
         spacing: Alone,
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Ident {
         ident: "B",
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Punct {
         ch: '>',
         spacing: Alone,
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Group {
         delimiter: Brace,
         stream: TokenStream [
             Ident {
                 ident: "second",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Ident {
                 ident: "bool",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Punct {
                 ch: ',',
                 spacing: Alone,
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Ident {
                 ident: "third",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Group {
                 delimiter: Bracket,
                 stream: TokenStream [
                     Ident {
                         ident: "u8",
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                     Punct {
                         ch: ';',
                         spacing: Alone,
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                     Group {
                         delimiter: Brace,
@@ -1353,58 +1353,58 @@
                             Punct {
                                 ch: '#',
                                 spacing: Alone,
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Bracket,
                                 stream: TokenStream [
                                     Ident {
                                         ident: "cfg",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Parenthesis,
                                         stream: TokenStream [
                                             Ident {
                                                 ident: "not",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Group {
                                                 delimiter: Parenthesis,
                                                 stream: TokenStream [
                                                     Ident {
                                                         ident: "FALSE",
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                 ],
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                         ],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "struct",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "Inner",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Punct {
                                 ch: ';',
                                 spacing: Alone,
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "match",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "true",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Brace,
@@ -1412,146 +1412,146 @@
                                     Punct {
                                         ch: '#',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Bracket,
                                         stream: TokenStream [
                                             Ident {
                                                 ident: "allow",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Group {
                                                 delimiter: Parenthesis,
                                                 stream: TokenStream [
                                                     Ident {
                                                         ident: "warnings",
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                 ],
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                         ],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Ident {
                                         ident: "false",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: '=',
                                         spacing: Joint,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: '>',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Brace,
                                         stream: TokenStream [],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Ident {
                                         ident: "_",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: '=',
                                         spacing: Joint,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: '>',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Brace,
                                         stream: TokenStream [],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Punct {
                                 ch: ';',
                                 spacing: Alone,
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Punct {
                                 ch: '#',
                                 spacing: Alone,
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Bracket,
                                 stream: TokenStream [
                                     Ident {
                                         ident: "print_helper",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Parenthesis,
                                         stream: TokenStream [
                                             Ident {
                                                 ident: "c",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                         ],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Punct {
                                 ch: '#',
                                 spacing: Alone,
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Bracket,
                                 stream: TokenStream [
                                     Ident {
                                         ident: "cfg",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Parenthesis,
                                         stream: TokenStream [
                                             Ident {
                                                 ident: "not",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Group {
                                                 delimiter: Parenthesis,
                                                 stream: TokenStream [
                                                     Ident {
                                                         ident: "FALSE",
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                 ],
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                         ],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "fn",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "kept_fn",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Parenthesis,
                                 stream: TokenStream [],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Brace,
@@ -1559,82 +1559,82 @@
                                     Punct {
                                         ch: '#',
                                         spacing: Joint,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: '!',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Bracket,
                                         stream: TokenStream [
                                             Ident {
                                                 ident: "cfg",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Group {
                                                 delimiter: Parenthesis,
                                                 stream: TokenStream [
                                                     Ident {
                                                         ident: "not",
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                     Group {
                                                         delimiter: Parenthesis,
                                                         stream: TokenStream [
                                                             Ident {
                                                                 ident: "FALSE",
-                                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                             },
                                                         ],
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                 ],
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                         ],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Ident {
                                         ident: "let",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Ident {
                                         ident: "my_val",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: '=',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Ident {
                                         ident: "true",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: ';',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "enum",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "TupleEnum",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Brace,
                                 stream: TokenStream [
                                     Ident {
                                         ident: "Foo",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Parenthesis,
@@ -1642,69 +1642,69 @@
                                             Punct {
                                                 ch: '#',
                                                 spacing: Alone,
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Group {
                                                 delimiter: Bracket,
                                                 stream: TokenStream [
                                                     Ident {
                                                         ident: "cfg",
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                     Group {
                                                         delimiter: Parenthesis,
                                                         stream: TokenStream [
                                                             Ident {
                                                                 ident: "not",
-                                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                             },
                                                             Group {
                                                                 delimiter: Parenthesis,
                                                                 stream: TokenStream [
                                                                     Ident {
                                                                         ident: "FALSE",
-                                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                                     },
                                                                 ],
-                                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                             },
                                                         ],
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                 ],
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Ident {
                                                 ident: "i32",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Punct {
                                                 ch: ',',
                                                 spacing: Alone,
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Ident {
                                                 ident: "u8",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                         ],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: ',',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "struct",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "TupleStruct",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Parenthesis,
@@ -1712,120 +1712,120 @@
                                     Punct {
                                         ch: '#',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Bracket,
                                         stream: TokenStream [
                                             Ident {
                                                 ident: "cfg",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Group {
                                                 delimiter: Parenthesis,
                                                 stream: TokenStream [
                                                     Ident {
                                                         ident: "not",
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                     Group {
                                                         delimiter: Parenthesis,
                                                         stream: TokenStream [
                                                             Ident {
                                                                 ident: "FALSE",
-                                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                             },
                                                         ],
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                 ],
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                         ],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Ident {
                                         ident: "i32",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: ',',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Ident {
                                         ident: "u8",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Punct {
                                 ch: ';',
                                 spacing: Alone,
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Literal {
                                 kind: Integer,
                                 symbol: "0",
                                 suffix: None,
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                         ],
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                 ],
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Punct {
                 ch: ',',
                 spacing: Alone,
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Punct {
                 ch: '#',
                 spacing: Alone,
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Group {
                 delimiter: Bracket,
                 stream: TokenStream [
                     Ident {
                         ident: "print_helper",
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                     Group {
                         delimiter: Parenthesis,
                         stream: TokenStream [
                             Ident {
                                 ident: "d",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                         ],
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                 ],
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Ident {
                 ident: "fourth",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Ident {
                 ident: "B",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Punct {
                 ch: ',',
                 spacing: Alone,
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
         ],
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
 ]
diff --git a/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout
index c4ee44f..40da5aa 100644
--- a/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout
+++ b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout
@@ -34,11 +34,11 @@
                 stream: TokenStream [
                     Ident {
                         ident: "mod",
-                        span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                        span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                     },
                     Ident {
                         ident: "bar",
-                        span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                        span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                     },
                     Group {
                         delimiter: Brace,
@@ -46,36 +46,36 @@
                             Punct {
                                 ch: '#',
                                 spacing: Joint,
-                                span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                                span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                             },
                             Punct {
                                 ch: '!',
                                 spacing: Alone,
-                                span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                                span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                             },
                             Group {
                                 delimiter: Bracket,
                                 stream: TokenStream [
                                     Ident {
                                         ident: "doc",
-                                        span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                                        span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                                     },
                                     Punct {
                                         ch: '=',
                                         spacing: Alone,
-                                        span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                                        span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                                     },
                                     Literal {
                                         kind: StrRaw(0),
                                         symbol: " Foo",
                                         suffix: None,
-                                        span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                                        span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                                span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                             },
                         ],
-                        span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                        span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                     },
                 ],
                 span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
diff --git a/src/test/ui/proc-macro/issue-80760-empty-stmt.rs b/src/test/ui/proc-macro/issue-80760-empty-stmt.rs
new file mode 100644
index 0000000..86865af
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-80760-empty-stmt.rs
@@ -0,0 +1,26 @@
+// check-pass
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+macro_rules! empty_stmt {
+    ($s:stmt) => {
+        print_bang!($s);
+
+        // Currently, all attributes are ignored
+        // on an empty statement
+        #[print_attr]
+        #[rustc_dummy(first)]
+        #[rustc_dummy(second)]
+        $s
+    }
+}
+
+fn main() {
+    empty_stmt!(;);
+}
diff --git a/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout b/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout
new file mode 100644
index 0000000..4b7ed87
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout
@@ -0,0 +1,14 @@
+PRINT-BANG INPUT (DISPLAY): ;
+PRINT-BANG INPUT (DEBUG): TokenStream [
+    Group {
+        delimiter: None,
+        stream: TokenStream [
+            Punct {
+                ch: ';',
+                spacing: Alone,
+                span: $DIR/issue-80760-empty-stmt.rs:25:17: 25:18 (#0),
+            },
+        ],
+        span: $DIR/issue-80760-empty-stmt.rs:13:21: 13:23 (#4),
+    },
+]
diff --git a/src/test/ui/proc-macro/macros-in-extern-derive.rs b/src/test/ui/proc-macro/macros-in-extern-derive.rs
index d2751a3..e52bf43 100644
--- a/src/test/ui/proc-macro/macros-in-extern-derive.rs
+++ b/src/test/ui/proc-macro/macros-in-extern-derive.rs
@@ -1,4 +1,4 @@
-extern {
+extern "C" {
     #[derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
     fn f();
 }
diff --git a/src/test/ui/proc-macro/macros-in-extern.rs b/src/test/ui/proc-macro/macros-in-extern.rs
index e2b1d55..57e2066 100644
--- a/src/test/ui/proc-macro/macros-in-extern.rs
+++ b/src/test/ui/proc-macro/macros-in-extern.rs
@@ -11,12 +11,14 @@
 }
 
 #[link(name = "rust_test_helpers", kind = "static")]
-extern {
+extern "C" {
     #[empty_attr]
     fn some_definitely_unknown_symbol_which_should_be_removed();
 
     #[identity_attr]
     fn rust_get_test_int() -> isize;
 
-    identity!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
+    identity!(
+        fn rust_dbg_extern_identity_u32(arg: u32) -> u32;
+    );
 }
diff --git a/src/test/ui/proc-macro/signature.rs b/src/test/ui/proc-macro/signature.rs
index dbc1577..e089287 100644
--- a/src/test/ui/proc-macro/signature.rs
+++ b/src/test/ui/proc-macro/signature.rs
@@ -7,7 +7,7 @@
 extern crate proc_macro;
 
 #[proc_macro_derive(A)]
-pub unsafe extern fn foo(a: i32, b: u32) -> u32 {
+pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
     //~^ ERROR: mismatched types
     loop {}
 }
diff --git a/src/test/ui/proc-macro/signature.stderr b/src/test/ui/proc-macro/signature.stderr
index 6ebc996..80a459c 100644
--- a/src/test/ui/proc-macro/signature.stderr
+++ b/src/test/ui/proc-macro/signature.stderr
@@ -1,7 +1,7 @@
 error[E0308]: mismatched types
   --> $DIR/signature.rs:10:1
    |
-LL | / pub unsafe extern fn foo(a: i32, b: u32) -> u32 {
+LL | / pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
 LL | |
 LL | |     loop {}
 LL | | }
diff --git a/src/test/ui/proc-macro/span-preservation.rs b/src/test/ui/proc-macro/span-preservation.rs
index b22e50c..0c73586 100644
--- a/src/test/ui/proc-macro/span-preservation.rs
+++ b/src/test/ui/proc-macro/span-preservation.rs
@@ -35,7 +35,7 @@
 }
 
 #[recollect_attr]
-extern fn bar() {
+extern "C" fn bar() {
     0 //~ ERROR mismatched types
 }
 
diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr
index 4064c5b..9e91ed4 100644
--- a/src/test/ui/proc-macro/span-preservation.stderr
+++ b/src/test/ui/proc-macro/span-preservation.stderr
@@ -37,8 +37,8 @@
 error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:39:5
    |
-LL | extern fn bar() {
-   |                 - possibly return type missing here?
+LL | extern "C" fn bar() {
+   |                     - possibly return type missing here?
 LL |     0
    |     ^ expected `()`, found integer
 
diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs
index f5d5823..ab1a025 100644
--- a/src/test/ui/range/issue-54505-no-std.rs
+++ b/src/test/ui/range/issue-54505-no-std.rs
@@ -13,7 +13,7 @@
 
 #[cfg(any(not(target_arch = "wasm32"), target_os = "emscripten"))]
 #[lang = "eh_personality"]
-extern fn eh_personality() {}
+extern "C" fn eh_personality() {}
 #[cfg(target_os = "emscripten")]
 #[lang = "eh_catch_typeinfo"]
 static EH_CATCH_TYPEINFO: u8 = 0;
diff --git a/src/test/ui/unreachable-code-ret.rs b/src/test/ui/reachable/unreachable-code-ret.rs
similarity index 100%
rename from src/test/ui/unreachable-code-ret.rs
rename to src/test/ui/reachable/unreachable-code-ret.rs
diff --git a/src/test/ui/unreachable-code-ret.stderr b/src/test/ui/reachable/unreachable-code-ret.stderr
similarity index 100%
rename from src/test/ui/unreachable-code-ret.stderr
rename to src/test/ui/reachable/unreachable-code-ret.stderr
diff --git a/src/test/ui/issues/issue-12470.rs b/src/test/ui/regions/issue-12470.rs
similarity index 100%
rename from src/test/ui/issues/issue-12470.rs
rename to src/test/ui/regions/issue-12470.rs
diff --git a/src/test/ui/issues/issue-12470.stderr b/src/test/ui/regions/issue-12470.stderr
similarity index 100%
rename from src/test/ui/issues/issue-12470.stderr
rename to src/test/ui/regions/issue-12470.stderr
diff --git a/src/test/ui/issues/issue-24085.rs b/src/test/ui/regions/issue-24085.rs
similarity index 100%
rename from src/test/ui/issues/issue-24085.rs
rename to src/test/ui/regions/issue-24085.rs
diff --git a/src/test/ui/issues/issue-2718.rs b/src/test/ui/regions/issue-2718.rs
similarity index 100%
rename from src/test/ui/issues/issue-2718.rs
rename to src/test/ui/regions/issue-2718.rs
diff --git a/src/test/ui/issues/issue-28848.nll.stderr b/src/test/ui/regions/issue-28848.nll.stderr
similarity index 100%
rename from src/test/ui/issues/issue-28848.nll.stderr
rename to src/test/ui/regions/issue-28848.nll.stderr
diff --git a/src/test/ui/issues/issue-28848.rs b/src/test/ui/regions/issue-28848.rs
similarity index 100%
rename from src/test/ui/issues/issue-28848.rs
rename to src/test/ui/regions/issue-28848.rs
diff --git a/src/test/ui/issues/issue-28848.stderr b/src/test/ui/regions/issue-28848.stderr
similarity index 100%
rename from src/test/ui/issues/issue-28848.stderr
rename to src/test/ui/regions/issue-28848.stderr
diff --git a/src/test/ui/issues/issue-5243.rs b/src/test/ui/regions/issue-5243.rs
similarity index 100%
rename from src/test/ui/issues/issue-5243.rs
rename to src/test/ui/regions/issue-5243.rs
diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr
index 5fcda34..e90754e 100644
--- a/src/test/ui/repeat_count.stderr
+++ b/src/test/ui/repeat_count.stderr
@@ -1,6 +1,8 @@
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/repeat_count.rs:5:17
    |
+LL |     let n = 1;
+   |     ----- help: consider using `const` instead of `let`: `const n`
 LL |     let a = [0; n];
    |                 ^ non-constant value
 
diff --git a/src/test/ui/issues/issue-10200.rs b/src/test/ui/resolve/issue-10200.rs
similarity index 100%
rename from src/test/ui/issues/issue-10200.rs
rename to src/test/ui/resolve/issue-10200.rs
diff --git a/src/test/ui/issues/issue-10200.stderr b/src/test/ui/resolve/issue-10200.stderr
similarity index 100%
rename from src/test/ui/issues/issue-10200.stderr
rename to src/test/ui/resolve/issue-10200.stderr
diff --git a/src/test/ui/resolve/resolve-primitive-fallback.stderr b/src/test/ui/resolve/resolve-primitive-fallback.stderr
index 8611306..5af0aef 100644
--- a/src/test/ui/resolve/resolve-primitive-fallback.stderr
+++ b/src/test/ui/resolve/resolve-primitive-fallback.stderr
@@ -22,6 +22,12 @@
    |     ^^^^^^^^^^^^^^^^^ --- supplied 1 argument
    |     |
    |     expected 0 arguments
+   |
+note: function defined here
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |
+LL | pub const fn size_of<T>() -> usize {
+   |              ^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
index 5feb9c9..15c0c69 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
+++ b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
@@ -6,9 +6,9 @@
 // This test checks that non-exhaustive types with `#[repr(C)]` from an extern crate are considered
 // improper.
 
-use types::{NonExhaustiveEnum, NormalStruct, UnitStruct, TupleStruct, NonExhaustiveVariants};
+use types::{NonExhaustiveEnum, NonExhaustiveVariants, NormalStruct, TupleStruct, UnitStruct};
 
-extern {
+extern "C" {
     pub fn non_exhaustive_enum(_: NonExhaustiveEnum);
     //~^ ERROR `extern` block uses type `NonExhaustiveEnum`, which is not FFI-safe
     pub fn non_exhaustive_normal_struct(_: NormalStruct);
@@ -21,4 +21,4 @@
     //~^ ERROR `extern` block uses type `NonExhaustiveVariants`, which is not FFI-safe
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs
index c09aa256e..fe4ae34 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs
+++ b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs
@@ -9,7 +9,7 @@
 pub enum NonExhaustiveEnum {
     Unit,
     Tuple(u32),
-    Struct { field: u32 }
+    Struct { field: u32 },
 }
 
 #[non_exhaustive]
@@ -25,16 +25,19 @@
 
 #[non_exhaustive]
 #[repr(C)]
-pub struct TupleStruct (pub u16, pub u16);
+pub struct TupleStruct(pub u16, pub u16);
 
 #[repr(C)]
 pub enum NonExhaustiveVariants {
-    #[non_exhaustive] Unit,
-    #[non_exhaustive] Tuple(u32),
-    #[non_exhaustive] Struct { field: u32 }
+    #[non_exhaustive]
+    Unit,
+    #[non_exhaustive]
+    Tuple(u32),
+    #[non_exhaustive]
+    Struct { field: u32 },
 }
 
-extern {
+extern "C" {
     // Unit structs aren't tested here because they will trigger `improper_ctypes` anyway.
     pub fn non_exhaustive_enum(_: NonExhaustiveEnum);
     pub fn non_exhaustive_normal_struct(_: NormalStruct);
@@ -42,4 +45,4 @@
     pub fn non_exhaustive_variant(_: NonExhaustiveVariants);
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs
index 14345ba..518aa20 100644
--- a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs
+++ b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs
@@ -1,5 +1,5 @@
-#[link(name="foo")]
-extern {
+#[link(name = "foo")]
+extern "C" {
     #[link_ordinal(42)]
     //~^ ERROR: the `#[link_ordinal]` attribute is an experimental feature
     fn foo();
diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs
index f0f83e0..29edd0f 100644
--- a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs
+++ b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs
@@ -1,5 +1,5 @@
-#[link(name="foo", kind="raw-dylib")]
+#[link(name = "foo", kind = "raw-dylib")]
 //~^ ERROR: kind="raw-dylib" is unstable
-extern {}
+extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr
index a69f677..a670b6c 100644
--- a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr
+++ b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr
@@ -1,8 +1,8 @@
 error[E0658]: kind="raw-dylib" is unstable
   --> $DIR/feature-gate-raw-dylib.rs:1:1
    |
-LL | #[link(name="foo", kind="raw-dylib")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[link(name = "foo", kind = "raw-dylib")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
    = help: add `#![feature(raw_dylib)]` to the crate attributes to enable
diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs
index bf08293..42685ca 100644
--- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs
+++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs
@@ -2,7 +2,7 @@
 //~^ WARN the feature `raw_dylib` is incomplete
 
 #[link(name="foo")]
-extern {
+extern "C" {
     #[link_name="foo"]
     #[link_ordinal(42)]
     //~^ ERROR cannot use `#[link_name]` with `#[link_ordinal]`
diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs
index ea633c5..135f590 100644
--- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs
+++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs
@@ -1,8 +1,8 @@
 #![feature(raw_dylib)]
 //~^ WARN the feature `raw_dylib` is incomplete
 
-#[link(name="foo")]
-extern {
+#[link(name = "foo")]
+extern "C" {
     #[link_ordinal("JustMonika")]
     //~^ ERROR illegal ordinal format in `link_ordinal`
     fn foo();
diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs
index 55cc329..10db497 100644
--- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs
+++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs
@@ -1,8 +1,8 @@
 #![feature(raw_dylib)]
 //~^ WARN the feature `raw_dylib` is incomplete
 
-#[link(name="foo")]
-extern {
+#[link(name = "foo")]
+extern "C" {
     #[link_ordinal(18446744073709551616)]
     //~^ ERROR ordinal value in `link_ordinal` is too large: `18446744073709551616`
     fn foo();
diff --git a/src/test/ui/auxiliary/rmeta-meta.rs b/src/test/ui/rmeta/auxiliary/rmeta-meta.rs
similarity index 100%
rename from src/test/ui/auxiliary/rmeta-meta.rs
rename to src/test/ui/rmeta/auxiliary/rmeta-meta.rs
diff --git a/src/test/ui/auxiliary/rmeta-rlib-rpass.rs b/src/test/ui/rmeta/auxiliary/rmeta-rlib-rpass.rs
similarity index 100%
rename from src/test/ui/auxiliary/rmeta-rlib-rpass.rs
rename to src/test/ui/rmeta/auxiliary/rmeta-rlib-rpass.rs
diff --git a/src/test/ui/auxiliary/rmeta-rlib.rs b/src/test/ui/rmeta/auxiliary/rmeta-rlib.rs
similarity index 100%
rename from src/test/ui/auxiliary/rmeta-rlib.rs
rename to src/test/ui/rmeta/auxiliary/rmeta-rlib.rs
diff --git a/src/test/ui/auxiliary/rmeta-rmeta.rs b/src/test/ui/rmeta/auxiliary/rmeta-rmeta.rs
similarity index 100%
rename from src/test/ui/auxiliary/rmeta-rmeta.rs
rename to src/test/ui/rmeta/auxiliary/rmeta-rmeta.rs
diff --git a/src/test/ui/rmeta-lib-pass.rs b/src/test/ui/rmeta/rmeta-lib-pass.rs
similarity index 100%
rename from src/test/ui/rmeta-lib-pass.rs
rename to src/test/ui/rmeta/rmeta-lib-pass.rs
diff --git a/src/test/ui/rmeta-pass.rs b/src/test/ui/rmeta/rmeta-pass.rs
similarity index 100%
rename from src/test/ui/rmeta-pass.rs
rename to src/test/ui/rmeta/rmeta-pass.rs
diff --git a/src/test/ui/rmeta-priv-warn.rs b/src/test/ui/rmeta/rmeta-priv-warn.rs
similarity index 100%
rename from src/test/ui/rmeta-priv-warn.rs
rename to src/test/ui/rmeta/rmeta-priv-warn.rs
diff --git a/src/test/ui/rmeta-rpass.rs b/src/test/ui/rmeta/rmeta-rpass.rs
similarity index 100%
rename from src/test/ui/rmeta-rpass.rs
rename to src/test/ui/rmeta/rmeta-rpass.rs
diff --git a/src/test/ui/rmeta.rs b/src/test/ui/rmeta/rmeta.rs
similarity index 100%
rename from src/test/ui/rmeta.rs
rename to src/test/ui/rmeta/rmeta.rs
diff --git a/src/test/ui/rmeta.stderr b/src/test/ui/rmeta/rmeta.stderr
similarity index 100%
rename from src/test/ui/rmeta.stderr
rename to src/test/ui/rmeta/rmeta.stderr
diff --git a/src/test/ui/rmeta_lib.rs b/src/test/ui/rmeta/rmeta_lib.rs
similarity index 100%
rename from src/test/ui/rmeta_lib.rs
rename to src/test/ui/rmeta/rmeta_lib.rs
diff --git a/src/test/ui/rmeta_lib.stderr b/src/test/ui/rmeta/rmeta_lib.stderr
similarity index 100%
rename from src/test/ui/rmeta_lib.stderr
rename to src/test/ui/rmeta/rmeta_lib.stderr
diff --git a/src/test/ui/rmeta_meta_main.rs b/src/test/ui/rmeta/rmeta_meta_main.rs
similarity index 100%
rename from src/test/ui/rmeta_meta_main.rs
rename to src/test/ui/rmeta/rmeta_meta_main.rs
diff --git a/src/test/ui/rmeta_meta_main.stderr b/src/test/ui/rmeta/rmeta_meta_main.stderr
similarity index 100%
rename from src/test/ui/rmeta_meta_main.stderr
rename to src/test/ui/rmeta/rmeta_meta_main.stderr
diff --git a/src/test/ui/safe-extern-statics-mut.rs b/src/test/ui/safe-extern-statics-mut.rs
index dbf0f52..324fa44 100644
--- a/src/test/ui/safe-extern-statics-mut.rs
+++ b/src/test/ui/safe-extern-statics-mut.rs
@@ -3,7 +3,7 @@
 extern crate extern_statics;
 use extern_statics::*;
 
-extern {
+extern "C" {
     static mut B: u8;
 }
 
diff --git a/src/test/ui/safe-extern-statics.rs b/src/test/ui/safe-extern-statics.rs
index 0535a07..6fa4c4a 100644
--- a/src/test/ui/safe-extern-statics.rs
+++ b/src/test/ui/safe-extern-statics.rs
@@ -3,7 +3,7 @@
 extern crate extern_statics;
 use extern_statics::*;
 
-extern {
+extern "C" {
     static A: u8;
 }
 
diff --git a/src/test/ui/sanitize/unsupported-target.stderr b/src/test/ui/sanitize/unsupported-target.stderr
index f5961a11..0936787 100644
--- a/src/test/ui/sanitize/unsupported-target.stderr
+++ b/src/test/ui/sanitize/unsupported-target.stderr
@@ -1,4 +1,4 @@
-error: `-Zsanitizer=leak` only works with targets: aarch64-unknown-linux-gnu, x86_64-apple-darwin, x86_64-unknown-linux-gnu
+error: `-Zsanitizer=leak` only works with targets: aarch64-apple-darwin, aarch64-unknown-linux-gnu, x86_64-apple-darwin, x86_64-unknown-linux-gnu
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/sepcomp/sepcomp-extern.rs b/src/test/ui/sepcomp/sepcomp-extern.rs
index c4ccf23..6323bf6 100644
--- a/src/test/ui/sepcomp/sepcomp-extern.rs
+++ b/src/test/ui/sepcomp/sepcomp-extern.rs
@@ -6,7 +6,7 @@
 
 extern crate sepcomp_extern_lib;
 
-extern {
+extern "C" {
     fn foo() -> usize;
 }
 
diff --git a/src/test/ui/seq-args.rs b/src/test/ui/seq-args.rs
index 9bb9f12..9a3c495 100644
--- a/src/test/ui/seq-args.rs
+++ b/src/test/ui/seq-args.rs
@@ -1,11 +1,13 @@
 fn main() {
-trait Seq { }
+    trait Seq { }
 
-impl<T> Seq<T> for Vec<T> { //~ ERROR wrong number of type arguments
-    /* ... */
-}
-impl Seq<bool> for u32 { //~ ERROR wrong number of type arguments
-   /* Treat the integer as a sequence of bits */
-}
+    impl<T> Seq<T> for Vec<T> {
+        //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+        /* ... */
+    }
 
+    impl Seq<bool> for u32 {
+        //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+        /* Treat the integer as a sequence of bits */
+    }
 }
diff --git a/src/test/ui/seq-args.stderr b/src/test/ui/seq-args.stderr
index 2e7d901..0e89fef 100644
--- a/src/test/ui/seq-args.stderr
+++ b/src/test/ui/seq-args.stderr
@@ -1,14 +1,30 @@
-error[E0107]: wrong number of type arguments: expected 0, found 1
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
   --> $DIR/seq-args.rs:4:13
    |
-LL | impl<T> Seq<T> for Vec<T> {
-   |             ^ unexpected type argument
-
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/seq-args.rs:7:10
+LL |     impl<T> Seq<T> for Vec<T> {
+   |             ^^^--- help: remove these generics
+   |             |
+   |             expected 0 type arguments
    |
-LL | impl Seq<bool> for u32 {
-   |          ^^^^ unexpected type argument
+note: trait defined here, with 0 type parameters
+  --> $DIR/seq-args.rs:2:11
+   |
+LL |     trait Seq { }
+   |           ^^^
+
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/seq-args.rs:9:10
+   |
+LL |     impl Seq<bool> for u32 {
+   |          ^^^------ help: remove these generics
+   |          |
+   |          expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/seq-args.rs:2:11
+   |
+LL |     trait Seq { }
+   |           ^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/signal-alternate-stack-cleanup.rs b/src/test/ui/signal-alternate-stack-cleanup.rs
index 15fcf78..8a6d738 100644
--- a/src/test/ui/signal-alternate-stack-cleanup.rs
+++ b/src/test/ui/signal-alternate-stack-cleanup.rs
@@ -13,11 +13,11 @@
 
 use libc::*;
 
-unsafe extern fn signal_handler(signum: c_int, _: *mut siginfo_t, _: *mut c_void) {
+unsafe extern "C" fn signal_handler(signum: c_int, _: *mut siginfo_t, _: *mut c_void) {
     assert_eq!(signum, SIGWINCH);
 }
 
-extern fn send_signal() {
+extern "C" fn send_signal() {
     unsafe {
         raise(SIGWINCH);
     }
diff --git a/src/test/ui/simple_global_asm.rs b/src/test/ui/simple_global_asm.rs
index d95fefe..75b4788 100644
--- a/src/test/ui/simple_global_asm.rs
+++ b/src/test/ui/simple_global_asm.rs
@@ -5,20 +5,26 @@
 #![allow(dead_code)]
 
 #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
-global_asm!(r#"
+global_asm!(
+    r#"
     .global foo
     .global _foo
 foo:
 _foo:
     ret
-"#);
+"#
+);
 
-extern {
+extern "C" {
     fn foo();
 }
 
 #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
-fn main() { unsafe { foo(); } }
+fn main() {
+    unsafe {
+        foo();
+    }
+}
 
 #[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))]
 fn main() {}
diff --git a/src/test/ui/span/lint-unused-unsafe.rs b/src/test/ui/span/lint-unused-unsafe.rs
index 338fbb9..b6c4894 100644
--- a/src/test/ui/span/lint-unused-unsafe.rs
+++ b/src/test/ui/span/lint-unused-unsafe.rs
@@ -5,7 +5,7 @@
 
 
 mod foo {
-    extern {
+    extern "C" {
         pub fn bar();
     }
 }
diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
index fee8b06..9220823 100644
--- a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
+++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
@@ -1,4 +1,4 @@
-error: cannot specialize on `ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,))`
+error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,)))`
   --> $DIR/repeated_projection_type.rs:19:1
    |
 LL | / impl<I, V: Id<This = (I,)>> X for V {
diff --git a/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs b/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs
index cc57071..656564f 100644
--- a/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs
+++ b/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs
@@ -22,7 +22,7 @@
 impl UnstableTrait for StableType {}
 
 #[unstable(feature = "x", issue = "none")]
-//~^ ERROR an `#[unstable]` annotation here has no effect [rustc::ineffective_unstable_trait_impl]
+//~^ ERROR an `#[unstable]` annotation here has no effect [ineffective_unstable_trait_impl]
 impl StableTrait for StableType {}
 
 fn main() {}
diff --git a/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr b/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr
index 1915d03..a11479c 100644
--- a/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr
+++ b/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr
@@ -4,7 +4,7 @@
 LL | #[unstable(feature = "x", issue = "none")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `#[deny(rustc::ineffective_unstable_trait_impl)]` on by default
+   = note: `#[deny(ineffective_unstable_trait_impl)]` on by default
    = note: see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
 
 error: aborting due to previous error
diff --git a/src/test/ui/static/static-mut-foreign-requires-unsafe.rs b/src/test/ui/static/static-mut-foreign-requires-unsafe.rs
index 535f6bc..90aa253 100644
--- a/src/test/ui/static/static-mut-foreign-requires-unsafe.rs
+++ b/src/test/ui/static/static-mut-foreign-requires-unsafe.rs
@@ -1,9 +1,9 @@
-extern {
+extern "C" {
     static mut a: i32;
 }
 
 fn main() {
-    a += 3;     //~ ERROR: requires unsafe
-    a = 4;      //~ ERROR: requires unsafe
+    a += 3; //~ ERROR: requires unsafe
+    a = 4; //~ ERROR: requires unsafe
     let _b = a; //~ ERROR: requires unsafe
 }
diff --git a/src/test/ui/static_sized_requirement.rs b/src/test/ui/static_sized_requirement.rs
index 074280b..3943b26 100644
--- a/src/test/ui/static_sized_requirement.rs
+++ b/src/test/ui/static_sized_requirement.rs
@@ -7,6 +7,6 @@
 #[lang = "sized"]
 trait Sized {}
 
-extern {
+extern "C" {
     pub static A: u32;
 }
diff --git a/src/test/ui/stmt_expr_attrs_no_feature.rs b/src/test/ui/stmt_expr_attrs_no_feature.rs
index 674a5ed..627c97d 100644
--- a/src/test/ui/stmt_expr_attrs_no_feature.rs
+++ b/src/test/ui/stmt_expr_attrs_no_feature.rs
@@ -89,7 +89,7 @@
 
 // check that the gate visitor works right:
 
-extern {
+extern "C" {
     #[cfg(unset)]
     fn x(a: [u8; #[rustc_dummy] 5]);
     fn y(a: [u8; #[rustc_dummy] 5]); //~ ERROR attributes on expressions are experimental
diff --git a/src/test/ui/structs-enums/class-dtor.rs b/src/test/ui/structs-enums/class-dtor.rs
index ee1cac0..583a5e2 100644
--- a/src/test/ui/structs-enums/class-dtor.rs
+++ b/src/test/ui/structs-enums/class-dtor.rs
@@ -5,7 +5,7 @@
 // pretty-expanded FIXME #23616
 
 struct cat {
-  done : extern fn(usize),
+  done : extern "C" fn(usize),
   meows : usize,
 }
 
@@ -15,7 +15,7 @@
     }
 }
 
-fn cat(done: extern fn(usize)) -> cat {
+fn cat(done: extern "C" fn(usize)) -> cat {
     cat {
         meows: 0,
         done: done
diff --git a/src/test/ui/structs-enums/foreign-struct.rs b/src/test/ui/structs-enums/foreign-struct.rs
index ce02c8f..00a23b3 100644
--- a/src/test/ui/structs-enums/foreign-struct.rs
+++ b/src/test/ui/structs-enums/foreign-struct.rs
@@ -6,14 +6,14 @@
 
 // pretty-expanded FIXME #23616
 
-pub enum void { }
+pub enum void {}
 
 mod bindgen {
     use super::void;
 
-    extern {
+    extern "C" {
         pub fn printf(v: void);
     }
 }
 
-pub fn main() { }
+pub fn main() {}
diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.rs b/src/test/ui/structs/structure-constructor-type-mismatch.rs
index 01cc176..56c8ffb 100644
--- a/src/test/ui/structs/structure-constructor-type-mismatch.rs
+++ b/src/test/ui/structs/structure-constructor-type-mismatch.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-linelength
+
 struct Point<T> {
     x: T,
     y: T,
@@ -45,13 +47,13 @@
         y: 8,
     };
 
-    let pt3 = PointF::<i32> { //~ ERROR wrong number of type arguments
+    let pt3 = PointF::<i32> { //~ ERROR this type alias takes 0 type arguments but 1 type argument was supplied
         x: 9,  //~ ERROR mismatched types
         y: 10, //~ ERROR mismatched types
     };
 
     match (Point { x: 1, y: 2 }) {
-        PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments
+        PointF::<u32> { .. } => {} //~ ERROR this type alias takes 0 type arguments but 1 type argument was supplied
         //~^ ERROR mismatched types
     }
 
diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.stderr b/src/test/ui/structs/structure-constructor-type-mismatch.stderr
index 8cfa118..4611414 100644
--- a/src/test/ui/structs/structure-constructor-type-mismatch.stderr
+++ b/src/test/ui/structs/structure-constructor-type-mismatch.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:17:12
+  --> $DIR/structure-constructor-type-mismatch.rs:19:12
    |
 LL |         x: 1,
    |            ^
@@ -8,7 +8,7 @@
    |            help: use a float literal: `1.0`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:20:12
+  --> $DIR/structure-constructor-type-mismatch.rs:22:12
    |
 LL |         y: 2,
    |            ^
@@ -17,7 +17,7 @@
    |            help: use a float literal: `2.0`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:26:12
+  --> $DIR/structure-constructor-type-mismatch.rs:28:12
    |
 LL |         x: 3,
    |            ^
@@ -26,7 +26,7 @@
    |            help: use a float literal: `3.0`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:29:12
+  --> $DIR/structure-constructor-type-mismatch.rs:31:12
    |
 LL |         y: 4,
    |            ^
@@ -35,7 +35,7 @@
    |            help: use a float literal: `4.0`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:35:12
+  --> $DIR/structure-constructor-type-mismatch.rs:37:12
    |
 LL |         x: 5,
    |            ^
@@ -44,7 +44,7 @@
    |            help: use a float literal: `5.0`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:42:12
+  --> $DIR/structure-constructor-type-mismatch.rs:44:12
    |
 LL |         x: 7,
    |            ^
@@ -52,14 +52,22 @@
    |            expected `f32`, found integer
    |            help: use a float literal: `7.0`
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/structure-constructor-type-mismatch.rs:48:24
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/structure-constructor-type-mismatch.rs:50:15
    |
 LL |     let pt3 = PointF::<i32> {
-   |                        ^^^ unexpected type argument
+   |               ^^^^^^------- help: remove these generics
+   |               |
+   |               expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/structure-constructor-type-mismatch.rs:8:6
+   |
+LL | type PointF = Point<f32>;
+   |      ^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:49:12
+  --> $DIR/structure-constructor-type-mismatch.rs:51:12
    |
 LL |         x: 9,
    |            ^
@@ -68,7 +76,7 @@
    |            help: use a float literal: `9.0`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:50:12
+  --> $DIR/structure-constructor-type-mismatch.rs:52:12
    |
 LL |         y: 10,
    |            ^^
@@ -76,14 +84,22 @@
    |            expected `f32`, found integer
    |            help: use a float literal: `10.0`
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/structure-constructor-type-mismatch.rs:54:18
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/structure-constructor-type-mismatch.rs:56:9
    |
 LL |         PointF::<u32> { .. } => {}
-   |                  ^^^ unexpected type argument
+   |         ^^^^^^------- help: remove these generics
+   |         |
+   |         expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/structure-constructor-type-mismatch.rs:8:6
+   |
+LL | type PointF = Point<f32>;
+   |      ^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:54:9
+  --> $DIR/structure-constructor-type-mismatch.rs:56:9
    |
 LL |     match (Point { x: 1, y: 2 }) {
    |           ---------------------- this expression has type `Point<{integer}>`
@@ -94,7 +110,7 @@
               found struct `Point<f32>`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:59:9
+  --> $DIR/structure-constructor-type-mismatch.rs:61:9
    |
 LL |     match (Point { x: 1, y: 2 }) {
    |           ---------------------- this expression has type `Point<{integer}>`
@@ -105,7 +121,7 @@
               found struct `Point<f32>`
 
 error[E0308]: mismatched types
-  --> $DIR/structure-constructor-type-mismatch.rs:67:9
+  --> $DIR/structure-constructor-type-mismatch.rs:69:9
    |
 LL |     match (Pair { x: 1, y: 2 }) {
    |           --------------------- this expression has type `Pair<{integer}, {integer}>`
diff --git a/src/test/ui/suggestions/borrow-for-loop-head.stderr b/src/test/ui/suggestions/borrow-for-loop-head.stderr
index de342a9..28c319b 100644
--- a/src/test/ui/suggestions/borrow-for-loop-head.stderr
+++ b/src/test/ui/suggestions/borrow-for-loop-head.stderr
@@ -15,8 +15,14 @@
 LL |         for j in a {
    |                  ^
    |                  |
-   |                  value moved here, in previous iteration of loop
+   |                  `a` moved due to this implicit call to `.into_iter()`, in previous iteration of loop
    |                  help: consider borrowing to avoid moving into the for loop: `&a`
+   |
+note: this function takes ownership of the receiver `self`, which moves `a`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |                  ^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.rs b/src/test/ui/suggestions/missing-lifetime-specifier.rs
index fe88d10..761922b 100644
--- a/src/test/ui/suggestions/missing-lifetime-specifier.rs
+++ b/src/test/ui/suggestions/missing-lifetime-specifier.rs
@@ -41,17 +41,17 @@
 
 thread_local! {
     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
-    //~| ERROR wrong number of lifetime arguments: expected 2, found 1
-    //~| ERROR wrong number of lifetime arguments: expected 2, found 1
-    //~| ERROR wrong number of lifetime arguments: expected 2, found 1
+    //~^ ERROR this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
+    //~| ERROR this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
+    //~| ERROR this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
+    //~| ERROR this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
 }
 thread_local! {
     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
-    //~| ERROR wrong number of lifetime arguments: expected 2, found 1
-    //~| ERROR wrong number of lifetime arguments: expected 2, found 1
-    //~| ERROR wrong number of lifetime arguments: expected 2, found 1
+    //~^ ERROR this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
+    //~| ERROR this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
+    //~| ERROR this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
+    //~| ERROR this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
     //~| ERROR missing lifetime specifier
     //~| ERROR missing lifetime specifier
 }
diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr
index 9838ac7..e6cec5c 100644
--- a/src/test/ui/suggestions/missing-lifetime-specifier.stderr
+++ b/src/test/ui/suggestions/missing-lifetime-specifier.stderr
@@ -166,53 +166,149 @@
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^^^^^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:43:44
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                            ^^^ ------- supplied 1 lifetime argument
+   |                                            |
+   |                                            expected 2 lifetime arguments
+   |
+note: union defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:11:11
+   |
+LL | pub union Qux<'t, 'k, I> {
+   |           ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                       ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:43:44
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                            ^^^ ------- supplied 1 lifetime argument
+   |                                            |
+   |                                            expected 2 lifetime arguments
+   |
+note: union defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:11:11
+   |
+LL | pub union Qux<'t, 'k, I> {
+   |           ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                       ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:43:44
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                            ^^^ ------- supplied 1 lifetime argument
+   |                                            |
+   |                                            expected 2 lifetime arguments
+   |
+note: union defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:11:11
+   |
+LL | pub union Qux<'t, 'k, I> {
+   |           ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                       ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:43:44
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                            ^^^ ------- supplied 1 lifetime argument
+   |                                            |
+   |                                            expected 2 lifetime arguments
+   |
+note: union defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:11:11
+   |
+LL | pub union Qux<'t, 'k, I> {
+   |           ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                       ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:50:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                             ^^^ ------- supplied 1 lifetime argument
+   |                                             |
+   |                                             expected 2 lifetime arguments
+   |
+note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:15:7
+   |
+LL | trait Tar<'t, 'k, I> {}
+   |       ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                        ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:50:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                             ^^^ ------- supplied 1 lifetime argument
+   |                                             |
+   |                                             expected 2 lifetime arguments
+   |
+note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:15:7
+   |
+LL | trait Tar<'t, 'k, I> {}
+   |       ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                        ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:50:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                             ^^^ ------- supplied 1 lifetime argument
+   |                                             |
+   |                                             expected 2 lifetime arguments
+   |
+note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:15:7
+   |
+LL | trait Tar<'t, 'k, I> {}
+   |       ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                        ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:50:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+   |                                             ^^^ ------- supplied 1 lifetime argument
+   |                                             |
+   |                                             expected 2 lifetime arguments
+   |
+note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:15:7
+   |
+LL | trait Tar<'t, 'k, I> {}
+   |       ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                        ^^^^
 
 error: aborting due to 22 previous errors
 
diff --git a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs
index 78487bd..05e2d38 100644
--- a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs
+++ b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs
@@ -6,7 +6,7 @@
 pub struct Foo {
     i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
     //~^ ERROR must be specified
-    //~| ERROR wrong number of type arguments
+    //~| ERROR this trait takes 2 type arguments but 4 type arguments were supplied
 }
 
 
diff --git a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr
index 58a7318..2d06591 100644
--- a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr
+++ b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr
@@ -1,10 +1,16 @@
-error[E0107]: wrong number of type arguments: expected 2, found 4
-  --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:32
+error[E0107]: this trait takes 2 type arguments but 4 type arguments were supplied
+  --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16
    |
 LL |     i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
-   |                                ^^^^^  ^^^^^ unexpected type argument
-   |                                |
-   |                                unexpected type argument
+   |                ^             -------------- help: remove these type arguments
+   |                |
+   |                expected 2 type arguments
+   |
+note: trait defined here, with 2 type parameters: `X`, `Y`
+  --> $DIR/use-type-argument-instead-of-assoc-type.rs:1:11
+   |
+LL | pub trait T<X, Y> {
+   |           ^ -  -
 
 error[E0191]: the value of the associated types `A` (from trait `T`), `C` (from trait `T`) must be specified
   --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16
diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.fixed b/src/test/ui/suggestions/vec-macro-in-pattern.fixed
deleted file mode 100644
index e1695d6..0000000
--- a/src/test/ui/suggestions/vec-macro-in-pattern.fixed
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-rustfix
-fn main() {
-    // everything after `.as_ref` should be suggested
-    match Some(vec![3]).as_ref().map(|v| v.as_slice()) {
-        Some([_x]) => (), //~ ERROR unexpected `(` after qualified path
-        _ => (),
-    }
-}
diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.rs b/src/test/ui/suggestions/vec-macro-in-pattern.rs
deleted file mode 100644
index 4843629..0000000
--- a/src/test/ui/suggestions/vec-macro-in-pattern.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-rustfix
-fn main() {
-    // everything after `.as_ref` should be suggested
-    match Some(vec![3]).as_ref().map(|v| v.as_slice()) {
-        Some(vec![_x]) => (), //~ ERROR unexpected `(` after qualified path
-        _ => (),
-    }
-}
diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.stderr b/src/test/ui/suggestions/vec-macro-in-pattern.stderr
deleted file mode 100644
index f9d0464..0000000
--- a/src/test/ui/suggestions/vec-macro-in-pattern.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error: unexpected `(` after qualified path
-  --> $DIR/vec-macro-in-pattern.rs:5:14
-   |
-LL |         Some(vec![_x]) => (),
-   |              ^^^^^^^^
-   |              |
-   |              unexpected `(` after qualified path
-   |              the qualified path
-   |              in this macro invocation
-   |              help: use a slice pattern here instead: `[_x]`
-   |
-   = help: for more information, see https://doc.rust-lang.org/edition-guide/rust-2018/slice-patterns.html
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs
index 05bd98d..24bdf6d 100644
--- a/src/test/ui/symbol-names/impl1.rs
+++ b/src/test/ui/symbol-names/impl1.rs
@@ -60,7 +60,7 @@
         }
 
         // Test type mangling, by putting them in an `impl` header.
-        impl Bar for [&'_ (dyn Foo<Assoc = extern fn(&u8, ...)> + AutoTrait); 3] {
+        impl Bar for [&'_ (dyn Foo<Assoc = extern "C" 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$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
diff --git a/src/test/ui/tag-type-args.rs b/src/test/ui/tag-type-args.rs
index 4f546fc..660d860 100644
--- a/src/test/ui/tag-type-args.rs
+++ b/src/test/ui/tag-type-args.rs
@@ -1,5 +1,5 @@
 enum Quux<T> { Bar }
 
-fn foo(c: Quux) { assert!((false)); } //~ ERROR wrong number of type arguments
+fn foo(c: Quux) { assert!((false)); } //~ ERROR missing generics for enum `Quux`
 
 fn main() { panic!(); }
diff --git a/src/test/ui/tag-type-args.stderr b/src/test/ui/tag-type-args.stderr
index ac44dad..c9888dc 100644
--- a/src/test/ui/tag-type-args.stderr
+++ b/src/test/ui/tag-type-args.stderr
@@ -1,8 +1,18 @@
-error[E0107]: wrong number of type arguments: expected 1, found 0
+error[E0107]: missing generics for enum `Quux`
   --> $DIR/tag-type-args.rs:3:11
    |
 LL | fn foo(c: Quux) { assert!((false)); }
    |           ^^^^ expected 1 type argument
+   |
+note: enum defined here, with 1 type parameter: `T`
+  --> $DIR/tag-type-args.rs:1:6
+   |
+LL | enum Quux<T> { Bar }
+   |      ^^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL | fn foo(c: Quux<T>) { assert!((false)); }
+   |               ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/terminal-width/tabs-trimming.rs b/src/test/ui/terminal-width/tabs-trimming.rs
new file mode 100644
index 0000000..ade2175
--- /dev/null
+++ b/src/test/ui/terminal-width/tabs-trimming.rs
@@ -0,0 +1,13 @@
+// Test for #78438: ensure underline alignment with many tabs on the left, long line on the right
+
+// ignore-tidy-linelength
+// ignore-tidy-tab
+
+					fn main() {
+						let money = 42i32;
+						match money {
+							v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
+							//~^ ERROR variable `v` is not bound in all patterns
+							v => println!("Enough money {}", v),
+						}
+					}
diff --git a/src/test/ui/terminal-width/tabs-trimming.stderr b/src/test/ui/terminal-width/tabs-trimming.stderr
new file mode 100644
index 0000000..6c8d9af
--- /dev/null
+++ b/src/test/ui/terminal-width/tabs-trimming.stderr
@@ -0,0 +1,12 @@
+error[E0408]: variable `v` is not bound in all patterns
+  --> $DIR/tabs-trimming.rs:9:16
+   |
+LL | ...   v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT...
+   |       -       ^   ^ pattern doesn't bind `v`
+   |       |       |
+   |       |       pattern doesn't bind `v`
+   |       variable not in all patterns
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0408`.
diff --git a/src/test/ui/eprint-on-tls-drop.rs b/src/test/ui/threads-sendsync/eprint-on-tls-drop.rs
similarity index 100%
rename from src/test/ui/eprint-on-tls-drop.rs
rename to src/test/ui/threads-sendsync/eprint-on-tls-drop.rs
diff --git a/src/test/ui/threads-sendsync/thread-local-extern-static.rs b/src/test/ui/threads-sendsync/thread-local-extern-static.rs
index e10f517..a2dda31 100644
--- a/src/test/ui/threads-sendsync/thread-local-extern-static.rs
+++ b/src/test/ui/threads-sendsync/thread-local-extern-static.rs
@@ -11,7 +11,7 @@
 use std::cell::Cell;
 
 #[cfg(target_thread_local)]
-extern {
+extern "C" {
     #[thread_local]
     static FOO: Cell<u32>;
 }
diff --git a/src/test/ui/issues/issue-6334.rs b/src/test/ui/traits/issue-6334.rs
similarity index 100%
rename from src/test/ui/issues/issue-6334.rs
rename to src/test/ui/traits/issue-6334.rs
diff --git a/src/test/ui/issues/issue-65673.rs b/src/test/ui/traits/issue-65673.rs
similarity index 100%
rename from src/test/ui/issues/issue-65673.rs
rename to src/test/ui/traits/issue-65673.rs
diff --git a/src/test/ui/issues/issue-65673.stderr b/src/test/ui/traits/issue-65673.stderr
similarity index 100%
rename from src/test/ui/issues/issue-65673.stderr
rename to src/test/ui/traits/issue-65673.stderr
diff --git a/src/test/ui/issues/issue-9394-inherited-trait-calls.rs b/src/test/ui/traits/issue-9394-inherited-trait-calls.rs
similarity index 100%
rename from src/test/ui/issues/issue-9394-inherited-trait-calls.rs
rename to src/test/ui/traits/issue-9394-inherited-trait-calls.rs
diff --git a/src/test/ui/traits/trait-object-vs-lifetime.rs b/src/test/ui/traits/trait-object-vs-lifetime.rs
index e885cd2..e49d276 100644
--- a/src/test/ui/traits/trait-object-vs-lifetime.rs
+++ b/src/test/ui/traits/trait-object-vs-lifetime.rs
@@ -9,8 +9,8 @@
     let _: S<'static, dyn 'static +>;
     //~^ at least one trait is required for an object type
     let _: S<'static, 'static>;
-    //~^ ERROR wrong number of lifetime arguments: expected 1, found 2
-    //~| ERROR wrong number of type arguments: expected 1, found 0
+    //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+    //~| ERROR this struct takes 1 type argument but 0 type arguments were supplied
     let _: S<dyn 'static +, 'static>;
     //~^ ERROR type provided when a lifetime was expected
     //~| ERROR at least one trait is required for an object type
diff --git a/src/test/ui/traits/trait-object-vs-lifetime.stderr b/src/test/ui/traits/trait-object-vs-lifetime.stderr
index 8958547..620c816 100644
--- a/src/test/ui/traits/trait-object-vs-lifetime.stderr
+++ b/src/test/ui/traits/trait-object-vs-lifetime.stderr
@@ -4,17 +4,35 @@
 LL |     let _: S<'static, dyn 'static +>;
    |                       ^^^^^^^^^^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 1, found 2
-  --> $DIR/trait-object-vs-lifetime.rs:11:23
-   |
-LL |     let _: S<'static, 'static>;
-   |                       ^^^^^^^ unexpected lifetime argument
-
-error[E0107]: wrong number of type arguments: expected 1, found 0
+error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
   --> $DIR/trait-object-vs-lifetime.rs:11:12
    |
 LL |     let _: S<'static, 'static>;
-   |            ^^^^^^^^^^^^^^^^^^^ expected 1 type argument
+   |            ^        --------- help: remove this lifetime argument
+   |            |
+   |            expected 1 lifetime argument
+   |
+note: struct defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/trait-object-vs-lifetime.rs:4:8
+   |
+LL | struct S<'a, T>(&'a u8, T);
+   |        ^ --
+
+error[E0107]: this struct takes 1 type argument but 0 type arguments were supplied
+  --> $DIR/trait-object-vs-lifetime.rs:11:12
+   |
+LL |     let _: S<'static, 'static>;
+   |            ^ expected 1 type argument
+   |
+note: struct defined here, with 1 type parameter: `T`
+  --> $DIR/trait-object-vs-lifetime.rs:4:8
+   |
+LL | struct S<'a, T>(&'a u8, T);
+   |        ^     -
+help: add missing type argument
+   |
+LL |     let _: S<'static, 'static, T>;
+   |                              ^^^
 
 error[E0224]: at least one trait is required for an object type
   --> $DIR/trait-object-vs-lifetime.rs:14:14
diff --git a/src/test/ui/traits/trait-test-2.rs b/src/test/ui/traits/trait-test-2.rs
index 86570f1..a337731 100644
--- a/src/test/ui/traits/trait-test-2.rs
+++ b/src/test/ui/traits/trait-test-2.rs
@@ -6,8 +6,10 @@
 impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
 
 fn main() {
-    10.dup::<i32>(); //~ ERROR wrong number of type arguments: expected 0, found 1
-    10.blah::<i32, i32>(); //~ ERROR wrong number of type arguments: expected 1, found 2
+    10.dup::<i32>();
+    //~^ ERROR this associated function takes 0 type arguments but 1 type argument was supplied
+    10.blah::<i32, i32>();
+    //~^ ERROR this associated function takes 1 type argument but 2 type arguments were supplied
     (box 10 as Box<dyn bar>).dup();
     //~^ ERROR E0038
     //~| ERROR E0038
diff --git a/src/test/ui/traits/trait-test-2.stderr b/src/test/ui/traits/trait-test-2.stderr
index a06f6a4..a38d338 100644
--- a/src/test/ui/traits/trait-test-2.stderr
+++ b/src/test/ui/traits/trait-test-2.stderr
@@ -1,17 +1,33 @@
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/trait-test-2.rs:9:14
+error[E0107]: this associated function takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/trait-test-2.rs:9:8
    |
 LL |     10.dup::<i32>();
-   |              ^^^ unexpected type argument
+   |        ^^^------- help: remove these generics
+   |        |
+   |        expected 0 type arguments
+   |
+note: associated function defined here, with 0 type parameters
+  --> $DIR/trait-test-2.rs:4:16
+   |
+LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
+   |                ^^^
 
-error[E0107]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/trait-test-2.rs:10:20
+error[E0107]: this associated function takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/trait-test-2.rs:11:8
    |
 LL |     10.blah::<i32, i32>();
-   |                    ^^^ unexpected type argument
+   |        ^^^^      ----- help: remove this type argument
+   |        |
+   |        expected 1 type argument
+   |
+note: associated function defined here, with 1 type parameter: `X`
+  --> $DIR/trait-test-2.rs:4:39
+   |
+LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
+   |                                       ^^^^ -
 
 error[E0038]: the trait `bar` cannot be made into an object
-  --> $DIR/trait-test-2.rs:11:16
+  --> $DIR/trait-test-2.rs:13:16
    |
 LL |     (box 10 as Box<dyn bar>).dup();
    |                ^^^^^^^^^^^^ `bar` cannot be made into an object
@@ -28,7 +44,7 @@
    |       this trait cannot be made into an object...
 
 error[E0038]: the trait `bar` cannot be made into an object
-  --> $DIR/trait-test-2.rs:11:6
+  --> $DIR/trait-test-2.rs:13:6
    |
 LL |     (box 10 as Box<dyn bar>).dup();
    |      ^^^^^^ `bar` cannot be made into an object
diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr
index 78cdfb2..0f3c14b 100644
--- a/src/test/ui/try-block/try-block-in-edition2015.stderr
+++ b/src/test/ui/try-block/try-block-in-edition2015.stderr
@@ -13,7 +13,7 @@
 LL |     let try_result: Option<_> = try {
    |                                 ^^^ not a struct, variant or union type
    |
-   = note: if you want the `try` keyword, you need to be in the 2018 edition
+   = note: if you want the `try` keyword, you need Rust 2018 or later
 help: use `!` to invoke the macro
    |
 LL |     let try_result: Option<_> = try! {
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs
index f182c3b..f204035 100644
--- a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs
@@ -16,10 +16,10 @@
         //~^ ERROR type arguments are not allowed for this type [E0109]
         Self::<()>::TSVariant(());
         //~^ ERROR type arguments are not allowed for this type [E0109]
-        //~^^ ERROR mismatched types [E0308]
+        //~| ERROR mismatched types [E0308]
         Self::<()>::TSVariant::<()>(());
         //~^ ERROR type arguments are not allowed for this type [E0109]
-        //~^^ ERROR type arguments are not allowed for this type [E0109]
+        //~| ERROR type arguments are not allowed for this type [E0109]
     }
 
     fn s_variant() {
@@ -27,14 +27,14 @@
         //~^ ERROR mismatched types [E0308]
         Self::SVariant::<()> { v: () };
         //~^ ERROR type arguments are not allowed for this type [E0109]
-        //~^^ ERROR mismatched types [E0308]
+        //~| ERROR mismatched types [E0308]
         Self::<()>::SVariant { v: () };
         //~^ ERROR type arguments are not allowed for this type [E0109]
-        //~^^ ERROR mismatched types [E0308]
+        //~| ERROR mismatched types [E0308]
         Self::<()>::SVariant::<()> { v: () };
         //~^ ERROR type arguments are not allowed for this type [E0109]
-        //~^^ ERROR type arguments are not allowed for this type [E0109]
-        //~^^^ ERROR mismatched types [E0308]
+        //~| ERROR type arguments are not allowed for this type [E0109]
+        //~| ERROR mismatched types [E0308]
     }
 
     fn u_variant() {
@@ -44,7 +44,7 @@
         //~^ ERROR type arguments are not allowed for this type [E0109]
         Self::<()>::UVariant::<()>;
         //~^ ERROR type arguments are not allowed for this type [E0109]
-        //~^^ ERROR type arguments are not allowed for this type [E0109]
+        //~| ERROR type arguments are not allowed for this type [E0109]
     }
 }
 
@@ -62,10 +62,10 @@
     AliasFixed::TSVariant::<()>(());
     //~^ ERROR type arguments are not allowed for this type [E0109]
     AliasFixed::<()>::TSVariant(());
-    //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    //~^ ERROR this type alias takes 0 type arguments but 1 type argument was supplied [E0107]
     AliasFixed::<()>::TSVariant::<()>(());
     //~^ ERROR type arguments are not allowed for this type [E0109]
-    //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    //~| ERROR this type alias takes 0 type arguments but 1 type argument was supplied [E0107]
 
     // Struct variant
 
@@ -80,10 +80,10 @@
     AliasFixed::SVariant::<()> { v: () };
     //~^ ERROR type arguments are not allowed for this type [E0109]
     AliasFixed::<()>::SVariant { v: () };
-    //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    //~^ ERROR this type alias takes 0 type arguments but 1 type argument was supplied [E0107]
     AliasFixed::<()>::SVariant::<()> { v: () };
     //~^ ERROR type arguments are not allowed for this type [E0109]
-    //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    //~| ERROR this type alias takes 0 type arguments but 1 type argument was supplied [E0107]
 
     // Unit variant
 
@@ -98,8 +98,8 @@
     AliasFixed::UVariant::<()>;
     //~^ ERROR type arguments are not allowed for this type [E0109]
     AliasFixed::<()>::UVariant;
-    //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    //~^ ERROR this type alias takes 0 type arguments but 1 type argument was supplied [E0107]
     AliasFixed::<()>::UVariant::<()>;
     //~^ ERROR type arguments are not allowed for this type [E0109]
-    //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    //~| ERROR this type alias takes 0 type arguments but 1 type argument was supplied [E0107]
 }
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
index caea791..e83db3b 100644
--- a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
@@ -166,17 +166,33 @@
 LL |     AliasFixed::TSVariant::<()>(());
    |                             ^^ type argument not allowed
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:64:18
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/enum-variant-generic-args.rs:64:5
    |
 LL |     AliasFixed::<()>::TSVariant(());
-   |                  ^^ unexpected type argument
+   |     ^^^^^^^^^^------ help: remove these generics
+   |     |
+   |     expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/enum-variant-generic-args.rs:9:6
+   |
+LL | type AliasFixed = Enum<()>;
+   |      ^^^^^^^^^^
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:66:18
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/enum-variant-generic-args.rs:66:5
    |
 LL |     AliasFixed::<()>::TSVariant::<()>(());
-   |                  ^^ unexpected type argument
+   |     ^^^^^^^^^^------ help: remove these generics
+   |     |
+   |     expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/enum-variant-generic-args.rs:9:6
+   |
+LL | type AliasFixed = Enum<()>;
+   |      ^^^^^^^^^^
 
 error[E0109]: type arguments are not allowed for this type
   --> $DIR/enum-variant-generic-args.rs:66:35
@@ -208,17 +224,33 @@
 LL |     AliasFixed::SVariant::<()> { v: () };
    |                            ^^ type argument not allowed
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:82:18
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/enum-variant-generic-args.rs:82:5
    |
 LL |     AliasFixed::<()>::SVariant { v: () };
-   |                  ^^ unexpected type argument
+   |     ^^^^^^^^^^------ help: remove these generics
+   |     |
+   |     expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/enum-variant-generic-args.rs:9:6
+   |
+LL | type AliasFixed = Enum<()>;
+   |      ^^^^^^^^^^
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:84:18
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/enum-variant-generic-args.rs:84:5
    |
 LL |     AliasFixed::<()>::SVariant::<()> { v: () };
-   |                  ^^ unexpected type argument
+   |     ^^^^^^^^^^------ help: remove these generics
+   |     |
+   |     expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/enum-variant-generic-args.rs:9:6
+   |
+LL | type AliasFixed = Enum<()>;
+   |      ^^^^^^^^^^
 
 error[E0109]: type arguments are not allowed for this type
   --> $DIR/enum-variant-generic-args.rs:84:34
@@ -250,17 +282,33 @@
 LL |     AliasFixed::UVariant::<()>;
    |                            ^^ type argument not allowed
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:100:18
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/enum-variant-generic-args.rs:100:5
    |
 LL |     AliasFixed::<()>::UVariant;
-   |                  ^^ unexpected type argument
+   |     ^^^^^^^^^^------ help: remove these generics
+   |     |
+   |     expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/enum-variant-generic-args.rs:9:6
+   |
+LL | type AliasFixed = Enum<()>;
+   |      ^^^^^^^^^^
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:102:18
+error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/enum-variant-generic-args.rs:102:5
    |
 LL |     AliasFixed::<()>::UVariant::<()>;
-   |                  ^^ unexpected type argument
+   |     ^^^^^^^^^^------ help: remove these generics
+   |     |
+   |     expected 0 type arguments
+   |
+note: type alias defined here, with 0 type parameters
+  --> $DIR/enum-variant-generic-args.rs:9:6
+   |
+LL | type AliasFixed = Enum<()>;
+   |      ^^^^^^^^^^
 
 error[E0109]: type arguments are not allowed for this type
   --> $DIR/enum-variant-generic-args.rs:102:34
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
index 20e2605..1d52061 100644
--- a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
@@ -5,12 +5,6 @@
    |     ^^^^^^-- supplied 0 arguments
    |     |
    |     expected 1 argument
-   |
-note: tuple variant defined here
-  --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:5:5
-   |
-LL |     V(u8)
-   |     ^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
index 790aea8..be1dd1a 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
@@ -18,6 +18,11 @@
    |
    = note: expected type `for<'r> Fn<(&'r X,)>`
               found type `Fn<(&'static X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:25:9
+   |
+LL |         |x| x
+   |         ^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-57611-trait-alias.rs:17:16
@@ -27,6 +32,11 @@
    |
    = note: expected type `FnOnce<(&X,)>`
               found type `FnOnce<(&'static X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:25:9
+   |
+LL |         |x| x
+   |         ^^^^^
 
 error: aborting due to 4 previous errors
 
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
index 5e2a8db..9d9293e 100644
--- 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
@@ -6,6 +6,11 @@
    |
    = note: expected type `FnOnce<(&X,)>`
               found type `FnOnce<(&X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:25:9
+   |
+LL |         |x| x
+   |         ^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-57611-trait-alias.rs:17:16
@@ -15,6 +20,11 @@
    |
    = note: expected type `for<'r> Fn<(&'r X,)>`
               found type `Fn<(&'<empty> X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:25:9
+   |
+LL |         |x| x
+   |         ^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-57611-trait-alias.rs:17:16
@@ -24,6 +34,11 @@
    |
    = note: expected type `FnOnce<(&X,)>`
               found type `FnOnce<(&'<empty> X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:25:9
+   |
+LL |         |x| x
+   |         ^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-57611-trait-alias.rs:17:16
@@ -33,6 +48,11 @@
    |
    = note: expected type `for<'r> Fn<(&'r X,)>`
               found type `Fn<(&'<empty> X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:25:9
+   |
+LL |         |x| x
+   |         ^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-57611-trait-alias.rs:17:16
@@ -42,6 +62,11 @@
    |
    = note: expected type `FnOnce<(&X,)>`
               found type `FnOnce<(&'<empty> X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:25:9
+   |
+LL |         |x| x
+   |         ^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/type-param.rs b/src/test/ui/type-param.rs
index f5ac19c..ca2f24d 100644
--- a/src/test/ui/type-param.rs
+++ b/src/test/ui/type-param.rs
@@ -6,6 +6,6 @@
 
 // pretty-expanded FIXME #23616
 
-type lteq<T> = extern fn(T) -> bool;
+type lteq<T> = extern "C" fn(T) -> bool;
 
 pub fn main() { }
diff --git a/src/test/ui/type-params-in-for-each.rs b/src/test/ui/type-params-in-for-each.rs
index be4a018..53475d2 100644
--- a/src/test/ui/type-params-in-for-each.rs
+++ b/src/test/ui/type-params-in-for-each.rs
@@ -14,7 +14,7 @@
     while lo_ < hi { it(lo_); lo_ += 1; }
 }
 
-fn create_index<T>(_index: Vec<S<T>> , _hash_fn: extern fn(T) -> usize) {
+fn create_index<T>(_index: Vec<S<T>> , _hash_fn: extern "C" fn(T) -> usize) {
     range_(0, 256, |_i| {
         let _bucket: Vec<T> = Vec::new();
     })
diff --git a/src/test/ui/type/ascription/issue-34255-1.rs b/src/test/ui/type/ascription/issue-34255-1.rs
index 3aad085..44b47cc 100644
--- a/src/test/ui/type/ascription/issue-34255-1.rs
+++ b/src/test/ui/type/ascription/issue-34255-1.rs
@@ -7,7 +7,7 @@
         input_cells: Vec::new()
         //~^ ERROR cannot find value `input_cells` in this scope
         //~| ERROR parenthesized type parameters may only be used with a `Fn` trait
-        //~| ERROR wrong number of type arguments: expected at least 1, found 0
+        //~| ERROR missing generics for struct `Vec`
     }
 }
 
diff --git a/src/test/ui/type/ascription/issue-34255-1.stderr b/src/test/ui/type/ascription/issue-34255-1.stderr
index 402e54d..fc474e1 100644
--- a/src/test/ui/type/ascription/issue-34255-1.stderr
+++ b/src/test/ui/type/ascription/issue-34255-1.stderr
@@ -10,11 +10,21 @@
 LL |         input_cells: Vec::new()
    |                           ^^^^^ only `Fn` traits may use parentheses
 
-error[E0107]: wrong number of type arguments: expected at least 1, found 0
+error[E0107]: missing generics for struct `Vec`
   --> $DIR/issue-34255-1.rs:7:22
    |
 LL |         input_cells: Vec::new()
-   |                      ^^^^^^^^^^ expected at least 1 type argument
+   |                      ^^^ expected at least 1 type argument
+   |
+note: struct defined here, with at least 1 type parameter: `T`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+   |
+LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
+   |            ^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL |         input_cells: Vec<T>::new()
+   |                         ^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/type/ascription/issue-47666.stderr b/src/test/ui/type/ascription/issue-47666.stderr
index ba393ff..755eec2 100644
--- a/src/test/ui/type/ascription/issue-47666.stderr
+++ b/src/test/ui/type/ascription/issue-47666.stderr
@@ -1,4 +1,4 @@
-error: expected type, found reserved keyword `box`
+error: expected type, found `<[_]>::into_vec(box [0, 1])`
   --> $DIR/issue-47666.rs:3:25
    |
 LL |     let _ = Option:Some(vec![0, 1]);
diff --git a/src/test/ui/type/type-ascription-instead-of-initializer.stderr b/src/test/ui/type/type-ascription-instead-of-initializer.stderr
index 530f77e..e5666d4 100644
--- a/src/test/ui/type/type-ascription-instead-of-initializer.stderr
+++ b/src/test/ui/type/type-ascription-instead-of-initializer.stderr
@@ -14,6 +14,12 @@
    |            ^^^^^^^^^^^^^^^^^^ --  -- supplied 2 arguments
    |            |
    |            expected 1 argument
+   |
+note: associated function defined here
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+   |
+LL |     pub fn with_capacity(capacity: usize) -> Self {
+   |            ^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/type/type-dependent-def-issue-49241.stderr b/src/test/ui/type/type-dependent-def-issue-49241.stderr
index c5dcfa7..64c7687 100644
--- a/src/test/ui/type/type-dependent-def-issue-49241.stderr
+++ b/src/test/ui/type/type-dependent-def-issue-49241.stderr
@@ -2,7 +2,9 @@
   --> $DIR/type-dependent-def-issue-49241.rs:3:22
    |
 LL |     const l: usize = v.count();
-   |                      ^ non-constant value
+   |     -------          ^ non-constant value
+   |     |
+   |     help: consider using `let` instead of `const`: `let l`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs
index f466c19..f1659d0 100644
--- a/src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs
+++ b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs
@@ -1,19 +1,17 @@
 fn foo1<T:Copy<U>, U>(x: T) {}
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+//~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
 
 trait Trait: Copy<dyn Send> {}
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+//~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
 
 struct MyStruct1<T: Copy<T>>;
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+//~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
 
 struct MyStruct2<'a, T: Copy<'a>>;
-//~^ ERROR: wrong number of lifetime arguments: expected 0, found 1 [E0107]
-
+//~^ ERROR this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
 
 fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
-//~| ERROR: wrong number of lifetime arguments: expected 0, found 1
+//~^ ERROR this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+//~| ERROR this trait takes 0 type arguments but 1 type argument was supplied
 
-fn main() {
-}
+fn main() { }
diff --git a/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr
index 0be1c8e..777bc1c 100644
--- a/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr
+++ b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr
@@ -1,38 +1,86 @@
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:1:16
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:1:11
    |
 LL | fn foo1<T:Copy<U>, U>(x: T) {}
-   |                ^ unexpected type argument
+   |           ^^^^--- help: remove these generics
+   |           |
+   |           expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   |
+LL | pub trait Copy: Clone {
+   |           ^^^^
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:4:19
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:4:14
    |
 LL | trait Trait: Copy<dyn Send> {}
-   |                   ^^^^^^^^ unexpected type argument
+   |              ^^^^---------- help: remove these generics
+   |              |
+   |              expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   |
+LL | pub trait Copy: Clone {
+   |           ^^^^
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:7:26
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:7:21
    |
 LL | struct MyStruct1<T: Copy<T>>;
-   |                          ^ unexpected type argument
+   |                     ^^^^--- help: remove these generics
+   |                     |
+   |                     expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   |
+LL | pub trait Copy: Clone {
+   |           ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:10:30
+error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:10:25
    |
 LL | struct MyStruct2<'a, T: Copy<'a>>;
-   |                              ^^ unexpected lifetime argument
+   |                         ^^^^---- help: remove these generics
+   |                         |
+   |                         expected 0 lifetime arguments
+   |
+note: trait defined here, with 0 lifetime parameters
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   |
+LL | pub trait Copy: Clone {
+   |           ^^^^
 
-error[E0107]: wrong number of lifetime arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:14:20
+error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:13:15
    |
 LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
-   |                    ^^ unexpected lifetime argument
+   |               ^^^^ ---- help: remove this lifetime argument
+   |               |
+   |               expected 0 lifetime arguments
+   |
+note: trait defined here, with 0 lifetime parameters
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   |
+LL | pub trait Copy: Clone {
+   |           ^^^^
 
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:14:24
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:13:15
    |
 LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
-   |                        ^ unexpected type argument
+   |               ^^^^   --- help: remove this type argument
+   |               |
+   |               expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   |
+LL | pub trait Copy: Clone {
+   |           ^^^^
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.rs b/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.rs
index 57ab7de..8f8917e 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.rs
+++ b/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.rs
@@ -7,5 +7,5 @@
 
 pub fn main() {
     let c: Foo<_, _> = Foo { r: &5 };
-    //~^ ERROR wrong number of type arguments: expected 1, found 2 [E0107]
+    //~^ ERROR this struct takes 1 type argument but 2 type arguments were supplied
 }
diff --git a/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr b/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr
index 8186d75..01ab8e7 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/typeck_type_placeholder_lifetime_1.rs:9:19
+error[E0107]: this struct takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/typeck_type_placeholder_lifetime_1.rs:9:12
    |
 LL |     let c: Foo<_, _> = Foo { r: &5 };
-   |                   ^ unexpected type argument
+   |            ^^^  --- help: remove this type argument
+   |            |
+   |            expected 1 type argument
+   |
+note: struct defined here, with 1 type parameter: `T`
+  --> $DIR/typeck_type_placeholder_lifetime_1.rs:4:8
+   |
+LL | struct Foo<'a, T:'a> {
+   |        ^^^     -
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.rs b/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.rs
index b68d283..b491a7e 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.rs
+++ b/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.rs
@@ -7,5 +7,5 @@
 
 pub fn main() {
     let c: Foo<_, usize> = Foo { r: &5 };
-    //~^ ERROR wrong number of type arguments: expected 1, found 2 [E0107]
+    //~^ ERROR this struct takes 1 type argument but 2 type arguments were supplied
 }
diff --git a/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr b/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr
index 9b0f969..6d03b83 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/typeck_type_placeholder_lifetime_2.rs:9:19
+error[E0107]: this struct takes 1 type argument but 2 type arguments were supplied
+  --> $DIR/typeck_type_placeholder_lifetime_2.rs:9:12
    |
 LL |     let c: Foo<_, usize> = Foo { r: &5 };
-   |                   ^^^^^ unexpected type argument
+   |            ^^^  ------- help: remove this type argument
+   |            |
+   |            expected 1 type argument
+   |
+note: struct defined here, with 1 type parameter: `T`
+  --> $DIR/typeck_type_placeholder_lifetime_2.rs:4:8
+   |
+LL | struct Foo<'a, T:'a> {
+   |        ^^^     -
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typestate-cfg-nesting.rs b/src/test/ui/typestate-cfg-nesting.rs
deleted file mode 100644
index 5718e0e..0000000
--- a/src/test/ui/typestate-cfg-nesting.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// run-pass
-
-#![allow(dead_code)]
-#![allow(unused_assignments)]
-#![allow(unknown_lints)]
-// pretty-expanded FIXME #23616
-
-#![allow(dead_assignment)]
-#![allow(unused_variables)]
-
-fn f() {
-    let x = 10; let mut y = 11;
-    if true { match x { _ => { y = x; } } } else { }
-}
-
-pub fn main() {
-    let x = 10;
-    let mut y = 11;
-    if true { while false { y = x; } } else { }
-}
diff --git a/src/test/ui/ufcs/ufcs-qpath-missing-params.rs b/src/test/ui/ufcs/ufcs-qpath-missing-params.rs
index 8b66a8f..7d2fbda 100644
--- a/src/test/ui/ufcs/ufcs-qpath-missing-params.rs
+++ b/src/test/ui/ufcs/ufcs-qpath-missing-params.rs
@@ -12,5 +12,9 @@
 
 fn main() {
     <String as IntoCow>::into_cow("foo".to_string());
-    //~^ ERROR wrong number of type arguments: expected 1, found 0
+    //~^ ERROR missing generics for trait `IntoCow`
+
+    <String as IntoCow>::into_cow::<str>("foo".to_string());
+    //~^ ERROR missing generics for trait `IntoCow`
+    //~| ERROR this associated function takes 0 type arguments but 1 type argument was supplied
 }
diff --git a/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr b/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
index 1145f1e..e3fcef3 100644
--- a/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
+++ b/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
@@ -1,9 +1,49 @@
-error[E0107]: wrong number of type arguments: expected 1, found 0
-  --> $DIR/ufcs-qpath-missing-params.rs:14:5
+error[E0107]: missing generics for trait `IntoCow`
+  --> $DIR/ufcs-qpath-missing-params.rs:14:16
    |
 LL |     <String as IntoCow>::into_cow("foo".to_string());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument
+   |                ^^^^^^^ expected 1 type argument
+   |
+note: trait defined here, with 1 type parameter: `B`
+  --> $DIR/ufcs-qpath-missing-params.rs:3:11
+   |
+LL | pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
+   |           ^^^^^^^     -
+help: use angle brackets to add missing type argument
+   |
+LL |     <String as IntoCow<B>>::into_cow("foo".to_string());
+   |                       ^^^
 
-error: aborting due to previous error
+error[E0107]: missing generics for trait `IntoCow`
+  --> $DIR/ufcs-qpath-missing-params.rs:17:16
+   |
+LL |     <String as IntoCow>::into_cow::<str>("foo".to_string());
+   |                ^^^^^^^ expected 1 type argument
+   |
+note: trait defined here, with 1 type parameter: `B`
+  --> $DIR/ufcs-qpath-missing-params.rs:3:11
+   |
+LL | pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
+   |           ^^^^^^^     -
+help: use angle brackets to add missing type argument
+   |
+LL |     <String as IntoCow<B>>::into_cow::<str>("foo".to_string());
+   |                       ^^^
+
+error[E0107]: this associated function takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/ufcs-qpath-missing-params.rs:17:26
+   |
+LL |     <String as IntoCow>::into_cow::<str>("foo".to_string());
+   |                          ^^^^^^^^------- help: remove these generics
+   |                          |
+   |                          expected 0 type arguments
+   |
+note: associated function defined here, with 0 type parameters
+  --> $DIR/ufcs-qpath-missing-params.rs:4:8
+   |
+LL |     fn into_cow(self) -> Cow<'a, B>;
+   |        ^^^^^^^^
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/unboxed-closures/issue-30906.stderr b/src/test/ui/unboxed-closures/issue-30906.stderr
index 5f343ff..ecf3a96 100644
--- a/src/test/ui/unboxed-closures/issue-30906.stderr
+++ b/src/test/ui/unboxed-closures/issue-30906.stderr
@@ -2,10 +2,15 @@
   --> $DIR/issue-30906.rs:15:5
    |
 LL |     test(Compose(f, |_| {}));
-   |     ^^^^ one type is more general than the other
+   |     ^^^^ lifetime mismatch
    |
    = note: expected type `FnOnce<(&'x str,)>`
               found type `FnOnce<(&str,)>`
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-30906.rs:3:12
+   |
+LL | fn test<F: for<'x> FnOnce<(&'x str,)>>(_: F) {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.rs
index 76c928d..65f4007 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.rs
@@ -28,7 +28,7 @@
 }
 
 fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) {
-//~^ ERROR wrong number of lifetime arguments: expected 1, found 0
+    //~^ ERROR this trait takes 1 lifetime argument but 0 lifetime arguments were supplied
     // Here, the omitted lifetimes are expanded to distinct things.
     same_type(x, y)
 }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr
index e9d5198..016fc4d 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr
@@ -1,8 +1,14 @@
-error[E0107]: wrong number of lifetime arguments: expected 1, found 0
+error[E0107]: this trait takes 1 lifetime argument but 0 lifetime arguments were supplied
   --> $DIR/unboxed-closure-sugar-region.rs:30:51
    |
 LL | fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) {
-   |                                                   ^^^^^^^^^^ expected 1 lifetime argument
+   |                                                   ^^^ expected 1 lifetime argument
+   |
+note: trait defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/unboxed-closure-sugar-region.rs:10:7
+   |
+LL | trait Foo<'a,T> {
+   |       ^^^ --
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
index c96a6fa..a82856a 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
@@ -7,7 +7,7 @@
 fn bar() {
     let x: Box<Bar()> = panic!();
     //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
-    //~| ERROR wrong number of type arguments: expected 1, found 0
+    //~| ERROR missing generics for struct `Bar`
 }
 
 fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
index 3261942..d81975a 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
@@ -4,11 +4,21 @@
 LL |     let x: Box<Bar()> = panic!();
    |                ^^^^^ only `Fn` traits may use parentheses
 
-error[E0107]: wrong number of type arguments: expected 1, found 0
+error[E0107]: missing generics for struct `Bar`
   --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:16
    |
 LL |     let x: Box<Bar()> = panic!();
-   |                ^^^^^ expected 1 type argument
+   |                ^^^ expected 1 type argument
+   |
+note: struct defined here, with 1 type parameter: `A`
+  --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:3:8
+   |
+LL | struct Bar<A> {
+   |        ^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL |     let x: Box<Bar<A>()> = panic!();
+   |                   ^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
index 1af7f55..b44505f 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
@@ -6,7 +6,7 @@
 
 fn foo(b: Box<Bar()>) {
     //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
-    //~| ERROR wrong number of type arguments: expected 1, found 0
+    //~| ERROR missing generics for struct `Bar`
 }
 
 fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
index ba93b60..80d7c24 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
@@ -4,11 +4,21 @@
 LL | fn foo(b: Box<Bar()>) {
    |               ^^^^^ only `Fn` traits may use parentheses
 
-error[E0107]: wrong number of type arguments: expected 1, found 0
+error[E0107]: missing generics for struct `Bar`
   --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:15
    |
 LL | fn foo(b: Box<Bar()>) {
-   |               ^^^^^ expected 1 type argument
+   |               ^^^ expected 1 type argument
+   |
+note: struct defined here, with 1 type parameter: `A`
+  --> $DIR/unboxed-closure-sugar-used-on-struct.rs:3:8
+   |
+LL | struct Bar<A> {
+   |        ^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL | fn foo(b: Box<Bar<A>()>) {
+   |                  ^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs
index 01c76d6..a496b7d 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs
@@ -3,7 +3,7 @@
 trait Three<A,B,C> { fn dummy(&self) -> (A,B,C); }
 
 fn foo(_: &dyn Three())
-//~^ ERROR wrong number of type arguments
+//~^ ERROR this trait takes 3 type arguments but only 1 type argument was supplied
 //~| ERROR associated type `Output` not found
 {}
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
index f42ac38..ef5e7d2 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of type arguments: expected 3, found 1
+error[E0107]: this trait takes 3 type arguments but only 1 type argument was supplied
   --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:16
    |
 LL | fn foo(_: &dyn Three())
-   |                ^^^^^^^ expected 3 type arguments
+   |                ^^^^^-- supplied 1 type argument
+   |                |
+   |                expected 3 type arguments
+   |
+note: trait defined here, with 3 type parameters: `A`, `B`, `C`
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:3:7
+   |
+LL | trait Three<A,B,C> { fn dummy(&self) -> (A,B,C); }
+   |       ^^^^^ - - -
 
 error[E0220]: associated type `Output` not found for `Three<(), [type error], [type error]>`
   --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:16
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs
index bc9901c..d0c8515 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs
@@ -2,9 +2,27 @@
 
 trait Zero { fn dummy(&self); }
 
-fn foo(_: dyn Zero())
-    //~^ ERROR wrong number of type arguments
+fn foo1(_: dyn Zero()) {
+    //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
     //~| ERROR associated type `Output` not found for `Zero`
-{}
+}
+
+fn foo2(_: dyn Zero<usize>) {
+    //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+}
+
+fn foo3(_: dyn Zero <   usize   >) {
+    //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+}
+
+fn foo4(_: dyn Zero(usize)) {
+    //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+    //~| ERROR associated type `Output` not found for `Zero`
+}
+
+fn foo5(_: dyn Zero (   usize   )) {
+    //~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+    //~| ERROR associated type `Output` not found for `Zero`
+}
 
 fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr
index 8185a79..2e620a5 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr
@@ -1,16 +1,92 @@
-error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:15
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:16
    |
-LL | fn foo(_: dyn Zero())
-   |               ^^^^^^ unexpected type argument
+LL | fn foo1(_: dyn Zero()) {
+   |                ^^^^-- help: remove these parenthetical generics
+   |                |
+   |                expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7
+   |
+LL | trait Zero { fn dummy(&self); }
+   |       ^^^^
 
 error[E0220]: associated type `Output` not found for `Zero`
-  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:15
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:16
    |
-LL | fn foo(_: dyn Zero())
-   |               ^^^^^^ associated type `Output` not found
+LL | fn foo1(_: dyn Zero()) {
+   |                ^^^^^^ associated type `Output` not found
 
-error: aborting due to 2 previous errors
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:10:16
+   |
+LL | fn foo2(_: dyn Zero<usize>) {
+   |                ^^^^------- help: remove these generics
+   |                |
+   |                expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7
+   |
+LL | trait Zero { fn dummy(&self); }
+   |       ^^^^
+
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:14:16
+   |
+LL | fn foo3(_: dyn Zero <   usize   >) {
+   |                ^^^^-------------- help: remove these generics
+   |                |
+   |                expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7
+   |
+LL | trait Zero { fn dummy(&self); }
+   |       ^^^^
+
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:18:16
+   |
+LL | fn foo4(_: dyn Zero(usize)) {
+   |                ^^^^------- help: remove these parenthetical generics
+   |                |
+   |                expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7
+   |
+LL | trait Zero { fn dummy(&self); }
+   |       ^^^^
+
+error[E0220]: associated type `Output` not found for `Zero`
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:18:16
+   |
+LL | fn foo4(_: dyn Zero(usize)) {
+   |                ^^^^^^^^^^^ associated type `Output` not found
+
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:23:16
+   |
+LL | fn foo5(_: dyn Zero (   usize   )) {
+   |                ^^^^-------------- help: remove these parenthetical generics
+   |                |
+   |                expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7
+   |
+LL | trait Zero { fn dummy(&self); }
+   |       ^^^^
+
+error[E0220]: associated type `Output` not found for `Zero`
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:23:16
+   |
+LL | fn foo5(_: dyn Zero (   usize   )) {
+   |                ^^^^^^^^^^^^^^^^^^ associated type `Output` not found
+
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0107, E0220.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs
index 3e5342c..5a47942 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs
@@ -3,7 +3,7 @@
 trait Trait {}
 
 fn f<F:Trait(isize) -> isize>(x: F) {}
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
-//~| ERROR E0220
+//~^ ERROR this trait takes 0 type arguments but 1 type argument was supplied
+//~| ERROR associated type `Output` not found for `Trait`
 
 fn main() {}
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr
index c81402a..b88a316 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr
@@ -1,8 +1,16 @@
-error[E0107]: wrong number of type arguments: expected 0, found 1
+error[E0107]: this trait takes 0 type arguments but 1 type argument was supplied
   --> $DIR/unboxed-closure-sugar-wrong-trait.rs:5:8
    |
 LL | fn f<F:Trait(isize) -> isize>(x: F) {}
-   |        ^^^^^^^^^^^^ unexpected type argument
+   |        ^^^^^------- help: remove these parenthetical generics
+   |        |
+   |        expected 0 type arguments
+   |
+note: trait defined here, with 0 type parameters
+  --> $DIR/unboxed-closure-sugar-wrong-trait.rs:3:7
+   |
+LL | trait Trait {}
+   |       ^^^^^
 
 error[E0220]: associated type `Output` not found for `Trait`
   --> $DIR/unboxed-closure-sugar-wrong-trait.rs:5:24
diff --git a/src/test/ui/underscore-imports/hygiene.rs b/src/test/ui/underscore-imports/hygiene.rs
index a254f6e..c4db652 100644
--- a/src/test/ui/underscore-imports/hygiene.rs
+++ b/src/test/ui/underscore-imports/hygiene.rs
@@ -1,5 +1,6 @@
-// Make sure that underscore imports have the same hygiene considerations as
-// other imports.
+// Make sure that underscore imports have the same hygiene considerations as other imports.
+
+// check-pass
 
 #![feature(decl_macro)]
 
@@ -7,7 +8,6 @@
     pub use std::ops::Deref as _;
 }
 
-
 macro glob_import() {
     pub use crate::x::*;
 }
@@ -35,6 +35,6 @@
     use crate::z::*;
     glob_import!();
     underscore_import!();
-    (&()).deref();              //~ ERROR no method named `deref`
-    (&mut ()).deref_mut();      //~ ERROR no method named `deref_mut`
+    (&()).deref();
+    (&mut ()).deref_mut();
 }
diff --git a/src/test/ui/underscore-imports/hygiene.stderr b/src/test/ui/underscore-imports/hygiene.stderr
deleted file mode 100644
index 2983613..0000000
--- a/src/test/ui/underscore-imports/hygiene.stderr
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0599]: no method named `deref` found for reference `&()` in the current scope
-  --> $DIR/hygiene.rs:38:11
-   |
-LL |     (&()).deref();
-   |           ^^^^^ method not found in `&()`
-   |
-   = help: items from traits can only be used if the trait is in scope
-help: the following trait is implemented but not in scope; perhaps add a `use` for it:
-   |
-LL | use std::ops::Deref;
-   |
-
-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();
-   |               ^^^^^^^^^ method not found in `&mut ()`
-   |
-   = help: items from traits can only be used if the trait is in scope
-help: the following trait is implemented but not in scope; perhaps add a `use` for it:
-   |
-LL | use std::ops::DerefMut;
-   |
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
index 960c479..7b999f5 100644
--- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
+++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
@@ -23,6 +23,7 @@
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&Void`
+   = note: references are always considered inhabited
 
 error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty
   --> $DIR/uninhabited-matches-feature-gated.rs:18:19
diff --git a/src/test/ui/unique/unique-ffi-symbols.rs b/src/test/ui/unique/unique-ffi-symbols.rs
index b0fe22b..77b5ead 100644
--- a/src/test/ui/unique/unique-ffi-symbols.rs
+++ b/src/test/ui/unique/unique-ffi-symbols.rs
@@ -3,12 +3,12 @@
 // whenever the item path wasn't enough to disambiguate between them.
 fn main() {
     let a = {
-        extern fn good() -> i32 { return 0; }
-        good as extern fn() -> i32
+        extern "C" fn good() -> i32 { return 0; }
+        good as extern "C" fn() -> i32
     };
     let b = {
-        extern fn good() -> i32 { return 5; }
-        good as extern fn() -> i32
+        extern "C" fn good() -> i32 { return 5; }
+        good as extern "C" fn() -> i32
     };
 
     assert!(a != b);
diff --git a/src/test/ui/issues/issue-45087-unreachable-unsafe.rs b/src/test/ui/unsafe/issue-45087-unreachable-unsafe.rs
similarity index 100%
rename from src/test/ui/issues/issue-45087-unreachable-unsafe.rs
rename to src/test/ui/unsafe/issue-45087-unreachable-unsafe.rs
diff --git a/src/test/ui/issues/issue-45087-unreachable-unsafe.stderr b/src/test/ui/unsafe/issue-45087-unreachable-unsafe.stderr
similarity index 100%
rename from src/test/ui/issues/issue-45087-unreachable-unsafe.stderr
rename to src/test/ui/unsafe/issue-45087-unreachable-unsafe.stderr
diff --git a/src/test/ui/unsafe/ranged_ints3_const.rs b/src/test/ui/unsafe/ranged_ints3_const.rs
index 7b03d8e..c069ae7 100644
--- a/src/test/ui/unsafe/ranged_ints3_const.rs
+++ b/src/test/ui/unsafe/ranged_ints3_const.rs
@@ -9,13 +9,13 @@
 
 const fn foo() -> NonZero<Cell<u32>> {
     let mut x = unsafe { NonZero(Cell::new(1)) };
-    let y = &x.0; //~ ERROR cannot borrow a constant which may contain interior mutability
+    let y = &x.0; //~ ERROR the borrowed element may contain interior mutability
     //~^ ERROR borrow of layout constrained field with interior mutability
     unsafe { NonZero(Cell::new(1)) }
 }
 
 const fn bar() -> NonZero<Cell<u32>> {
     let mut x = unsafe { NonZero(Cell::new(1)) };
-    let y = unsafe { &x.0 }; //~ ERROR cannot borrow a constant which may contain interior mut
+    let y = unsafe { &x.0 }; //~ ERROR the borrowed element may contain interior mutability
     unsafe { NonZero(Cell::new(1)) }
 }
diff --git a/src/test/ui/unsafe/ranged_ints3_const.stderr b/src/test/ui/unsafe/ranged_ints3_const.stderr
index d2eb3bc..2150055 100644
--- a/src/test/ui/unsafe/ranged_ints3_const.stderr
+++ b/src/test/ui/unsafe/ranged_ints3_const.stderr
@@ -1,14 +1,20 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/ranged_ints3_const.rs:12:13
    |
 LL |     let y = &x.0;
    |             ^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
 
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/ranged_ints3_const.rs:19:22
    |
 LL |     let y = unsafe { &x.0 };
    |                      ^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
 
 error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
   --> $DIR/ranged_ints3_const.rs:12:13
@@ -20,5 +26,5 @@
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0133, E0492.
+Some errors have detailed explanations: E0133, E0658.
 For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-move-val-init.rs b/src/test/ui/unsafe/unsafe-move-val-init.rs
deleted file mode 100644
index 24249a7..0000000
--- a/src/test/ui/unsafe/unsafe-move-val-init.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![feature(core_intrinsics)]
-
-use std::intrinsics;
-
-// `move_val_init` has an odd desugaring, check that it is still treated
-// as unsafe.
-fn main() {
-    intrinsics::move_val_init(1 as *mut u32, 1);
-    //~^ ERROR dereference of raw pointer is unsafe
-}
diff --git a/src/test/ui/unsafe/unsafe-move-val-init.stderr b/src/test/ui/unsafe/unsafe-move-val-init.stderr
deleted file mode 100644
index 44c2aae..0000000
--- a/src/test/ui/unsafe/unsafe-move-val-init.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/unsafe-move-val-init.rs:8:5
-   |
-LL |     intrinsics::move_val_init(1 as *mut u32, 1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
-   |
-   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsized-locals/borrow-after-move.stderr b/src/test/ui/unsized-locals/borrow-after-move.stderr
index 5934276..4f2bc06 100644
--- a/src/test/ui/unsized-locals/borrow-after-move.stderr
+++ b/src/test/ui/unsized-locals/borrow-after-move.stderr
@@ -51,7 +51,7 @@
 LL |         println!("{}", &y);
    |                        ^^ value borrowed here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `y`
+note: this function takes ownership of the receiver `self`, which moves `y`
   --> $DIR/borrow-after-move.rs:5:12
    |
 LL |     fn foo(self) -> String;
diff --git a/src/test/ui/unsized-locals/double-move.stderr b/src/test/ui/unsized-locals/double-move.stderr
index b897dbb..4bb2ad8 100644
--- a/src/test/ui/unsized-locals/double-move.stderr
+++ b/src/test/ui/unsized-locals/double-move.stderr
@@ -47,7 +47,7 @@
 LL |         y.foo();
    |         ^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `y`
+note: this function takes ownership of the receiver `self`, which moves `y`
   --> $DIR/double-move.rs:5:12
    |
 LL |     fn foo(self) -> String;
diff --git a/src/test/ui/use/use-after-move-self-based-on-type.stderr b/src/test/ui/use/use-after-move-self-based-on-type.stderr
index b9440f4..7fdc4ab 100644
--- a/src/test/ui/use/use-after-move-self-based-on-type.stderr
+++ b/src/test/ui/use/use-after-move-self-based-on-type.stderr
@@ -8,7 +8,7 @@
 LL |         return self.x;
    |                ^^^^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `self`
+note: this function takes ownership of the receiver `self`, which moves `self`
   --> $DIR/use-after-move-self-based-on-type.rs:15:16
    |
 LL |     pub fn bar(self) {}
diff --git a/src/test/ui/use/use-after-move-self.stderr b/src/test/ui/use/use-after-move-self.stderr
index 3da53b0..073deee 100644
--- a/src/test/ui/use/use-after-move-self.stderr
+++ b/src/test/ui/use/use-after-move-self.stderr
@@ -8,7 +8,7 @@
 LL |         return *self.x;
    |                ^^^^^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `self`
+note: this function takes ownership of the receiver `self`, which moves `self`
   --> $DIR/use-after-move-self.rs:13:16
    |
 LL |     pub fn bar(self) {}
diff --git a/src/test/ui/walk-struct-literal-with.stderr b/src/test/ui/walk-struct-literal-with.stderr
index ece63a2..cda08b0 100644
--- a/src/test/ui/walk-struct-literal-with.stderr
+++ b/src/test/ui/walk-struct-literal-with.stderr
@@ -8,7 +8,7 @@
 LL |     println!("{}", start.test);
    |                    ^^^^^^^^^^ value borrowed here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `start`
+note: this function takes ownership of the receiver `self`, which moves `start`
   --> $DIR/walk-struct-literal-with.rs:7:28
    |
 LL |     fn make_string_bar(mut self) -> Mine{
diff --git a/src/test/ui/warn-ctypes-inhibit.rs b/src/test/ui/warn-ctypes-inhibit.rs
index ab9634d..15d8b09 100644
--- a/src/test/ui/warn-ctypes-inhibit.rs
+++ b/src/test/ui/warn-ctypes-inhibit.rs
@@ -4,14 +4,12 @@
 // compile-flags:-D improper-ctypes
 
 // pretty-expanded FIXME #23616
-
 #![allow(improper_ctypes)]
 
 mod libc {
-    extern {
+    extern "C" {
         pub fn malloc(size: isize) -> *const u8;
     }
 }
 
-pub fn main() {
-}
+pub fn main() {}
diff --git a/src/test/ui/wasm-import-module.rs b/src/test/ui/wasm-import-module.rs
index 16d628a..4152a10 100644
--- a/src/test/ui/wasm-import-module.rs
+++ b/src/test/ui/wasm-import-module.rs
@@ -1,10 +1,10 @@
 #[link(name = "...", wasm_import_module)] //~ ERROR: must be of the form
-extern {}
+extern "C" {}
 
 #[link(name = "...", wasm_import_module(x))] //~ ERROR: must be of the form
-extern {}
+extern "C" {}
 
 #[link(name = "...", wasm_import_module())] //~ ERROR: must be of the form
-extern {}
+extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/wasm/wasm-hang-issue-76281.rs b/src/test/ui/wasm/wasm-hang-issue-76281.rs
new file mode 100644
index 0000000..a4adfa6
--- /dev/null
+++ b/src/test/ui/wasm/wasm-hang-issue-76281.rs
@@ -0,0 +1,12 @@
+// only-wasm32
+// compile-flags: -C opt-level=2
+// build-pass
+
+// Regression test for #76281.
+// This seems like an issue related to LLVM rather than
+// libs-impl so place here.
+
+fn main() {
+    let mut v: Vec<&()> = Vec::new();
+    v.sort_by_key(|&r| r as *const ());
+}
diff --git a/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs b/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs
new file mode 100644
index 0000000..8386959
--- /dev/null
+++ b/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs
@@ -0,0 +1,17 @@
+// Regression test for #80468.
+
+#![crate_type = "lib"]
+
+pub trait Trait {}
+
+#[repr(transparent)]
+pub struct Wrapper<T: Trait>(T);
+
+#[repr(transparent)]
+pub struct Ref<'a>(&'a u8);
+
+impl Trait for Ref {} //~ ERROR:  implicit elided lifetime not allowed here
+
+extern "C" {
+    pub fn repro(_: Wrapper<Ref>); //~ ERROR: mismatched types
+}
diff --git a/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr b/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr
new file mode 100644
index 0000000..bb839d0
--- /dev/null
+++ b/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr
@@ -0,0 +1,24 @@
+error[E0726]: implicit elided lifetime not allowed here
+  --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:16
+   |
+LL | impl Trait for Ref {}
+   |                ^^^- help: indicate the anonymous lifetime: `<'_>`
+
+error[E0308]: mismatched types
+  --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:21
+   |
+LL |     pub fn repro(_: Wrapper<Ref>);
+   |                     ^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected trait `Trait`
+              found trait `Trait`
+note: the anonymous lifetime #1 defined on the method body at 16:5...
+  --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:5
+   |
+LL |     pub fn repro(_: Wrapper<Ref>);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/tools/cargo b/src/tools/cargo
index 75d5d8c..a73e5b7 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 75d5d8cffe3464631f82dcd3c470b78dc1dda8bb
+Subproject commit a73e5b7d567c3036b296fc6b33ed52c5edcd882e
diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md
new file mode 100644
index 0000000..f46828f
--- /dev/null
+++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md
@@ -0,0 +1,35 @@
+---
+name: Bug Report (False Negative)
+about: Create a bug report about missing warnings from a lint
+labels: L-bug, L-false-negative
+---
+<!--
+Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
+along with any information you feel relevant to replicating the bug.
+-->
+Lint name:
+
+
+I tried this code:
+
+```rust
+<code>
+```
+
+I expected to see this happen: *explanation*
+
+Instead, this happened: *explanation*
+
+### Meta
+
+- `cargo clippy -V`: e.g. clippy 0.0.212 (f455e46 2020-06-20)
+- `rustc -Vv`:
+  ```
+  rustc 1.46.0-nightly (f455e46ea 2020-06-20)
+  binary: rustc
+  commit-hash: f455e46eae1a227d735091091144601b467e1565
+  commit-date: 2020-06-20
+  host: x86_64-unknown-linux-gnu
+  release: 1.46.0-nightly
+  LLVM version: 10.0
+  ```
diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md
new file mode 100644
index 0000000..92a7373
--- /dev/null
+++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md
@@ -0,0 +1,35 @@
+---
+name: Bug Report (False Positive)
+about: Create a bug report about a wrongly emitted lint warning
+labels: L-bug, L-false-positive
+---
+<!--
+Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
+along with any information you feel relevant to replicating the bug.
+-->
+Lint name:
+
+
+I tried this code:
+
+```rust
+<code>
+```
+
+I expected to see this happen: *explanation*
+
+Instead, this happened: *explanation*
+
+### Meta
+
+- `cargo clippy -V`: e.g. clippy 0.0.212 (f455e46 2020-06-20)
+- `rustc -Vv`:
+  ```
+  rustc 1.46.0-nightly (f455e46ea 2020-06-20)
+  binary: rustc
+  commit-hash: f455e46eae1a227d735091091144601b467e1565
+  commit-date: 2020-06-20
+  host: x86_64-unknown-linux-gnu
+  release: 1.46.0-nightly
+  LLVM version: 10.0
+  ```
diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml
index 530e600..9d5e12a 100644
--- a/src/tools/clippy/.github/workflows/clippy.yml
+++ b/src/tools/clippy/.github/workflows/clippy.yml
@@ -50,6 +50,9 @@
     - name: Build
       run: cargo build --features deny-warnings,internal-lints
 
+    - name: Test "--fix -Zunstable-options"
+      run: cargo run --features deny-warnings,internal-lints --bin cargo-clippy -- clippy --fix -Zunstable-options
+
     - name: Test
       run: cargo test --features deny-warnings,internal-lints
 
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index af3b1c1..de8da99 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -1841,6 +1841,7 @@
 [`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy
 [`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref
 [`from_iter_instead_of_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_iter_instead_of_collect
+[`from_over_into`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into
 [`future_not_send`]: https://rust-lang.github.io/rust-clippy/master/index.html#future_not_send
 [`get_last_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_last_with_len
 [`get_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_unwrap
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index a765390..e60aa47 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.0.212"
+version = "0.1.51"
 authors = [
 	"Manish Goregaokar <manishsmail@gmail.com>",
 	"Andre Bogus <bogusandre@gmail.com>",
@@ -29,7 +29,7 @@
 
 [dependencies]
 # begin automatic update
-clippy_lints = { version = "0.0.212", path = "clippy_lints" }
+clippy_lints = { version = "0.1.50", path = "clippy_lints" }
 # end automatic update
 semver = "0.11"
 rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" }
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index aaa55e1..a4928e1 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -10,16 +10,16 @@
 Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html).
 You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category.
 
-Category | Description | Default level
--- | -- | --
-`clippy::all` | all lints that are on by default (correctness, style, complexity, perf) | **warn/deny**
-`clippy::correctness` | code that is outright wrong or very useless | **deny**
-`clippy::style` | code that should be written in a more idiomatic way | **warn**
-`clippy::complexity` | code that does something simple but in a complex way | **warn**
-`clippy::perf` | code that can be written to run faster | **warn**
-`clippy::pedantic` | lints which are rather strict or might have false positives | allow
-`clippy::nursery` | new lints that are still under development | allow
-`clippy::cargo` | lints for the cargo manifest | allow
+| Category              | Description                                                             | Default level |
+| --------------------- | ----------------------------------------------------------------------- | ------------- |
+| `clippy::all`         | all lints that are on by default (correctness, style, complexity, perf) | **warn/deny** |
+| `clippy::correctness` | code that is outright wrong or very useless                             | **deny**      |
+| `clippy::style`       | code that should be written in a more idiomatic way                     | **warn**      |
+| `clippy::complexity`  | code that does something simple but in a complex way                    | **warn**      |
+| `clippy::perf`        | code that can be written to run faster                                  | **warn**      |
+| `clippy::pedantic`    | lints which are rather strict or might have false positives             | allow         |
+| `clippy::nursery`     | new lints that are still under development                              | allow         |
+| `clippy::cargo`       | lints for the cargo manifest                                            | allow         |
 
 More to come, please [file an issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas!
 
@@ -98,17 +98,6 @@
 cargo clippy -p example -- --no-deps 
 ```
 
-### Running Clippy from the command line without installing it
-
-To have cargo compile your crate with Clippy without Clippy installation
-in your code, you can use:
-
-```terminal
-cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml
-```
-
-*Note:* Be sure that Clippy was compiled with the same version of rustc that cargo invokes here!
-
 ### Travis CI
 
 You can add Clippy to Travis CI in the same way you use it locally:
@@ -130,18 +119,6 @@
   # etc.
 ```
 
-If you are on nightly, It might happen that Clippy is not available for a certain nightly release.
-In this case you can try to conditionally install Clippy from the Git repo.
-
-```yaml
-language: rust
-rust:
-  - nightly
-before_script:
-   - rustup component add clippy --toolchain=nightly || cargo install --git https://github.com/rust-lang/rust-clippy/ --force clippy
-   # etc.
-```
-
 Note that adding `-D warnings` will cause your build to fail if **any** warnings are found in your code.
 That includes warnings found by rustc (e.g. `dead_code`, etc.). If you want to avoid this and only cause
 an error for Clippy warnings, use `#![deny(clippy::all)]` in your code or `-D clippy::all` on the command
diff --git a/src/tools/clippy/clippy_dev/src/ra_setup.rs b/src/tools/clippy/clippy_dev/src/ra_setup.rs
index 40bf4a9..5f5048e 100644
--- a/src/tools/clippy/clippy_dev/src/ra_setup.rs
+++ b/src/tools/clippy/clippy_dev/src/ra_setup.rs
@@ -3,7 +3,7 @@
 use std::fs;
 use std::fs::File;
 use std::io::prelude::*;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 
 // This module takes an absolute path to a rustc repo and alters the dependencies to point towards
 // the respective rustc subcrates instead of using extern crate xyz.
@@ -44,7 +44,7 @@
 }
 
 fn inject_deps_into_manifest(
-    rustc_source_dir: &PathBuf,
+    rustc_source_dir: &Path,
     manifest_path: &str,
     cargo_toml: &str,
     lib_rs: &str,
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 7697eba..a951656 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "clippy_lints"
 # begin automatic update
-version = "0.0.212"
+version = "0.1.51"
 # end automatic update
 authors = [
 	"Manish Goregaokar <manishsmail@gmail.com>",
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
index 62c73db..aa431f0 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
@@ -1,8 +1,7 @@
 use crate::consts::{constant, Constant};
 use crate::utils::{is_direct_expn_of, is_expn_of, match_panic_call, snippet_opt, span_lint_and_help};
 use if_chain::if_chain;
-use rustc_ast::ast::LitKind;
-use rustc_hir::{Expr, ExprKind, PatKind, UnOp};
+use rustc_hir::{Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -102,31 +101,22 @@
 /// Check if the expression matches
 ///
 /// ```rust,ignore
-/// match { let _t = !c; _t } {
-///     true => {
-///         {
-///             ::std::rt::begin_panic(message, _)
-///         }
-///     }
-///     _ => { }
-/// };
+/// if !c {
+///   {
+///     ::std::rt::begin_panic(message, _)
+///   }
+/// }
 /// ```
 ///
 /// where `message` is any expression and `c` is a constant bool.
 fn match_assert_with_message<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<AssertKind> {
     if_chain! {
-        if let ExprKind::Match(ref expr, ref arms, _) = expr.kind;
-        // matches { let _t = expr; _t }
-        if let ExprKind::DropTemps(ref expr) = expr.kind;
-        if let ExprKind::Unary(UnOp::UnNot, ref expr) = expr.kind;
+        if let ExprKind::If(ref cond, ref then, _) = expr.kind;
+        if let ExprKind::Unary(UnOp::UnNot, ref expr) = cond.kind;
         // bind the first argument of the `assert!` macro
         if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.typeck_results(), expr);
-        // arm 1 pattern
-        if let PatKind::Lit(ref lit_expr) = arms[0].pat.kind;
-        if let ExprKind::Lit(ref lit) = lit_expr.kind;
-        if let LitKind::Bool(true) = lit.node;
-        // arm 1 block
-        if let ExprKind::Block(ref block, _) = arms[0].body.kind;
+        // block
+        if let ExprKind::Block(ref block, _) = then.kind;
         if block.stmts.is_empty();
         if let Some(block_expr) = &block.expr;
         // inner block is optional. unwrap it if it exists, or use the expression as is otherwise.
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 3edbe723..7607394 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -10,11 +10,10 @@
 use rustc_hir::{
     Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind,
 };
-use rustc_lint::{CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::Span;
 use rustc_span::sym;
 use rustc_span::symbol::{Symbol, SymbolStr};
@@ -157,33 +156,6 @@
 }
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for `allow`/`warn`/`deny`/`forbid` attributes with scoped clippy
-    /// lints and if those lints exist in clippy. If there is an uppercase letter in the lint name
-    /// (not the tool name) and a lowercase version of this lint exists, it will suggest to lowercase
-    /// the lint name.
-    ///
-    /// **Why is this bad?** A lint attribute with a mistyped lint name won't have an effect.
-    ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
-    /// Bad:
-    /// ```rust
-    /// #![warn(if_not_els)]
-    /// #![deny(clippy::All)]
-    /// ```
-    ///
-    /// Good:
-    /// ```rust
-    /// #![warn(if_not_else)]
-    /// #![deny(clippy::all)]
-    /// ```
-    pub UNKNOWN_CLIPPY_LINTS,
-    style,
-    "unknown_lints for scoped Clippy lints"
-}
-
-declare_clippy_lint! {
     /// **What it does:** Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category.
     ///
     /// **Why is this bad?** Restriction lints sometimes are in contrast with other lints or even go against idiomatic rust.
@@ -272,7 +244,6 @@
     INLINE_ALWAYS,
     DEPRECATED_SEMVER,
     USELESS_ATTRIBUTE,
-    UNKNOWN_CLIPPY_LINTS,
     BLANKET_CLIPPY_RESTRICTION_LINTS,
 ]);
 
@@ -409,48 +380,9 @@
 }
 
 fn check_clippy_lint_names(cx: &LateContext<'_>, ident: &str, items: &[NestedMetaItem]) {
-    let lint_store = cx.lints();
     for lint in items {
         if let Some(lint_name) = extract_clippy_lint(lint) {
-            if let CheckLintNameResult::Tool(Err((None, _))) = lint_store.check_lint_name(&lint_name, Some(sym::clippy))
-            {
-                span_lint_and_then(
-                    cx,
-                    UNKNOWN_CLIPPY_LINTS,
-                    lint.span(),
-                    &format!("unknown clippy lint: clippy::{}", lint_name),
-                    |diag| {
-                        let name_lower = lint_name.to_lowercase();
-                        let symbols = lint_store
-                            .get_lints()
-                            .iter()
-                            .map(|l| Symbol::intern(&l.name_lower()))
-                            .collect::<Vec<_>>();
-                        let sugg = find_best_match_for_name(
-                            &symbols,
-                            Symbol::intern(&format!("clippy::{}", name_lower)),
-                            None,
-                        );
-                        if lint_name.chars().any(char::is_uppercase)
-                            && lint_store.find_lints(&format!("clippy::{}", name_lower)).is_ok()
-                        {
-                            diag.span_suggestion(
-                                lint.span(),
-                                "lowercase the lint name",
-                                format!("clippy::{}", name_lower),
-                                Applicability::MachineApplicable,
-                            );
-                        } else if let Some(sugg) = sugg {
-                            diag.span_suggestion(
-                                lint.span(),
-                                "did you mean",
-                                sugg.to_string(),
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                    },
-                );
-            } else if lint_name == "restriction" && ident != "allow" {
+            if lint_name == "restriction" && ident != "allow" {
                 span_lint_and_help(
                     cx,
                     BLANKET_CLIPPY_RESTRICTION_LINTS,
diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
index 736730d..4efca10 100644
--- a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
+++ b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
@@ -1,4 +1,4 @@
-use crate::utils::{differing_macro_contexts, higher, snippet_block_with_applicability, span_lint, span_lint_and_sugg};
+use crate::utils::{differing_macro_contexts, snippet_block_with_applicability, span_lint, span_lint_and_sugg};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
 use rustc_hir::{BlockCheckMode, Expr, ExprKind};
@@ -75,7 +75,7 @@
         if in_external_macro(cx.sess(), expr.span) {
             return;
         }
-        if let Some((cond, _, _)) = higher::if_block(&expr) {
+        if let ExprKind::If(cond, _, _) = &expr.kind {
             if let ExprKind::Block(block, _) = &cond.kind {
                 if block.rules == BlockCheckMode::DefaultBlock {
                     if block.stmts.is_empty() {
diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
index b1bc2ec..b3ebdf4 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
@@ -147,6 +147,9 @@
     fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
         walk_expr(self, e);
         match e.kind {
+            ExprKind::If(_, _, _) => {
+                self.cc += 1;
+            },
             ExprKind::Match(_, ref arms, _) => {
                 if arms.len() > 1 {
                     self.cc += 1;
diff --git a/src/tools/clippy/clippy_lints/src/consts.rs b/src/tools/clippy/clippy_lints/src/consts.rs
index 0035ded..166eadf 100644
--- a/src/tools/clippy/clippy_lints/src/consts.rs
+++ b/src/tools/clippy/clippy_lints/src/consts.rs
@@ -1,6 +1,6 @@
 #![allow(clippy::float_cmp)]
 
-use crate::utils::{clip, higher, sext, unsext};
+use crate::utils::{clip, sext, unsext};
 use if_chain::if_chain;
 use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
 use rustc_data_structures::sync::Lrc;
@@ -228,9 +228,6 @@
 impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     /// Simple constant folding: Insert an expression, get a constant or none.
     pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant> {
-        if let Some((ref cond, ref then, otherwise)) = higher::if_block(&e) {
-            return self.ifthenelse(cond, then, otherwise);
-        }
         match e.kind {
             ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.typeck_results.expr_ty(e)),
             ExprKind::Block(ref block, _) => self.block(block),
@@ -249,6 +246,7 @@
                 UnOp::UnNeg => self.constant_negate(&o, self.typeck_results.expr_ty(e)),
                 UnOp::UnDeref => Some(if let Constant::Ref(r) = o { *r } else { o }),
             }),
+            ExprKind::If(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, *otherwise),
             ExprKind::Binary(op, ref left, ref right) => self.binop(op, left, right),
             ExprKind::Call(ref callee, ref args) => {
                 // We only handle a few const functions for now.
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index 46ce92e..6f48ffe 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -1,6 +1,6 @@
 use crate::utils::{eq_expr_value, in_macro, search_same, SpanlessEq, SpanlessHash};
-use crate::utils::{get_parent_expr, higher, if_sequence, span_lint_and_note};
-use rustc_hir::{Block, Expr};
+use crate::utils::{get_parent_expr, if_sequence, span_lint_and_note};
+use rustc_hir::{Block, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -109,11 +109,12 @@
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if !expr.span.from_expansion() {
             // skip ifs directly in else, it will be checked in the parent if
-            if let Some(expr) = get_parent_expr(cx, expr) {
-                if let Some((_, _, Some(ref else_expr))) = higher::if_block(&expr) {
-                    if else_expr.hir_id == expr.hir_id {
-                        return;
-                    }
+            if let Some(&Expr {
+                kind: ExprKind::If(_, _, Some(ref else_expr)),
+                ..
+            }) = get_parent_expr(cx, expr) {
+                if else_expr.hir_id == expr.hir_id {
+                    return;
                 }
             }
 
diff --git a/src/tools/clippy/clippy_lints/src/copy_iterator.rs b/src/tools/clippy/clippy_lints/src/copy_iterator.rs
index 3494024..a7aa2cb 100644
--- a/src/tools/clippy/clippy_lints/src/copy_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/copy_iterator.rs
@@ -1,5 +1,5 @@
 use crate::utils::{is_copy, match_path, paths, span_lint_and_note};
-use rustc_hir::{Item, ItemKind};
+use rustc_hir::{Item, ItemKind, Impl};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -33,10 +33,10 @@
 
 impl<'tcx> LateLintPass<'tcx> for CopyIterator {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if let ItemKind::Impl {
+        if let ItemKind::Impl(Impl {
             of_trait: Some(ref trait_ref),
             ..
-        } = item.kind
+        }) = item.kind
         {
             let ty = cx.tcx.type_of(cx.tcx.hir().local_def_id(item.hir_id));
 
diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs
index f69f6f1..b0d7c7b 100644
--- a/src/tools/clippy/clippy_lints/src/default.rs
+++ b/src/tools/clippy/clippy_lints/src/default.rs
@@ -6,7 +6,7 @@
 use rustc_hir::def::Res;
 use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, Adt, Ty};
+use rustc_middle::ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::Span;
@@ -103,18 +103,41 @@
     }
 
     fn check_block<'tcx>(&mut self, cx: &LateContext<'tcx>, block: &Block<'tcx>) {
-        // find all binding statements like `let mut _ = T::default()` where `T::default()` is the
-        // `default` method of the `Default` trait, and store statement index in current block being
-        // checked and the name of the bound variable
-        let binding_statements_using_default = enumerate_bindings_using_default(cx, block);
-
         // start from the `let mut _ = _::default();` and look at all the following
         // statements, see if they re-assign the fields of the binding
-        for (stmt_idx, binding_name, binding_type, span) in binding_statements_using_default {
-            // the last statement of a block cannot trigger the lint
-            if stmt_idx == block.stmts.len() - 1 {
-                break;
-            }
+        let stmts_head = match block.stmts {
+            // Skip the last statement since there cannot possibly be any following statements that re-assign fields.
+            [head @ .., _] if !head.is_empty() => head,
+            _ => return,
+        };
+        for (stmt_idx, stmt) in stmts_head.iter().enumerate() {
+            // find all binding statements like `let mut _ = T::default()` where `T::default()` is the
+            // `default` method of the `Default` trait, and store statement index in current block being
+            // checked and the name of the bound variable
+            let (local, variant, binding_name, binding_type, span) = if_chain! {
+                // only take `let ...` statements
+                if let StmtKind::Local(local) = stmt.kind;
+                if let Some(expr) = local.init;
+                // only take bindings to identifiers
+                if let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind;
+                // only when assigning `... = Default::default()`
+                if is_expr_default(expr, cx);
+                let binding_type = cx.typeck_results().node_type(binding_id);
+                if let Some(adt) = binding_type.ty_adt_def();
+                if adt.is_struct();
+                let variant = adt.non_enum_variant();
+                if adt.did.is_local() || !variant.is_field_list_non_exhaustive();
+                let module_did = cx.tcx.parent_module(stmt.hir_id).to_def_id();
+                if variant
+                    .fields
+                    .iter()
+                    .all(|field| field.vis.is_accessible_from(module_did, cx.tcx));
+                then {
+                    (local, variant, ident.name, binding_type, expr.span)
+                } else {
+                    continue;
+                }
+            };
 
             // find all "later statement"'s where the fields of the binding set as
             // Default::default() get reassigned, unless the reassignment refers to the original binding
@@ -122,15 +145,8 @@
             let mut assigned_fields = Vec::new();
             let mut cancel_lint = false;
             for consecutive_statement in &block.stmts[stmt_idx + 1..] {
-                // interrupt if the statement is a let binding (`Local`) that shadows the original
-                // binding
-                if stmt_shadows_binding(consecutive_statement, binding_name) {
-                    break;
-                }
                 // find out if and which field was set by this `consecutive_statement`
-                else if let Some((field_ident, assign_rhs)) =
-                    field_reassigned_by_stmt(consecutive_statement, binding_name)
-                {
+                if let Some((field_ident, assign_rhs)) = field_reassigned_by_stmt(consecutive_statement, binding_name) {
                     // interrupt and cancel lint if assign_rhs references the original binding
                     if contains_name(binding_name, assign_rhs) {
                         cancel_lint = true;
@@ -152,7 +168,7 @@
                         first_assign = Some(consecutive_statement);
                     }
                 }
-                // interrupt also if no field was assigned, since we only want to look at consecutive statements
+                // interrupt if no field was assigned, since we only want to look at consecutive statements
                 else {
                     break;
                 }
@@ -161,55 +177,45 @@
             // if there are incorrectly assigned fields, do a span_lint_and_note to suggest
             // construction using `Ty { fields, ..Default::default() }`
             if !assigned_fields.is_empty() && !cancel_lint {
-                // take the original assignment as span
-                let stmt = &block.stmts[stmt_idx];
+                // if all fields of the struct are not assigned, add `.. Default::default()` to the suggestion.
+                let ext_with_default = !variant
+                    .fields
+                    .iter()
+                    .all(|field| assigned_fields.iter().any(|(a, _)| a == &field.ident.name));
 
-                if let StmtKind::Local(preceding_local) = &stmt.kind {
-                    // filter out fields like `= Default::default()`, because the FRU already covers them
-                    let assigned_fields = assigned_fields
-                        .into_iter()
-                        .filter(|(_, rhs)| !is_expr_default(rhs, cx))
-                        .collect::<Vec<(Symbol, &Expr<'_>)>>();
+                let field_list = assigned_fields
+                    .into_iter()
+                    .map(|(field, rhs)| {
+                        // extract and store the assigned value for help message
+                        let value_snippet = snippet(cx, rhs.span, "..");
+                        format!("{}: {}", field, value_snippet)
+                    })
+                    .collect::<Vec<String>>()
+                    .join(", ");
 
-                    // if all fields of the struct are not assigned, add `.. Default::default()` to the suggestion.
-                    let ext_with_default = !fields_of_type(binding_type)
-                        .iter()
-                        .all(|field| assigned_fields.iter().any(|(a, _)| a == &field.name));
-
-                    let field_list = assigned_fields
-                        .into_iter()
-                        .map(|(field, rhs)| {
-                            // extract and store the assigned value for help message
-                            let value_snippet = snippet(cx, rhs.span, "..");
-                            format!("{}: {}", field, value_snippet)
-                        })
-                        .collect::<Vec<String>>()
-                        .join(", ");
-
-                    let sugg = if ext_with_default {
-                        if field_list.is_empty() {
-                            format!("{}::default()", binding_type)
-                        } else {
-                            format!("{} {{ {}, ..Default::default() }}", binding_type, field_list)
-                        }
+                let sugg = if ext_with_default {
+                    if field_list.is_empty() {
+                        format!("{}::default()", binding_type)
                     } else {
-                        format!("{} {{ {} }}", binding_type, field_list)
-                    };
+                        format!("{} {{ {}, ..Default::default() }}", binding_type, field_list)
+                    }
+                } else {
+                    format!("{} {{ {} }}", binding_type, field_list)
+                };
 
-                    // span lint once per statement that binds default
-                    span_lint_and_note(
-                        cx,
-                        FIELD_REASSIGN_WITH_DEFAULT,
-                        first_assign.unwrap().span,
-                        "field assignment outside of initializer for an instance created with Default::default()",
-                        Some(preceding_local.span),
-                        &format!(
-                            "consider initializing the variable with `{}` and removing relevant reassignments",
-                            sugg
-                        ),
-                    );
-                    self.reassigned_linted.insert(span);
-                }
+                // span lint once per statement that binds default
+                span_lint_and_note(
+                    cx,
+                    FIELD_REASSIGN_WITH_DEFAULT,
+                    first_assign.unwrap().span,
+                    "field assignment outside of initializer for an instance created with Default::default()",
+                    Some(local.span),
+                    &format!(
+                        "consider initializing the variable with `{}` and removing relevant reassignments",
+                        sugg
+                    ),
+                );
+                self.reassigned_linted.insert(span);
             }
         }
     }
@@ -230,47 +236,6 @@
     }
 }
 
-/// Returns the block indices, identifiers and types of bindings set as `Default::default()`, except
-/// for when the pattern type is a tuple.
-fn enumerate_bindings_using_default<'tcx>(
-    cx: &LateContext<'tcx>,
-    block: &Block<'tcx>,
-) -> Vec<(usize, Symbol, Ty<'tcx>, Span)> {
-    block
-        .stmts
-        .iter()
-        .enumerate()
-        .filter_map(|(idx, stmt)| {
-            if_chain! {
-                // only take `let ...` statements
-                if let StmtKind::Local(ref local) = stmt.kind;
-                // only take bindings to identifiers
-                if let PatKind::Binding(_, _, ident, _) = local.pat.kind;
-                // that are not tuples
-                let ty = cx.typeck_results().pat_ty(local.pat);
-                if !matches!(ty.kind(), ty::Tuple(_));
-                // only when assigning `... = Default::default()`
-                if let Some(ref expr) = local.init;
-                if is_expr_default(expr, cx);
-                then {
-                    Some((idx, ident.name, ty, expr.span))
-                } else {
-                    None
-                }
-            }
-        })
-        .collect()
-}
-
-fn stmt_shadows_binding(this: &Stmt<'_>, shadowed: Symbol) -> bool {
-    if let StmtKind::Local(local) = &this.kind {
-        if let PatKind::Binding(_, _, ident, _) = local.pat.kind {
-            return ident.name == shadowed;
-        }
-    }
-    false
-}
-
 /// Returns the reassigned field and the assigning expression (right-hand side of assign).
 fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Option<(Ident, &'tcx Expr<'tcx>)> {
     if_chain! {
@@ -290,14 +255,3 @@
         }
     }
 }
-
-/// Returns the vec of fields for a struct and an empty vec for non-struct ADTs.
-fn fields_of_type(ty: Ty<'_>) -> Vec<Ident> {
-    if let Adt(adt, _) = ty.kind() {
-        if adt.is_struct() {
-            let variant = &adt.non_enum_variant();
-            return variant.fields.iter().map(|f| f.ident).collect();
-        }
-    }
-    vec![]
-}
diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
index bec0c9f..47b3cc3 100644
--- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
@@ -163,6 +163,19 @@
 }
 
 declare_deprecated_lint! {
+    /// **What it does:** Nothing. This lint has been deprecated.
+    ///
+    /// **Deprecation reason:** This lint has been uplifted to rustc and is now called
+    /// `panic_fmt`.
     pub PANIC_PARAMS,
     "this lint has been uplifted to rustc and is now called `panic_fmt`"
 }
+
+declare_deprecated_lint! {
+    /// **What it does:** Nothing. This lint has been deprecated.
+    ///
+    /// **Deprecation reason:** This lint has been integrated into the `unknown_lints`
+    /// rustc lint.
+    pub UNKNOWN_CLIPPY_LINTS,
+    "this lint has been integrated into the `unknown_lints` rustc lint"
+}
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index c75efc6..b55f59f 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -7,7 +7,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor};
 use rustc_hir::{
-    BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Item, ItemKind, TraitRef, UnsafeSource, Unsafety,
+    BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Item, ItemKind, Impl, TraitRef, UnsafeSource, Unsafety,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::map::Map;
@@ -164,10 +164,10 @@
 
 impl<'tcx> LateLintPass<'tcx> for Derive {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if let ItemKind::Impl {
+        if let ItemKind::Impl(Impl {
             of_trait: Some(ref trait_ref),
             ..
-        } = item.kind
+        }) = item.kind
         {
             let ty = cx.tcx.type_of(cx.tcx.hir().local_def_id(item.hir_id));
             let is_automatically_derived = is_automatically_derived(&*item.attrs);
diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs
index aba6553..f518da5 100644
--- a/src/tools/clippy/clippy_lints/src/doc.rs
+++ b/src/tools/clippy/clippy_lints/src/doc.rs
@@ -182,11 +182,8 @@
                     lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers, Some(body_id));
                 }
             },
-            hir::ItemKind::Impl {
-                of_trait: ref trait_ref,
-                ..
-            } => {
-                self.in_trait_impl = trait_ref.is_some();
+            hir::ItemKind::Impl(ref impl_) => {
+                self.in_trait_impl = impl_.of_trait.is_some();
             },
             _ => {},
         }
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index 35a5d00..37948e0 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -1,5 +1,5 @@
 use crate::utils::SpanlessEq;
-use crate::utils::{get_item_name, higher, is_type_diagnostic_item, match_type, paths, snippet, snippet_opt};
+use crate::utils::{get_item_name, is_type_diagnostic_item, match_type, paths, snippet, snippet_opt};
 use crate::utils::{snippet_with_applicability, span_lint_and_then};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
@@ -54,7 +54,7 @@
 
 impl<'tcx> LateLintPass<'tcx> for HashMapPass {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let Some((ref check, ref then_block, ref else_block)) = higher::if_block(&expr) {
+        if let ExprKind::If(ref check, ref then_block, ref else_block) = expr.kind {
             if let ExprKind::Unary(UnOp::UnNot, ref check) = check.kind {
                 if let Some((ty, map, key)) = check_cond(cx, check) {
                     // in case of `if !m.contains_key(&k) { m.insert(k, v); }`
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index d2dcb3e..5508769 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -1,5 +1,5 @@
 use rustc_hir::intravisit;
-use rustc_hir::{self, Body, FnDecl, HirId, HirIdSet, ItemKind, Node};
+use rustc_hir::{self, Body, FnDecl, HirId, HirIdSet, ItemKind, Impl, Node};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, Ty};
@@ -77,7 +77,7 @@
         let parent_node = cx.tcx.hir().find(parent_id);
 
         if let Some(Node::Item(item)) = parent_node {
-            if let ItemKind::Impl { of_trait: Some(_), .. } = item.kind {
+            if let ItemKind::Impl(Impl { of_trait: Some(_), .. }) = item.kind {
                 return;
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
index 509a4a4..9f389c8 100644
--- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
+++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
@@ -57,11 +57,11 @@
         // check for `impl From<???> for ..`
         let impl_def_id = cx.tcx.hir().local_def_id(item.hir_id);
         if_chain! {
-            if let hir::ItemKind::Impl{ items: impl_items, .. } = item.kind;
+            if let hir::ItemKind::Impl(impl_) = &item.kind;
             if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id);
             if match_def_path(cx, impl_trait_ref.def_id, &FROM_TRAIT);
             then {
-                lint_impl_body(cx, item.span, impl_items);
+                lint_impl_body(cx, item.span, impl_.items);
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index 18fea8b..ffef78a 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -2,7 +2,7 @@
     constant, constant_simple, Constant,
     Constant::{Int, F32, F64},
 };
-use crate::utils::{eq_expr_value, get_parent_expr, higher, numeric_literal, span_lint_and_sugg, sugg};
+use crate::utils::{eq_expr_value, get_parent_expr, numeric_literal, span_lint_and_sugg, sugg};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp};
@@ -556,11 +556,11 @@
 
 fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if_chain! {
-        if let Some((cond, body, Some(else_body))) = higher::if_block(&expr);
+        if let ExprKind::If(cond, body, else_body) = expr.kind;
         if let ExprKind::Block(block, _) = body.kind;
         if block.stmts.is_empty();
         if let Some(if_body_expr) = block.expr;
-        if let ExprKind::Block(else_block, _) = else_body.kind;
+        if let Some(ExprKind::Block(else_block, _)) = else_body.map(|el| &el.kind);
         if else_block.stmts.is_empty();
         if let Some(else_body_expr) = else_block.expr;
         if let Some((if_expr_positive, body)) = are_negated(cx, if_body_expr, else_body_expr);
diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs
new file mode 100644
index 0000000..1e7e5f5
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs
@@ -0,0 +1,83 @@
+use crate::utils::paths::INTO;
+use crate::utils::{match_def_path, meets_msrv, span_lint_and_help};
+use if_chain::if_chain;
+use rustc_hir as hir;
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+
+const FROM_OVER_INTO_MSRV: RustcVersion = RustcVersion::new(1, 41, 0);
+
+declare_clippy_lint! {
+    /// **What it does:** Searches for implementations of the `Into<..>` trait and suggests to implement `From<..>` instead.
+    ///
+    /// **Why is this bad?** According the std docs implementing `From<..>` is preferred since it gives you `Into<..>` for free where the reverse isn't true.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// struct StringWrapper(String);
+    ///
+    /// impl Into<StringWrapper> for String {
+    ///     fn into(self) -> StringWrapper {
+    ///         StringWrapper(self)
+    ///     }
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// struct StringWrapper(String);
+    ///
+    /// impl From<String> for StringWrapper {
+    ///     fn from(s: String) -> StringWrapper {
+    ///         StringWrapper(s)
+    ///     }
+    /// }
+    /// ```
+    pub FROM_OVER_INTO,
+    style,
+    "Warns on implementations of `Into<..>` to use `From<..>`"
+}
+
+pub struct FromOverInto {
+    msrv: Option<RustcVersion>,
+}
+
+impl FromOverInto {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        FromOverInto { msrv }
+    }
+}
+
+impl_lint_pass!(FromOverInto => [FROM_OVER_INTO]);
+
+impl LateLintPass<'_> for FromOverInto {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
+        if !meets_msrv(self.msrv.as_ref(), &FROM_OVER_INTO_MSRV) {
+            return;
+        }
+
+        let impl_def_id = cx.tcx.hir().local_def_id(item.hir_id);
+        if_chain! {
+            if let hir::ItemKind::Impl{ .. } = &item.kind;
+            if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id);
+            if match_def_path(cx, impl_trait_ref.def_id, &INTO);
+
+            then {
+                span_lint_and_help(
+                    cx,
+                    FROM_OVER_INTO,
+                    item.span,
+                    "an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true",
+                    None,
+                    "consider to implement `From` instead",
+                );
+            }
+        }
+    }
+
+    extract_msrv_attr!(LateContext);
+}
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index f9697af..a3a38fa 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -4,7 +4,7 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::subst::Subst;
-use rustc_middle::ty::{Opaque, PredicateAtom::Trait};
+use rustc_middle::ty::{Opaque, PredicateKind::Trait};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, Span};
 use rustc_trait_selection::traits::error_reporting::suggestions::InferCtxtExt;
@@ -97,7 +97,7 @@
                                         &obligation,
                                     );
                                     if let Trait(trait_pred, _) =
-                                        obligation.predicate.skip_binders()
+                                        obligation.predicate.kind().skip_binder()
                                     {
                                         db.note(&format!(
                                             "`{}` doesn't implement `{}`",
diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs
index 03e95c9..109d90f 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_return.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs
@@ -81,6 +81,13 @@
                 lint(cx, expr.span, break_expr.span, LINT_BREAK);
             }
         },
+        ExprKind::If(.., if_expr, else_expr) => {
+            expr_match(cx, if_expr);
+
+            if let Some(else_expr) = else_expr {
+                expr_match(cx, else_expr);
+            }
+        },
         ExprKind::Match(.., arms, source) => {
             let check_all_arms = match source {
                 MatchSource::IfLetDesugar {
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
index 3a01acd..16e162b 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
@@ -1,4 +1,4 @@
-use crate::utils::{higher, in_macro, match_qpath, span_lint_and_sugg, SpanlessEq};
+use crate::utils::{in_macro, match_qpath, span_lint_and_sugg, SpanlessEq};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
@@ -42,7 +42,7 @@
             return;
         }
         if_chain! {
-            if let Some((ref cond, ref then, None)) = higher::if_block(&expr);
+            if let ExprKind::If(cond, then, None) = &expr.kind;
 
             // Check if the conditional expression is a binary operation
             if let ExprKind::Binary(ref cond_op, ref cond_left, ref cond_right) = cond.kind;
diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
index 4e6bb60..e287aec 100644
--- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
@@ -2,7 +2,7 @@
 
 use crate::utils::{in_macro, span_lint_and_then};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::{def_id, Crate, Item, ItemKind};
+use rustc_hir::{def_id, Crate, Item, ItemKind, Impl};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::Span;
@@ -49,11 +49,11 @@
 
 impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
     fn check_item(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if let ItemKind::Impl {
+        if let ItemKind::Impl(Impl {
             ref generics,
             of_trait: None,
             ..
-        } = item.kind
+        }) = item.kind
         {
             // Remember for each inherent implementation encountered its span and generics
             // but filter out implementations that have generic params (type or lifetime)
diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
index 3c7880d..ad9b4f3 100644
--- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
+++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
@@ -4,6 +4,7 @@
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind, VariantData};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_target::abi::LayoutOf;
 
@@ -58,6 +59,9 @@
 
 impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+        if in_external_macro(cx.tcx.sess, item.span) {
+            return;
+        }
         let did = cx.tcx.hir().local_def_id(item.hir_id);
         if let ItemKind::Enum(ref def, _) = item.kind {
             let ty = cx.tcx.type_of(did);
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 6fe5335..5474b30 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -3,7 +3,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{AssocItemKind, BinOpKind, Expr, ExprKind, ImplItemRef, Item, ItemKind, TraitItemRef};
+use rustc_hir::{AssocItemKind, BinOpKind, Expr, ExprKind, ImplItemRef, Item, ItemKind, Impl, TraitItemRef};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -115,11 +115,11 @@
 
         match item.kind {
             ItemKind::Trait(_, _, _, _, ref trait_items) => check_trait_items(cx, item, trait_items),
-            ItemKind::Impl {
+            ItemKind::Impl(Impl {
                 of_trait: None,
                 items: ref impl_items,
                 ..
-            } => check_impl_items(cx, item, impl_items),
+            }) => check_impl_items(cx, item, impl_items),
             _ => (),
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs
index 0d2d953..db717cd 100644
--- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs
+++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs
@@ -1,5 +1,4 @@
-use crate::utils::visitors::LocalUsedVisitor;
-use crate::utils::{higher, qpath_res, snippet, span_lint_and_then};
+use crate::utils::{qpath_res, snippet, span_lint_and_then, visitors::LocalUsedVisitor};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -64,7 +63,7 @@
                 if let hir::StmtKind::Local(ref local) = stmt.kind;
                 if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind;
                 if let hir::StmtKind::Expr(ref if_) = expr.kind;
-                if let Some((ref cond, ref then, ref else_)) = higher::if_block(&if_);
+                if let hir::ExprKind::If(ref cond, ref then, ref else_) = if_.kind;
                 if !LocalUsedVisitor::new(canonical_id).check_expr(cond);
                 if let hir::ExprKind::Block(ref then, _) = then.kind;
                 if let Some(value) = check_assign(cx, canonical_id, &*then);
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 02ba422..aaa1756 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -207,6 +207,7 @@
 mod floating_point_arithmetic;
 mod format;
 mod formatting;
+mod from_over_into;
 mod functions;
 mod future_not_send;
 mod get_last_with_len;
@@ -499,6 +500,10 @@
         "clippy::panic_params",
         "this lint has been uplifted to rustc and is now called `panic_fmt`",
     );
+    store.register_removed(
+        "clippy::unknown_clippy_lints",
+        "this lint has been integrated into the `unknown_lints` rustc lint",
+    );
     // end deprecated lints, do not remove this comment, it’s used in `update_lints`
 
     // begin register lints, do not remove this comment, it’s used in `update_lints`
@@ -540,7 +545,6 @@
         &attrs::EMPTY_LINE_AFTER_OUTER_ATTR,
         &attrs::INLINE_ALWAYS,
         &attrs::MISMATCHED_TARGET_OS,
-        &attrs::UNKNOWN_CLIPPY_LINTS,
         &attrs::USELESS_ATTRIBUTE,
         &await_holding_invalid::AWAIT_HOLDING_LOCK,
         &await_holding_invalid::AWAIT_HOLDING_REFCELL_REF,
@@ -614,6 +618,7 @@
         &formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING,
         &formatting::SUSPICIOUS_ELSE_FORMATTING,
         &formatting::SUSPICIOUS_UNARY_OP_FORMATTING,
+        &from_over_into::FROM_OVER_INTO,
         &functions::DOUBLE_MUST_USE,
         &functions::MUST_USE_CANDIDATE,
         &functions::MUST_USE_UNIT,
@@ -1014,6 +1019,7 @@
     store.register_late_pass(move || box checked_conversions::CheckedConversions::new(msrv));
     store.register_late_pass(move || box mem_replace::MemReplace::new(msrv));
     store.register_late_pass(move || box ranges::Ranges::new(msrv));
+    store.register_late_pass(move || box from_over_into::FromOverInto::new(msrv));
     store.register_late_pass(move || box use_self::UseSelf::new(msrv));
     store.register_late_pass(move || box missing_const_for_fn::MissingConstForFn::new(msrv));
 
@@ -1372,7 +1378,6 @@
         LintId::of(&attrs::DEPRECATED_CFG_ATTR),
         LintId::of(&attrs::DEPRECATED_SEMVER),
         LintId::of(&attrs::MISMATCHED_TARGET_OS),
-        LintId::of(&attrs::UNKNOWN_CLIPPY_LINTS),
         LintId::of(&attrs::USELESS_ATTRIBUTE),
         LintId::of(&bit_mask::BAD_BIT_MASK),
         LintId::of(&bit_mask::INEFFECTIVE_BIT_MASK),
@@ -1417,6 +1422,7 @@
         LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
         LintId::of(&formatting::SUSPICIOUS_ELSE_FORMATTING),
         LintId::of(&formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
+        LintId::of(&from_over_into::FROM_OVER_INTO),
         LintId::of(&functions::DOUBLE_MUST_USE),
         LintId::of(&functions::MUST_USE_UNIT),
         LintId::of(&functions::NOT_UNSAFE_PTR_ARG_DEREF),
@@ -1646,7 +1652,6 @@
         LintId::of(&assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
         LintId::of(&assign_ops::ASSIGN_OP_PATTERN),
         LintId::of(&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
-        LintId::of(&attrs::UNKNOWN_CLIPPY_LINTS),
         LintId::of(&blacklisted_name::BLACKLISTED_NAME),
         LintId::of(&blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS),
         LintId::of(&collapsible_if::COLLAPSIBLE_IF),
@@ -1663,6 +1668,7 @@
         LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
         LintId::of(&formatting::SUSPICIOUS_ELSE_FORMATTING),
         LintId::of(&formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
+        LintId::of(&from_over_into::FROM_OVER_INTO),
         LintId::of(&functions::DOUBLE_MUST_USE),
         LintId::of(&functions::MUST_USE_UNIT),
         LintId::of(&functions::RESULT_UNIT_ERR),
diff --git a/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs
index 1bd96b2..281964e 100644
--- a/src/tools/clippy/clippy_lints/src/loops.rs
+++ b/src/tools/clippy/clippy_lints/src/loops.rs
@@ -742,6 +742,14 @@
             // Break can come from the inner loop so remove them.
             absorb_break(&never_loop_block(b, main_loop_id))
         },
+        ExprKind::If(ref e, ref e2, ref e3) => {
+            let e1 = never_loop_expr(e, main_loop_id);
+            let e2 = never_loop_expr(e2, main_loop_id);
+            let e3 = e3
+                .as_ref()
+                .map_or(NeverLoopResult::Otherwise, |e| never_loop_expr(e, main_loop_id));
+            combine_seq(e1, combine_branches(e2, e3))
+        },
         ExprKind::Match(ref e, ref arms, _) => {
             let e = never_loop_expr(e, main_loop_id);
             if arms.is_empty() {
@@ -2594,7 +2602,7 @@
 }
 
 fn is_conditional(expr: &Expr<'_>) -> bool {
-    matches!(expr.kind, ExprKind::Match(..))
+    matches!(expr.kind, ExprKind::If(..) | ExprKind::Match(..))
 }
 
 fn is_nested(cx: &LateContext<'_>, match_expr: &Expr<'_>, iter_expr: &Expr<'_>) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs
index b4b4b3d..bb52888 100644
--- a/src/tools/clippy/clippy_lints/src/macro_use.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_use.rs
@@ -105,7 +105,7 @@
 impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
         if_chain! {
-            if cx.sess().opts.edition == Edition::Edition2018;
+            if cx.sess().opts.edition >= Edition::Edition2018;
             if let hir::ItemKind::Use(path, _kind) = &item.kind;
             if let Some(mac_attr) = item
                 .attrs
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index 7b3b450..29439e5 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -69,7 +69,7 @@
                     |diag| {
                         if_chain! {
                             if let Some(header_snip) = snippet_opt(cx, header_span);
-                            if let Some(ret_pos) = position_before_rarrow(header_snip.clone());
+                            if let Some(ret_pos) = position_before_rarrow(&header_snip);
                             if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output);
                             then {
                                 let help = format!("make the function `async` and {}", ret_sugg);
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 3c4368a..a0cfe14 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -80,7 +80,7 @@
         }
 
         if_chain! {
-            if let Some((cond, then, _)) = higher::if_block(&expr);
+            if let ExprKind::If(cond, then, _) = &expr.kind;
             if let ExprKind::MethodCall(_, _, [target_arg, pattern], _) = cond.kind;
             if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id);
             if let ExprKind::Path(target_path) = &target_arg.kind;
diff --git a/src/tools/clippy/clippy_lints/src/map_err_ignore.rs b/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
index f3c0515..76fe8e7 100644
--- a/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
+++ b/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
@@ -7,7 +7,7 @@
 declare_clippy_lint! {
     /// **What it does:** Checks for instances of `map_err(|_| Some::Enum)`
     ///
-    /// **Why is this bad?** This map_err throws away the original error rather than allowing the enum to contain and report the cause of the error
+    /// **Why is this bad?** This `map_err` throws away the original error rather than allowing the enum to contain and report the cause of the error
     ///
     /// **Known problems:** None.
     ///
@@ -135,7 +135,7 @@
                                     body_span,
                                     "`map_err(|_|...` wildcard pattern discards the original error",
                                     None,
-                                    "Consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)",
+                                    "consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)",
                                 );
                             }
                         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index e99fe1b..f7231bb 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -1626,7 +1626,7 @@
         let self_ty = cx.tcx.type_of(def_id);
 
         // if this impl block implements a trait, lint in trait definition instead
-        if let hir::ItemKind::Impl { of_trait: Some(_), .. } = item.kind {
+        if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind {
             return;
         }
 
@@ -1697,7 +1697,7 @@
             if let ty::Opaque(def_id, _) = *ret_ty.kind() {
                 // one of the associated types must be Self
                 for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
-                    if let ty::PredicateAtom::Projection(projection_predicate) = predicate.skip_binders() {
+                    if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
                         // walk the associated type and check for Self
                         if contains_ty(projection_predicate.ty, self_ty) {
                             return;
@@ -2048,6 +2048,7 @@
             hir::ExprKind::Call(..)
             | hir::ExprKind::MethodCall(..)
             // These variants are debatable or require further examination
+            | hir::ExprKind::If(..)
             | hir::ExprKind::Match(..)
             | hir::ExprKind::Block{ .. } => true,
             _ => false,
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
index d082a88..d98e616 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
@@ -90,6 +90,12 @@
             }
             (found_mapping, found_filtering)
         },
+        // There must be an else_arm or there will be a type error
+        hir::ExprKind::If(_, ref if_arm, Some(ref else_arm)) => {
+            let if_check = check_expression(cx, arg_id, if_arm);
+            let else_check = check_expression(cx, arg_id, else_arm);
+            (if_check.0 | else_check.0, if_check.1 | else_check.1)
+        },
         hir::ExprKind::Path(path) if match_qpath(path, &paths::OPTION_NONE) => (false, true),
         _ => (true, true),
     }
diff --git a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
index 76417aa..71f91eb 100644
--- a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
+++ b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
@@ -90,6 +90,10 @@
                 self.found = true;
                 return;
             },
+            ExprKind::If(..) => {
+                self.found = true;
+                return;
+            },
             ExprKind::Path(_) => {
                 if let Some(adj) = self.cx.typeck_results().adjustments().get(expr.hir_id) {
                     if adj
diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs
index 42f97b2..6b9a37b 100644
--- a/src/tools/clippy/clippy_lints/src/needless_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs
@@ -4,7 +4,7 @@
 
 use crate::utils::sugg::Sugg;
 use crate::utils::{
-    higher, is_expn_of, parent_node_is_if_expr, snippet_with_applicability, span_lint, span_lint_and_sugg,
+    is_expn_of, parent_node_is_if_expr, snippet_with_applicability, span_lint, span_lint_and_sugg,
 };
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
@@ -71,7 +71,7 @@
 impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         use self::Expression::{Bool, RetBool};
-        if let Some((ref pred, ref then_block, Some(ref else_expr))) = higher::if_block(&e) {
+        if let ExprKind::If(ref pred, ref then_block, Some(ref else_expr)) = e.kind {
             let reduce = |ret, not| {
                 let mut applicability = Applicability::MachineApplicable;
                 let snip = Sugg::hir_with_applicability(cx, pred, "<predicate>", &mut applicability);
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 5043b7b..3b71f1b 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -8,7 +8,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir::intravisit::FnKind;
-use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, ItemKind, Node, PatKind, QPath, TyKind};
+use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, ItemKind, Impl, Node, PatKind, QPath, TyKind};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, TypeFoldable};
@@ -92,7 +92,7 @@
         if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
             if matches!(
                 item.kind,
-                ItemKind::Impl { of_trait: Some(_), .. } | ItemKind::Trait(..)
+                ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
             ) {
                 return;
             }
@@ -115,13 +115,11 @@
             .filter(|p| !p.is_global())
             .filter_map(|obligation| {
                 // Note that we do not want to deal with qualified predicates here.
-                if let ty::PredicateKind::Atom(ty::PredicateAtom::Trait(pred, _)) = obligation.predicate.kind() {
-                    if pred.def_id() == sized_trait {
-                        return None;
-                    }
-                    Some(pred)
-                } else {
-                    None
+                match obligation.predicate.kind().no_bound_vars() {
+                    Some(ty::PredicateKind::Trait(pred, _)) if pred.def_id() != sized_trait => {
+                        Some(pred)
+                    },
+                    _ => None,
                 }
             })
             .collect::<Vec<_>>();
diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs
index 68fdd0e..bd3dac6 100644
--- a/src/tools/clippy/clippy_lints/src/new_without_default.rs
+++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs
@@ -60,9 +60,9 @@
 impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
     #[allow(clippy::too_many_lines)]
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
-        if let hir::ItemKind::Impl {
+        if let hir::ItemKind::Impl(hir::Impl {
             of_trait: None, items, ..
-        } = item.kind
+        }) = item.kind
         {
             for assoc_item in items {
                 if let hir::AssocItemKind::Fn { has_self: false } = assoc_item.kind {
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 6b0d198..3a9aa6c 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -7,7 +7,7 @@
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{
-    BodyId, Expr, ExprKind, HirId, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
+    BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
 };
 use rustc_infer::traits::specialization_graph;
 use rustc_lint::{LateContext, LateLintPass, Lint};
@@ -275,10 +275,10 @@
             let item = cx.tcx.hir().expect_item(item_hir_id);
 
             match &item.kind {
-                ItemKind::Impl {
+                ItemKind::Impl(Impl {
                     of_trait: Some(of_trait_ref),
                     ..
-                } => {
+                }) => {
                     if_chain! {
                         // Lint a trait impl item only when the definition is a generic type,
                         // assuming a assoc const is not meant to be a interior mutable type.
@@ -317,7 +317,7 @@
                         }
                     }
                 },
-                ItemKind::Impl { of_trait: None, .. } => {
+                ItemKind::Impl(Impl { of_trait: None, .. }) => {
                     let ty = hir_ty_to_ty(cx.tcx, hir_ty);
                     // Normalize assoc types originated from generic params.
                     let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
index 681dbce..391f893 100644
--- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
@@ -109,25 +109,26 @@
 /// it in curly braces. Otherwise, we don't.
 fn should_wrap_in_braces(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| {
+        let mut should_wrap = false;
+        
         if let Some(Expr {
             kind:
                 ExprKind::Match(
                     _,
                     arms,
-                    MatchSource::IfDesugar {
-                        contains_else_clause: true,
-                    }
-                    | MatchSource::IfLetDesugar {
+                    MatchSource::IfLetDesugar {
                         contains_else_clause: true,
                     },
                 ),
             ..
         }) = parent.expr
         {
-            expr.hir_id == arms[1].body.hir_id
-        } else {
-            false
+            should_wrap = expr.hir_id == arms[1].body.hir_id;
+        } else if let Some(Expr { kind: ExprKind::If(_, _, Some(else_clause)), .. }) = parent.expr {
+            should_wrap = expr.hir_id == else_clause.hir_id;
         }
+
+        should_wrap
     })
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs
index ceecc8d..04b6e5d 100644
--- a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs
@@ -1,6 +1,6 @@
 use crate::utils::{is_automatically_derived, span_lint_hir};
 use if_chain::if_chain;
-use rustc_hir::{Item, ItemKind};
+use rustc_hir::{Item, ItemKind, Impl};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
@@ -34,7 +34,7 @@
 impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
         if_chain! {
-            if let ItemKind::Impl{ of_trait: Some(ref trait_ref), items: impl_items, .. } = item.kind;
+            if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items: impl_items, .. }) = item.kind;
             if !is_automatically_derived(&*item.attrs);
             if let Some(eq_trait) = cx.tcx.lang_items().eq_trait();
             if trait_ref.path.res.def_id() == eq_trait;
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 6a17d65..7814065 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -6,7 +6,7 @@
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::intravisit::FnKind;
-use rustc_hir::{BindingAnnotation, Body, FnDecl, HirId, ItemKind, MutTy, Mutability, Node, PatKind};
+use rustc_hir::{BindingAnnotation, Body, FnDecl, HirId, ItemKind, MutTy, Mutability, Node, PatKind, Impl};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -246,7 +246,7 @@
         if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
             if matches!(
                 item.kind,
-                ItemKind::Impl { of_trait: Some(_), .. } | ItemKind::Trait(..)
+                ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
             ) {
                 return;
             }
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index dcb643a..b832add 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -8,7 +8,7 @@
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{
-    BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind,
+    BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind, Impl,
     Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
@@ -132,7 +132,7 @@
         if let ImplItemKind::Fn(ref sig, body_id) = item.kind {
             let parent_item = cx.tcx.hir().get_parent_item(item.hir_id);
             if let Some(Node::Item(it)) = cx.tcx.hir().find(parent_item) {
-                if let ItemKind::Impl { of_trait: Some(_), .. } = it.kind {
+                if let ItemKind::Impl(Impl { of_trait: Some(_), .. }) = it.kind {
                     return; // ignore trait impls
                 }
             }
@@ -182,20 +182,6 @@
 
         if let ty::Ref(_, ty, Mutability::Not) = ty.kind() {
             if is_type_diagnostic_item(cx, ty, sym::vec_type) {
-                let mut ty_snippet = None;
-                if_chain! {
-                    if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).kind;
-                    if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last();
-                    then {
-                        let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg {
-                            GenericArg::Type(ty) => Some(ty),
-                            _ => None,
-                        }).collect();
-                        if types.len() == 1 {
-                            ty_snippet = snippet_opt(cx, types[0].span);
-                        }
-                    }
-                };
                 if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) {
                     span_lint_and_then(
                         cx,
@@ -204,7 +190,7 @@
                         "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \
                          with non-Vec-based slices.",
                         |diag| {
-                            if let Some(ref snippet) = ty_snippet {
+                            if let Some(ref snippet) = get_only_generic_arg_snippet(cx, arg) {
                                 diag.span_suggestion(
                                     arg.span,
                                     "change this to",
@@ -247,6 +233,33 @@
                         },
                     );
                 }
+            } else if match_type(cx, ty, &paths::PATH_BUF) {
+                if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_path_buf()"), ("as_path", "")]) {
+                    span_lint_and_then(
+                        cx,
+                        PTR_ARG,
+                        arg.span,
+                        "writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.",
+                        |diag| {
+                            diag.span_suggestion(
+                                arg.span,
+                                "change this to",
+                                "&Path".into(),
+                                Applicability::Unspecified,
+                            );
+                            for (clonespan, suggestion) in spans {
+                                diag.span_suggestion_short(
+                                    clonespan,
+                                    &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| {
+                                        Cow::Owned(format!("change `{}` to", x))
+                                    }),
+                                    suggestion.into(),
+                                    Applicability::Unspecified,
+                                );
+                            }
+                        },
+                    );
+                }
             } else if match_type(cx, ty, &paths::COW) {
                 if_chain! {
                     if let TyKind::Rptr(_, MutTy { ref ty, ..} ) = arg.kind;
@@ -309,6 +322,23 @@
     }
 }
 
+fn get_only_generic_arg_snippet(cx: &LateContext<'_>, arg: &Ty<'_>) -> Option<String> {
+    if_chain! {
+        if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).kind;
+        if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last();
+        let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg {
+            GenericArg::Type(ty) => Some(ty),
+            _ => None,
+        }).collect();
+        if types.len() == 1;
+        then {
+            snippet_opt(cx, types[0].span)
+        } else {
+            None
+        }
+    }
+}
+
 fn get_rptr_lm<'tcx>(ty: &'tcx Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> {
     if let TyKind::Rptr(ref lt, ref m) = ty.kind {
         Some((lt, m.mutbl, ty.span))
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index b91233a..6c480d4 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -8,7 +8,7 @@
 
 use crate::utils::sugg::Sugg;
 use crate::utils::{
-    eq_expr_value, higher, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet_with_applicability,
+    eq_expr_value, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet_with_applicability,
     span_lint_and_sugg,
 };
 
@@ -50,7 +50,7 @@
     /// If it matches, it will suggest to use the question mark operator instead
     fn check_is_none_and_early_return_none(cx: &LateContext<'_>, expr: &Expr<'_>) {
         if_chain! {
-            if let Some((if_expr, body, else_)) = higher::if_block(&expr);
+            if let ExprKind::If(if_expr, body, else_) = &expr.kind;
             if let ExprKind::MethodCall(segment, _, args, _) = &if_expr.kind;
             if segment.ident.name == sym!(is_none);
             if Self::expression_returns_none(cx, body);
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 7f4913a..35827e0 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -184,6 +184,14 @@
         ExprKind::Block(ref block, _) => {
             check_block_return(cx, block);
         },
+        ExprKind::If(_, then, else_clause_opt) => {
+            if let ExprKind::Block(ref ifblock, _) = then.kind {
+                check_block_return(cx, ifblock);
+            }
+            if let Some(else_clause) = else_clause_opt {
+                check_final_expr(cx, else_clause, None, RetReplacement::Empty);
+            }
+        },
         // a match expr, check all arms
         // an if/if let expr, check both exprs
         // note, if without else is going to be a type checking error anyways
@@ -194,9 +202,6 @@
                     check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Block);
                 }
             },
-            MatchSource::IfDesugar {
-                contains_else_clause: true,
-            }
             | MatchSource::IfLetDesugar {
                 contains_else_clause: true,
             } => {
diff --git a/src/tools/clippy/clippy_lints/src/serde_api.rs b/src/tools/clippy/clippy_lints/src/serde_api.rs
index 339a7cf..ca4fd9f 100644
--- a/src/tools/clippy/clippy_lints/src/serde_api.rs
+++ b/src/tools/clippy/clippy_lints/src/serde_api.rs
@@ -1,5 +1,5 @@
 use crate::utils::{get_trait_def_id, paths, span_lint};
-use rustc_hir::{Item, ItemKind};
+use rustc_hir::{Item, ItemKind, Impl};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -22,11 +22,11 @@
 
 impl<'tcx> LateLintPass<'tcx> for SerdeAPI {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if let ItemKind::Impl {
+        if let ItemKind::Impl(Impl {
             of_trait: Some(ref trait_ref),
             items,
             ..
-        } = item.kind
+        }) = item.kind
         {
             let did = trait_ref.path.res.def_id();
             if let Some(visit_did) = get_trait_def_id(cx, &paths::SERDE_DE_VISITOR) {
diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs
index f839659..f2f3dfa 100644
--- a/src/tools/clippy/clippy_lints/src/shadow.rs
+++ b/src/tools/clippy/clippy_lints/src/shadow.rs
@@ -333,6 +333,13 @@
                 check_expr(cx, e, bindings)
             }
         },
+        ExprKind::If(ref cond, ref then, ref otherwise) => {
+            check_expr(cx, cond, bindings);
+            check_expr(cx, &**then, bindings);
+            if let Some(ref o) = *otherwise {
+                check_expr(cx, o, bindings);
+            }
+        },
         ExprKind::Match(ref init, arms, _) => {
             check_expr(cx, init, bindings);
             let len = bindings.len();
diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
index 35b38ec..1fc4ff5 100644
--- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
@@ -40,7 +40,7 @@
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
         if_chain! {
             if !in_macro(item.span);
-            if cx.sess.opts.edition == Edition::Edition2018;
+            if cx.sess.opts.edition >= Edition::Edition2018;
             if !item.vis.kind.is_pub();
             if let ItemKind::Use(use_tree) = &item.kind;
             if let segments = &use_tree.prefix.segments;
diff --git a/src/tools/clippy/clippy_lints/src/to_string_in_display.rs b/src/tools/clippy/clippy_lints/src/to_string_in_display.rs
index 006d7a3..675eaf4 100644
--- a/src/tools/clippy/clippy_lints/src/to_string_in_display.rs
+++ b/src/tools/clippy/clippy_lints/src/to_string_in_display.rs
@@ -1,7 +1,7 @@
 use crate::utils::{match_def_path, match_trait_method, paths, qpath_res, span_lint};
 use if_chain::if_chain;
 use rustc_hir::def::Res;
-use rustc_hir::{Expr, ExprKind, HirId, ImplItem, ImplItemKind, Item, ItemKind};
+use rustc_hir::{Expr, ExprKind, HirId, ImplItem, ImplItemKind, Item, ItemKind, Impl};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 
@@ -111,7 +111,7 @@
 
 fn is_display_impl(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
     if_chain! {
-        if let ItemKind::Impl { of_trait: Some(trait_ref), .. } = &item.kind;
+        if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), .. }) = &item.kind;
         if let Some(did) = trait_ref.trait_def_id();
         then {
             match_def_path(cx, did, &paths::DISPLAY_TRAIT)
diff --git a/src/tools/clippy/clippy_lints/src/types.rs b/src/tools/clippy/clippy_lints/src/types.rs
index fd74783..2696c5e 100644
--- a/src/tools/clippy/clippy_lints/src/types.rs
+++ b/src/tools/clippy/clippy_lints/src/types.rs
@@ -258,7 +258,7 @@
     fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) {
         // Skip trait implementations; see issue #605.
         if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(id)) {
-            if let ItemKind::Impl { of_trait: Some(_), .. } = item.kind {
+            if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind {
                 return;
             }
         }
@@ -2558,21 +2558,16 @@
         }
 
         match item.kind {
-            ItemKind::Impl {
-                ref generics,
-                self_ty: ref ty,
-                ref items,
-                ..
-            } => {
+            ItemKind::Impl(ref impl_) => {
                 let mut vis = ImplicitHasherTypeVisitor::new(cx);
-                vis.visit_ty(ty);
+                vis.visit_ty(impl_.self_ty);
 
                 for target in &vis.found {
                     if differing_macro_contexts(item.span, target.span()) {
                         return;
                     }
 
-                    let generics_suggestion_span = generics.span.substitute_dummy({
+                    let generics_suggestion_span = impl_.generics.span.substitute_dummy({
                         let pos = snippet_opt(cx, item.span.until(target.span()))
                             .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4)));
                         if let Some(pos) = pos {
@@ -2583,7 +2578,7 @@
                     });
 
                     let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
-                    for item in items.iter().map(|item| cx.tcx.hir().impl_item(item.id)) {
+                    for item in impl_.items.iter().map(|item| cx.tcx.hir().impl_item(item.id)) {
                         ctr_vis.visit_impl_item(item);
                     }
 
@@ -2596,7 +2591,7 @@
                             target.type_name()
                         ),
                         move |diag| {
-                            suggestion(cx, diag, generics.span, generics_suggestion_span, target, ctr_vis);
+                            suggestion(cx, diag, impl_.generics.span, generics_suggestion_span, target, ctr_vis);
                         },
                     );
                 }
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
index 2501635..c6ae8b9 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -4,7 +4,7 @@
 use rustc_hir::{Expr, ExprKind, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
-use rustc_middle::ty::{GenericPredicates, PredicateAtom, ProjectionPredicate, TraitPredicate};
+use rustc_middle::ty::{GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{BytePos, Span};
 
@@ -42,7 +42,7 @@
     let mut preds = Vec::new();
     for (pred, _) in generics.predicates {
         if_chain! {
-            if let PredicateAtom::Trait(poly_trait_pred, _) = pred.skip_binders();
+            if let PredicateKind::Trait(poly_trait_pred, _) = pred.kind().skip_binder();
             let trait_pred = cx.tcx.erase_late_bound_regions(ty::Binder::bind(poly_trait_pred));
             if let Some(trait_def_id) = trait_id;
             if trait_def_id == trait_pred.trait_ref.def_id;
@@ -60,7 +60,7 @@
     pred: TraitPredicate<'tcx>,
 ) -> Option<ProjectionPredicate<'tcx>> {
     generics.predicates.iter().find_map(|(proj_pred, _)| {
-        if let ty::PredicateAtom::Projection(proj_pred) = proj_pred.skip_binders() {
+        if let ty::PredicateKind::Projection(proj_pred) = proj_pred.kind().skip_binder() {
             let projection_pred = cx.tcx.erase_late_bound_regions(ty::Binder::bind(proj_pred));
             if projection_pred.projection_ty.substs == pred.trait_ref.substs {
                 return Some(projection_pred);
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
index 5b9a80f..07cd752 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
@@ -5,7 +5,7 @@
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, ExprKind, FnDecl, HirId, ItemKind, Node};
+use rustc_hir::{Body, ExprKind, FnDecl, HirId, ItemKind, Impl, Node};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -77,7 +77,7 @@
         if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
             if matches!(
                 item.kind,
-                ItemKind::Impl { of_trait: Some(_), .. } | ItemKind::Trait(..)
+                ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
             ) {
                 return;
             }
diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs
index da75171..a617179 100644
--- a/src/tools/clippy/clippy_lints/src/unused_self.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_self.rs
@@ -1,7 +1,7 @@
 use if_chain::if_chain;
 use rustc_hir::def::Res;
 use rustc_hir::intravisit::{walk_path, NestedVisitorMap, Visitor};
-use rustc_hir::{HirId, ImplItem, ImplItemKind, ItemKind, Path};
+use rustc_hir::{HirId, ImplItem, ImplItemKind, ItemKind, Impl, Path};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::map::Map;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -49,7 +49,7 @@
         let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id);
         let assoc_item = cx.tcx.associated_item(def_id);
         if_chain! {
-            if let ItemKind::Impl { of_trait: None, .. } = parent_item.kind;
+            if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind;
             if assoc_item.fn_has_self_parameter;
             if let ImplItemKind::Fn(.., body_id) = &impl_item.kind;
             let body = cx.tcx.hir().body(*body_id);
diff --git a/src/tools/clippy/clippy_lints/src/unused_unit.rs b/src/tools/clippy/clippy_lints/src/unused_unit.rs
index f61fd2e..a31cd5f 100644
--- a/src/tools/clippy/clippy_lints/src/unused_unit.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_unit.rs
@@ -120,7 +120,7 @@
 
 fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) {
     let (ret_span, appl) = if let Ok(fn_source) = cx.sess().source_map().span_to_snippet(span.with_hi(ty.span.hi())) {
-        position_before_rarrow(fn_source).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
+        position_before_rarrow(&fn_source).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
             (
                 #[allow(clippy::cast_possible_truncation)]
                 ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)),
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index f4a77e5..6a87f53 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -1,5 +1,5 @@
 use crate::utils::{
-    differing_macro_contexts, higher::if_block, is_type_diagnostic_item, span_lint_and_then,
+    differing_macro_contexts, is_type_diagnostic_item, span_lint_and_then,
     usage::is_potentially_mutated,
 };
 use if_chain::if_chain;
@@ -158,7 +158,7 @@
         if in_external_macro(self.cx.tcx.sess, expr.span) {
             return;
         }
-        if let Some((cond, then, els)) = if_block(&expr) {
+        if let ExprKind::If(cond, then, els) = &expr.kind {
             walk_expr(self, cond);
             self.visit_branch(cond, then, false);
             if let Some(els) = els {
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index 3b23f88..b82ea66 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -181,8 +181,8 @@
             return;
         }
         if_chain! {
-            if let ItemKind::Impl{ self_ty: ref item_type, items: refs, .. } = item.kind;
-            if let TyKind::Path(QPath::Resolved(_, ref item_path)) = item_type.kind;
+            if let ItemKind::Impl(impl_) = &item.kind;
+            if let TyKind::Path(QPath::Resolved(_, ref item_path)) = impl_.self_ty.kind;
             then {
                 let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args;
                 let should_check = parameters.as_ref().map_or(
@@ -200,7 +200,7 @@
                     let impl_trait_ref = cx.tcx.impl_trait_ref(impl_def_id);
 
                     if let Some(impl_trait_ref) = impl_trait_ref {
-                        for impl_item_ref in refs {
+                        for impl_item_ref in impl_.items {
                             let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id);
                             if let ImplItemKind::Fn(FnSig{ decl: impl_decl, .. }, impl_body_id)
                                     = &impl_item.kind {
@@ -213,7 +213,7 @@
                             }
                         }
                     } else {
-                        for impl_item_ref in refs {
+                        for impl_item_ref in impl_.items {
                             let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id);
                             visitor.visit_impl_item(impl_item);
                         }
diff --git a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs
index f0267e4..eac5d0a 100644
--- a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs
@@ -407,6 +407,10 @@
     }
 }
 
+pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool {
+    eq_expr(&l.value, &r.value)
+}
+
 pub fn eq_defaultness(l: Defaultness, r: Defaultness) -> bool {
     matches!(
         (l, r),
@@ -497,7 +501,18 @@
         && match (&l.kind, &r.kind) {
             (Lifetime, Lifetime) => true,
             (Type { default: l }, Type { default: r }) => both(l, r, |l, r| eq_ty(l, r)),
-            (Const { ty: l, kw_span: _ }, Const { ty: r, kw_span: _ }) => eq_ty(l, r),
+            (
+                Const {
+                    ty: lt,
+                    kw_span: _,
+                    default: ld,
+                },
+                Const {
+                    ty: rt,
+                    kw_span: _,
+                    default: rd,
+                },
+            ) => eq_ty(lt, rt) && both(ld, rd, |ld, rd| eq_anon_const(ld, rd)),
             _ => false,
         }
         && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r))
@@ -541,7 +556,7 @@
     match (l, r) {
         (Empty, Empty) => true,
         (Delimited(_, ld, lts), Delimited(_, rd, rts)) => ld == rd && lts.eq_unspanned(rts),
-        (Eq(_, lts), Eq(_, rts)) => lts.eq_unspanned(rts),
+        (Eq(_, lt), Eq(_, rt)) => lt.kind == rt.kind,
         _ => false,
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 4249dbb..43afa65 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -1,7 +1,7 @@
 //! A group of attributes that can be attached to Rust code in order
 //! to generate a clippy lint detecting said code automatically.
 
-use crate::utils::{get_attr, higher};
+use crate::utils::get_attr;
 use rustc_ast::ast::{Attribute, LitFloatType, LitKind};
 use rustc_ast::walk_list;
 use rustc_data_structures::fx::FxHashMap;
@@ -201,32 +201,6 @@
 
     #[allow(clippy::too_many_lines)]
     fn visit_expr(&mut self, expr: &Expr<'_>) {
-        // handle if desugarings
-        // TODO add more desugarings here
-        if let Some((cond, then, opt_else)) = higher::if_block(&expr) {
-            let cond_pat = self.next("cond");
-            let then_pat = self.next("then");
-            if let Some(else_) = opt_else {
-                let else_pat = self.next("else_");
-                println!(
-                    "    if let Some((ref {}, ref {}, Some({}))) = higher::if_block(&{});",
-                    cond_pat, then_pat, else_pat, self.current
-                );
-                self.current = else_pat;
-                self.visit_expr(else_);
-            } else {
-                println!(
-                    "    if let Some((ref {}, ref {}, None)) = higher::if_block(&{});",
-                    cond_pat, then_pat, self.current
-                );
-            }
-            self.current = cond_pat;
-            self.visit_expr(cond);
-            self.current = then_pat;
-            self.visit_expr(then);
-            return;
-        }
-
         print!("    if let ExprKind::");
         let current = format!("{}.kind", self.current);
         match expr.kind {
@@ -351,6 +325,25 @@
                 self.current = body_pat;
                 self.visit_block(body);
             },
+            ExprKind::If(ref cond, ref then, ref opt_else) => {
+                let cond_pat = self.next("cond");
+                let then_pat = self.next("then");
+                if let Some(ref else_) = *opt_else {
+                    let else_pat = self.next("else_");
+                    println!(
+                        "If(ref {}, ref {}, Some(ref {})) = {};",
+                        cond_pat, then_pat, else_pat, current
+                    );
+                    self.current = else_pat;
+                    self.visit_expr(else_);
+                } else {
+                    println!("If(ref {}, ref {}, None) = {};", cond_pat, then_pat, current);
+                }
+                self.current = cond_pat;
+                self.visit_expr(cond);
+                self.current = then_pat;
+                self.visit_expr(then);
+            },
             ExprKind::Match(ref expr, ref arms, desugaring) => {
                 let des = desugaring_name(desugaring);
                 let expr_pat = self.next("expr");
@@ -743,10 +736,6 @@
             contains_else_clause
         ),
         hir::MatchSource::IfLetGuardDesugar => "MatchSource::IfLetGuardDesugar".to_string(),
-        hir::MatchSource::IfDesugar { contains_else_clause } => format!(
-            "MatchSource::IfDesugar {{ contains_else_clause: {} }}",
-            contains_else_clause
-        ),
         hir::MatchSource::AwaitDesugar => "MatchSource::AwaitDesugar".to_string(),
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/utils/eager_or_lazy.rs b/src/tools/clippy/clippy_lints/src/utils/eager_or_lazy.rs
index 8fe5dde..2f157c5 100644
--- a/src/tools/clippy/clippy_lints/src/utils/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/eager_or_lazy.rs
@@ -62,6 +62,7 @@
         | ExprKind::Type(..)
         | ExprKind::DropTemps(..)
         | ExprKind::Loop(..)
+        | ExprKind::If(..)
         | ExprKind::Match(..)
         | ExprKind::Closure(..)
         | ExprKind::Block(..)
diff --git a/src/tools/clippy/clippy_lints/src/utils/higher.rs b/src/tools/clippy/clippy_lints/src/utils/higher.rs
index 01ffac5..9b35858 100644
--- a/src/tools/clippy/clippy_lints/src/utils/higher.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/higher.rs
@@ -170,33 +170,6 @@
     None
 }
 
-/// Recover the essential nodes of a desugared if block
-/// `if cond { then } else { els }` becomes `(cond, then, Some(els))`
-pub fn if_block<'tcx>(
-    expr: &'tcx hir::Expr<'tcx>,
-) -> Option<(
-    &'tcx hir::Expr<'tcx>,
-    &'tcx hir::Expr<'tcx>,
-    Option<&'tcx hir::Expr<'tcx>>,
-)> {
-    if let hir::ExprKind::Match(ref cond, ref arms, hir::MatchSource::IfDesugar { contains_else_clause }) = expr.kind {
-        let cond = if let hir::ExprKind::DropTemps(ref cond) = cond.kind {
-            cond
-        } else {
-            panic!("If block desugar must contain DropTemps");
-        };
-        let then = &arms[0].body;
-        let els = if contains_else_clause {
-            Some(&*arms[1].body)
-        } else {
-            None
-        };
-        Some((cond, then, els))
-    } else {
-        None
-    }
-}
-
 /// Represent the pre-expansion arguments of a `vec!` invocation.
 pub enum VecArgs<'a> {
     /// `vec![elem; len]`
@@ -267,12 +240,11 @@
 
     if let ExprKind::Block(ref block, _) = e.kind {
         if block.stmts.len() == 1 {
-            if let StmtKind::Semi(ref matchexpr) = block.stmts[0].kind {
+            if let StmtKind::Semi(ref matchexpr) = block.stmts.get(0)?.kind {
                 // macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`)
                 if_chain! {
-                    if let ExprKind::Match(ref ifclause, _, _) = matchexpr.kind;
-                    if let ExprKind::DropTemps(ref droptmp) = ifclause.kind;
-                    if let ExprKind::Unary(UnOp::UnNot, condition) = droptmp.kind;
+                    if let ExprKind::If(ref clause, _, _)  = matchexpr.kind;
+                    if let ExprKind::Unary(UnOp::UnNot, condition) = clause.kind;
                     then {
                         return Some(vec![condition]);
                     }
diff --git a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
index a8fbb2f..062df68 100644
--- a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
@@ -119,6 +119,9 @@
             (&ExprKind::Index(ref la, ref li), &ExprKind::Index(ref ra, ref ri)) => {
                 self.eq_expr(la, ra) && self.eq_expr(li, ri)
             },
+            (&ExprKind::If(ref lc, ref lt, ref le), &ExprKind::If(ref rc, ref rt, ref re)) => {
+                self.eq_expr(lc, rc) && self.eq_expr(&**lt, &**rt) && both(le, re, |l, r| self.eq_expr(l, r))
+            },
             (&ExprKind::Lit(ref l), &ExprKind::Lit(ref r)) => l.node == r.node,
             (&ExprKind::Loop(ref lb, ref ll, ref lls), &ExprKind::Loop(ref rb, ref rl, ref rls)) => {
                 lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.as_str() == r.ident.as_str())
@@ -564,6 +567,15 @@
                     self.hash_name(i.ident.name);
                 }
             },
+            ExprKind::If(ref cond, ref then, ref else_opt) => {
+                let c: fn(_, _, _) -> _ = ExprKind::If;
+                c.hash(&mut self.s);
+                self.hash_expr(cond);
+                self.hash_expr(&**then);
+                if let Some(ref e) = *else_opt {
+                    self.hash_expr(e);
+                }
+            },
             ExprKind::Match(ref e, arms, ref s) => {
                 self.hash_expr(e);
 
@@ -744,7 +756,7 @@
                     }
                     for segment in path.segments {
                         segment.ident.name.hash(&mut self.s);
-                        self.hash_generic_args(segment.generic_args().args);
+                        self.hash_generic_args(segment.args().args);
                     }
                 },
                 QPath::TypeRelative(ref ty, ref segment) => {
diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
index 5d946e4..9bec24b 100644
--- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
@@ -213,6 +213,15 @@
         hir::ExprKind::Loop(..) => {
             println!("{}Loop", ind);
         },
+        hir::ExprKind::If(ref cond, _, ref else_opt) => {
+            println!("{}If", ind);
+            println!("{}condition:", ind);
+            print_expr(cx, cond, indent + 1);
+            if let Some(ref els) = *else_opt {
+                println!("{}else:", ind);
+                print_expr(cx, els, indent + 1);
+            }
+        },
         hir::ExprKind::Match(ref cond, _, ref source) => {
             println!("{}Match", ind);
             println!("{}condition:", ind);
@@ -423,13 +432,13 @@
         hir::ItemKind::TraitAlias(..) => {
             println!("trait alias");
         },
-        hir::ItemKind::Impl {
+        hir::ItemKind::Impl(hir::Impl {
             of_trait: Some(ref _trait_ref),
             ..
-        } => {
+        }) => {
             println!("trait impl");
         },
-        hir::ItemKind::Impl { of_trait: None, .. } => {
+        hir::ItemKind::Impl(hir::Impl { of_trait: None, .. }) => {
             println!("impl");
         },
     }
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
index 9ba39f7..407f06f 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
@@ -352,11 +352,11 @@
         } else if is_expn_of(item.span, "impl_lint_pass").is_some()
             || is_expn_of(item.span, "declare_lint_pass").is_some()
         {
-            if let hir::ItemKind::Impl {
+            if let hir::ItemKind::Impl(hir::Impl {
                 of_trait: None,
                 items: ref impl_item_refs,
                 ..
-            } = item.kind
+            }) = item.kind
             {
                 let mut collector = LintCollector {
                     output: &mut self.registered_lints,
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index 4248560..4c707c4 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -439,8 +439,8 @@
     if_chain! {
         if parent_impl != hir::CRATE_HIR_ID;
         if let hir::Node::Item(item) = cx.tcx.hir().get(parent_impl);
-        if let hir::ItemKind::Impl{ of_trait: trait_ref, .. } = &item.kind;
-        then { return trait_ref.as_ref(); }
+        if let hir::ItemKind::Impl(impl_) = &item.kind;
+        then { return impl_.of_trait.as_ref(); }
     }
     None
 }
@@ -788,8 +788,7 @@
 /// fn into3(self)   -> () {}
 ///               ^
 /// ```
-#[allow(clippy::needless_pass_by_value)]
-pub fn position_before_rarrow(s: String) -> Option<usize> {
+pub fn position_before_rarrow(s: &str) -> Option<usize> {
     s.rfind("->").map(|rpos| {
         let mut rpos = rpos;
         let chars: Vec<char> = s.chars().collect();
@@ -1406,7 +1405,7 @@
     let mut conds = SmallVec::new();
     let mut blocks: SmallVec<[&Block<'_>; 1]> = SmallVec::new();
 
-    while let Some((ref cond, ref then_expr, ref else_expr)) = higher::if_block(&expr) {
+    while let ExprKind::If(ref cond, ref then_expr, ref else_expr) = expr.kind {
         conds.push(&**cond);
         if let ExprKind::Block(ref block, _) = then_expr.kind {
             blocks.push(block);
@@ -1435,11 +1434,11 @@
     let map = cx.tcx.hir();
     let parent_id = map.get_parent_node(expr.hir_id);
     let parent_node = map.get(parent_id);
-
-    match parent_node {
-        Node::Expr(e) => higher::if_block(&e).is_some(),
-        Node::Arm(e) => higher::if_block(&e.body).is_some(),
-        _ => false,
+    if let Node::Expr(Expr { kind: ExprKind::If(_, _, _), .. }) = parent_node {
+        true
+    }
+    else {
+        false
     }
 }
 
@@ -1471,7 +1470,7 @@
         ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
         ty::Opaque(ref def_id, _) => {
             for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
-                if let ty::PredicateAtom::Trait(trait_predicate, _) = predicate.skip_binders() {
+                if let ty::PredicateKind::Trait(trait_predicate, _) = predicate.kind().skip_binder() {
                     if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() {
                         return true;
                     }
@@ -1531,7 +1530,7 @@
 /// ```
 pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool {
     if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
-        matches!(item.kind, ItemKind::Impl { of_trait: Some(_), .. })
+        matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
     } else {
         false
     }
diff --git a/src/tools/clippy/clippy_lints/src/utils/ptr.rs b/src/tools/clippy/clippy_lints/src/utils/ptr.rs
index bd2c619..b330f3d 100644
--- a/src/tools/clippy/clippy_lints/src/utils/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/ptr.rs
@@ -72,7 +72,6 @@
                     }
                 }
             }
-            return;
         }
         walk_expr(self, expr);
     }
diff --git a/src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs b/src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs
index 7cb7d0a..a482017 100644
--- a/src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs
@@ -19,18 +19,18 @@
     loop {
         let predicates = tcx.predicates_of(current);
         for (predicate, _) in predicates.predicates {
-            match predicate.skip_binders() {
-                ty::PredicateAtom::RegionOutlives(_)
-                | ty::PredicateAtom::TypeOutlives(_)
-                | ty::PredicateAtom::WellFormed(_)
-                | ty::PredicateAtom::Projection(_)
-                | ty::PredicateAtom::ConstEvaluatable(..)
-                | ty::PredicateAtom::ConstEquate(..)
-                | ty::PredicateAtom::TypeWellFormedFromEnv(..) => continue,
-                ty::PredicateAtom::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate),
-                ty::PredicateAtom::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate),
-                ty::PredicateAtom::Subtype(_) => panic!("subtype predicate on function: {:#?}", predicate),
-                ty::PredicateAtom::Trait(pred, _) => {
+            match predicate.kind().skip_binder() {
+                ty::PredicateKind::RegionOutlives(_)
+                | ty::PredicateKind::TypeOutlives(_)
+                | ty::PredicateKind::WellFormed(_)
+                | ty::PredicateKind::Projection(_)
+                | ty::PredicateKind::ConstEvaluatable(..)
+                | ty::PredicateKind::ConstEquate(..)
+                | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
+                ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate),
+                ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate),
+                ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {:#?}", predicate),
+                ty::PredicateKind::Trait(pred, _) => {
                     if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
                         continue;
                     }
diff --git a/src/tools/clippy/clippy_lints/src/utils/sugg.rs b/src/tools/clippy/clippy_lints/src/utils/sugg.rs
index 1fcd41e..03678db 100644
--- a/src/tools/clippy/clippy_lints/src/utils/sugg.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/sugg.rs
@@ -103,6 +103,7 @@
         match expr.kind {
             hir::ExprKind::AddrOf(..)
             | hir::ExprKind::Box(..)
+            | hir::ExprKind::If(..)
             | hir::ExprKind::Closure(..)
             | hir::ExprKind::Unary(..)
             | hir::ExprKind::Match(..) => Sugg::MaybeParen(snippet),
diff --git a/src/tools/clippy/clippy_lints/src/utils/visitors.rs b/src/tools/clippy/clippy_lints/src/utils/visitors.rs
index 28b3e79..b769a18 100644
--- a/src/tools/clippy/clippy_lints/src/utils/visitors.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/visitors.rs
@@ -101,6 +101,13 @@
                 }
             } else {
                 match expr.kind {
+                    hir::ExprKind::If(cond, then, else_opt) => {
+                        self.inside_stmt(true).visit_expr(cond);
+                        self.visit_expr(then);
+                        if let Some(el) = else_opt {
+                            self.visit_expr(el);
+                        }
+                    }
                     hir::ExprKind::Match(cond, arms, _) => {
                         self.inside_stmt(true).visit_expr(cond);
                         for arm in arms {
diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
index 1d5fa8d..9761e82 100644
--- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
@@ -62,7 +62,7 @@
 fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool {
     let parent_id = cx.tcx.hir().get_parent_item(hir_id);
     if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(parent_id)) {
-        if let ItemKind::Impl { of_trait: Some(_), .. } = item.kind {
+        if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind {
             return true;
         }
     }
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index d2e8413..c579bee 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2020-12-20"
+channel = "nightly-2021-01-02"
 components = ["llvm-tools-preview", "rustc-dev", "rust-src", "rustfmt"]
diff --git a/src/tools/clippy/tests/ui/author/if.stdout b/src/tools/clippy/tests/ui/author/if.stdout
index c18d035..cac64a3 100644
--- a/src/tools/clippy/tests/ui/author/if.stdout
+++ b/src/tools/clippy/tests/ui/author/if.stdout
@@ -1,7 +1,7 @@
 if_chain! {
     if let StmtKind::Local(ref local) = stmt.kind;
     if let Some(ref init) = local.init;
-    if let Some((ref cond, ref then, Some(else_))) = higher::if_block(&init);
+    if let ExprKind::If(ref cond, ref then, Some(ref else_)) = init.kind;
     if let ExprKind::Block(ref block) = else_.kind;
     if let Some(trailing_expr) = &block.expr;
     if block.stmts.len() == 1;
diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
index f985a15..1832482 100644
--- a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
@@ -84,3 +84,13 @@
         0u32 as u64
     };
 }
+
+#[macro_export]
+macro_rules! large_enum_variant {
+    () => {
+        enum LargeEnumInMacro {
+            A(i32),
+            B([i32; 8000]),
+        }
+    };
+}
diff --git a/src/tools/clippy/tests/ui/deprecated.rs b/src/tools/clippy/tests/ui/deprecated.rs
index e1ee8db..4a53802 100644
--- a/src/tools/clippy/tests/ui/deprecated.rs
+++ b/src/tools/clippy/tests/ui/deprecated.rs
@@ -9,5 +9,6 @@
 #[warn(clippy::drop_bounds)]
 #[warn(clippy::temporary_cstring_as_ptr)]
 #[warn(clippy::panic_params)]
+#[warn(clippy::unknown_clippy_lints)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr
index edbb891..3429317 100644
--- a/src/tools/clippy/tests/ui/deprecated.stderr
+++ b/src/tools/clippy/tests/ui/deprecated.stderr
@@ -66,11 +66,17 @@
 LL | #[warn(clippy::panic_params)]
    |        ^^^^^^^^^^^^^^^^^^^^
 
+error: lint `clippy::unknown_clippy_lints` has been removed: `this lint has been integrated into the `unknown_lints` rustc lint`
+  --> $DIR/deprecated.rs:12:8
+   |
+LL | #[warn(clippy::unknown_clippy_lints)]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: lint `clippy::unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7`
   --> $DIR/deprecated.rs:1:8
    |
 LL | #[warn(clippy::unstable_as_slice)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 12 previous errors
+error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.rs b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
index 79a30c2..3e09210 100644
--- a/src/tools/clippy/tests/ui/field_reassign_with_default.rs
+++ b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
@@ -107,4 +107,16 @@
     x.i = side_effect.next();
     x.j = 2;
     x.i = side_effect.next();
+
+    // don't lint - some private fields
+    let mut x = m::F::default();
+    x.a = 1;
+}
+
+mod m {
+    #[derive(Default)]
+    pub struct F {
+        pub a: u64,
+        b: u64,
+    }
 }
diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
index c788eba..9a2bc77 100644
--- a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
+++ b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
@@ -53,7 +53,7 @@
 LL |     a.i = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: consider initializing the variable with `A::default()` and removing relevant reassignments
+note: consider initializing the variable with `A { i: Default::default(), ..Default::default() }` and removing relevant reassignments
   --> $DIR/field_reassign_with_default.rs:90:5
    |
 LL |     let mut a: A = Default::default();
@@ -65,7 +65,7 @@
 LL |     a.i = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: consider initializing the variable with `A { j: 45, ..Default::default() }` and removing relevant reassignments
+note: consider initializing the variable with `A { i: Default::default(), j: 45 }` and removing relevant reassignments
   --> $DIR/field_reassign_with_default.rs:94:5
    |
 LL |     let mut a: A = Default::default();
diff --git a/src/tools/clippy/tests/ui/from_over_into.rs b/src/tools/clippy/tests/ui/from_over_into.rs
new file mode 100644
index 0000000..292d092
--- /dev/null
+++ b/src/tools/clippy/tests/ui/from_over_into.rs
@@ -0,0 +1,21 @@
+#![warn(clippy::from_over_into)]
+
+// this should throw an error
+struct StringWrapper(String);
+
+impl Into<StringWrapper> for String {
+    fn into(self) -> StringWrapper {
+        StringWrapper(self)
+    }
+}
+
+// this is fine
+struct A(String);
+
+impl From<String> for A {
+    fn from(s: String) -> A {
+        A(s)
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into.stderr b/src/tools/clippy/tests/ui/from_over_into.stderr
new file mode 100644
index 0000000..18f56f8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/from_over_into.stderr
@@ -0,0 +1,15 @@
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+  --> $DIR/from_over_into.rs:6:1
+   |
+LL | / impl Into<StringWrapper> for String {
+LL | |     fn into(self) -> StringWrapper {
+LL | |         StringWrapper(self)
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = note: `-D clippy::from-over-into` implied by `-D warnings`
+   = help: consider to implement `From` instead
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/large_enum_variant.rs b/src/tools/clippy/tests/ui/large_enum_variant.rs
index 852ef5f..d22fee3 100644
--- a/src/tools/clippy/tests/ui/large_enum_variant.rs
+++ b/src/tools/clippy/tests/ui/large_enum_variant.rs
@@ -1,7 +1,12 @@
+// aux-build:macro_rules.rs
+
 #![allow(dead_code)]
 #![allow(unused_variables)]
 #![warn(clippy::large_enum_variant)]
 
+#[macro_use]
+extern crate macro_rules;
+
 enum LargeEnum {
     A(i32),
     B([i32; 8000]),
@@ -51,4 +56,6 @@
     LargeB([i32; 8001]),
 }
 
-fn main() {}
+fn main() {
+    large_enum_variant!();
+}
diff --git a/src/tools/clippy/tests/ui/large_enum_variant.stderr b/src/tools/clippy/tests/ui/large_enum_variant.stderr
index 8ce641a..d39a4d4 100644
--- a/src/tools/clippy/tests/ui/large_enum_variant.stderr
+++ b/src/tools/clippy/tests/ui/large_enum_variant.stderr
@@ -1,12 +1,12 @@
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:7:5
+  --> $DIR/large_enum_variant.rs:12:5
    |
 LL |     B([i32; 8000]),
    |     ^^^^^^^^^^^^^^ this variant is 32000 bytes
    |
    = note: `-D clippy::large-enum-variant` implied by `-D warnings`
 note: and the second-largest variant is 4 bytes:
-  --> $DIR/large_enum_variant.rs:6:5
+  --> $DIR/large_enum_variant.rs:11:5
    |
 LL |     A(i32),
    |     ^^^^^^
@@ -16,13 +16,13 @@
    |       ^^^^^^^^^^^^^^^^
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:31:5
+  --> $DIR/large_enum_variant.rs:36:5
    |
 LL |     ContainingLargeEnum(LargeEnum),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this variant is 32004 bytes
    |
 note: and the second-largest variant is 8 bytes:
-  --> $DIR/large_enum_variant.rs:30:5
+  --> $DIR/large_enum_variant.rs:35:5
    |
 LL |     VariantOk(i32, u32),
    |     ^^^^^^^^^^^^^^^^^^^
@@ -32,30 +32,30 @@
    |                         ^^^^^^^^^^^^^^
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:41:5
+  --> $DIR/large_enum_variant.rs:46:5
    |
 LL |     StructLikeLarge { x: [i32; 8000], y: i32 },
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this variant is 32004 bytes
    |
 note: and the second-largest variant is 8 bytes:
-  --> $DIR/large_enum_variant.rs:40:5
+  --> $DIR/large_enum_variant.rs:45:5
    |
 LL |     VariantOk(i32, u32),
    |     ^^^^^^^^^^^^^^^^^^^
 help: consider boxing the large fields to reduce the total size of the enum
-  --> $DIR/large_enum_variant.rs:41:5
+  --> $DIR/large_enum_variant.rs:46:5
    |
 LL |     StructLikeLarge { x: [i32; 8000], y: i32 },
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:46:5
+  --> $DIR/large_enum_variant.rs:51:5
    |
 LL |     StructLikeLarge2 { x: [i32; 8000] },
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this variant is 32000 bytes
    |
 note: and the second-largest variant is 8 bytes:
-  --> $DIR/large_enum_variant.rs:45:5
+  --> $DIR/large_enum_variant.rs:50:5
    |
 LL |     VariantOk(i32, u32),
    |     ^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/map_err.stderr b/src/tools/clippy/tests/ui/map_err.stderr
index 8ee2941..37e87e6 100644
--- a/src/tools/clippy/tests/ui/map_err.stderr
+++ b/src/tools/clippy/tests/ui/map_err.stderr
@@ -5,7 +5,7 @@
    |                                ^^^
    |
    = note: `-D clippy::map-err-ignore` implied by `-D warnings`
-   = help: Consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)
+   = help: consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)
 
 error: aborting due to previous error
 
diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_attr.rs
index 3848bca..0f47f1c 100644
--- a/src/tools/clippy/tests/ui/min_rust_version_attr.rs
+++ b/src/tools/clippy/tests/ui/min_rust_version_attr.rs
@@ -57,6 +57,14 @@
     let _ = value <= (u32::MAX as i64) && value >= 0;
 }
 
+pub struct FromOverInto(String);
+
+impl Into<FromOverInto> for String {
+    fn into(self) -> FromOverInto {
+        FromOverInto(self)
+    }
+}
+
 pub fn filter_map_next() {
     let a = ["1", "lol", "3", "NaN", "5"];
 
diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr
index 3480526..e3e3b33 100644
--- a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr
+++ b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr
@@ -1,12 +1,12 @@
 error: stripping a prefix manually
-  --> $DIR/min_rust_version_attr.rs:142:24
+  --> $DIR/min_rust_version_attr.rs:150:24
    |
 LL |             assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
    |                        ^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::manual-strip` implied by `-D warnings`
 note: the prefix was tested here
-  --> $DIR/min_rust_version_attr.rs:141:9
+  --> $DIR/min_rust_version_attr.rs:149:9
    |
 LL |         if s.starts_with("hello, ") {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,13 +17,13 @@
    |
 
 error: stripping a prefix manually
-  --> $DIR/min_rust_version_attr.rs:154:24
+  --> $DIR/min_rust_version_attr.rs:162:24
    |
 LL |             assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
    |                        ^^^^^^^^^^^^^^^^^^^^
    |
 note: the prefix was tested here
-  --> $DIR/min_rust_version_attr.rs:153:9
+  --> $DIR/min_rust_version_attr.rs:161:9
    |
 LL |         if s.starts_with("hello, ") {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.stderr b/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.stderr
index 86f61ad..a17f043 100644
--- a/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.stderr
+++ b/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.stderr
@@ -14,7 +14,7 @@
   --> $DIR/panic_in_result_fn_assertions.rs:9:9
    |
 LL |         assert!(x == 5, "wrong argument");
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
diff --git a/src/tools/clippy/tests/ui/ptr_arg.rs b/src/tools/clippy/tests/ui/ptr_arg.rs
index 541225e..06370df 100644
--- a/src/tools/clippy/tests/ui/ptr_arg.rs
+++ b/src/tools/clippy/tests/ui/ptr_arg.rs
@@ -2,6 +2,7 @@
 #![warn(clippy::ptr_arg)]
 
 use std::borrow::Cow;
+use std::path::PathBuf;
 
 fn do_vec(x: &Vec<i64>) {
     //Nothing here
@@ -21,6 +22,15 @@
     //Nothing here either
 }
 
+fn do_path(x: &PathBuf) {
+    //Nothing here either
+}
+
+fn do_path_mut(x: &mut PathBuf) {
+    // no error here
+    //Nothing here either
+}
+
 fn main() {}
 
 trait Foo {
@@ -55,6 +65,14 @@
     x.clone()
 }
 
+fn path_cloned(x: &PathBuf) -> PathBuf {
+    let a = x.clone();
+    let b = x.clone();
+    let c = b.clone();
+    let d = a.clone().clone().clone();
+    x.clone()
+}
+
 fn false_positive_capacity(x: &Vec<u8>, y: &String) {
     let a = x.capacity();
     let b = y.clone();
@@ -87,10 +105,12 @@
 // Check that the allow attribute on parameters is honored
 mod issue_5644 {
     use std::borrow::Cow;
+    use std::path::PathBuf;
 
     fn allowed(
         #[allow(clippy::ptr_arg)] _v: &Vec<u32>,
         #[allow(clippy::ptr_arg)] _s: &String,
+        #[allow(clippy::ptr_arg)] _p: &PathBuf,
         #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>,
     ) {
     }
@@ -100,6 +120,7 @@
         fn allowed(
             #[allow(clippy::ptr_arg)] _v: &Vec<u32>,
             #[allow(clippy::ptr_arg)] _s: &String,
+            #[allow(clippy::ptr_arg)] _p: &PathBuf,
             #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>,
         ) {
         }
@@ -109,8 +130,28 @@
         fn allowed(
             #[allow(clippy::ptr_arg)] _v: &Vec<u32>,
             #[allow(clippy::ptr_arg)] _s: &String,
+            #[allow(clippy::ptr_arg)] _p: &PathBuf,
             #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>,
         ) {
         }
     }
 }
+
+mod issue6509 {
+    use std::path::PathBuf;
+
+    fn foo_vec(vec: &Vec<u8>) {
+        let _ = vec.clone().pop();
+        let _ = vec.clone().clone();
+    }
+
+    fn foo_path(path: &PathBuf) {
+        let _ = path.clone().pop();
+        let _ = path.clone().clone();
+    }
+
+    fn foo_str(str: &PathBuf) {
+        let _ = str.clone().pop();
+        let _ = str.clone().clone();
+    }
+}
diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr
index 314f234..708318b 100644
--- a/src/tools/clippy/tests/ui/ptr_arg.stderr
+++ b/src/tools/clippy/tests/ui/ptr_arg.stderr
@@ -1,5 +1,5 @@
 error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices.
-  --> $DIR/ptr_arg.rs:6:14
+  --> $DIR/ptr_arg.rs:7:14
    |
 LL | fn do_vec(x: &Vec<i64>) {
    |              ^^^^^^^^^ help: change this to: `&[i64]`
@@ -7,19 +7,25 @@
    = note: `-D clippy::ptr-arg` implied by `-D warnings`
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do.
-  --> $DIR/ptr_arg.rs:15:14
+  --> $DIR/ptr_arg.rs:16:14
    |
 LL | fn do_str(x: &String) {
    |              ^^^^^^^ help: change this to: `&str`
 
+error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.
+  --> $DIR/ptr_arg.rs:25:15
+   |
+LL | fn do_path(x: &PathBuf) {
+   |               ^^^^^^^^ help: change this to: `&Path`
+
 error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices.
-  --> $DIR/ptr_arg.rs:28:18
+  --> $DIR/ptr_arg.rs:38:18
    |
 LL |     fn do_vec(x: &Vec<i64>);
    |                  ^^^^^^^^^ help: change this to: `&[i64]`
 
 error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices.
-  --> $DIR/ptr_arg.rs:41:14
+  --> $DIR/ptr_arg.rs:51:14
    |
 LL | fn cloned(x: &Vec<u8>) -> Vec<u8> {
    |              ^^^^^^^^
@@ -38,7 +44,7 @@
    |
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do.
-  --> $DIR/ptr_arg.rs:50:18
+  --> $DIR/ptr_arg.rs:60:18
    |
 LL | fn str_cloned(x: &String) -> String {
    |                  ^^^^^^^
@@ -60,8 +66,31 @@
 LL |     x.to_string()
    |
 
+error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.
+  --> $DIR/ptr_arg.rs:68:19
+   |
+LL | fn path_cloned(x: &PathBuf) -> PathBuf {
+   |                   ^^^^^^^^
+   |
+help: change this to
+   |
+LL | fn path_cloned(x: &Path) -> PathBuf {
+   |                   ^^^^^
+help: change `x.clone()` to
+   |
+LL |     let a = x.to_path_buf();
+   |             ^^^^^^^^^^^^^^^
+help: change `x.clone()` to
+   |
+LL |     let b = x.to_path_buf();
+   |             ^^^^^^^^^^^^^^^
+help: change `x.clone()` to
+   |
+LL |     x.to_path_buf()
+   |
+
 error: writing `&String` instead of `&str` involves a new object where a slice will do.
-  --> $DIR/ptr_arg.rs:58:44
+  --> $DIR/ptr_arg.rs:76:44
    |
 LL | fn false_positive_capacity(x: &Vec<u8>, y: &String) {
    |                                            ^^^^^^^
@@ -80,10 +109,67 @@
    |             ^
 
 error: using a reference to `Cow` is not recommended.
-  --> $DIR/ptr_arg.rs:72:25
+  --> $DIR/ptr_arg.rs:90:25
    |
 LL | fn test_cow_with_ref(c: &Cow<[i32]>) {}
    |                         ^^^^^^^^^^^ help: change this to: `&[i32]`
 
-error: aborting due to 7 previous errors
+error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices.
+  --> $DIR/ptr_arg.rs:143:21
+   |
+LL |     fn foo_vec(vec: &Vec<u8>) {
+   |                     ^^^^^^^^
+   |
+help: change this to
+   |
+LL |     fn foo_vec(vec: &[u8]) {
+   |                     ^^^^^
+help: change `vec.clone()` to
+   |
+LL |         let _ = vec.to_owned().pop();
+   |                 ^^^^^^^^^^^^^^
+help: change `vec.clone()` to
+   |
+LL |         let _ = vec.to_owned().clone();
+   |                 ^^^^^^^^^^^^^^
+
+error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.
+  --> $DIR/ptr_arg.rs:148:23
+   |
+LL |     fn foo_path(path: &PathBuf) {
+   |                       ^^^^^^^^
+   |
+help: change this to
+   |
+LL |     fn foo_path(path: &Path) {
+   |                       ^^^^^
+help: change `path.clone()` to
+   |
+LL |         let _ = path.to_path_buf().pop();
+   |                 ^^^^^^^^^^^^^^^^^^
+help: change `path.clone()` to
+   |
+LL |         let _ = path.to_path_buf().clone();
+   |                 ^^^^^^^^^^^^^^^^^^
+
+error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.
+  --> $DIR/ptr_arg.rs:153:21
+   |
+LL |     fn foo_str(str: &PathBuf) {
+   |                     ^^^^^^^^
+   |
+help: change this to
+   |
+LL |     fn foo_str(str: &Path) {
+   |                     ^^^^^
+help: change `str.clone()` to
+   |
+LL |         let _ = str.to_path_buf().pop();
+   |                 ^^^^^^^^^^^^^^^^^
+help: change `str.clone()` to
+   |
+LL |         let _ = str.to_path_buf().clone();
+   |                 ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr b/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
index 1b85904..94a667e 100644
--- a/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
+++ b/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
@@ -1,52 +1,58 @@
-error: unknown clippy lint: clippy::if_not_els
+error: unknown lint: `clippy::All`
+  --> $DIR/unknown_clippy_lints.rs:5:10
+   |
+LL | #![allow(clippy::All)]
+   |          ^^^^^^^^^^^ help: did you mean: `clippy::all`
+   |
+   = note: `-D unknown-lints` implied by `-D warnings`
+
+error: unknown lint: `clippy::CMP_NAN`
+  --> $DIR/unknown_clippy_lints.rs:6:9
+   |
+LL | #![warn(clippy::CMP_NAN)]
+   |         ^^^^^^^^^^^^^^^ help: did you mean: `clippy::cmp_nan`
+
+error: unknown lint: `clippy::if_not_els`
   --> $DIR/unknown_clippy_lints.rs:9:8
    |
 LL | #[warn(clippy::if_not_els)]
    |        ^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::if_not_else`
-   |
-   = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings`
 
-error: unknown clippy lint: clippy::UNNecsaRy_cAst
+error: unknown lint: `clippy::UNNecsaRy_cAst`
   --> $DIR/unknown_clippy_lints.rs:10:8
    |
 LL | #[warn(clippy::UNNecsaRy_cAst)]
    |        ^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::unnecessary_cast`
 
-error: unknown clippy lint: clippy::useles_transute
+error: unknown lint: `clippy::useles_transute`
   --> $DIR/unknown_clippy_lints.rs:11:8
    |
 LL | #[warn(clippy::useles_transute)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::useless_transmute`
 
-error: unknown clippy lint: clippy::dead_cod
+error: unknown lint: `clippy::dead_cod`
   --> $DIR/unknown_clippy_lints.rs:13:8
    |
 LL | #[warn(clippy::dead_cod)]
    |        ^^^^^^^^^^^^^^^^ help: did you mean: `clippy::drop_copy`
 
-error: unknown clippy lint: clippy::unused_colle
+error: unknown lint: `clippy::unused_colle`
   --> $DIR/unknown_clippy_lints.rs:15:8
    |
 LL | #[warn(clippy::unused_colle)]
    |        ^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::unused_self`
 
-error: unknown clippy lint: clippy::const_static_lifetim
+error: unknown lint: `clippy::const_static_lifetim`
   --> $DIR/unknown_clippy_lints.rs:17:8
    |
 LL | #[warn(clippy::const_static_lifetim)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::redundant_static_lifetimes`
 
-error: unknown clippy lint: clippy::All
+error: unknown lint: `clippy::All`
   --> $DIR/unknown_clippy_lints.rs:5:10
    |
 LL | #![allow(clippy::All)]
-   |          ^^^^^^^^^^^ help: lowercase the lint name: `clippy::all`
+   |          ^^^^^^^^^^^ help: did you mean: `clippy::all`
 
-error: unknown clippy lint: clippy::CMP_NAN
-  --> $DIR/unknown_clippy_lints.rs:6:9
-   |
-LL | #![warn(clippy::CMP_NAN)]
-   |         ^^^^^^^^^^^^^^^ help: lowercase the lint name: `clippy::cmp_nan`
-
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unused_unit.fixed b/src/tools/clippy/tests/ui/unused_unit.fixed
index 7afc536..a192ebd 100644
--- a/src/tools/clippy/tests/ui/unused_unit.fixed
+++ b/src/tools/clippy/tests/ui/unused_unit.fixed
@@ -11,6 +11,7 @@
 
 #![deny(clippy::unused_unit)]
 #![allow(dead_code)]
+#![allow(clippy::from_over_into)]
 
 struct Unitter;
 impl Unitter {
diff --git a/src/tools/clippy/tests/ui/unused_unit.rs b/src/tools/clippy/tests/ui/unused_unit.rs
index 96cef1e..96041a7 100644
--- a/src/tools/clippy/tests/ui/unused_unit.rs
+++ b/src/tools/clippy/tests/ui/unused_unit.rs
@@ -11,6 +11,7 @@
 
 #![deny(clippy::unused_unit)]
 #![allow(dead_code)]
+#![allow(clippy::from_over_into)]
 
 struct Unitter;
 impl Unitter {
diff --git a/src/tools/clippy/tests/ui/unused_unit.stderr b/src/tools/clippy/tests/ui/unused_unit.stderr
index c45634c..02038b5 100644
--- a/src/tools/clippy/tests/ui/unused_unit.stderr
+++ b/src/tools/clippy/tests/ui/unused_unit.stderr
@@ -1,5 +1,5 @@
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:18:28
+  --> $DIR/unused_unit.rs:19:28
    |
 LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
    |                            ^^^^^^ help: remove the `-> ()`
@@ -11,109 +11,109 @@
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:19:18
+  --> $DIR/unused_unit.rs:20:18
    |
 LL |     where G: Fn() -> () {
    |                  ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:18:58
+  --> $DIR/unused_unit.rs:19:58
    |
 LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
    |                                                          ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:20:26
+  --> $DIR/unused_unit.rs:21:26
    |
 LL |         let _y: &dyn Fn() -> () = &f;
    |                          ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:27:18
+  --> $DIR/unused_unit.rs:28:18
    |
 LL |     fn into(self) -> () {
    |                  ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit expression
-  --> $DIR/unused_unit.rs:28:9
+  --> $DIR/unused_unit.rs:29:9
    |
 LL |         ()
    |         ^^ help: remove the final `()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:33:29
+  --> $DIR/unused_unit.rs:34:29
    |
 LL |     fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H)
    |                             ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:35:19
+  --> $DIR/unused_unit.rs:36:19
    |
 LL |         G: FnMut() -> (),
    |                   ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:36:16
+  --> $DIR/unused_unit.rs:37:16
    |
 LL |         H: Fn() -> ();
    |                ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:40:29
+  --> $DIR/unused_unit.rs:41:29
    |
 LL |     fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H)
    |                             ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:42:19
+  --> $DIR/unused_unit.rs:43:19
    |
 LL |         G: FnMut() -> (),
    |                   ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:43:16
+  --> $DIR/unused_unit.rs:44:16
    |
 LL |         H: Fn() -> () {}
    |                ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:46:17
+  --> $DIR/unused_unit.rs:47:17
    |
 LL | fn return_unit() -> () { () }
    |                 ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit expression
-  --> $DIR/unused_unit.rs:46:26
+  --> $DIR/unused_unit.rs:47:26
    |
 LL | fn return_unit() -> () { () }
    |                          ^^ help: remove the final `()`
 
 error: unneeded `()`
-  --> $DIR/unused_unit.rs:56:14
+  --> $DIR/unused_unit.rs:57:14
    |
 LL |         break();
    |              ^^ help: remove the `()`
 
 error: unneeded `()`
-  --> $DIR/unused_unit.rs:58:11
+  --> $DIR/unused_unit.rs:59:11
    |
 LL |     return();
    |           ^^ help: remove the `()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:75:10
+  --> $DIR/unused_unit.rs:76:10
    |
 LL | fn test()->(){}
    |          ^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:78:11
+  --> $DIR/unused_unit.rs:79:11
    |
 LL | fn test2() ->(){}
    |           ^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:81:11
+  --> $DIR/unused_unit.rs:82:11
    |
 LL | fn test3()-> (){}
    |           ^^^^^ help: remove the `-> ()`
diff --git a/src/tools/clippy/tests/versioncheck.rs b/src/tools/clippy/tests/versioncheck.rs
index f5d03c6..76b6126 100644
--- a/src/tools/clippy/tests/versioncheck.rs
+++ b/src/tools/clippy/tests/versioncheck.rs
@@ -1,3 +1,6 @@
+#![allow(clippy::single_match_else)]
+use rustc_tools_util::VersionInfo;
+
 #[test]
 fn check_that_clippy_lints_has_the_same_version_as_clippy() {
     let clippy_meta = cargo_metadata::MetadataCommand::new()
@@ -17,3 +20,54 @@
         }
     }
 }
+
+#[test]
+fn check_that_clippy_has_the_same_major_version_as_rustc() {
+    let clippy_version = rustc_tools_util::get_version_info!();
+    let clippy_major = clippy_version.major;
+    let clippy_minor = clippy_version.minor;
+    let clippy_patch = clippy_version.patch;
+
+    // get the rustc version either from the rustc installed with the toolchain file or from
+    // `RUSTC_REAL` if Clippy is build in the Rust repo with `./x.py`.
+    let rustc = std::env::var("RUSTC_REAL").unwrap_or_else(|_| "rustc".to_string());
+    let rustc_version = String::from_utf8(
+        std::process::Command::new(&rustc)
+            .arg("--version")
+            .output()
+            .expect("failed to run `rustc --version`")
+            .stdout,
+    )
+    .unwrap();
+    // extract "1 XX 0" from "rustc 1.XX.0-nightly (<commit> <date>)"
+    let vsplit: Vec<&str> = rustc_version
+        .split(' ')
+        .nth(1)
+        .unwrap()
+        .split('-')
+        .next()
+        .unwrap()
+        .split('.')
+        .collect();
+    match vsplit.as_slice() {
+        [rustc_major, rustc_minor, _rustc_patch] => {
+            // clippy 0.1.XX should correspond to rustc 1.XX.0
+            assert_eq!(clippy_major, 0); // this will probably stay the same for a long time
+            assert_eq!(
+                clippy_minor.to_string(),
+                *rustc_major,
+                "clippy minor version does not equal rustc major version"
+            );
+            assert_eq!(
+                clippy_patch.to_string(),
+                *rustc_minor,
+                "clippy patch version does not equal rustc minor version"
+            );
+            // do not check rustc_patch because when a stable-patch-release is made (like 1.50.2),
+            // we don't want our tests failing suddenly
+        },
+        _ => {
+            panic!("Failed to parse rustc version: {:?}", vsplit);
+        },
+    };
+}
diff --git a/src/tools/clippy/util/gh-pages/index.html b/src/tools/clippy/util/gh-pages/index.html
index 4287081..1852fb6 100644
--- a/src/tools/clippy/util/gh-pages/index.html
+++ b/src/tools/clippy/util/gh-pages/index.html
@@ -77,7 +77,7 @@
                     <div class="col-md-12 form-horizontal">
                         <div class="input-group">
                             <label class="input-group-addon" id="filter-label" for="filter-input">Filter:</label>
-                            <input type="text" class="form-control" placeholder="Keywords or search string" id="filter-input" ng-model="search" />
+                            <input type="text" class="form-control" placeholder="Keywords or search string" id="filter-input" ng-model="search" ng-model-options="{debounce: 50}"/>
                             <span class="input-group-btn">
                                 <button class="btn btn-default" type="button" ng-click="search = ''">
                                     Clear
@@ -119,6 +119,7 @@
                             {{title}}
                         </h4>
                         <div class="list-group-item-text" ng-bind-html="text | markdown"></div>
+                        <a ng-if="title == 'Known problems'" href="https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+is%3Aopen+{{lint.id}}">Search on GitHub</a>
                     </li>
                 </ul>
             </article>
@@ -180,6 +181,22 @@
             }
         }
 
+        function searchLint(lint, term) {
+            for (const field in lint.docs) {
+                // Continue if it's not a property
+                if (!lint.docs.hasOwnProperty(field)) {
+                    continue;
+                }
+
+                // Return if not found
+                if (lint.docs[field].toLowerCase().indexOf(term) !== -1) {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
         angular.module("clippy", [])
         .filter('markdown', function ($sce) {
             return function (text) {
@@ -216,40 +233,31 @@
             };
 
             $scope.bySearch = function (lint, index, array) {
-                let search_str = $scope.search;
+                let searchStr = $scope.search;
                 // It can be `null` I haven't missed this value 
-                if (search_str == null || search_str.length == 0) {
+                if (searchStr == null || searchStr.length < 3) {
                     return true;
                 }
-                search_str = search_str.toLowerCase();
+                searchStr = searchStr.toLowerCase();
 
                 // Search by id
-                let id_search = search_str.trim().replace(/(\-| )/g, "_");
-                if (lint.id.includes(id_search)) {
+                if (lint.id.indexOf(searchStr.replace("-", "_")) !== -1) {
                     return true;
                 }
 
                 // Search the description
                 // The use of `for`-loops instead of `foreach` enables us to return early 
-                let search_lint = (lint, therm) => {
-                    for (const field in lint.docs) {
-                        // Continue if it's not a property
-                        if (!lint.docs.hasOwnProperty(field)) {
-                            continue;
-                        }
+                let terms = searchStr.split(" ");
+                for (index = 0; index < terms.length; index++) {
+                    if (lint.id.indexOf(terms[index]) !== -1) {
+                        continue;
+                    }
 
-                        // Return if not found
-                        if (lint.docs[field].toLowerCase().includes(therm)) {
-                            return true;
-                        }
+                    if (searchLint(lint, terms[index])) {
+                        continue;
                     }
+
                     return false;
-                };
-                let therms = search_str.split(" ");
-                for (index = 0; index < therms.length; index++) {
-                    if (!search_lint(lint, therms[index])) {
-                        return false;
-                    }
                 }
 
                 return true;
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 4f77e71..1647df8 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -82,6 +82,7 @@
 ];
 
 pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[
+    "aarch64-apple-darwin",
     "aarch64-fuchsia",
     "aarch64-unknown-linux-gnu",
     "x86_64-apple-darwin",
@@ -90,13 +91,18 @@
     "x86_64-unknown-linux-gnu",
 ];
 
-pub const LSAN_SUPPORTED_TARGETS: &[&str] =
-    &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
+pub const LSAN_SUPPORTED_TARGETS: &[&str] = &[
+    "aarch64-apple-darwin",
+    "aarch64-unknown-linux-gnu",
+    "x86_64-apple-darwin",
+    "x86_64-unknown-linux-gnu",
+];
 
 pub const MSAN_SUPPORTED_TARGETS: &[&str] =
     &["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
 
 pub const TSAN_SUPPORTED_TARGETS: &[&str] = &[
+    "aarch64-apple-darwin",
     "aarch64-unknown-linux-gnu",
     "x86_64-apple-darwin",
     "x86_64-unknown-freebsd",
diff --git a/src/tools/miri b/src/tools/miri
index 2065b52..1cf1a2e 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit 2065b52dfef3cd5a5216e65c21a056a69574bddc
+Subproject commit 1cf1a2e40a6867948db84f806085a875fbefce3c
diff --git a/src/tools/rls b/src/tools/rls
index 2cf84ba..88a58d1 160000
--- a/src/tools/rls
+++ b/src/tools/rls
@@ -1 +1 @@
-Subproject commit 2cf84baa5e3c55ac02f42919e67440acb5417125
+Subproject commit 88a58d1f484af31d87b75e1d17655b59910f41fe
diff --git a/src/tools/rust-installer b/src/tools/rust-installer
index d66f476..5254dbf 160000
--- a/src/tools/rust-installer
+++ b/src/tools/rust-installer
@@ -1 +1 @@
-Subproject commit d66f476b4d5e7fdf1ec215c9ac16c923dc292324
+Subproject commit 5254dbfd25d5284728ab624dca1969d61427a0db
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 9931015..26a66fb 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -10,6 +10,6 @@
 env_logger = "0.7.1"
 
 [dependencies.mdbook]
-version = "0.4.3"
+version = "0.4.6"
 default-features = false
 features = ["search"]
diff --git a/src/tools/rustfmt b/src/tools/rustfmt
index acd9486..216a643 160000
--- a/src/tools/rustfmt
+++ b/src/tools/rustfmt
@@ -1 +1 @@
-Subproject commit acd94866fd0ff5eacb7e184ae21c19e5440fc5fb
+Subproject commit 216a64300563351cad20bb3847110c14561687e0
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index d8d2b44..e687901 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -7,8 +7,8 @@
 
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
-const ROOT_ENTRY_LIMIT: usize = 1580;
-const ISSUES_ENTRY_LIMIT: usize = 2830;
+const ROOT_ENTRY_LIMIT: usize = 1458;
+const ISSUES_ENTRY_LIMIT: usize = 2669;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
@@ -30,7 +30,7 @@
             };
 
             let count = std::fs::read_dir(dir_path).unwrap().count();
-            if count >= limit {
+            if count > limit {
                 tidy_error!(
                     bad,
                     "following path contains more than {} entries, \
diff --git a/x.py b/x.py
index 7973730..4f64ea9 100755
--- a/x.py
+++ b/x.py
@@ -4,6 +4,22 @@
 
 import os
 import sys
+
+# If this is python2, check if python3 is available and re-execute with that
+# interpreter.
+if sys.version_info.major < 3:
+    try:
+        # On Windows, `py -3` sometimes works.
+        # Try this first, because 'python3' sometimes tries to launch the app
+        # store on Windows
+        os.execvp("py", ["py", "-3"] + sys.argv)
+    except OSError:
+        try:
+            os.execvp("python3", ["python3"] + sys.argv)
+        except OSError:
+            # Python 3 isn't available, fall back to python 2
+            pass
+
 rust_dir = os.path.dirname(os.path.abspath(__file__))
 sys.path.append(os.path.join(rust_dir, "src", "bootstrap"))