about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock34
-rw-r--r--compiler/rustc/Cargo.toml6
-rw-r--r--compiler/rustc/src/main.rs4
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs9
-rw-r--r--compiler/rustc_attr/src/builtin.rs141
-rw-r--r--compiler/rustc_attr/src/lib.rs1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/proc_macro_harness.rs44
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs25
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/back/command.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs45
-rw-r--r--compiler/rustc_codegen_ssa/src/common.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs12
-rw-r--r--compiler/rustc_data_structures/src/lib.rs25
-rw-r--r--compiler/rustc_expand/src/base.rs6
-rw-r--r--compiler/rustc_expand/src/proc_macro.rs6
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_interface/src/passes.rs1
-rw-r--r--compiler/rustc_log/src/lib.rs8
-rw-r--r--compiler/rustc_metadata/src/lib.rs1
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs9
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs30
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs96
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs7
-rw-r--r--compiler/rustc_middle/src/mir/patch.rs3
-rw-r--r--compiler/rustc_middle/src/query/mod.rs4
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs221
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs50
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs8
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs18
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs110
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs9
-rw-r--r--compiler/rustc_passes/src/lib.rs2
-rw-r--r--compiler/rustc_span/src/lib.rs4
-rw-r--r--compiler/rustc_span/src/source_map.rs21
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_target/src/spec/mod.rs17
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs33
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/on_unimplemented.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs54
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs32
-rw-r--r--compiler/rustc_typeck/src/check/check.rs10
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs18
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs26
-rw-r--r--compiler/rustc_typeck/src/check/inherited.rs6
-rw-r--r--compiler/rustc_typeck/src/check/intrinsicck.rs (renamed from compiler/rustc_passes/src/intrinsicck.rs)145
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs10
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs7
-rw-r--r--compiler/rustc_typeck/src/check/op.rs2
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs30
-rw-r--r--compiler/rustc_typeck/src/check/writeback.rs3
-rw-r--r--compiler/rustc_typeck/src/lib.rs1
-rw-r--r--library/alloc/src/str.rs74
-rw-r--r--library/alloc/src/vec/mod.rs2
-rw-r--r--library/alloc/tests/str.rs14
-rw-r--r--library/core/src/asserting.rs109
-rw-r--r--library/core/src/iter/mod.rs6
-rw-r--r--library/core/src/iter/sources.rs8
-rw-r--r--library/core/src/iter/sources/from_generator.rs43
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/option.rs20
-rw-r--r--library/core/src/ptr/mod.rs46
-rw-r--r--library/core/src/result.rs20
-rw-r--r--library/core/src/time.rs136
-rw-r--r--library/core/tests/asserting.rs37
-rw-r--r--library/core/tests/lib.rs2
-rw-r--r--library/core/tests/ptr.rs12
-rw-r--r--library/proc_macro/src/bridge/buffer.rs48
-rw-r--r--library/proc_macro/src/bridge/client.rs50
-rw-r--r--library/proc_macro/src/bridge/closure.rs6
-rw-r--r--library/proc_macro/src/bridge/handle.rs3
-rw-r--r--library/proc_macro/src/bridge/mod.rs11
-rw-r--r--library/proc_macro/src/bridge/rpc.rs2
-rw-r--r--library/proc_macro/src/bridge/server.rs107
-rw-r--r--library/std/src/error.rs138
-rw-r--r--library/std/src/os/unix/net/ancillary.rs2
-rw-r--r--library/std/src/os/unix/net/datagram.rs73
-rw-r--r--library/std/src/os/unix/net/mod.rs33
-rw-r--r--library/std/src/os/unix/net/stream.rs37
-rw-r--r--library/std/src/os/unix/net/tests.rs41
-rw-r--r--library/std/src/sys/unix/net.rs20
-rw-r--r--src/bootstrap/builder.rs9
-rw-r--r--src/bootstrap/compile.rs13
-rw-r--r--src/bootstrap/config.rs2
-rw-r--r--src/bootstrap/dist.rs7
-rw-r--r--src/bootstrap/flags.rs8
-rw-r--r--src/bootstrap/format.rs6
-rw-r--r--src/bootstrap/lib.rs4
-rw-r--r--src/bootstrap/native.rs8
-rw-r--r--src/bootstrap/setup.rs24
-rw-r--r--src/bootstrap/tool.rs23
-rw-r--r--src/bootstrap/util.rs2
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
m---------src/doc/book0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/librustdoc/clean/types.rs2
-rw-r--r--src/librustdoc/doctest.rs4
-rw-r--r--src/librustdoc/html/render/context.rs81
-rw-r--r--src/librustdoc/html/render/mod.rs58
-rw-r--r--src/librustdoc/html/render/print_item.rs61
-rw-r--r--src/librustdoc/html/render/write_shared.rs12
-rw-r--r--src/librustdoc/html/sources.rs27
-rw-r--r--src/librustdoc/html/static/.eslintrc.js16
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css24
-rw-r--r--src/librustdoc/html/static/css/settings.css40
-rw-r--r--src/librustdoc/html/static/js/main.js8
-rw-r--r--src/librustdoc/html/static/js/scrape-examples.js2
-rw-r--r--src/librustdoc/html/static/js/search.js8
-rw-r--r--src/librustdoc/html/static/js/settings.js13
-rw-r--r--src/librustdoc/html/static/js/source-script.js2
-rw-r--r--src/librustdoc/html/static/js/storage.js4
-rw-r--r--src/librustdoc/lib.rs4
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs165
-rw-r--r--src/test/rustdoc-gui/settings.goml10
-rw-r--r--src/test/rustdoc-ui/doc-comment-multi-line-attr.rs11
-rw-r--r--src/test/rustdoc-ui/doc-comment-multi-line-attr.stdout6
-rw-r--r--src/test/ui/asm/aarch64/bad-reg.rs2
-rw-r--r--src/test/ui/asm/aarch64/bad-reg.stderr34
-rw-r--r--src/test/ui/asm/aarch64/type-check-2-2.rs37
-rw-r--r--src/test/ui/asm/aarch64/type-check-2-2.stderr34
-rw-r--r--src/test/ui/asm/aarch64/type-check-2.rs17
-rw-r--r--src/test/ui/asm/aarch64/type-check-2.stderr82
-rw-r--r--src/test/ui/asm/aarch64/type-check-3.rs18
-rw-r--r--src/test/ui/asm/aarch64/type-check-3.stderr27
-rw-r--r--src/test/ui/asm/aarch64/type-check-4.rs32
-rw-r--r--src/test/ui/asm/aarch64/type-check-4.stderr27
-rw-r--r--src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr36
-rw-r--r--src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr36
-rw-r--r--src/test/ui/asm/bad-template.rs1
-rw-r--r--src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr36
-rw-r--r--src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr36
-rw-r--r--src/test/ui/asm/naked-functions.rs1
-rw-r--r--src/test/ui/asm/naked-functions.stderr58
-rw-r--r--src/test/ui/asm/type-check-1.rs3
-rw-r--r--src/test/ui/asm/type-check-1.stderr48
-rw-r--r--src/test/ui/asm/x86_64/bad-reg.rs8
-rw-r--r--src/test/ui/asm/x86_64/bad-reg.stderr90
-rw-r--r--src/test/ui/asm/x86_64/type-check-2.rs6
-rw-r--r--src/test/ui/asm/x86_64/type-check-2.stderr90
-rw-r--r--src/test/ui/asm/x86_64/type-check-3.rs18
-rw-r--r--src/test/ui/asm/x86_64/type-check-3.stderr27
-rw-r--r--src/test/ui/asm/x86_64/type-check-4.rs29
-rw-r--r--src/test/ui/asm/x86_64/type-check-4.stderr27
-rw-r--r--src/test/ui/asm/x86_64/type-check-5.rs63
-rw-r--r--src/test/ui/asm/x86_64/type-check-5.stderr34
-rw-r--r--src/test/ui/async-await/issue-68112.stderr4
-rw-r--r--src/test/ui/async-await/partial-drop-partial-reinit.stderr2
-rw-r--r--src/test/ui/borrowck/issue-81899.rs13
-rw-r--r--src/test/ui/borrowck/issue-81899.stderr17
-rw-r--r--src/test/ui/cast/casts-issue-46365.rs2
-rw-r--r--src/test/ui/cfg/cfg-target-compact-errors.rs17
-rw-r--r--src/test/ui/cfg/cfg-target-compact-errors.stderr22
-rw-r--r--src/test/ui/cfg/cfg-target-compact.rs10
-rw-r--r--src/test/ui/chalkify/bugs/async.stderr8
-rw-r--r--src/test/ui/check-cfg/compact-names.rs15
-rw-r--r--src/test/ui/check-cfg/compact-names.stderr10
-rw-r--r--src/test/ui/check-cfg/compact-values.rs15
-rw-r--r--src/test/ui/check-cfg/compact-values.stderr11
-rw-r--r--src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr4
-rw-r--r--src/test/ui/const-generics/issues/issue-97278.rs14
-rw-r--r--src/test/ui/const-generics/issues/issue-97278.stderr9
-rw-r--r--src/test/ui/consts/issue-91434.rs1
-rw-r--r--src/test/ui/consts/issue-91434.stderr10
-rw-r--r--src/test/ui/consts/nested_erroneous_ctfe.rs4
-rw-r--r--src/test/ui/consts/nested_erroneous_ctfe.stderr12
-rw-r--r--src/test/ui/consts/transmute-size-mismatch-before-typeck.rs10
-rw-r--r--src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr28
-rw-r--r--src/test/ui/derives/issue-97343.rs8
-rw-r--r--src/test/ui/derives/issue-97343.stderr13
-rw-r--r--src/test/ui/drop/repeat-drop-2.rs15
-rw-r--r--src/test/ui/drop/repeat-drop-2.stderr29
-rw-r--r--src/test/ui/drop/repeat-drop.rs120
-rw-r--r--src/test/ui/feature-gates/feature-gate-cfg-target-compact.rs13
-rw-r--r--src/test/ui/feature-gates/feature-gate-cfg-target-compact.stderr39
-rw-r--r--src/test/ui/native-library-link-flags/modifiers-override-3.rs7
-rw-r--r--src/test/ui/native-library-link-flags/modifiers-override-3.stderr4
-rw-r--r--src/test/ui/parser/else-no-if.stderr12
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-with-naked.rs2
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-with-naked.stderr19
-rw-r--r--src/test/ui/traits/issue-82830.rs16
-rw-r--r--src/test/ui/traits/issue-82830.stderr15
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-53092-2.rs15
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-53092-2.stderr55
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-53092.rs7
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-53092.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs14
-rw-r--r--src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr18
-rw-r--r--src/test/ui/type/type-check/unknown_type_for_closure.rs18
-rw-r--r--src/test/ui/type/type-check/unknown_type_for_closure.stderr29
m---------src/tools/cargo0
-rw-r--r--src/tools/lld-wrapper/Cargo.toml6
-rw-r--r--src/tools/lld-wrapper/src/main.rs95
-rw-r--r--src/tools/rustdoc-gui/tester.js18
-rw-r--r--triagebot.toml7
207 files changed, 3261 insertions, 1748 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f9f8362fb7e..538e88355ef 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -311,7 +311,7 @@ dependencies = [
 
 [[package]]
 name = "cargo"
-version = "0.63.0"
+version = "0.64.0"
 dependencies = [
  "anyhow",
  "atty",
@@ -970,9 +970,9 @@ dependencies = [
 
 [[package]]
 name = "curl"
-version = "0.4.41"
+version = "0.4.43"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bc6d233563261f8db6ffb83bbaad5a73837a6e6b28868e926337ebbdece0be3"
+checksum = "37d855aeef205b43f65a5001e0997d81f8efca7badad4fad7d897aa7f0d0651f"
 dependencies = [
  "curl-sys",
  "libc",
@@ -985,9 +985,9 @@ dependencies = [
 
 [[package]]
 name = "curl-sys"
-version = "0.4.51+curl-7.80.0"
+version = "0.4.55+curl-7.83.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d130987e6a6a34fe0889e1083022fa48cd90e6709a84be3fb8dd95801de5af20"
+checksum = "23734ec77368ec583c2e61dd3f0b0e5c98b93abe6d2a004ca06b91dd7e3e2762"
 dependencies = [
  "cc",
  "libc",
@@ -1898,6 +1898,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
 
 [[package]]
+name = "jemalloc-sys"
+version = "0.5.0+5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f655c3ecfa6b0d03634595b4b54551d4bd5ac208b9e0124873949a7ab168f70b"
+dependencies = [
+ "cc",
+ "fs_extra",
+ "libc",
+]
+
+[[package]]
 name = "jobserver"
 version = "0.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3360,9 +3371,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 name = "rustc-main"
 version = "0.0.0"
 dependencies = [
+ "jemalloc-sys",
  "rustc_codegen_ssa",
  "rustc_driver",
- "tikv-jemalloc-sys",
 ]
 
 [[package]]
@@ -5235,17 +5246,6 @@ name = "tier-check"
 version = "0.1.0"
 
 [[package]]
-name = "tikv-jemalloc-sys"
-version = "0.4.1+5.2.1-patched"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a26331b05179d4cb505c8d6814a7e18d298972f0a551b0e3cefccff927f86d3"
-dependencies = [
- "cc",
- "fs_extra",
- "libc",
-]
-
-[[package]]
 name = "time"
 version = "0.1.43"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml
index b642e891956..5e0bb1a7f95 100644
--- a/compiler/rustc/Cargo.toml
+++ b/compiler/rustc/Cargo.toml
@@ -10,13 +10,13 @@ rustc_driver = { path = "../rustc_driver" }
 # crate is intended to be used by codegen backends, which may not be in-tree.
 rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
 
-[dependencies.tikv-jemalloc-sys]
-version = '0.4.0'
+[dependencies.jemalloc-sys]
+version = "0.5.0"
 optional = true
 features = ['unprefixed_malloc_on_supported_platforms']
 
 [features]
-jemalloc = ['tikv-jemalloc-sys']
+jemalloc = ['jemalloc-sys']
 llvm = ['rustc_driver/llvm']
 max_level_info = ['rustc_driver/max_level_info']
 rustc_use_parallel_compiler = ['rustc_driver/rustc_use_parallel_compiler']
diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs
index 4edd095af10..0de1a781913 100644
--- a/compiler/rustc/src/main.rs
+++ b/compiler/rustc/src/main.rs
@@ -22,12 +22,10 @@
 // The two crates we link to here, `std` and `rustc_driver`, are both dynamic
 // libraries. So we must reference jemalloc symbols one way or another, because
 // this file is the only object code in the rustc executable.
-#[cfg(feature = "tikv-jemalloc-sys")]
-use tikv_jemalloc_sys as jemalloc_sys;
 
 fn main() {
     // See the comment at the top of this file for an explanation of this.
-    #[cfg(feature = "tikv-jemalloc-sys")]
+    #[cfg(feature = "jemalloc-sys")]
     {
         use std::os::raw::{c_int, c_void};
 
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 14e5d2ae623..0520c9ac60c 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1463,10 +1463,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         if let GenericBound::Trait(ref poly, modify) = *bound {
             match (ctxt, modify) {
                 (BoundKind::SuperTraits, TraitBoundModifier::Maybe) => {
-                    let mut err = self.err_handler().struct_span_err(
-                        poly.span,
-                        &format!("`?Trait` is not permitted in supertraits"),
-                    );
+                    let mut err = self
+                        .err_handler()
+                        .struct_span_err(poly.span, "`?Trait` is not permitted in supertraits");
                     let path_str = pprust::path_to_string(&poly.trait_ref.path);
                     err.note(&format!("traits are `?{}` by default", path_str));
                     err.emit();
@@ -1474,7 +1473,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 (BoundKind::TraitObject, TraitBoundModifier::Maybe) => {
                     let mut err = self.err_handler().struct_span_err(
                         poly.span,
-                        &format!("`?Trait` is not permitted in trait object types"),
+                        "`?Trait` is not permitted in trait object types",
                     );
                     err.emit();
                 }
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 2704cb8d785..c8f1e1dbb01 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -454,6 +454,15 @@ pub fn find_crate_name(sess: &Session, attrs: &[Attribute]) -> Option<Symbol> {
     sess.first_attr_value_str_by_name(attrs, sym::crate_name)
 }
 
+#[derive(Clone, Debug)]
+pub struct Condition {
+    pub name: Symbol,
+    pub name_span: Span,
+    pub value: Option<Symbol>,
+    pub value_span: Option<Span>,
+    pub span: Span,
+}
+
 /// Tests if a cfg-pattern matches the cfg set
 pub fn cfg_matches(
     cfg: &ast::MetaItem,
@@ -462,70 +471,42 @@ pub fn cfg_matches(
     features: Option<&Features>,
 ) -> bool {
     eval_condition(cfg, sess, features, &mut |cfg| {
-        try_gate_cfg(cfg, sess, features);
-        let error = |span, msg| {
-            sess.span_diagnostic.span_err(span, msg);
-            true
-        };
-        if cfg.path.segments.len() != 1 {
-            return error(cfg.path.span, "`cfg` predicate key must be an identifier");
-        }
-        match &cfg.kind {
-            MetaItemKind::List(..) => {
-                error(cfg.span, "unexpected parentheses after `cfg` predicate key")
-            }
-            MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
-                handle_errors(
-                    sess,
-                    lit.span,
-                    AttrError::UnsupportedLiteral(
-                        "literal in `cfg` predicate value must be a string",
-                        lit.kind.is_bytestr(),
-                    ),
+        try_gate_cfg(cfg.name, cfg.span, sess, features);
+        if let Some(names_valid) = &sess.check_config.names_valid {
+            if !names_valid.contains(&cfg.name) {
+                sess.buffer_lint_with_diagnostic(
+                    UNEXPECTED_CFGS,
+                    cfg.span,
+                    lint_node_id,
+                    "unexpected `cfg` condition name",
+                    BuiltinLintDiagnostics::UnexpectedCfg((cfg.name, cfg.name_span), None),
                 );
-                true
             }
-            MetaItemKind::NameValue(..) | MetaItemKind::Word => {
-                let ident = cfg.ident().expect("multi-segment cfg predicate");
-                let name = ident.name;
-                let value = cfg.value_str();
-                if let Some(names_valid) = &sess.check_config.names_valid {
-                    if !names_valid.contains(&name) {
-                        sess.buffer_lint_with_diagnostic(
-                            UNEXPECTED_CFGS,
-                            cfg.span,
-                            lint_node_id,
-                            "unexpected `cfg` condition name",
-                            BuiltinLintDiagnostics::UnexpectedCfg((name, ident.span), None),
-                        );
-                    }
-                }
-                if let Some(value) = value {
-                    if let Some(values) = &sess.check_config.values_valid.get(&name) {
-                        if !values.contains(&value) {
-                            sess.buffer_lint_with_diagnostic(
-                                UNEXPECTED_CFGS,
-                                cfg.span,
-                                lint_node_id,
-                                "unexpected `cfg` condition value",
-                                BuiltinLintDiagnostics::UnexpectedCfg(
-                                    (name, ident.span),
-                                    Some((value, cfg.name_value_literal_span().unwrap())),
-                                ),
-                            );
-                        }
-                    }
+        }
+        if let Some(value) = cfg.value {
+            if let Some(values) = &sess.check_config.values_valid.get(&cfg.name) {
+                if !values.contains(&value) {
+                    sess.buffer_lint_with_diagnostic(
+                        UNEXPECTED_CFGS,
+                        cfg.span,
+                        lint_node_id,
+                        "unexpected `cfg` condition value",
+                        BuiltinLintDiagnostics::UnexpectedCfg(
+                            (cfg.name, cfg.name_span),
+                            cfg.value_span.map(|vs| (value, vs)),
+                        ),
+                    );
                 }
-                sess.config.contains(&(name, value))
             }
         }
+        sess.config.contains(&(cfg.name, cfg.value))
     })
 }
 
-fn try_gate_cfg(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) {
-    let gate = find_gated_cfg(|sym| cfg.has_name(sym));
+fn try_gate_cfg(name: Symbol, span: Span, sess: &ParseSess, features: Option<&Features>) {
+    let gate = find_gated_cfg(|sym| sym == name);
     if let (Some(feats), Some(gated_cfg)) = (features, gate) {
-        gate_cfg(&gated_cfg, cfg.span, sess, feats);
+        gate_cfg(&gated_cfg, span, sess, feats);
     }
 }
 
@@ -563,11 +544,11 @@ pub fn eval_condition(
     cfg: &ast::MetaItem,
     sess: &ParseSess,
     features: Option<&Features>,
-    eval: &mut impl FnMut(&ast::MetaItem) -> bool,
+    eval: &mut impl FnMut(Condition) -> bool,
 ) -> bool {
     match cfg.kind {
         ast::MetaItemKind::List(ref mis) if cfg.name_or_empty() == sym::version => {
-            try_gate_cfg(cfg, sess, features);
+            try_gate_cfg(sym::version, cfg.span, sess, features);
             let (min_version, span) = match &mis[..] {
                 [NestedMetaItem::Literal(Lit { kind: LitKind::Str(sym, ..), span, .. })] => {
                     (sym, span)
@@ -649,6 +630,25 @@ pub fn eval_condition(
 
                     !eval_condition(mis[0].meta_item().unwrap(), sess, features, eval)
                 }
+                sym::target => {
+                    if let Some(features) = features && !features.cfg_target_compact {
+                        feature_err(
+                            sess,
+                            sym::cfg_target_compact,
+                            cfg.span,
+                            &"compact `cfg(target(..))` is experimental and subject to change"
+                        ).emit();
+                    }
+
+                    mis.iter().fold(true, |res, mi| {
+                        let mut mi = mi.meta_item().unwrap().clone();
+                        if let [seg, ..] = &mut mi.path.segments[..] {
+                            seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name));
+                        }
+
+                        res & eval_condition(&mi, sess, features, eval)
+                    })
+                }
                 _ => {
                     struct_span_err!(
                         sess.span_diagnostic,
@@ -662,7 +662,32 @@ pub fn eval_condition(
                 }
             }
         }
-        ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => eval(cfg),
+        ast::MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
+            sess.span_diagnostic
+                .span_err(cfg.path.span, "`cfg` predicate key must be an identifier");
+            true
+        }
+        MetaItemKind::NameValue(ref lit) if !lit.kind.is_str() => {
+            handle_errors(
+                sess,
+                lit.span,
+                AttrError::UnsupportedLiteral(
+                    "literal in `cfg` predicate value must be a string",
+                    lit.kind.is_bytestr(),
+                ),
+            );
+            true
+        }
+        ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => {
+            let ident = cfg.ident().expect("multi-segment cfg predicate");
+            eval(Condition {
+                name: ident.name,
+                name_span: ident.span,
+                value: cfg.value_str(),
+                value_span: cfg.name_value_literal_span(),
+                span: cfg.span,
+            })
+        }
     }
 }
 
diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs
index c95c1c40a34..c3f9f0cf362 100644
--- a/compiler/rustc_attr/src/lib.rs
+++ b/compiler/rustc_attr/src/lib.rs
@@ -4,6 +4,7 @@
 //! The goal is to move the definition of `MetaItem` and things that don't need to be in `syntax`
 //! to this crate.
 
+#![feature(let_chains)]
 #![feature(let_else)]
 
 #[macro_use]
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 48b8230857a..35f805ce76e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -522,10 +522,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 _ => None,
             };
 
-            if defined_hir.is_some() {
+            if let Some(def_hir) = defined_hir {
                 let upvars_map = self.infcx.tcx.upvars_mentioned(def_id).unwrap();
-                let upvar_def_span = self.infcx.tcx.hir().span(defined_hir.unwrap());
-                let upvar_span = upvars_map.get(&defined_hir.unwrap()).unwrap().span;
+                let upvar_def_span = self.infcx.tcx.hir().span(def_hir);
+                let upvar_span = upvars_map.get(&def_hir).unwrap().span;
                 diag.span_label(upvar_def_span, "variable defined here");
                 diag.span_label(upvar_span, "variable captured here");
             }
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 0fd23fd281e..53369afae27 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -257,7 +257,7 @@ pub struct Substructure<'a> {
     pub type_ident: Ident,
     /// ident of the method
     pub method_ident: Ident,
-    /// dereferenced access to any [`Self_`] or [`Ptr(Self_, _)][ptr]` arguments
+    /// dereferenced access to any [`Self_`] or [`Ptr(Self_, _)`][ptr] arguments
     ///
     /// [`Self_`]: ty::Ty::Self_
     /// [ptr]: ty::Ty::Ptr
@@ -1039,7 +1039,9 @@ impl<'a> MethodDef<'a> {
         let span = trait_.span;
         let mut patterns = Vec::new();
         for i in 0..self_args.len() {
-            let struct_path = cx.path(span, vec![type_ident]);
+            // We could use `type_ident` instead of `Self`, but in the case of a type parameter
+            // shadowing the struct name, that causes a second, unnecessary E0578 error. #97343
+            let struct_path = cx.path(span, vec![Ident::new(kw::SelfUpper, type_ident.span)]);
             let (pat, ident_expr) = trait_.create_struct_pattern(
                 cx,
                 struct_path,
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index 407ca2301e1..71e98bb447a 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -22,21 +22,16 @@ struct ProcMacroDerive {
     attrs: Vec<Symbol>,
 }
 
-enum ProcMacroDefType {
-    Attr,
-    Bang,
-}
-
 struct ProcMacroDef {
     id: NodeId,
     function_name: Ident,
     span: Span,
-    def_type: ProcMacroDefType,
 }
 
 enum ProcMacro {
     Derive(ProcMacroDerive),
-    Def(ProcMacroDef),
+    Attr(ProcMacroDef),
+    Bang(ProcMacroDef),
 }
 
 struct CollectProcMacros<'a> {
@@ -128,11 +123,10 @@ impl<'a> CollectProcMacros<'a> {
 
     fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) {
         if self.in_root && item.vis.kind.is_pub() {
-            self.macros.push(ProcMacro::Def(ProcMacroDef {
+            self.macros.push(ProcMacro::Attr(ProcMacroDef {
                 id: item.id,
                 span: item.span,
                 function_name: item.ident,
-                def_type: ProcMacroDefType::Attr,
             }));
         } else {
             let msg = if !self.in_root {
@@ -147,11 +141,10 @@ impl<'a> CollectProcMacros<'a> {
 
     fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) {
         if self.in_root && item.vis.kind.is_pub() {
-            self.macros.push(ProcMacro::Def(ProcMacroDef {
+            self.macros.push(ProcMacro::Bang(ProcMacroDef {
                 id: item.id,
                 span: item.span,
                 function_name: item.ident,
-                def_type: ProcMacroDefType::Bang,
             }));
         } else {
             let msg = if !self.in_root {
@@ -308,6 +301,17 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
         let proc_macro_ty_method_path = |cx: &ExtCtxt<'_>, method| {
             cx.expr_path(cx.path(span, vec![proc_macro, bridge, client, proc_macro_ty, method]))
         };
+        let attr_or_bang = |cx: &mut ExtCtxt<'_>, ca: &ProcMacroDef, ident| {
+            cx.resolver.declare_proc_macro(ca.id);
+            cx.expr_call(
+                span,
+                proc_macro_ty_method_path(cx, ident),
+                vec![
+                    cx.expr_str(ca.span, ca.function_name.name),
+                    local_path(cx, ca.span, ca.function_name),
+                ],
+            )
+        };
         macros
             .iter()
             .map(|m| match m {
@@ -329,22 +333,8 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
                         ],
                     )
                 }
-                ProcMacro::Def(ca) => {
-                    cx.resolver.declare_proc_macro(ca.id);
-                    let ident = match ca.def_type {
-                        ProcMacroDefType::Attr => attr,
-                        ProcMacroDefType::Bang => bang,
-                    };
-
-                    cx.expr_call(
-                        span,
-                        proc_macro_ty_method_path(cx, ident),
-                        vec![
-                            cx.expr_str(ca.span, ca.function_name.name),
-                            local_path(cx, ca.span, ca.function_name),
-                        ],
-                    )
-                }
+                ProcMacro::Attr(ca) => attr_or_bang(cx, &ca, attr),
+                ProcMacro::Bang(ca) => attr_or_bang(cx, &ca, bang),
             })
             .collect()
     };
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 41f88f119e2..479328a557c 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -61,24 +61,6 @@ enum ExtremumOperation {
     Min,
 }
 
-trait EnumClone {
-    fn clone(&self) -> Self;
-}
-
-impl EnumClone for AtomicOrdering {
-    fn clone(&self) -> Self {
-        match *self {
-            AtomicOrdering::NotAtomic => AtomicOrdering::NotAtomic,
-            AtomicOrdering::Unordered => AtomicOrdering::Unordered,
-            AtomicOrdering::Monotonic => AtomicOrdering::Monotonic,
-            AtomicOrdering::Acquire => AtomicOrdering::Acquire,
-            AtomicOrdering::Release => AtomicOrdering::Release,
-            AtomicOrdering::AcquireRelease => AtomicOrdering::AcquireRelease,
-            AtomicOrdering::SequentiallyConsistent => AtomicOrdering::SequentiallyConsistent,
-        }
-    }
-}
-
 pub struct Builder<'a: 'gcc, 'gcc, 'tcx> {
     pub cx: &'a CodegenCx<'gcc, 'tcx>,
     pub block: Block<'gcc>,
@@ -103,9 +85,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             match order {
                 // TODO(antoyo): does this make sense?
                 AtomicOrdering::AcquireRelease | AtomicOrdering::Release => AtomicOrdering::Acquire,
-                _ => order.clone(),
+                _ => order,
             };
-        let previous_value = self.atomic_load(dst.get_type(), dst, load_ordering.clone(), Size::from_bytes(size));
+        let previous_value = self.atomic_load(dst.get_type(), dst, load_ordering, Size::from_bytes(size));
         let previous_var = func.new_local(None, previous_value.get_type(), "previous_value");
         let return_value = func.new_local(None, previous_value.get_type(), "return_value");
         self.llbb().add_assignment(None, previous_var, previous_value);
@@ -1384,9 +1366,8 @@ impl ToGccOrdering for AtomicOrdering {
 
         let ordering =
             match self {
-                AtomicOrdering::NotAtomic => __ATOMIC_RELAXED, // TODO(antoyo): check if that's the same.
                 AtomicOrdering::Unordered => __ATOMIC_RELAXED,
-                AtomicOrdering::Monotonic => __ATOMIC_RELAXED, // TODO(antoyo): check if that's the same.
+                AtomicOrdering::Relaxed => __ATOMIC_RELAXED, // TODO(antoyo): check if that's the same.
                 AtomicOrdering::Acquire => __ATOMIC_ACQUIRE,
                 AtomicOrdering::Release => __ATOMIC_RELEASE,
                 AtomicOrdering::AcquireRelease => __ATOMIC_ACQ_REL,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 37409dbb447..1d9a4655db6 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -381,9 +381,8 @@ pub enum AtomicOrdering {
 impl AtomicOrdering {
     pub fn from_generic(ao: rustc_codegen_ssa::common::AtomicOrdering) -> Self {
         match ao {
-            rustc_codegen_ssa::common::AtomicOrdering::NotAtomic => AtomicOrdering::NotAtomic,
             rustc_codegen_ssa::common::AtomicOrdering::Unordered => AtomicOrdering::Unordered,
-            rustc_codegen_ssa::common::AtomicOrdering::Monotonic => AtomicOrdering::Monotonic,
+            rustc_codegen_ssa::common::AtomicOrdering::Relaxed => AtomicOrdering::Monotonic,
             rustc_codegen_ssa::common::AtomicOrdering::Acquire => AtomicOrdering::Acquire,
             rustc_codegen_ssa::common::AtomicOrdering::Release => AtomicOrdering::Release,
             rustc_codegen_ssa::common::AtomicOrdering::AcquireRelease => {
diff --git a/compiler/rustc_codegen_ssa/src/back/command.rs b/compiler/rustc_codegen_ssa/src/back/command.rs
index 17071ba1b5b..6c29692bd3b 100644
--- a/compiler/rustc_codegen_ssa/src/back/command.rs
+++ b/compiler/rustc_codegen_ssa/src/back/command.rs
@@ -105,12 +105,7 @@ impl Command {
             }
             Program::Lld(ref p, flavor) => {
                 let mut c = process::Command::new(p);
-                c.arg("-flavor").arg(match flavor {
-                    LldFlavor::Wasm => "wasm",
-                    LldFlavor::Ld => "gnu",
-                    LldFlavor::Link => "link",
-                    LldFlavor::Ld64 => "darwin",
-                });
+                c.arg("-flavor").arg(flavor.as_str());
                 if let LldFlavor::Wasm = flavor {
                     // LLVM expects host-specific formatting for @file
                     // arguments, but we always generate posix formatted files
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 04ec1e7f3c1..00f85852493 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2698,37 +2698,20 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
         if let LinkerFlavor::Gcc = flavor {
             match ld_impl {
                 LdImpl::Lld => {
-                    if sess.target.lld_flavor == LldFlavor::Ld64 {
-                        let tools_path = sess.get_tools_search_paths(false);
-                        let ld64_exe = tools_path
-                            .into_iter()
-                            .map(|p| p.join("gcc-ld"))
-                            .map(|p| {
-                                p.join(if sess.host.is_like_windows { "ld64.exe" } else { "ld64" })
-                            })
-                            .find(|p| p.exists())
-                            .unwrap_or_else(|| sess.fatal("rust-lld (as ld64) not found"));
-                        cmd.cmd().arg({
-                            let mut arg = OsString::from("-fuse-ld=");
-                            arg.push(ld64_exe);
-                            arg
-                        });
-                    } else {
-                        let tools_path = sess.get_tools_search_paths(false);
-                        let lld_path = tools_path
-                            .into_iter()
-                            .map(|p| p.join("gcc-ld"))
-                            .find(|p| {
-                                p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" })
-                                    .exists()
-                            })
-                            .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found"));
-                        cmd.cmd().arg({
-                            let mut arg = OsString::from("-B");
-                            arg.push(lld_path);
-                            arg
-                        });
-                    }
+                    let tools_path = sess.get_tools_search_paths(false);
+                    let gcc_ld_dir = tools_path
+                        .into_iter()
+                        .map(|p| p.join("gcc-ld"))
+                        .find(|p| {
+                            p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" }).exists()
+                        })
+                        .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found"));
+                    cmd.arg({
+                        let mut arg = OsString::from("-B");
+                        arg.push(gcc_ld_dir);
+                        arg
+                    });
+                    cmd.arg(format!("-Wl,-rustc-lld-flavor={}", sess.target.lld_flavor.as_str()));
                 }
             }
         } else {
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index 1574b30497b..8ca1a6084cf 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -11,6 +11,7 @@ use rustc_span::Span;
 use crate::base;
 use crate::traits::*;
 
+#[derive(Copy, Clone)]
 pub enum IntPredicate {
     IntEQ,
     IntNE,
@@ -24,6 +25,7 @@ pub enum IntPredicate {
     IntSLE,
 }
 
+#[derive(Copy, Clone)]
 pub enum RealPredicate {
     RealPredicateFalse,
     RealOEQ,
@@ -43,6 +45,7 @@ pub enum RealPredicate {
     RealPredicateTrue,
 }
 
+#[derive(Copy, Clone)]
 pub enum AtomicRmwBinOp {
     AtomicXchg,
     AtomicAdd,
@@ -57,17 +60,17 @@ pub enum AtomicRmwBinOp {
     AtomicUMin,
 }
 
+#[derive(Copy, Clone)]
 pub enum AtomicOrdering {
-    NotAtomic,
     Unordered,
-    Monotonic,
-    // Consume,  // Not specified yet.
+    Relaxed,
     Acquire,
     Release,
     AcquireRelease,
     SequentiallyConsistent,
 }
 
+#[derive(Copy, Clone)]
 pub enum SynchronizationScope {
     SingleThread,
     CrossThread,
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 6d6d3ae01f4..0ed4c3f1d94 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -388,17 +388,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     2 => (SequentiallyConsistent, SequentiallyConsistent),
                     3 => match split[2] {
                         "unordered" => (Unordered, Unordered),
-                        "relaxed" => (Monotonic, Monotonic),
+                        "relaxed" => (Relaxed, Relaxed),
                         "acq" => (Acquire, Acquire),
-                        "rel" => (Release, Monotonic),
+                        "rel" => (Release, Relaxed),
                         "acqrel" => (AcquireRelease, Acquire),
-                        "failrelaxed" if is_cxchg => (SequentiallyConsistent, Monotonic),
+                        "failrelaxed" if is_cxchg => (SequentiallyConsistent, Relaxed),
                         "failacq" if is_cxchg => (SequentiallyConsistent, Acquire),
                         _ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
                     },
                     4 => match (split[2], split[3]) {
-                        ("acq", "failrelaxed") if is_cxchg => (Acquire, Monotonic),
-                        ("acqrel", "failrelaxed") if is_cxchg => (AcquireRelease, Monotonic),
+                        ("acq", "failrelaxed") if is_cxchg => (Acquire, Relaxed),
+                        ("acqrel", "failrelaxed") if is_cxchg => (AcquireRelease, Relaxed),
                         _ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
                     },
                     _ => bx.sess().fatal("Atomic intrinsic not in correct format"),
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index b6a7bcae932..3185b952ab8 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -462,7 +462,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
         };
         for elem in place_ref.projection[base..].iter() {
-            cg_base = match elem.clone() {
+            cg_base = match *elem {
                 mir::ProjectionElem::Deref => {
                     // a box with a non-zst allocator should not be directly dereferenced
                     if cg_base.layout.ty.is_box() && !cg_base.layout.field(cx, 1).is_zst() {
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 4c84bd090cb..0c954ac6e5f 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -520,13 +520,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         frame
             .instance
             .try_subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, value)
-            .or_else(|e| {
+            .map_err(|e| {
                 self.tcx.sess.delay_span_bug(
                     self.cur_span(),
                     format!("failed to normalize {}", e.get_type_for_failure()).as_str(),
                 );
 
-                Err(InterpError::InvalidProgram(InvalidProgramInfo::TooGeneric))
+                InterpError::InvalidProgram(InvalidProgramInfo::TooGeneric)
             })
     }
 
@@ -1009,11 +1009,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug
                     }
                 }
 
-                write!(
-                    fmt,
-                    ": {:?}",
-                    self.ecx.dump_allocs(allocs.into_iter().filter_map(|x| x).collect())
-                )
+                write!(fmt, ": {:?}", self.ecx.dump_allocs(allocs.into_iter().flatten().collect()))
             }
             Place::Ptr(mplace) => match mplace.ptr.provenance.and_then(Provenance::get_alloc_id) {
                 Some(alloc_id) => write!(
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index dc49a45fe73..955480a1a74 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -906,16 +906,12 @@ where
         }
         // We still require the sizes to match.
         if src.layout.size != dest.layout.size {
-            // FIXME: This should be an assert instead of an error, but if we transmute within an
-            // array length computation, `typeck` may not have yet been run and errored out. In fact
-            // most likely we *are* running `typeck` right now. Investigate whether we can bail out
-            // on `typeck_results().has_errors` at all const eval entry points.
-            debug!("Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest);
-            self.tcx.sess.delay_span_bug(
+            span_bug!(
                 self.cur_span(),
-                "size-changing transmute, should have been caught by transmute checking",
+                "size-changing transmute, should have been caught by transmute checking: {:#?}\ndest: {:#?}",
+                src,
+                dest
             );
-            throw_inval!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty));
         }
         // Unsized copies rely on interpreting `src.meta` with `dest.layout`, we want
         // to avoid that here.
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 76ae17f28c6..0d072046d58 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -13,8 +13,6 @@
 #![feature(control_flow_enum)]
 #![feature(core_intrinsics)]
 #![feature(extend_one)]
-#![feature(generator_trait)]
-#![feature(generators)]
 #![feature(let_else)]
 #![feature(hash_raw_entry)]
 #![feature(hasher_prefixfree_extras)]
@@ -114,9 +112,6 @@ pub mod unhash;
 pub use ena::undo_log;
 pub use ena::unify;
 
-use std::ops::{Generator, GeneratorState};
-use std::pin::Pin;
-
 pub struct OnDrop<F: Fn()>(pub F);
 
 impl<F: Fn()> OnDrop<F> {
@@ -135,26 +130,6 @@ impl<F: Fn()> Drop for OnDrop<F> {
     }
 }
 
-struct IterFromGenerator<G>(G);
-
-impl<G: Generator<Return = ()> + Unpin> Iterator for IterFromGenerator<G> {
-    type Item = G::Yield;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        match Pin::new(&mut self.0).resume(()) {
-            GeneratorState::Yielded(n) => Some(n),
-            GeneratorState::Complete(_) => None,
-        }
-    }
-}
-
-/// An adapter for turning a generator closure into an iterator, similar to `iter::from_fn`.
-pub fn iter_from_generator<G: Generator<Return = ()> + Unpin>(
-    generator: G,
-) -> impl Iterator<Item = G::Yield> {
-    IterFromGenerator(generator)
-}
-
 // See comments in src/librustc_middle/lib.rs
 #[doc(hidden)]
 pub fn __noop_fix_for_27438() {}
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index e48ce602185..bb671b8705e 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -266,7 +266,7 @@ where
     }
 }
 
-pub trait ProcMacro {
+pub trait BangProcMacro {
     fn expand<'cx>(
         &self,
         ecx: &'cx mut ExtCtxt<'_>,
@@ -275,7 +275,7 @@ pub trait ProcMacro {
     ) -> Result<TokenStream, ErrorGuaranteed>;
 }
 
-impl<F> ProcMacro for F
+impl<F> BangProcMacro for F
 where
     F: Fn(TokenStream) -> TokenStream,
 {
@@ -640,7 +640,7 @@ pub enum SyntaxExtensionKind {
     /// A token-based function-like macro.
     Bang(
         /// An expander with signature TokenStream -> TokenStream.
-        Box<dyn ProcMacro + sync::Sync + sync::Send>,
+        Box<dyn BangProcMacro + sync::Sync + sync::Send>,
     ),
 
     /// An AST-based function-like macro.
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index b3679b31c6c..eb59c5a1854 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -17,7 +17,7 @@ pub struct BangProcMacro {
     pub client: pm::bridge::client::Client<fn(pm::TokenStream) -> pm::TokenStream>,
 }
 
-impl base::ProcMacro for BangProcMacro {
+impl base::BangProcMacro for BangProcMacro {
     fn expand<'cx>(
         &self,
         ecx: &'cx mut ExtCtxt<'_>,
@@ -72,11 +72,11 @@ impl base::AttrProcMacro for AttrProcMacro {
     }
 }
 
-pub struct ProcMacroDerive {
+pub struct DeriveProcMacro {
     pub client: pm::bridge::client::Client<fn(pm::TokenStream) -> pm::TokenStream>,
 }
 
-impl MultiItemModifier for ProcMacroDerive {
+impl MultiItemModifier for DeriveProcMacro {
     fn expand(
         &self,
         ecx: &mut ExtCtxt<'_>,
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 1956327dfab..5a02661513c 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -319,6 +319,8 @@ declare_features! (
     (active, cfg_sanitize, "1.41.0", Some(39699), None),
     /// Allows `cfg(target_abi = "...")`.
     (active, cfg_target_abi, "1.55.0", Some(80970), None),
+    /// Allows `cfg(target(abi = "..."))`.
+    (active, cfg_target_compact, "1.63.0", Some(96901), None),
     /// Allows `cfg(target_has_atomic_load_store = "...")`.
     (active, cfg_target_has_atomic, "1.60.0", Some(94039), None),
     /// Allows `cfg(target_has_atomic_equal_alignment = "...")`.
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index afbf48fceb5..e6c9c6693c5 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -937,7 +937,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
                         //
                         // maybe move the check to a MIR pass?
                         tcx.ensure().check_mod_liveness(module);
-                        tcx.ensure().check_mod_intrinsics(module);
                     });
                 });
             }
diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs
index c152815eeca..f2ec80b0c1b 100644
--- a/compiler/rustc_log/src/lib.rs
+++ b/compiler/rustc_log/src/lib.rs
@@ -69,13 +69,7 @@ pub fn init_env_logger(env: &str) -> Result<(), Error> {
 
     let verbose_entry_exit = match env::var_os(String::from(env) + "_ENTRY_EXIT") {
         None => false,
-        Some(v) => {
-            if &v == "0" {
-                false
-            } else {
-                true
-            }
-        }
+        Some(v) => &v != "0",
     };
 
     let layer = tracing_tree::HierarchicalLayer::default()
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index 4c5d13dfa6c..eb008fd2693 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -3,6 +3,7 @@
 #![feature(drain_filter)]
 #![feature(generators)]
 #![feature(generic_associated_types)]
+#![feature(iter_from_generator)]
 #![feature(let_chains)]
 #![feature(let_else)]
 #![feature(nll)]
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 8d044be195a..95892d83414 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -418,10 +418,11 @@ impl<'tcx> Collector<'tcx> {
                             // involved or not, library reordering and kind overriding without
                             // explicit `:rename` in particular.
                             if lib.has_modifiers() || passed_lib.has_modifiers() {
-                                self.tcx.sess.span_err(
-                                    self.tcx.def_span(lib.foreign_module.unwrap()),
-                                    "overriding linking modifiers from command line is not supported"
-                                );
+                                let msg = "overriding linking modifiers from command line is not supported";
+                                match lib.foreign_module {
+                                    Some(def_id) => self.tcx.sess.span_err(self.tcx.def_span(def_id), msg),
+                                    None => self.tcx.sess.err(msg),
+                                };
                             }
                             if passed_lib.kind != NativeLibKind::Unspecified {
                                 lib.kind = passed_lib.kind;
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 1420871b025..7f0b595347f 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -11,7 +11,7 @@ use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{Lock, LockGuard, Lrc, OnceCell};
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
-use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
+use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro};
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
@@ -837,7 +837,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                     attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
                 (
                     trait_name,
-                    SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { client })),
+                    SyntaxExtensionKind::Derive(Box::new(DeriveProcMacro { client })),
                     helper_attrs,
                 )
             }
@@ -1565,10 +1565,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                         src_hash,
                         start_pos,
                         end_pos,
-                        mut lines,
-                        mut multibyte_chars,
-                        mut non_narrow_chars,
-                        mut normalized_pos,
+                        lines,
+                        multibyte_chars,
+                        non_narrow_chars,
+                        normalized_pos,
                         name_hash,
                         ..
                     } = source_file_to_import;
@@ -1605,24 +1605,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
 
                     let source_length = (end_pos - start_pos).to_usize();
 
-                    // Translate line-start positions and multibyte character
-                    // position into frame of reference local to file.
-                    // `SourceMap::new_imported_source_file()` will then translate those
-                    // coordinates to their new global frame of reference when the
-                    // offset of the SourceFile is known.
-                    for pos in &mut lines {
-                        *pos = *pos - start_pos;
-                    }
-                    for mbc in &mut multibyte_chars {
-                        mbc.pos = mbc.pos - start_pos;
-                    }
-                    for swc in &mut non_narrow_chars {
-                        *swc = *swc - start_pos;
-                    }
-                    for np in &mut normalized_pos {
-                        np.pos = np.pos - start_pos;
-                    }
-
                     let local_version = sess.source_map().new_imported_source_file(
                         name,
                         src_hash,
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 1e83434b9d0..339d2fc0867 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -4,7 +4,6 @@ use crate::rmeta::*;
 
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
-use rustc_data_structures::iter_from_generator;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
 use rustc_hir as hir;
@@ -39,6 +38,7 @@ use rustc_span::{
 use rustc_target::abi::VariantIdx;
 use std::borrow::Borrow;
 use std::hash::Hash;
+use std::iter;
 use std::num::NonZeroUsize;
 use tracing::{debug, trace};
 
@@ -536,9 +536,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
     fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
         let tcx = self.tcx;
-        let mut i = self.position();
+        let mut i = 0;
+        let preamble_bytes = self.position() - i;
 
         // Encode the crate deps
+        i = self.position();
         let crate_deps = self.encode_crate_deps();
         let dylib_dependency_formats = self.encode_dylib_dependency_formats();
         let dep_bytes = self.position() - i;
@@ -564,7 +566,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let native_libraries = self.encode_native_libraries();
         let native_lib_bytes = self.position() - i;
 
+        i = self.position();
         let foreign_modules = self.encode_foreign_modules();
+        let foreign_modules_bytes = self.position() - i;
 
         // Encode DefPathTable
         i = self.position();
@@ -584,6 +588,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         i = self.position();
         let incoherent_impls = self.encode_incoherent_impls();
         let incoherent_impls_bytes = self.position() - i;
+
         // Encode MIR.
         i = self.position();
         self.encode_mir();
@@ -596,6 +601,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let item_bytes = self.position() - i;
 
         // Encode the allocation index
+        i = self.position();
         let interpret_alloc_index = {
             let mut interpret_alloc_index = Vec::new();
             let mut n = 0;
@@ -618,6 +624,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             }
             self.lazy_array(interpret_alloc_index)
         };
+        let interpret_alloc_index_bytes = self.position() - i;
 
         // Encode the proc macro data. This affects 'tables',
         // so we need to do this before we encode the tables
@@ -662,9 +669,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let source_map = self.encode_source_map();
         let source_map_bytes = self.position() - i;
 
+        i = self.position();
         let attrs = tcx.hir().krate_attrs();
         let has_default_lib_allocator = tcx.sess.contains_name(&attrs, sym::default_lib_allocator);
-
         let root = self.lazy(CrateRoot {
             name: tcx.crate_name(LOCAL_CRATE),
             extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
@@ -707,9 +714,34 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             expn_hashes,
             def_path_hash_map,
         });
+        let final_bytes = self.position() - i;
 
         let total_bytes = self.position();
 
+        let computed_total_bytes = preamble_bytes
+            + dep_bytes
+            + lib_feature_bytes
+            + lang_item_bytes
+            + diagnostic_item_bytes
+            + native_lib_bytes
+            + foreign_modules_bytes
+            + def_path_table_bytes
+            + traits_bytes
+            + impls_bytes
+            + incoherent_impls_bytes
+            + mir_bytes
+            + item_bytes
+            + interpret_alloc_index_bytes
+            + proc_macro_data_bytes
+            + tables_bytes
+            + debugger_visualizers_bytes
+            + exported_symbols_bytes
+            + hygiene_bytes
+            + def_path_hash_map_bytes
+            + source_map_bytes
+            + final_bytes;
+        assert_eq!(total_bytes, computed_total_bytes);
+
         if tcx.sess.meta_stats() {
             let mut zero_bytes = 0;
             for e in self.opaque.data.iter() {
@@ -718,27 +750,41 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 }
             }
 
-            eprintln!("metadata stats:");
-            eprintln!("                  dep bytes: {}", dep_bytes);
-            eprintln!("          lib feature bytes: {}", lib_feature_bytes);
-            eprintln!("            lang item bytes: {}", lang_item_bytes);
-            eprintln!("      diagnostic item bytes: {}", diagnostic_item_bytes);
-            eprintln!("               native bytes: {}", native_lib_bytes);
-            eprintln!(" debugger visualizers bytes: {}", debugger_visualizers_bytes);
-            eprintln!("           source_map bytes: {}", source_map_bytes);
-            eprintln!("               traits bytes: {}", traits_bytes);
-            eprintln!("                impls bytes: {}", impls_bytes);
-            eprintln!("     incoherent_impls bytes: {}", incoherent_impls_bytes);
-            eprintln!("         exp. symbols bytes: {}", exported_symbols_bytes);
-            eprintln!("       def-path table bytes: {}", def_path_table_bytes);
-            eprintln!("      def-path hashes bytes: {}", def_path_hash_map_bytes);
-            eprintln!("      proc-macro-data-bytes: {}", proc_macro_data_bytes);
-            eprintln!("                  mir bytes: {}", mir_bytes);
-            eprintln!("                 item bytes: {}", item_bytes);
-            eprintln!("                table bytes: {}", tables_bytes);
-            eprintln!("              hygiene bytes: {}", hygiene_bytes);
-            eprintln!("                 zero bytes: {}", zero_bytes);
-            eprintln!("                total bytes: {}", total_bytes);
+            let perc = |bytes| (bytes * 100) as f64 / total_bytes as f64;
+            let p = |label, bytes| {
+                eprintln!("{:>21}: {:>8} bytes ({:4.1}%)", label, bytes, perc(bytes));
+            };
+
+            eprintln!("");
+            eprintln!(
+                "{} metadata bytes, of which {} bytes ({:.1}%) are zero",
+                total_bytes,
+                zero_bytes,
+                perc(zero_bytes)
+            );
+            p("preamble", preamble_bytes);
+            p("dep", dep_bytes);
+            p("lib feature", lib_feature_bytes);
+            p("lang item", lang_item_bytes);
+            p("diagnostic item", diagnostic_item_bytes);
+            p("native lib", native_lib_bytes);
+            p("foreign modules", foreign_modules_bytes);
+            p("def-path table", def_path_table_bytes);
+            p("traits", traits_bytes);
+            p("impls", impls_bytes);
+            p("incoherent_impls", incoherent_impls_bytes);
+            p("mir", mir_bytes);
+            p("item", item_bytes);
+            p("interpret_alloc_index", interpret_alloc_index_bytes);
+            p("proc-macro-data", proc_macro_data_bytes);
+            p("tables", tables_bytes);
+            p("debugger visualizers", debugger_visualizers_bytes);
+            p("exported symbols", exported_symbols_bytes);
+            p("hygiene", hygiene_bytes);
+            p("def-path hashes", def_path_hash_map_bytes);
+            p("source_map", source_map_bytes);
+            p("final", final_bytes);
+            eprintln!("");
         }
 
         root
@@ -1088,7 +1134,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             // Encode this here because we don't do it in encode_def_ids.
             record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
         } else {
-            record_array!(self.tables.children[def_id] <- iter_from_generator(|| {
+            record_array!(self.tables.children[def_id] <- iter::from_generator(|| {
                 for item_id in md.item_ids {
                     match tcx.hir().item(*item_id).kind {
                         // Foreign items are planted into their parent modules
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index bb6b10149ab..cb6fd006c3e 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -149,8 +149,6 @@ pub enum InvalidProgramInfo<'tcx> {
     /// (which unfortunately typeck does not reject).
     /// Not using `FnAbiError` as that contains a nested `LayoutError`.
     FnAbiAdjustForForeignAbi(call::AdjustForForeignAbiError),
-    /// An invalid transmute happened.
-    TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>),
     /// SizeOf of unsized type was requested.
     SizeOfUnsizedType(Ty<'tcx>),
 }
@@ -166,11 +164,6 @@ impl fmt::Display for InvalidProgramInfo<'_> {
             }
             Layout(ref err) => write!(f, "{}", err),
             FnAbiAdjustForForeignAbi(ref err) => write!(f, "{}", err),
-            TransmuteSizeDiff(from_ty, to_ty) => write!(
-                f,
-                "transmuting `{}` to `{}` is not possible, because these types do not have the same size",
-                from_ty, to_ty
-            ),
             SizeOfUnsizedType(ty) => write!(f, "size_of called on unsized type `{}`", ty),
         }
     }
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index 1bc53d3c9f1..c1e1cfef9f8 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -167,8 +167,7 @@ impl<'tcx> MirPatch<'tcx> {
             if loc.statement_index > body[loc.block].statements.len() {
                 let term = body[loc.block].terminator();
                 for i in term.successors() {
-                    stmts_and_targets
-                        .push((Statement { source_info, kind: stmt.clone() }, i.clone()));
+                    stmts_and_targets.push((Statement { source_info, kind: stmt.clone() }, i));
                 }
                 delta += 1;
                 continue;
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 0c936b7ae10..68b81efaa00 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -804,10 +804,6 @@ rustc_queries! {
         desc { |tcx| "checking privacy in {}", describe_as_module(key, tcx) }
     }
 
-    query check_mod_intrinsics(key: LocalDefId) -> () {
-        desc { |tcx| "checking intrinsics in {}", describe_as_module(key, tcx) }
-    }
-
     query check_mod_liveness(key: LocalDefId) -> () {
         desc { |tcx| "checking liveness of variables in {}", describe_as_module(key, tcx) }
     }
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index de4cc67893b..f7ced066062 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -1,8 +1,10 @@
 use crate::mir::Mutability;
+use crate::ty::subst::GenericArgKind;
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_hir::def_id::DefId;
 use std::fmt::Debug;
 use std::hash::Hash;
+use std::iter;
 
 use self::SimplifiedTypeGen::*;
 
@@ -72,6 +74,10 @@ pub enum TreatParams {
 
 /// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
 ///
+/// **This function should only be used if you need to store or retrieve the type from some
+/// hashmap. If you want to quickly decide whether two types may unify, use the [DeepRejectCtxt]
+/// instead.**
+///
 /// The idea is to get something simple that we can use to quickly decide if two types could unify,
 /// for example during method lookup. If this function returns `Some(x)` it can only unify with
 /// types for which this method returns either `Some(x)` as well or `None`.
@@ -182,3 +188,218 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
         }
     }
 }
+
+/// Given generic arguments from an obligation and an impl,
+/// could these two be unified after replacing parameters in the
+/// the impl with inference variables.
+///
+/// For obligations, parameters won't be replaced by inference
+/// variables and only unify with themselves. We treat them
+/// the same way we treat placeholders.
+///
+/// We also use this function during coherence. For coherence the
+/// impls only have to overlap for some value, so we treat parameters
+/// on both sides like inference variables. This behavior is toggled
+/// using the `treat_obligation_params` field.
+#[derive(Debug, Clone, Copy)]
+pub struct DeepRejectCtxt {
+    pub treat_obligation_params: TreatParams,
+}
+
+impl DeepRejectCtxt {
+    pub fn generic_args_may_unify(
+        self,
+        obligation_arg: ty::GenericArg<'_>,
+        impl_arg: ty::GenericArg<'_>,
+    ) -> bool {
+        match (obligation_arg.unpack(), impl_arg.unpack()) {
+            // We don't fast reject based on regions for now.
+            (GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => true,
+            (GenericArgKind::Type(obl), GenericArgKind::Type(imp)) => {
+                self.types_may_unify(obl, imp)
+            }
+            (GenericArgKind::Const(obl), GenericArgKind::Const(imp)) => {
+                self.consts_may_unify(obl, imp)
+            }
+            _ => bug!("kind mismatch: {obligation_arg} {impl_arg}"),
+        }
+    }
+
+    pub fn types_may_unify(self, obligation_ty: Ty<'_>, impl_ty: Ty<'_>) -> bool {
+        match impl_ty.kind() {
+            // Start by checking whether the type in the impl may unify with
+            // pretty much everything. Just return `true` in that case.
+            ty::Param(_) | ty::Projection(_) | ty::Error(_) => return true,
+            // These types only unify with inference variables or their own
+            // variant.
+            ty::Bool
+            | ty::Char
+            | ty::Int(_)
+            | ty::Uint(_)
+            | ty::Float(_)
+            | ty::Adt(..)
+            | ty::Str
+            | ty::Array(..)
+            | ty::Slice(..)
+            | ty::RawPtr(..)
+            | ty::Dynamic(..)
+            | ty::Ref(..)
+            | ty::Never
+            | ty::Tuple(..)
+            | ty::FnPtr(..)
+            | ty::Foreign(..)
+            | ty::Opaque(..) => {}
+            ty::FnDef(..)
+            | ty::Closure(..)
+            | ty::Generator(..)
+            | ty::GeneratorWitness(..)
+            | ty::Placeholder(..)
+            | ty::Bound(..)
+            | ty::Infer(_) => bug!("unexpected impl_ty: {impl_ty}"),
+        }
+
+        let k = impl_ty.kind();
+        match *obligation_ty.kind() {
+            // Purely rigid types, use structural equivalence.
+            ty::Bool
+            | ty::Char
+            | ty::Int(_)
+            | ty::Uint(_)
+            | ty::Float(_)
+            | ty::Str
+            | ty::Never
+            | ty::Foreign(_) => obligation_ty == impl_ty,
+            ty::Ref(_, obl_ty, obl_mutbl) => match k {
+                &ty::Ref(_, impl_ty, impl_mutbl) => {
+                    obl_mutbl == impl_mutbl && self.types_may_unify(obl_ty, impl_ty)
+                }
+                _ => false,
+            },
+            ty::Adt(obl_def, obl_substs) => match k {
+                &ty::Adt(impl_def, impl_substs) => {
+                    obl_def == impl_def
+                        && iter::zip(obl_substs, impl_substs)
+                            .all(|(obl, imp)| self.generic_args_may_unify(obl, imp))
+                }
+                _ => false,
+            },
+            ty::Slice(obl_ty) => {
+                matches!(k, &ty::Slice(impl_ty) if self.types_may_unify(obl_ty, impl_ty))
+            }
+            ty::Array(obl_ty, obl_len) => match k {
+                &ty::Array(impl_ty, impl_len) => {
+                    self.types_may_unify(obl_ty, impl_ty)
+                        && self.consts_may_unify(obl_len, impl_len)
+                }
+                _ => false,
+            },
+            ty::Tuple(obl) => match k {
+                &ty::Tuple(imp) => {
+                    obl.len() == imp.len()
+                        && iter::zip(obl, imp).all(|(obl, imp)| self.types_may_unify(obl, imp))
+                }
+                _ => false,
+            },
+            ty::RawPtr(obl) => match k {
+                ty::RawPtr(imp) => obl.mutbl == imp.mutbl && self.types_may_unify(obl.ty, imp.ty),
+                _ => false,
+            },
+            ty::Dynamic(obl_preds, ..) => {
+                // Ideally we would walk the existential predicates here or at least
+                // compare their length. But considering that the relevant `Relate` impl
+                // actually sorts and deduplicates these, that doesn't work.
+                matches!(k, ty::Dynamic(impl_preds, ..) if
+                    obl_preds.principal_def_id() == impl_preds.principal_def_id()
+                )
+            }
+            ty::FnPtr(obl_sig) => match k {
+                ty::FnPtr(impl_sig) => {
+                    let ty::FnSig { inputs_and_output, c_variadic, unsafety, abi } =
+                        obl_sig.skip_binder();
+                    let impl_sig = impl_sig.skip_binder();
+
+                    abi == impl_sig.abi
+                        && c_variadic == impl_sig.c_variadic
+                        && unsafety == impl_sig.unsafety
+                        && inputs_and_output.len() == impl_sig.inputs_and_output.len()
+                        && iter::zip(inputs_and_output, impl_sig.inputs_and_output)
+                            .all(|(obl, imp)| self.types_may_unify(obl, imp))
+                }
+                _ => false,
+            },
+
+            // Opaque types in impls should be forbidden, but that doesn't
+            // stop compilation. So this match arm should never return true
+            // if compilation succeeds.
+            ty::Opaque(..) => matches!(k, ty::Opaque(..)),
+
+            // Impls cannot contain these types as these cannot be named directly.
+            ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
+
+            ty::Placeholder(..) => false,
+
+            // Depending on the value of `treat_obligation_params`, we either
+            // treat generic parameters like placeholders or like inference variables.
+            ty::Param(_) => match self.treat_obligation_params {
+                TreatParams::AsPlaceholder => false,
+                TreatParams::AsInfer => true,
+            },
+
+            ty::Infer(_) => true,
+
+            // As we're walking the whole type, it may encounter projections
+            // inside of binders and what not, so we're just going to assume that
+            // projections can unify with other stuff.
+            //
+            // Looking forward to lazy normalization this is the safer strategy anyways.
+            ty::Projection(_) => true,
+
+            ty::Error(_) => true,
+
+            ty::GeneratorWitness(..) | ty::Bound(..) => {
+                bug!("unexpected obligation type: {:?}", obligation_ty)
+            }
+        }
+    }
+
+    pub fn consts_may_unify(self, obligation_ct: ty::Const<'_>, impl_ct: ty::Const<'_>) -> bool {
+        match impl_ct.val() {
+            ty::ConstKind::Param(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => {
+                return true;
+            }
+            ty::ConstKind::Value(_) => {}
+            ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
+                bug!("unexpected impl arg: {:?}", impl_ct)
+            }
+        }
+
+        let k = impl_ct.val();
+        match obligation_ct.val() {
+            ty::ConstKind::Param(_) => match self.treat_obligation_params {
+                TreatParams::AsPlaceholder => false,
+                TreatParams::AsInfer => true,
+            },
+
+            // As we don't necessarily eagerly evaluate constants,
+            // they might unify with any value.
+            ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => true,
+            ty::ConstKind::Value(obl) => match k {
+                ty::ConstKind::Value(imp) => {
+                    // FIXME(valtrees): Once we have valtrees, we can just
+                    // compare them directly here.
+                    match (obl.try_to_scalar_int(), imp.try_to_scalar_int()) {
+                        (Some(obl), Some(imp)) => obl == imp,
+                        _ => true,
+                    }
+                }
+                _ => true,
+            },
+
+            ty::ConstKind::Infer(_) => true,
+
+            ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
+                bug!("unexpected obl const: {:?}", obligation_ct)
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index a973a5c9b50..2dabc696388 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1469,7 +1469,7 @@ impl ParamConst {
     }
 }
 
-/// Use this rather than `TyKind`, whenever possible.
+/// Use this rather than `RegionKind`, whenever possible.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
 #[rustc_pass_by_value]
 pub struct Region<'tcx>(pub Interned<'tcx, RegionKind>);
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 fb0537c543d..0a0c7659b08 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -52,11 +52,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 })
             }
             ExprKind::Repeat { value, count } => {
-                let value_operand = unpack!(
-                    block =
-                        this.as_operand(block, scope, &this.thir[value], None, NeedsTemporary::No)
-                );
-                block.and(Rvalue::Repeat(value_operand, count))
+                if Some(0) == count.try_eval_usize(this.tcx, this.param_env) {
+                    this.build_zero_repeat(block, value, scope, source_info)
+                } else {
+                    let value_operand = unpack!(
+                        block = this.as_operand(
+                            block,
+                            scope,
+                            &this.thir[value],
+                            None,
+                            NeedsTemporary::No
+                        )
+                    );
+                    block.and(Rvalue::Repeat(value_operand, count))
+                }
             }
             ExprKind::Binary { op, lhs, rhs } => {
                 let lhs = unpack!(
@@ -516,6 +525,37 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
+    fn build_zero_repeat(
+        &mut self,
+        mut block: BasicBlock,
+        value: ExprId,
+        scope: Option<region::Scope>,
+        outer_source_info: SourceInfo,
+    ) -> BlockAnd<Rvalue<'tcx>> {
+        let this = self;
+        let value = &this.thir[value];
+        let elem_ty = value.ty;
+        if let Some(Category::Constant) = Category::of(&value.kind) {
+            // Repeating a const does nothing
+        } else {
+            // For a non-const, we may need to generate an appropriate `Drop`
+            let value_operand =
+                unpack!(block = this.as_operand(block, scope, value, None, NeedsTemporary::No));
+            if let Operand::Move(to_drop) = value_operand {
+                let success = this.cfg.start_new_block();
+                this.cfg.terminate(
+                    block,
+                    outer_source_info,
+                    TerminatorKind::Drop { place: to_drop, target: success, unwind: None },
+                );
+                this.diverge_from(block);
+                block = success;
+            }
+            this.record_operands_moved(&[value_operand]);
+        }
+        block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(elem_ty)), Vec::new()))
+    }
+
     fn limit_capture_mutability(
         &mut self,
         upvar_span: Span,
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 569012e152b..ccbb518e72d 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -435,11 +435,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         }
                         thir::InlineAsmOperand::SymFn { value, span } => {
                             mir::InlineAsmOperand::SymFn {
-                                value: Box::new(Constant {
-                                    span,
-                                    user_ty: None,
-                                    literal: value.into(),
-                                }),
+                                value: Box::new(Constant { span, user_ty: None, literal: value }),
                             }
                         }
                         thir::InlineAsmOperand::SymStatic { def_id } => {
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index c15b3db1caa..3774a395035 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -264,7 +264,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     );
                 } else if let [success, fail] = *make_target_blocks(self) {
                     assert_eq!(value.ty(), ty);
-                    let expect = self.literal_operand(test.span, value.into());
+                    let expect = self.literal_operand(test.span, value);
                     let val = Operand::Copy(place);
                     self.compare(block, success, fail, source_info, BinOp::Eq, expect, val);
                 } else {
@@ -277,8 +277,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let target_blocks = make_target_blocks(self);
 
                 // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
-                let lo = self.literal_operand(test.span, lo.into());
-                let hi = self.literal_operand(test.span, hi.into());
+                let lo = self.literal_operand(test.span, lo);
+                let hi = self.literal_operand(test.span, hi);
                 let val = Operand::Copy(place);
 
                 let [success, fail] = *target_blocks else {
@@ -370,7 +370,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         place: Place<'tcx>,
         mut ty: Ty<'tcx>,
     ) {
-        let mut expect = self.literal_operand(source_info.span, value.into());
+        let mut expect = self.literal_operand(source_info.span, value);
         let mut val = Operand::Copy(place);
 
         // If we're using `b"..."` as a pattern, we need to insert an
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 53f9706f021..a5f8a5847c2 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -1033,6 +1033,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 self.cfg.block_data(start).terminator().kind,
                 TerminatorKind::Assert { .. }
                     | TerminatorKind::Call { .. }
+                    | TerminatorKind::Drop { .. }
                     | TerminatorKind::DropAndReplace { .. }
                     | TerminatorKind::FalseUnwind { .. }
                     | TerminatorKind::InlineAsm { .. }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 880f86aff5d..f694e009ab9 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -121,27 +121,27 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
 
     fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String> {
         traits::search_for_structural_match_violation(self.span, self.tcx(), ty).map(|non_sm_ty| {
-            with_no_trimmed_paths!(match non_sm_ty {
-                traits::NonStructuralMatchTy::Adt(adt) => self.adt_derive_msg(adt),
-                traits::NonStructuralMatchTy::Dynamic => {
+            with_no_trimmed_paths!(match non_sm_ty.kind {
+                traits::NonStructuralMatchTyKind::Adt(adt) => self.adt_derive_msg(adt),
+                traits::NonStructuralMatchTyKind::Dynamic => {
                     "trait objects cannot be used in patterns".to_string()
                 }
-                traits::NonStructuralMatchTy::Opaque => {
+                traits::NonStructuralMatchTyKind::Opaque => {
                     "opaque types cannot be used in patterns".to_string()
                 }
-                traits::NonStructuralMatchTy::Closure => {
+                traits::NonStructuralMatchTyKind::Closure => {
                     "closures cannot be used in patterns".to_string()
                 }
-                traits::NonStructuralMatchTy::Generator => {
+                traits::NonStructuralMatchTyKind::Generator => {
                     "generators cannot be used in patterns".to_string()
                 }
-                traits::NonStructuralMatchTy::Param => {
+                traits::NonStructuralMatchTyKind::Param => {
                     bug!("use of a constant whose type is a parameter inside a pattern")
                 }
-                traits::NonStructuralMatchTy::Projection => {
+                traits::NonStructuralMatchTyKind::Projection => {
                     bug!("use of a constant whose type is a projection inside a pattern")
                 }
-                traits::NonStructuralMatchTy::Foreign => {
+                traits::NonStructuralMatchTyKind::Foreign => {
                     bug!("use of a value of a foreign type inside a pattern")
                 }
             })
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index ee02151152c..a9ca8921797 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -201,7 +201,6 @@ use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
 use rustc_session::Limit;
 use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
 use rustc_target::abi::Size;
-use smallvec::SmallVec;
 use std::iter;
 use std::ops::Range;
 use std::path::PathBuf;
@@ -226,6 +225,44 @@ pub struct InliningMap<'tcx> {
     inlines: GrowableBitSet<usize>,
 }
 
+/// Struct to store mono items in each collecting and if they should
+/// be inlined. We call `instantiation_mode` to get their inlining
+/// status when inserting new elements, which avoids calling it in
+/// `inlining_map.lock_mut()`. See the `collect_items_rec` implementation
+/// below.
+struct MonoItems<'tcx> {
+    // If this is false, we do not need to compute whether items
+    // will need to be inlined.
+    compute_inlining: bool,
+
+    // The TyCtxt used to determine whether the a item should
+    // be inlined.
+    tcx: TyCtxt<'tcx>,
+
+    // The collected mono items. The bool field in each element
+    // indicates whether this element should be inlined.
+    items: Vec<(Spanned<MonoItem<'tcx>>, bool /*inlined*/)>,
+}
+
+impl<'tcx> MonoItems<'tcx> {
+    #[inline]
+    fn push(&mut self, item: Spanned<MonoItem<'tcx>>) {
+        self.extend([item]);
+    }
+
+    #[inline]
+    fn extend<T: IntoIterator<Item = Spanned<MonoItem<'tcx>>>>(&mut self, iter: T) {
+        self.items.extend(iter.into_iter().map(|mono_item| {
+            let inlined = if !self.compute_inlining {
+                false
+            } else {
+                mono_item.node.instantiation_mode(self.tcx) == InstantiationMode::LocalCopy
+            };
+            (mono_item, inlined)
+        }))
+    }
+}
+
 impl<'tcx> InliningMap<'tcx> {
     fn new() -> InliningMap<'tcx> {
         InliningMap {
@@ -235,7 +272,13 @@ impl<'tcx> InliningMap<'tcx> {
         }
     }
 
-    fn record_accesses(&mut self, source: MonoItem<'tcx>, new_targets: &[(MonoItem<'tcx>, bool)]) {
+    fn record_accesses<'a>(
+        &mut self,
+        source: MonoItem<'tcx>,
+        new_targets: &'a [(Spanned<MonoItem<'tcx>>, bool)],
+    ) where
+        'tcx: 'a,
+    {
         let start_index = self.targets.len();
         let new_items_count = new_targets.len();
         let new_items_count_total = new_items_count + self.targets.len();
@@ -243,9 +286,9 @@ impl<'tcx> InliningMap<'tcx> {
         self.targets.reserve(new_items_count);
         self.inlines.ensure(new_items_count_total);
 
-        for (i, (target, inline)) in new_targets.iter().enumerate() {
-            self.targets.push(*target);
-            if *inline {
+        for (i, (Spanned { node: mono_item, .. }, inlined)) in new_targets.into_iter().enumerate() {
+            self.targets.push(*mono_item);
+            if *inlined {
                 self.inlines.insert(i + start_index);
             }
         }
@@ -321,7 +364,7 @@ pub fn collect_crate_mono_items(
 // start monomorphizing from.
 fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<'_>> {
     debug!("collecting roots");
-    let mut roots = Vec::new();
+    let mut roots = MonoItems { compute_inlining: false, tcx, items: Vec::new() };
 
     {
         let entry_fn = tcx.entry_fn(());
@@ -347,8 +390,11 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
     // whose predicates hold. Luckily, items that aren't instantiable
     // can't actually be used, so we can just skip codegenning them.
     roots
+        .items
         .into_iter()
-        .filter_map(|root| root.node.is_instantiable(tcx).then_some(root.node))
+        .filter_map(|(Spanned { node: mono_item, .. }, _)| {
+            mono_item.is_instantiable(tcx).then_some(mono_item)
+        })
         .collect()
 }
 
@@ -368,7 +414,7 @@ fn collect_items_rec<'tcx>(
     }
     debug!("BEGIN collect_items_rec({})", starting_point.node);
 
-    let mut neighbors = Vec::new();
+    let mut neighbors = MonoItems { compute_inlining: true, tcx, items: Vec::new() };
     let recursion_depth_reset;
 
     //
@@ -483,10 +529,9 @@ fn collect_items_rec<'tcx>(
             &format!("the above error was encountered while instantiating `{}`", formatted_item),
         );
     }
+    inlining_map.lock_mut().record_accesses(starting_point.node, &neighbors.items);
 
-    record_accesses(tcx, starting_point.node, neighbors.iter().map(|i| &i.node), inlining_map);
-
-    for neighbour in neighbors {
+    for (neighbour, _) in neighbors.items {
         collect_items_rec(tcx, neighbour, visited, recursion_depths, recursion_limit, inlining_map);
     }
 
@@ -497,25 +542,6 @@ fn collect_items_rec<'tcx>(
     debug!("END collect_items_rec({})", starting_point.node);
 }
 
-fn record_accesses<'a, 'tcx: 'a>(
-    tcx: TyCtxt<'tcx>,
-    caller: MonoItem<'tcx>,
-    callees: impl Iterator<Item = &'a MonoItem<'tcx>>,
-    inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>,
-) {
-    let is_inlining_candidate = |mono_item: &MonoItem<'tcx>| {
-        mono_item.instantiation_mode(tcx) == InstantiationMode::LocalCopy
-    };
-
-    // We collect this into a `SmallVec` to avoid calling `is_inlining_candidate` in the lock.
-    // FIXME: Call `is_inlining_candidate` when pushing to `neighbors` in `collect_items_rec`
-    // instead to avoid creating this `SmallVec`.
-    let accesses: SmallVec<[_; 128]> =
-        callees.map(|mono_item| (*mono_item, is_inlining_candidate(mono_item))).collect();
-
-    inlining_map.lock_mut().record_accesses(caller, &accesses);
-}
-
 /// Format instance name that is already known to be too long for rustc.
 /// Show only the first and last 32 characters to avoid blasting
 /// the user's terminal with thousands of lines of type-name.
@@ -627,7 +653,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
 struct MirNeighborCollector<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     body: &'a mir::Body<'tcx>,
-    output: &'a mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &'a mut MonoItems<'tcx>,
     instance: Instance<'tcx>,
 }
 
@@ -905,7 +931,7 @@ fn visit_drop_use<'tcx>(
     ty: Ty<'tcx>,
     is_direct_call: bool,
     source: Span,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &mut MonoItems<'tcx>,
 ) {
     let instance = Instance::resolve_drop_in_place(tcx, ty);
     visit_instance_use(tcx, instance, is_direct_call, source, output);
@@ -916,7 +942,7 @@ fn visit_fn_use<'tcx>(
     ty: Ty<'tcx>,
     is_direct_call: bool,
     source: Span,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &mut MonoItems<'tcx>,
 ) {
     if let ty::FnDef(def_id, substs) = *ty.kind() {
         let instance = if is_direct_call {
@@ -934,7 +960,7 @@ fn visit_instance_use<'tcx>(
     instance: ty::Instance<'tcx>,
     is_direct_call: bool,
     source: Span,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &mut MonoItems<'tcx>,
 ) {
     debug!("visit_item_use({:?}, is_direct_call={:?})", instance, is_direct_call);
     if !should_codegen_locally(tcx, &instance) {
@@ -1117,7 +1143,7 @@ fn create_mono_items_for_vtable_methods<'tcx>(
     trait_ty: Ty<'tcx>,
     impl_ty: Ty<'tcx>,
     source: Span,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &mut MonoItems<'tcx>,
 ) {
     assert!(!trait_ty.has_escaping_bound_vars() && !impl_ty.has_escaping_bound_vars());
 
@@ -1159,7 +1185,7 @@ fn create_mono_items_for_vtable_methods<'tcx>(
 struct RootCollector<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     mode: MonoItemCollectionMode,
-    output: &'a mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &'a mut MonoItems<'tcx>,
     entry_fn: Option<(DefId, EntryFnType)>,
 }
 
@@ -1305,7 +1331,7 @@ fn item_requires_monomorphization(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
 fn create_mono_items_for_default_impls<'tcx>(
     tcx: TyCtxt<'tcx>,
     item: &'tcx hir::Item<'tcx>,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &mut MonoItems<'tcx>,
 ) {
     match item.kind {
         hir::ItemKind::Impl(ref impl_) => {
@@ -1361,11 +1387,7 @@ fn create_mono_items_for_default_impls<'tcx>(
 }
 
 /// Scans the miri alloc in order to find function calls, closures, and drop-glue.
-fn collect_miri<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    alloc_id: AllocId,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
-) {
+fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoItems<'tcx>) {
     match tcx.global_alloc(alloc_id) {
         GlobalAlloc::Static(def_id) => {
             assert!(!tcx.is_thread_local_static(def_id));
@@ -1396,7 +1418,7 @@ fn collect_miri<'tcx>(
 fn collect_neighbours<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: Instance<'tcx>,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &mut MonoItems<'tcx>,
 ) {
     debug!("collect_neighbours: {:?}", instance.def_id());
     let body = tcx.instance_mir(instance.def);
@@ -1407,7 +1429,7 @@ fn collect_neighbours<'tcx>(
 fn collect_const_value<'tcx>(
     tcx: TyCtxt<'tcx>,
     value: ConstValue<'tcx>,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &mut MonoItems<'tcx>,
 ) {
     match value {
         ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => collect_miri(tcx, ptr.provenance, output),
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 37e34656941..bb6d892138a 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2291,16 +2291,9 @@ impl<'a> Parser<'a> {
                         .span_label(else_span, "expected an `if` or a block after this `else`")
                         .span_suggestion(
                             cond.span.shrink_to_lo(),
-                            "add an `if` if this is the condition to an chained `if` statement after the `else`",
+                            "add an `if` if this is the condition of a chained `else if` statement",
                             "if ".to_string(),
                             Applicability::MaybeIncorrect,
-                        ).multipart_suggestion(
-                            "... otherwise, place this expression inside of a block if it is not an `if` condition",
-                            vec![
-                                (cond.span.shrink_to_lo(), "{ ".to_string()),
-                                (cond.span.shrink_to_hi(), " }".to_string()),
-                            ],
-                            Applicability::MaybeIncorrect,
                         )
                         .emit();
                     self.parse_if_after_cond(AttrVec::new(), cond.span.shrink_to_lo(), cond)?
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 510280ee386..a2d8e5168c4 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -30,7 +30,6 @@ mod diagnostic_items;
 pub mod entry;
 pub mod hir_id_validator;
 pub mod hir_stats;
-mod intrinsicck;
 mod lang_items;
 pub mod layout_test;
 mod lib_features;
@@ -54,7 +53,6 @@ pub fn provide(providers: &mut Providers) {
     loops::provide(providers);
     naked_functions::provide(providers);
     liveness::provide(providers);
-    intrinsicck::provide(providers);
     reachable::provide(providers);
     stability::provide(providers);
     upvars::provide(providers);
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 8737e45487e..f44eac63cef 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -1270,7 +1270,9 @@ impl<S: Encoder> Encodable<S> for SourceFile {
                     // the lines list is sorted and individual lines are
                     // probably not that long. Because of that we can store lines
                     // as a difference list, using as little space as possible
-                    // for the differences.
+                    // for the differences. But note that the first line is
+                    // always encoded as a `BytePos` because its position is
+                    // often much larger than any of the differences.
                     let max_line_length = if lines.len() == 1 {
                         0
                     } else {
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 020ae3ad0c7..d60b4d3d021 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -345,20 +345,27 @@ impl SourceMap {
         let end_pos = Pos::from_usize(start_pos + source_len);
         let start_pos = Pos::from_usize(start_pos);
 
+        // Translate these positions into the new global frame of reference,
+        // now that the offset of the SourceFile is known.
+        //
+        // These are all unsigned values. `original_start_pos` may be larger or
+        // smaller than `start_pos`, but `pos` is always larger than both.
+        // Therefore, `(pos - original_start_pos) + start_pos` won't overflow
+        // but `start_pos - original_start_pos` might. So we use the former
+        // form rather than pre-computing the offset into a local variable. The
+        // compiler backend can optimize away the repeated computations in a
+        // way that won't trigger overflow checks.
         for pos in &mut file_local_lines {
-            *pos = *pos + start_pos;
+            *pos = (*pos - original_start_pos) + start_pos;
         }
-
         for mbc in &mut file_local_multibyte_chars {
-            mbc.pos = mbc.pos + start_pos;
+            mbc.pos = (mbc.pos - original_start_pos) + start_pos;
         }
-
         for swc in &mut file_local_non_narrow_chars {
-            *swc = *swc + start_pos;
+            *swc = (*swc - original_start_pos) + start_pos;
         }
-
         for nc in &mut file_local_normalized_pos {
-            nc.pos = nc.pos + start_pos;
+            nc.pos = (nc.pos - original_start_pos) + start_pos;
         }
 
         let source_file = Lrc::new(SourceFile {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 5c9c16350e4..406e9a4113e 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -427,6 +427,7 @@ symbols! {
         cfg_panic,
         cfg_sanitize,
         cfg_target_abi,
+        cfg_target_compact,
         cfg_target_feature,
         cfg_target_has_atomic,
         cfg_target_has_atomic_equal_alignment,
@@ -1375,6 +1376,7 @@ symbols! {
         sym,
         sync,
         t32,
+        target,
         target_abi,
         target_arch,
         target_endian,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 832eeec3e8b..6dd245b047c 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -108,6 +108,15 @@ pub enum LldFlavor {
 }
 
 impl LldFlavor {
+    pub fn as_str(&self) -> &'static str {
+        match self {
+            LldFlavor::Wasm => "wasm",
+            LldFlavor::Ld64 => "darwin",
+            LldFlavor::Ld => "gnu",
+            LldFlavor::Link => "link",
+        }
+    }
+
     fn from_str(s: &str) -> Option<Self> {
         Some(match s {
             "darwin" => LldFlavor::Ld64,
@@ -121,13 +130,7 @@ impl LldFlavor {
 
 impl ToJson for LldFlavor {
     fn to_json(&self) -> Json {
-        match *self {
-            LldFlavor::Ld64 => "darwin",
-            LldFlavor::Ld => "gnu",
-            LldFlavor::Link => "link",
-            LldFlavor::Wasm => "wasm",
-        }
-        .to_json()
+        self.as_str().to_json()
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index a7893c0193f..e7f0e47f12c 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -20,7 +20,7 @@ use rustc_hir::CRATE_HIR_ID;
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::{util, TraitEngine};
 use rustc_middle::traits::specialization_graph::OverlapMode;
-use rustc_middle::ty::fast_reject::{self, TreatParams};
+use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt};
@@ -79,26 +79,21 @@ where
     // Before doing expensive operations like entering an inference context, do
     // a quick check via fast_reject to tell if the impl headers could possibly
     // unify.
+    let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer };
     let impl1_ref = tcx.impl_trait_ref(impl1_def_id);
     let impl2_ref = tcx.impl_trait_ref(impl2_def_id);
-
-    // Check if any of the input types definitely do not unify.
-    if iter::zip(
-        impl1_ref.iter().flat_map(|tref| tref.substs.types()),
-        impl2_ref.iter().flat_map(|tref| tref.substs.types()),
-    )
-    .any(|(ty1, ty2)| {
-        let t1 = fast_reject::simplify_type(tcx, ty1, TreatParams::AsInfer);
-        let t2 = fast_reject::simplify_type(tcx, ty2, TreatParams::AsInfer);
-
-        if let (Some(t1), Some(t2)) = (t1, t2) {
-            // Simplified successfully
-            t1 != t2
-        } else {
-            // Types might unify
-            false
+    let may_overlap = match (impl1_ref, impl2_ref) {
+        (Some(a), Some(b)) => iter::zip(a.substs, b.substs)
+            .all(|(arg1, arg2)| drcx.generic_args_may_unify(arg1, arg2)),
+        (None, None) => {
+            let self_ty1 = tcx.type_of(impl1_def_id);
+            let self_ty2 = tcx.type_of(impl2_def_id);
+            drcx.types_may_unify(self_ty1, self_ty2)
         }
-    }) {
+        _ => bug!("unexpected impls: {impl1_def_id:?} {impl2_def_id:?}"),
+    };
+
+    if !may_overlap {
         // Some types involved are definitely different, so the impls couldn't possibly overlap.
         debug!("overlapping_impls: fast_reject early-exit");
         return no_overlap();
@@ -519,7 +514,7 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
 /// 3. Before this local type, no generic type parameter of the impl must
 ///    be reachable through fundamental types.
 ///     - e.g. `impl<T> Trait<LocalType> for Vec<T>` is fine, as `Vec` is not fundamental.
-///     - while `impl<T> Trait<LocalType for Box<T>` results in an error, as `T` is
+///     - while `impl<T> Trait<LocalType> for Box<T>` results in an error, as `T` is
 ///       reachable through the fundamental type `Box`.
 /// 4. Every type in the local key parameter not known in C, going
 ///    through the parameter's type tree, must appear only as a subtree of
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 266fcc777ef..0cefa802c85 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -273,6 +273,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         error: &SelectionError<'tcx>,
         fallback_has_occurred: bool,
     ) {
+        self.set_tainted_by_errors();
         let tcx = self.tcx;
         let mut span = obligation.cause.span;
 
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 81819534e8b..dcfdff68640 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -62,7 +62,7 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapError;
 pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
 pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
 pub use self::structural_match::search_for_structural_match_violation;
-pub use self::structural_match::NonStructuralMatchTy;
+pub use self::structural_match::{NonStructuralMatchTy, NonStructuralMatchTyKind};
 pub use self::util::{
     elaborate_obligations, elaborate_predicates, elaborate_predicates_with_span,
     elaborate_trait_ref, elaborate_trait_refs,
diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
index 7d418198195..ed7d16f7a54 100644
--- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
@@ -89,8 +89,8 @@ impl<'tcx> OnUnimplementedDirective {
                         None,
                     )
                 })?;
-            attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
-                if let Some(symbol) = item.value_str() && let Err(guar) = parse_value(symbol) {
+            attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| {
+                if let Some(value) = cfg.value && let Err(guar) = parse_value(value) {
                     errored = Some(guar);
                 }
                 true
@@ -226,14 +226,12 @@ impl<'tcx> OnUnimplementedDirective {
                 condition,
                 &tcx.sess.parse_sess,
                 Some(tcx.features()),
-                &mut |c| {
-                    c.ident().map_or(false, |ident| {
-                        let value = c.value_str().map(|s| {
-                            OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map)
-                        });
+                &mut |cfg| {
+                    let value = cfg.value.map(|v| {
+                        OnUnimplementedFormatString(v).format(tcx, trait_ref, &options_map)
+                    });
 
-                        options.contains(&(ident.name, value))
-                    })
+                    options.contains(&(cfg.name, value))
                 },
             ) {
                 debug!("evaluate: skipping {:?} due to condition", command);
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 07720ba71ca..c8b4303e1e0 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -539,8 +539,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             obligation.predicate.def_id(),
             obligation.predicate.skip_binder().trait_ref.self_ty(),
             |impl_def_id| {
+                // Before we create the substitutions and everything, first
+                // consider a "quick reject". This avoids creating more types
+                // and so forth that we need to.
+                let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap();
+                if self.fast_reject_trait_refs(obligation, &impl_trait_ref.0) {
+                    return;
+                }
+
                 self.infcx.probe(|_| {
-                    if let Ok(_substs) = self.match_impl(impl_def_id, obligation) {
+                    if let Ok(_substs) = self.match_impl(impl_def_id, impl_trait_ref, obligation) {
                         candidates.vec.push(ImplCandidate(impl_def_id));
                     }
                 });
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index b0b17d0f9e6..c7ebc194ea5 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -33,11 +33,11 @@ use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::thir::abstract_const::NotConstEvaluatable;
-use rustc_middle::ty::fast_reject::{self, TreatParams};
+use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::relate::TypeRelation;
-use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef};
+use rustc_middle::ty::subst::{Subst, SubstsRef};
 use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
 use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable};
 use rustc_span::symbol::sym;
@@ -2043,7 +2043,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         impl_def_id: DefId,
         obligation: &TraitObligation<'tcx>,
     ) -> Normalized<'tcx, SubstsRef<'tcx>> {
-        match self.match_impl(impl_def_id, obligation) {
+        let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap();
+        match self.match_impl(impl_def_id, impl_trait_ref, obligation) {
             Ok(substs) => substs,
             Err(()) => {
                 self.infcx.tcx.sess.delay_span_bug(
@@ -2070,17 +2071,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn match_impl(
         &mut self,
         impl_def_id: DefId,
+        impl_trait_ref: EarlyBinder<ty::TraitRef<'tcx>>,
         obligation: &TraitObligation<'tcx>,
     ) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
-        let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap();
-
-        // Before we create the substitutions and everything, first
-        // consider a "quick reject". This avoids creating more types
-        // and so forth that we need to.
-        if self.fast_reject_trait_refs(obligation, &impl_trait_ref.0) {
-            return Err(());
-        }
-
         let placeholder_obligation =
             self.infcx().replace_bound_vars_with_placeholders(obligation.predicate);
         let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;
@@ -2137,40 +2130,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // We can avoid creating type variables and doing the full
         // substitution if we find that any of the input types, when
         // simplified, do not match.
-
-        iter::zip(obligation.predicate.skip_binder().trait_ref.substs, impl_trait_ref.substs).any(
-            |(obligation_arg, impl_arg)| {
-                match (obligation_arg.unpack(), impl_arg.unpack()) {
-                    (GenericArgKind::Type(obligation_ty), GenericArgKind::Type(impl_ty)) => {
-                        // Note, we simplify parameters for the obligation but not the
-                        // impl so that we do not reject a blanket impl but do reject
-                        // more concrete impls if we're searching for `T: Trait`.
-                        let simplified_obligation_ty = fast_reject::simplify_type(
-                            self.tcx(),
-                            obligation_ty,
-                            TreatParams::AsPlaceholder,
-                        );
-                        let simplified_impl_ty =
-                            fast_reject::simplify_type(self.tcx(), impl_ty, TreatParams::AsInfer);
-
-                        simplified_obligation_ty.is_some()
-                            && simplified_impl_ty.is_some()
-                            && simplified_obligation_ty != simplified_impl_ty
-                    }
-                    (GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => {
-                        // Lifetimes can never cause a rejection.
-                        false
-                    }
-                    (GenericArgKind::Const(_), GenericArgKind::Const(_)) => {
-                        // Conservatively ignore consts (i.e. assume they might
-                        // unify later) until we have `fast_reject` support for
-                        // them (if we'll ever need it, even).
-                        false
-                    }
-                    _ => unreachable!(),
-                }
-            },
-        )
+        let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder };
+        iter::zip(obligation.predicate.skip_binder().trait_ref.substs, impl_trait_ref.substs)
+            .any(|(obl, imp)| !drcx.generic_args_may_unify(obl, imp))
     }
 
     /// Normalize `where_clause_trait_ref` and try to match it against
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index 67e3bf80486..5465395768c 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -11,7 +11,13 @@ use rustc_span::Span;
 use std::ops::ControlFlow;
 
 #[derive(Debug)]
-pub enum NonStructuralMatchTy<'tcx> {
+pub struct NonStructuralMatchTy<'tcx> {
+    pub ty: Ty<'tcx>,
+    pub kind: NonStructuralMatchTyKind<'tcx>,
+}
+
+#[derive(Debug)]
+pub enum NonStructuralMatchTyKind<'tcx> {
     Adt(AdtDef<'tcx>),
     Param,
     Dynamic,
@@ -137,25 +143,32 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
         let (adt_def, substs) = match *ty.kind() {
             ty::Adt(adt_def, substs) => (adt_def, substs),
             ty::Param(_) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Param);
+                let kind = NonStructuralMatchTyKind::Param;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Dynamic(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Dynamic);
+                let kind = NonStructuralMatchTyKind::Dynamic;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Foreign(_) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Foreign);
+                let kind = NonStructuralMatchTyKind::Foreign;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Opaque(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Opaque);
+                let kind = NonStructuralMatchTyKind::Opaque;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Projection(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Projection);
+                let kind = NonStructuralMatchTyKind::Projection;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Closure(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Closure);
+                let kind = NonStructuralMatchTyKind::Closure;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Generator(..) | ty::GeneratorWitness(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Generator);
+                let kind = NonStructuralMatchTyKind::Generator;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::RawPtr(..) => {
                 // structural-match ignores substructure of
@@ -215,7 +228,8 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
 
         if !self.type_marked_structural(ty) {
             debug!("Search found ty: {:?}", ty);
-            return ControlFlow::Break(NonStructuralMatchTy::Adt(adt_def));
+            let kind = NonStructuralMatchTyKind::Adt(adt_def);
+            return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
         }
 
         // structural-match does not care about the
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 3e76738cc5d..a6d7fecb2e8 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -1,3 +1,5 @@
+use crate::check::wfcheck::for_item;
+
 use super::coercion::CoerceMany;
 use super::compare_method::check_type_bounds;
 use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl};
@@ -871,6 +873,14 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
                 }
             }
         }
+        DefKind::GlobalAsm => {
+            let it = tcx.hir().item(id);
+            let hir::ItemKind::GlobalAsm(asm) = it.kind else { span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it) };
+            for_item(tcx, it).with_fcx(|fcx| {
+                fcx.check_asm(asm, it.hir_id());
+                Default::default()
+            })
+        }
         _ => {}
     }
 }
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 09b0dc0a0ea..ea81f1ef90c 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -51,6 +51,7 @@ use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Pos};
+use rustc_target::spec::abi::Abi::RustIntrinsic;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::{self, ObligationCauseCode};
 
@@ -294,7 +295,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.check_lang_item_path(lang_item, expr, hir_id)
             }
             ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]),
-            ExprKind::InlineAsm(asm) => self.check_expr_asm(asm),
+            ExprKind::InlineAsm(asm) => {
+                // We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars).
+                self.deferred_asm_checks.borrow_mut().push((asm, expr.hir_id));
+                self.check_expr_asm(asm)
+            }
             ExprKind::Break(destination, ref expr_opt) => {
                 self.check_expr_break(destination, expr_opt.as_deref(), expr)
             }
@@ -530,8 +535,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
         };
 
-        if let ty::FnDef(..) = ty.kind() {
+        if let ty::FnDef(did, ..) = *ty.kind() {
             let fn_sig = ty.fn_sig(tcx);
+            if tcx.fn_sig(did).abi() == RustIntrinsic && tcx.item_name(did) == sym::transmute {
+                let from = fn_sig.inputs().skip_binder()[0];
+                let to = fn_sig.output().skip_binder();
+                // We defer the transmute to the end of typeck, once all inference vars have
+                // been resolved or we errored. This is important as we can only check transmute
+                // on concrete types, but the output type may not be known yet (it would only
+                // be known if explicitly specified via turbofish).
+                self.deferred_transmute_checks.borrow_mut().push((from, to, expr.span));
+            }
             if !tcx.features().unsized_fn_params {
                 // We want to remove some Sized bounds from std functions,
                 // but don't want to expose the removal to stable Rust.
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index a02d8c89772..34cc02f180b 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -47,6 +47,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    pub(in super::super) fn check_transmutes(&self) {
+        let mut deferred_transmute_checks = self.deferred_transmute_checks.borrow_mut();
+        debug!("FnCtxt::check_transmutes: {} deferred checks", deferred_transmute_checks.len());
+        for (from, to, span) in deferred_transmute_checks.drain(..) {
+            self.check_transmute(span, from, to);
+        }
+    }
+
+    pub(in super::super) fn check_asms(&self) {
+        let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
+        debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
+        for (asm, hir_id) in deferred_asm_checks.drain(..) {
+            let enclosing_id = self.tcx.hir().enclosing_body_owner(hir_id);
+            self.check_asm(asm, enclosing_id);
+        }
+    }
+
     pub(in super::super) fn check_method_argument_types(
         &self,
         sp: Span,
@@ -845,7 +862,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let first_provided_ty = if let Some((ty, _)) = final_arg_types[input_idx] {
                             format!(",found `{}`", ty)
                         } else {
-                            "".into()
+                            String::new()
                         };
                         labels.push((
                             first_span,
@@ -857,7 +874,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             if let Some((ty, _)) = final_arg_types[other_input_idx] {
                                 format!(",found `{}`", ty)
                             } else {
-                                "".into()
+                                String::new()
                             };
                         labels.push((
                             second_span,
@@ -875,7 +892,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             let provided_ty = if let Some((ty, _)) = final_arg_types[dst_arg] {
                                 format!(",found `{}`", ty)
                             } else {
-                                "".into()
+                                String::new()
                             };
                             labels.push((
                                 provided_args[dst_arg].span,
@@ -1744,8 +1761,7 @@ fn label_fn_like<'tcx>(
             .get_if_local(def_id)
             .and_then(|node| node.body_id())
             .into_iter()
-            .map(|id| tcx.hir().body(id).params)
-            .flatten();
+            .flat_map(|id| tcx.hir().body(id).params);
 
         for param in params {
             spans.push_span_label(param.span, String::new());
diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs
index 5cd63cae8ad..08a64d8e673 100644
--- a/compiler/rustc_typeck/src/check/inherited.rs
+++ b/compiler/rustc_typeck/src/check/inherited.rs
@@ -50,6 +50,10 @@ pub struct Inherited<'a, 'tcx> {
 
     pub(super) deferred_cast_checks: RefCell<Vec<super::cast::CastCheck<'tcx>>>,
 
+    pub(super) deferred_transmute_checks: RefCell<Vec<(Ty<'tcx>, Ty<'tcx>, Span)>>,
+
+    pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, hir::HirId)>>,
+
     pub(super) deferred_generator_interiors:
         RefCell<Vec<(hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>,
 
@@ -113,6 +117,8 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
             deferred_sized_obligations: RefCell::new(Vec::new()),
             deferred_call_resolutions: RefCell::new(Default::default()),
             deferred_cast_checks: RefCell::new(Vec::new()),
+            deferred_transmute_checks: RefCell::new(Vec::new()),
+            deferred_asm_checks: RefCell::new(Vec::new()),
             deferred_generator_interiors: RefCell::new(Vec::new()),
             diverging_type_vars: RefCell::new(Default::default()),
             body_id,
diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_typeck/src/check/intrinsicck.rs
index 9c840777baf..027868be8bb 100644
--- a/compiler/rustc_passes/src/intrinsicck.rs
+++ b/compiler/rustc_typeck/src/check/intrinsicck.rs
@@ -1,37 +1,16 @@
-use hir::intravisit::walk_inline_asm;
 use rustc_ast::InlineAsmTemplatePiece;
 use rustc_data_structures::stable_set::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::{self, Visitor};
 use rustc_index::vec::Idx;
 use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
-use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, UintTy};
+use rustc_middle::ty::{self, FloatTy, InferTy, IntTy, Ty, TyCtxt, TypeFoldable, UintTy};
 use rustc_session::lint;
-use rustc_span::{sym, Span, Symbol, DUMMY_SP};
+use rustc_span::{Span, Symbol, DUMMY_SP};
 use rustc_target::abi::{Pointer, VariantIdx};
-use rustc_target::asm::{InlineAsmRegOrRegClass, InlineAsmType};
+use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType};
 
-fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
-    tcx.hir().deep_visit_item_likes_in_module(module_def_id, &mut ItemVisitor { tcx });
-}
-
-pub fn provide(providers: &mut Providers) {
-    *providers = Providers { check_mod_intrinsics, ..*providers };
-}
-
-struct ItemVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
-
-struct ExprVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    typeck_results: &'tcx ty::TypeckResults<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-}
+use super::FnCtxt;
 
 /// If the type is `Option<T>`, it will return `T`, otherwise
 /// the type itself. Works on most `Option`-like types.
@@ -60,14 +39,15 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
     ty
 }
 
-impl<'tcx> ExprVisitor<'tcx> {
-    fn def_id_is_transmute(&self, def_id: DefId) -> bool {
-        self.tcx.is_intrinsic(def_id) && self.tcx.item_name(def_id) == sym::transmute
-    }
-
-    fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
-        let sk_from = SizeSkeleton::compute(from, self.tcx, self.param_env);
-        let sk_to = SizeSkeleton::compute(to, self.tcx, self.param_env);
+impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+    pub fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
+        let convert = |ty: Ty<'tcx>| {
+            let ty = self.resolve_vars_if_possible(ty);
+            let ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
+            (SizeSkeleton::compute(ty, self.tcx, self.param_env), ty)
+        };
+        let (sk_from, from) = convert(from);
+        let (sk_to, to) = convert(to);
 
         // Check for same size using the skeletons.
         if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) {
@@ -139,7 +119,8 @@ impl<'tcx> ExprVisitor<'tcx> {
         target_features: &FxHashSet<Symbol>,
     ) -> Option<InlineAsmType> {
         // Check the type against the allowed types for inline asm.
-        let ty = self.typeck_results.expr_ty_adjusted(expr);
+        let ty = self.typeck_results.borrow().expr_ty_adjusted(expr);
+        let ty = self.resolve_vars_if_possible(ty);
         let asm_ty_isize = match self.tcx.sess.target.pointer_width {
             16 => InlineAsmType::I16,
             32 => InlineAsmType::I32,
@@ -152,10 +133,24 @@ impl<'tcx> ExprVisitor<'tcx> {
             ty::Error(_) => return None,
             ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::I8),
             ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Some(InlineAsmType::I16),
+            // Somewhat of a hack: fallback in the presence of errors does not actually
+            // fall back to i32, but to ty::Error. For integer inference variables this
+            // means that they don't get any fallback and stay as `{integer}`.
+            // Since compilation can't succeed anyway, it's fine to use this to avoid printing
+            // "cannot use value of type `{integer}`", even though that would absolutely
+            // work due due i32 fallback if the current function had no other errors.
+            ty::Infer(InferTy::IntVar(_)) => {
+                assert!(self.is_tainted_by_errors());
+                Some(InlineAsmType::I32)
+            }
             ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Some(InlineAsmType::I32),
             ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Some(InlineAsmType::I64),
             ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Some(InlineAsmType::I128),
             ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(asm_ty_isize),
+            ty::Infer(InferTy::FloatVar(_)) => {
+                assert!(self.is_tainted_by_errors());
+                Some(InlineAsmType::F32)
+            }
             ty::Float(FloatTy::F32) => Some(InlineAsmType::F32),
             ty::Float(FloatTy::F64) => Some(InlineAsmType::F64),
             ty::FnPtr(_) => Some(asm_ty_isize),
@@ -208,6 +203,11 @@ impl<'tcx> ExprVisitor<'tcx> {
             return None;
         };
 
+        if ty.has_infer_types_or_consts() {
+            assert!(self.is_tainted_by_errors());
+            return None;
+        }
+
         // Check that the type implements Copy. The only case where this can
         // possibly fail is for SIMD types which don't #[derive(Copy)].
         if !ty.is_copy_modulo_regions(self.tcx.at(DUMMY_SP), self.param_env) {
@@ -230,10 +230,10 @@ impl<'tcx> ExprVisitor<'tcx> {
             if in_asm_ty != asm_ty {
                 let msg = "incompatible types for asm inout argument";
                 let mut err = self.tcx.sess.struct_span_err(vec![in_expr.span, expr.span], msg);
-                err.span_label(
-                    in_expr.span,
-                    &format!("type `{}`", self.typeck_results.expr_ty_adjusted(in_expr)),
-                );
+
+                let in_expr_ty = self.typeck_results.borrow().expr_ty_adjusted(in_expr);
+                let in_expr_ty = self.resolve_vars_if_possible(in_expr_ty);
+                err.span_label(in_expr.span, &format!("type `{in_expr_ty}`"));
                 err.span_label(expr.span, &format!("type `{ty}`"));
                 err.note(
                     "asm inout arguments must have the same type, \
@@ -337,12 +337,14 @@ impl<'tcx> ExprVisitor<'tcx> {
         Some(asm_ty)
     }
 
-    fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, hir_id: hir::HirId) {
+    pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, enclosing_id: hir::HirId) {
         let hir = self.tcx.hir();
-        let enclosing_id = hir.enclosing_body_owner(hir_id);
         let enclosing_def_id = hir.local_def_id(enclosing_id).to_def_id();
         let target_features = self.tcx.asm_target_features(enclosing_def_id);
-        let asm_arch = self.tcx.sess.asm_arch.unwrap();
+        let Some(asm_arch) = self.tcx.sess.asm_arch else {
+            self.tcx.sess.delay_span_bug(DUMMY_SP, "target architecture does not support asm");
+            return;
+        };
         for (idx, (op, op_sp)) in asm.operands.iter().enumerate() {
             // Validate register classes against currently enabled target
             // features. We check that at least one type is available for
@@ -358,6 +360,11 @@ impl<'tcx> ExprVisitor<'tcx> {
                 // Some explicit registers cannot be used depending on the
                 // target. Reject those here.
                 if let InlineAsmRegOrRegClass::Reg(reg) = reg {
+                    if let InlineAsmReg::Err = reg {
+                        // `validate` will panic on `Err`, as an error must
+                        // already have been reported.
+                        continue;
+                    }
                     if let Err(msg) = reg.validate(
                         asm_arch,
                         self.tcx.sess.relocation_model(),
@@ -374,6 +381,9 @@ impl<'tcx> ExprVisitor<'tcx> {
                 if !op.is_clobber() {
                     let mut missing_required_features = vec![];
                     let reg_class = reg.reg_class();
+                    if let InlineAsmRegClass::Err = reg_class {
+                        continue;
+                    }
                     for &(_, feature) in reg_class.supported_types(asm_arch) {
                         match feature {
                             Some(feature) => {
@@ -482,33 +492,6 @@ impl<'tcx> ExprVisitor<'tcx> {
                         );
                     }
                 }
-                // These are checked in ItemVisitor.
-                hir::InlineAsmOperand::Const { .. }
-                | hir::InlineAsmOperand::SymFn { .. }
-                | hir::InlineAsmOperand::SymStatic { .. } => {}
-            }
-        }
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for ItemVisitor<'tcx> {
-    fn visit_nested_body(&mut self, body_id: hir::BodyId) {
-        let owner_def_id = self.tcx.hir().body_owner_def_id(body_id);
-        let body = self.tcx.hir().body(body_id);
-        let param_env = self.tcx.param_env(owner_def_id.to_def_id());
-        let typeck_results = self.tcx.typeck(owner_def_id);
-        ExprVisitor { tcx: self.tcx, param_env, typeck_results }.visit_body(body);
-        self.visit_body(body);
-    }
-
-    fn visit_inline_asm(&mut self, asm: &'tcx hir::InlineAsm<'tcx>, id: hir::HirId) {
-        for (op, op_sp) in asm.operands.iter() {
-            match *op {
-                // These are checked in ExprVisitor.
-                hir::InlineAsmOperand::In { .. }
-                | hir::InlineAsmOperand::Out { .. }
-                | hir::InlineAsmOperand::InOut { .. }
-                | hir::InlineAsmOperand::SplitInOut { .. } => {}
                 // No special checking is needed for these:
                 // - Typeck has checked that Const operands are integers.
                 // - AST lowering guarantees that SymStatic points to a static.
@@ -534,31 +517,5 @@ impl<'tcx> Visitor<'tcx> for ItemVisitor<'tcx> {
                 }
             }
         }
-        walk_inline_asm(self, asm, id);
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for ExprVisitor<'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
-        match expr.kind {
-            hir::ExprKind::Path(ref qpath) => {
-                let res = self.typeck_results.qpath_res(qpath, expr.hir_id);
-                if let Res::Def(DefKind::Fn, did) = res
-                    && self.def_id_is_transmute(did)
-                {
-                    let typ = self.typeck_results.node_type(expr.hir_id);
-                    let sig = typ.fn_sig(self.tcx);
-                    let from = sig.inputs().skip_binder()[0];
-                    let to = sig.output().skip_binder();
-                    self.check_transmute(expr.span, from, to);
-                }
-            }
-
-            hir::ExprKind::InlineAsm(asm) => self.check_asm(asm, expr.hir_id),
-
-            _ => {}
-        }
-
-        intravisit::walk_expr(self, expr);
     }
 }
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index f9c0ea82e02..4e54d554c6e 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -492,7 +492,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 Obligation {
                                     cause: cause.clone(),
                                     param_env: self.param_env,
-                                    predicate: predicate.clone(),
+                                    predicate: *predicate,
                                     recursion_depth: 0,
                                 },
                             ));
@@ -676,7 +676,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 let span = self_ty.span.ctxt().outer_expn_data().call_site;
                                 let mut spans: MultiSpan = span.into();
                                 spans.push_span_label(span, derive_msg.to_string());
-                                let entry = spanned_predicates.entry(spans.into());
+                                let entry = spanned_predicates.entry(spans);
                                 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
                             }
 
@@ -704,7 +704,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                     ident.span.into()
                                 };
                                 spans.push_span_label(ident.span, "in this trait".to_string());
-                                let entry = spanned_predicates.entry(spans.into());
+                                let entry = spanned_predicates.entry(spans);
                                 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
                             }
 
@@ -748,7 +748,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 }
                                 spans.push_span_label(self_ty.span, String::new());
 
-                                let entry = spanned_predicates.entry(spans.into());
+                                let entry = spanned_predicates.entry(spans);
                                 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
                             }
                             _ => {}
@@ -1460,7 +1460,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             {
                                 derives.push((
                                     self_name.clone(),
-                                    self_span.clone(),
+                                    self_span,
                                     parent_diagnostic_name.to_string(),
                                 ));
                             }
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 280fae5fe6d..7e686d0f5e9 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -81,6 +81,7 @@ mod gather_locals;
 mod generator_interior;
 mod inherited;
 pub mod intrinsic;
+mod intrinsicck;
 pub mod method;
 mod op;
 mod pat;
@@ -487,6 +488,12 @@ fn typeck_with_fallback<'tcx>(
 
         fcx.select_all_obligations_or_error();
 
+        if !fcx.infcx.is_tainted_by_errors() {
+            fcx.check_transmutes();
+        }
+
+        fcx.check_asms();
+
         if fn_sig.is_some() {
             fcx.regionck_fn(id, body, span, wf_tys);
         } else {
diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs
index c99d9d8f923..637f6459525 100644
--- a/compiler/rustc_typeck/src/check/op.rs
+++ b/compiler/rustc_typeck/src/check/op.rs
@@ -705,7 +705,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let predicates = errors
                             .iter()
                             .filter_map(|error| {
-                                error.obligation.predicate.clone().to_opt_poly_trait_pred()
+                                error.obligation.predicate.to_opt_poly_trait_pred()
                             });
                         for pred in predicates {
                             self.infcx.suggest_restricting_param_bound(
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 50966868ec7..a6c7573b787 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -41,7 +41,7 @@ use std::ops::ControlFlow;
 /// ```ignore (illustrative)
 /// F: for<'b, 'tcx> where 'tcx FnOnce(FnCtxt<'b, 'tcx>)
 /// ```
-struct CheckWfFcxBuilder<'tcx> {
+pub(super) struct CheckWfFcxBuilder<'tcx> {
     inherited: super::InheritedBuilder<'tcx>,
     id: hir::HirId,
     span: Span,
@@ -49,7 +49,7 @@ struct CheckWfFcxBuilder<'tcx> {
 }
 
 impl<'tcx> CheckWfFcxBuilder<'tcx> {
-    fn with_fcx<F>(&mut self, f: F)
+    pub(super) fn with_fcx<F>(&mut self, f: F)
     where
         F: for<'b> FnOnce(&FnCtxt<'b, 'tcx>) -> FxHashSet<Ty<'tcx>>,
     {
@@ -827,7 +827,9 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
                     );
                 }
 
-                if traits::search_for_structural_match_violation(param.span, tcx, ty).is_some() {
+                if let Some(non_structural_match_ty) =
+                    traits::search_for_structural_match_violation(param.span, tcx, ty)
+                {
                     // We use the same error code in both branches, because this is really the same
                     // issue: we just special-case the message for type parameters to make it
                     // clearer.
@@ -853,19 +855,23 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
                         )
                         .emit();
                     } else {
-                        struct_span_err!(
+                        let mut diag = struct_span_err!(
                             tcx.sess,
                             hir_ty.span,
                             E0741,
                             "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
                             the type of a const parameter",
-                            ty,
-                        )
-                        .span_label(
-                            hir_ty.span,
-                            format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
-                        )
-                        .emit();
+                            non_structural_match_ty.ty,
+                        );
+
+                        if ty == non_structural_match_ty.ty {
+                            diag.span_label(
+                                hir_ty.span,
+                                format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
+                            );
+                        }
+
+                        diag.emit();
                     }
                 }
             } else {
@@ -966,7 +972,7 @@ fn check_associated_item(
     })
 }
 
-fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder<'tcx> {
+pub(super) fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder<'tcx> {
     for_id(tcx, item.def_id, item.span)
 }
 
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index 16096ea3d74..4fe5b26dc05 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -263,8 +263,6 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
         self.fix_scalar_builtin_expr(e);
         self.fix_index_builtin_expr(e);
 
-        self.visit_node_id(e.span, e.hir_id);
-
         match e.kind {
             hir::ExprKind::Closure(_, _, body, _, _) => {
                 let body = self.fcx.tcx.hir().body(body);
@@ -291,6 +289,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
             _ => {}
         }
 
+        self.visit_node_id(e.span, e.hir_id);
         intravisit::walk_expr(self, e);
     }
 
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index 4ffd199b133..454c71d4971 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -63,6 +63,7 @@ This API is completely unstable and subject to change.
 #![feature(hash_drain_filter)]
 #![feature(if_let_guard)]
 #![feature(is_sorted)]
+#![feature(iter_intersperse)]
 #![feature(label_break_value)]
 #![feature(let_chains)]
 #![feature(let_else)]
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 0eaa2639863..39dfd98ddcc 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -383,15 +383,23 @@ impl str {
                   without modifying the original"]
     #[stable(feature = "unicode_case_mapping", since = "1.2.0")]
     pub fn to_lowercase(&self) -> String {
-        let mut s = String::with_capacity(self.len());
-        for (i, c) in self[..].char_indices() {
+        let out = convert_while_ascii(self.as_bytes(), u8::to_ascii_lowercase);
+
+        // Safety: we know this is a valid char boundary since
+        // out.len() is only progressed if ascii bytes are found
+        let rest = unsafe { self.get_unchecked(out.len()..) };
+
+        // Safety: We have written only valid ASCII to our vec
+        let mut s = unsafe { String::from_utf8_unchecked(out) };
+
+        for (i, c) in rest[..].char_indices() {
             if c == 'Σ' {
                 // Σ maps to σ, except at the end of a word where it maps to ς.
                 // This is the only conditional (contextual) but language-independent mapping
                 // in `SpecialCasing.txt`,
                 // so hard-code it rather than have a generic "condition" mechanism.
                 // See https://github.com/rust-lang/rust/issues/26035
-                map_uppercase_sigma(self, i, &mut s)
+                map_uppercase_sigma(rest, i, &mut s)
             } else {
                 match conversions::to_lower(c) {
                     [a, '\0', _] => s.push(a),
@@ -466,8 +474,16 @@ impl str {
                   without modifying the original"]
     #[stable(feature = "unicode_case_mapping", since = "1.2.0")]
     pub fn to_uppercase(&self) -> String {
-        let mut s = String::with_capacity(self.len());
-        for c in self[..].chars() {
+        let out = convert_while_ascii(self.as_bytes(), u8::to_ascii_uppercase);
+
+        // Safety: we know this is a valid char boundary since
+        // out.len() is only progressed if ascii bytes are found
+        let rest = unsafe { self.get_unchecked(out.len()..) };
+
+        // Safety: We have written only valid ASCII to our vec
+        let mut s = unsafe { String::from_utf8_unchecked(out) };
+
+        for c in rest.chars() {
             match conversions::to_upper(c) {
                 [a, '\0', _] => s.push(a),
                 [a, b, '\0'] => {
@@ -619,3 +635,51 @@ impl str {
 pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> {
     unsafe { Box::from_raw(Box::into_raw(v) as *mut str) }
 }
+
+/// Converts the bytes while the bytes are still ascii.
+/// For better average performance, this is happens in chunks of `2*size_of::<usize>()`.
+/// Returns a vec with the converted bytes.
+#[inline]
+#[cfg(not(test))]
+#[cfg(not(no_global_oom_handling))]
+fn convert_while_ascii(b: &[u8], convert: fn(&u8) -> u8) -> Vec<u8> {
+    let mut out = Vec::with_capacity(b.len());
+
+    const USIZE_SIZE: usize = mem::size_of::<usize>();
+    const MAGIC_UNROLL: usize = 2;
+    const N: usize = USIZE_SIZE * MAGIC_UNROLL;
+    const NONASCII_MASK: usize = usize::from_ne_bytes([0x80; USIZE_SIZE]);
+
+    let mut i = 0;
+    unsafe {
+        while i + N <= b.len() {
+            // Safety: we have checks the sizes `b` and `out` to know that our
+            let in_chunk = b.get_unchecked(i..i + N);
+            let out_chunk = out.spare_capacity_mut().get_unchecked_mut(i..i + N);
+
+            let mut bits = 0;
+            for j in 0..MAGIC_UNROLL {
+                // read the bytes 1 usize at a time (unaligned since we haven't checked the alignment)
+                // safety: in_chunk is valid bytes in the range
+                bits |= in_chunk.as_ptr().cast::<usize>().add(j).read_unaligned();
+            }
+            // if our chunks aren't ascii, then return only the prior bytes as init
+            if bits & NONASCII_MASK != 0 {
+                break;
+            }
+
+            // perform the case conversions on N bytes (gets heavily autovec'd)
+            for j in 0..N {
+                // safety: in_chunk and out_chunk is valid bytes in the range
+                let out = out_chunk.get_unchecked_mut(j);
+                out.write(convert(in_chunk.get_unchecked(j)));
+            }
+
+            // mark these bytes as initialised
+            i += N;
+        }
+        out.set_len(i);
+    }
+
+    out
+}
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index c157aba83c2..d222fcb445f 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1771,7 +1771,7 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// # Panics
     ///
-    /// Panics if the number of elements in the vector overflows a `usize`.
+    /// Panics if the new capacity exceeds `isize::MAX` bytes.
     ///
     /// # Examples
     ///
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index 273b39aa45a..7379569dd68 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -1772,6 +1772,20 @@ fn to_lowercase() {
     assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
     assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
     assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
+
+    // a really long string that has it's lowercase form
+    // even longer. this tests that implementations don't assume
+    // an incorrect upper bound on allocations
+    let upper = str::repeat("İ", 512);
+    let lower = str::repeat("i̇", 512);
+    assert_eq!(upper.to_lowercase(), lower);
+
+    // a really long ascii-only string.
+    // This test that the ascii hot-path
+    // functions correctly
+    let upper = str::repeat("A", 511);
+    let lower = str::repeat("a", 511);
+    assert_eq!(upper.to_lowercase(), lower);
 }
 
 #[test]
diff --git a/library/core/src/asserting.rs b/library/core/src/asserting.rs
new file mode 100644
index 00000000000..212b637d343
--- /dev/null
+++ b/library/core/src/asserting.rs
@@ -0,0 +1,109 @@
+// Contains the machinery necessary to print useful `assert!` messages. Not intended for public
+// usage, not even nightly use-cases.
+//
+// Based on https://github.com/dtolnay/case-studies/tree/master/autoref-specialization. When
+// 'specialization' is robust enough (5 years? 10 years? Never?), `Capture` can be specialized
+// to [Printable].
+
+#![allow(missing_debug_implementations)]
+#![doc(hidden)]
+#![unstable(feature = "generic_assert_internals", issue = "44838")]
+
+use crate::{
+    fmt::{Debug, Formatter},
+    marker::PhantomData,
+};
+
+// ***** TryCapture - Generic *****
+
+/// Marker used by [Capture]
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub struct TryCaptureWithoutDebug;
+
+/// Catches an arbitrary `E` and modifies `to` accordingly
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub trait TryCaptureGeneric<E, M> {
+    /// Similar to [TryCapturePrintable] but generic to any `E`.
+    fn try_capture(&self, to: &mut Capture<E, M>);
+}
+
+impl<E> TryCaptureGeneric<E, TryCaptureWithoutDebug> for &Wrapper<&E> {
+    #[inline]
+    fn try_capture(&self, _: &mut Capture<E, TryCaptureWithoutDebug>) {}
+}
+
+impl<E> Debug for Capture<E, TryCaptureWithoutDebug> {
+    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
+        f.write_str("N/A")
+    }
+}
+
+// ***** TryCapture - Printable *****
+
+/// Marker used by [Capture]
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub struct TryCaptureWithDebug;
+
+/// Catches an arbitrary `E: Printable` and modifies `to` accordingly
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub trait TryCapturePrintable<E, M> {
+    /// Similar as [TryCaptureGeneric] but specialized to any `E: Printable`.
+    fn try_capture(&self, to: &mut Capture<E, M>);
+}
+
+impl<E> TryCapturePrintable<E, TryCaptureWithDebug> for Wrapper<&E>
+where
+    E: Printable,
+{
+    #[inline]
+    fn try_capture(&self, to: &mut Capture<E, TryCaptureWithDebug>) {
+        to.elem = Some(*self.0);
+    }
+}
+
+impl<E> Debug for Capture<E, TryCaptureWithDebug>
+where
+    E: Printable,
+{
+    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
+        match self.elem {
+            None => f.write_str("N/A"),
+            Some(ref value) => Debug::fmt(value, f),
+        }
+    }
+}
+
+// ***** Others *****
+
+/// All possible captured `assert!` elements
+///
+/// # Types
+///
+/// * `E`: **E**lement that is going to be displayed.
+/// * `M`: **M**arker used to differentiate [Capture]s in regards to [Debug].
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub struct Capture<E, M> {
+    // If None, then `E` does not implements [Printable] or `E` wasn't evaluated (`assert!( ... )`
+    // short-circuited).
+    //
+    // If Some, then `E` implements [Printable] and was evaluated.
+    pub elem: Option<E>,
+    phantom: PhantomData<M>,
+}
+
+impl<M, T> Capture<M, T> {
+    #[inline]
+    pub const fn new() -> Self {
+        Self { elem: None, phantom: PhantomData }
+    }
+}
+
+/// Necessary for the implementations of `TryCapture*`
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub struct Wrapper<T>(pub T);
+
+/// Tells which elements can be copied and displayed
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub trait Printable: Copy + Debug {}
+
+impl<T> Printable for T where T: Copy + Debug {}
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index 22b76ea66ff..15362d2330a 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -362,6 +362,12 @@ pub use self::traits::Iterator;
 )]
 pub use self::range::Step;
 
+#[unstable(
+    feature = "iter_from_generator",
+    issue = "43122",
+    reason = "generators are unstable"
+)]
+pub use self::sources::from_generator;
 #[stable(feature = "iter_empty", since = "1.2.0")]
 pub use self::sources::{empty, Empty};
 #[stable(feature = "iter_from_fn", since = "1.34.0")]
diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs
index 37b6f2e2565..d34772cd304 100644
--- a/library/core/src/iter/sources.rs
+++ b/library/core/src/iter/sources.rs
@@ -1,5 +1,6 @@
 mod empty;
 mod from_fn;
+mod from_generator;
 mod once;
 mod once_with;
 mod repeat;
@@ -21,6 +22,13 @@ pub use self::repeat_with::{repeat_with, RepeatWith};
 #[stable(feature = "iter_from_fn", since = "1.34.0")]
 pub use self::from_fn::{from_fn, FromFn};
 
+#[unstable(
+    feature = "iter_from_generator",
+    issue = "43122",
+    reason = "generators are unstable"
+)]
+pub use self::from_generator::from_generator;
+
 #[stable(feature = "iter_successors", since = "1.34.0")]
 pub use self::successors::{successors, Successors};
 
diff --git a/library/core/src/iter/sources/from_generator.rs b/library/core/src/iter/sources/from_generator.rs
new file mode 100644
index 00000000000..8e7cbd34a4f
--- /dev/null
+++ b/library/core/src/iter/sources/from_generator.rs
@@ -0,0 +1,43 @@
+use crate::ops::{Generator, GeneratorState};
+use crate::pin::Pin;
+
+/// Creates a new iterator where each iteration calls the provided generator.
+///
+/// Similar to [`iter::from_fn`].
+///
+/// [`iter::from_fn`]: crate::iter::from_fn
+///
+/// # Examples
+///
+/// ```
+/// #![feature(generators)]
+/// #![feature(iter_from_generator)]
+///
+/// let it = std::iter::from_generator(|| {
+///     yield 1;
+///     yield 2;
+///     yield 3;
+/// });
+/// let v: Vec<_> = it.collect();
+/// assert_eq!(v, [1, 2, 3]);
+/// ```
+#[inline]
+#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")]
+pub fn from_generator<G: Generator<Return = ()> + Unpin>(
+    generator: G,
+) -> impl Iterator<Item = G::Yield> {
+    FromGenerator(generator)
+}
+
+struct FromGenerator<G>(G);
+
+impl<G: Generator<Return = ()> + Unpin> Iterator for FromGenerator<G> {
+    type Item = G::Yield;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match Pin::new(&mut self.0).resume(()) {
+            GeneratorState::Yielded(n) => Some(n),
+            GeneratorState::Complete(()) => None,
+        }
+    }
+}
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 7b04e4423b7..cfcc3ffb9c0 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -310,6 +310,7 @@ pub mod ops;
 pub mod any;
 pub mod array;
 pub mod ascii;
+pub mod asserting;
 #[unstable(feature = "async_iterator", issue = "79024")]
 pub mod async_iter;
 pub mod cell;
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index d0746698f40..28ea45ed235 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -708,6 +708,26 @@ impl<T> Option<T> {
     /// let x: Option<&str> = None;
     /// x.expect("fruits are healthy"); // panics with `fruits are healthy`
     /// ```
+    ///
+    /// # Recommended Message Style
+    ///
+    /// We recommend that `expect` messages are used to describe the reason you
+    /// _expect_ the `Option` should be `Some`.
+    ///
+    /// ```should_panic
+    /// # let slice: &[u8] = &[];
+    /// let item = slice.get(0)
+    ///     .expect("slice should not be empty");
+    /// ```
+    ///
+    /// **Hint**: If you're having trouble remembering how to phrase expect
+    /// error messages remember to focus on the word "should" as in "env
+    /// variable should be set by blah" or "the given binary should be available
+    /// and executable by the current user".
+    ///
+    /// For more detail on expect message styles and the reasoning behind our
+    /// recommendation please refer to the section on ["Common Message
+    /// Styles"](../../std/error/index.html#common-message-styles) in the [`std::error`](../../std/error/index.html) module docs.
     #[inline]
     #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index dc229c9ff9b..d2e680ecd20 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -507,10 +507,33 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
 #[rustc_promotable]
 #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
 #[rustc_diagnostic_item = "ptr_null"]
+#[cfg(bootstrap)]
 pub const fn null<T>() -> *const T {
     invalid(0)
 }
 
+/// Creates a null raw pointer.
+///
+/// # Examples
+///
+/// ```
+/// use std::ptr;
+///
+/// let p: *const i32 = ptr::null();
+/// assert!(p.is_null());
+/// ```
+#[inline(always)]
+#[must_use]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_promotable]
+#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
+#[rustc_allow_const_fn_unstable(ptr_metadata)]
+#[rustc_diagnostic_item = "ptr_null"]
+#[cfg(not(bootstrap))]
+pub const fn null<T: ?Sized + Thin>() -> *const T {
+    from_raw_parts(0 as *const (), ())
+}
+
 /// Creates a null mutable raw pointer.
 ///
 /// # Examples
@@ -527,6 +550,7 @@ pub const fn null<T>() -> *const T {
 #[rustc_promotable]
 #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
 #[rustc_diagnostic_item = "ptr_null_mut"]
+#[cfg(bootstrap)]
 pub const fn null_mut<T>() -> *mut T {
     invalid_mut(0)
 }
@@ -665,6 +689,28 @@ where
     addr as *mut T
 }
 
+/// Creates a null mutable raw pointer.
+///
+/// # Examples
+///
+/// ```
+/// use std::ptr;
+///
+/// let p: *mut i32 = ptr::null_mut();
+/// assert!(p.is_null());
+/// ```
+#[inline(always)]
+#[must_use]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_promotable]
+#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
+#[rustc_allow_const_fn_unstable(ptr_metadata)]
+#[rustc_diagnostic_item = "ptr_null_mut"]
+#[cfg(not(bootstrap))]
+pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {
+    from_raw_parts_mut(0 as *mut (), ())
+}
+
 /// Forms a raw slice from a pointer and a length.
 ///
 /// The `len` argument is the number of **elements**, not the number of bytes.
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 5e5f8a5ab95..c4dc34fff97 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1023,6 +1023,26 @@ impl<T, E> Result<T, E> {
     /// let x: Result<u32, &str> = Err("emergency failure");
     /// x.expect("Testing expect"); // panics with `Testing expect: emergency failure`
     /// ```
+    ///
+    /// # Recommended Message Style
+    ///
+    /// We recommend that `expect` messages are used to describe the reason you
+    /// _expect_ the `Result` should be `Ok`.
+    ///
+    /// ```should_panic
+    /// let path = std::env::var("IMPORTANT_PATH")
+    ///     .expect("env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`");
+    /// ```
+    ///
+    /// **Hint**: If you're having trouble remembering how to phrase expect
+    /// error messages remember to focus on the word "should" as in "env
+    /// variable should be set by blah" or "the given binary should be available
+    /// and executable by the current user".
+    ///
+    /// For more detail on expect message styles and the reasoning behind our recommendation please
+    /// refer to the section on ["Common Message
+    /// Styles"](../../std/error/index.html#common-message-styles) in the
+    /// [`std::error`](../../std/error/index.html) module docs.
     #[inline]
     #[track_caller]
     #[stable(feature = "result_expect", since = "1.4.0")]
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 6c97305b1a8..756f1a1663c 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -730,9 +730,9 @@ impl Duration {
     /// // subnormal float
     /// let res = Duration::from_secs_f64(f64::from_bits(1));
     /// assert_eq!(res, Duration::new(0, 0));
-    /// // conversion uses truncation, not rounding
+    /// // conversion uses rounding
     /// let res = Duration::from_secs_f64(0.999e-9);
-    /// assert_eq!(res, Duration::new(0, 0));
+    /// assert_eq!(res, Duration::new(0, 1));
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[must_use]
@@ -760,17 +760,17 @@ impl Duration {
     /// let res = Duration::from_secs_f32(1e-20);
     /// assert_eq!(res, Duration::new(0, 0));
     /// let res = Duration::from_secs_f32(4.2e-7);
-    /// assert_eq!(res, Duration::new(0, 419));
+    /// assert_eq!(res, Duration::new(0, 420));
     /// let res = Duration::from_secs_f32(2.7);
-    /// assert_eq!(res, Duration::new(2, 700_000_047));
+    /// assert_eq!(res, Duration::new(2, 700_000_048));
     /// let res = Duration::from_secs_f32(3e10);
     /// assert_eq!(res, Duration::new(30_000_001_024, 0));
     /// // subnormal float
     /// let res = Duration::from_secs_f32(f32::from_bits(1));
     /// assert_eq!(res, Duration::new(0, 0));
-    /// // conversion uses truncation, not rounding
+    /// // conversion uses rounding
     /// let res = Duration::from_secs_f32(0.999e-9);
-    /// assert_eq!(res, Duration::new(0, 0));
+    /// assert_eq!(res, Duration::new(0, 1));
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[must_use]
@@ -815,7 +815,7 @@ impl Duration {
     /// use std::time::Duration;
     ///
     /// let dur = Duration::new(2, 700_000_000);
-    /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_640));
+    /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_641));
     /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847800, 0));
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
@@ -838,8 +838,7 @@ impl Duration {
     ///
     /// let dur = Duration::new(2, 700_000_000);
     /// assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611));
-    /// // note that truncation is used, not rounding
-    /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_598));
+    /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_599));
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[must_use = "this returns the result of the operation, \
@@ -862,9 +861,8 @@ impl Duration {
     /// let dur = Duration::new(2, 700_000_000);
     /// // note that due to rounding errors result is slightly
     /// // different from 0.859_872_611
-    /// assert_eq!(dur.div_f32(3.14), Duration::new(0, 859_872_579));
-    /// // note that truncation is used, not rounding
-    /// assert_eq!(dur.div_f32(3.14e5), Duration::new(0, 8_598));
+    /// assert_eq!(dur.div_f32(3.14), Duration::new(0, 859_872_580));
+    /// assert_eq!(dur.div_f32(3.14e5), Duration::new(0, 8_599));
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[must_use = "this returns the result of the operation, \
@@ -1272,19 +1270,53 @@ macro_rules! try_from_secs {
         let mant = (bits & MANT_MASK) | (MANT_MASK + 1);
         let exp = ((bits >> $mant_bits) & EXP_MASK) as i16 + MIN_EXP;
 
-        let (secs, nanos) = if exp < -30 {
-            // the input represents less than 1ns.
+        let (secs, nanos) = if exp < -31 {
+            // the input represents less than 1ns and can not be rounded to it
             (0u64, 0u32)
         } else if exp < 0 {
             // the input is less than 1 second
             let t = <$double_ty>::from(mant) << ($offset + exp);
-            let nanos = (u128::from(NANOS_PER_SEC) * u128::from(t)) >> ($mant_bits + $offset);
-            (0, nanos as u32)
+            let nanos_offset = $mant_bits + $offset;
+            let nanos_tmp = u128::from(NANOS_PER_SEC) * u128::from(t);
+            let nanos = (nanos_tmp >> nanos_offset) as u32;
+
+            let rem_mask = (1 << nanos_offset) - 1;
+            let rem_msb_mask = 1 << (nanos_offset - 1);
+            let rem = nanos_tmp & rem_mask;
+            let is_tie = rem == rem_msb_mask;
+            let is_even = (nanos & 1) == 0;
+            let rem_msb = nanos_tmp & rem_msb_mask == 0;
+            let add_ns = !(rem_msb || (is_even && is_tie));
+
+            // f32 does not have enough presicion to trigger the second branch
+            // since it can not represent numbers between 0.999_999_940_395 and 1.0.
+            let nanos = nanos + add_ns as u32;
+            if ($mant_bits == 23) || (nanos != NANOS_PER_SEC) { (0, nanos) } else { (1, 0) }
         } else if exp < $mant_bits {
-            let secs = mant >> ($mant_bits - exp);
+            let secs = u64::from(mant >> ($mant_bits - exp));
             let t = <$double_ty>::from((mant << exp) & MANT_MASK);
-            let nanos = (<$double_ty>::from(NANOS_PER_SEC) * t) >> $mant_bits;
-            (u64::from(secs), nanos as u32)
+            let nanos_offset = $mant_bits;
+            let nanos_tmp = <$double_ty>::from(NANOS_PER_SEC) * t;
+            let nanos = (nanos_tmp >> nanos_offset) as u32;
+
+            let rem_mask = (1 << nanos_offset) - 1;
+            let rem_msb_mask = 1 << (nanos_offset - 1);
+            let rem = nanos_tmp & rem_mask;
+            let is_tie = rem == rem_msb_mask;
+            let is_even = (nanos & 1) == 0;
+            let rem_msb = nanos_tmp & rem_msb_mask == 0;
+            let add_ns = !(rem_msb || (is_even && is_tie));
+
+            // f32 does not have enough presicion to trigger the second branch.
+            // For example, it can not represent numbers between 1.999_999_880...
+            // and 2.0. Bigger values result in even smaller presicion of the
+            // fractional part.
+            let nanos = nanos + add_ns as u32;
+            if ($mant_bits == 23) || (nanos != NANOS_PER_SEC) {
+                (secs, nanos)
+            } else {
+                (secs + 1, 0)
+            }
         } else if exp < 64 {
             // the input has no fractional part
             let secs = u64::from(mant) << (exp - $mant_bits);
@@ -1315,17 +1347,14 @@ impl Duration {
     /// let res = Duration::try_from_secs_f32(1e-20);
     /// assert_eq!(res, Ok(Duration::new(0, 0)));
     /// let res = Duration::try_from_secs_f32(4.2e-7);
-    /// assert_eq!(res, Ok(Duration::new(0, 419)));
+    /// assert_eq!(res, Ok(Duration::new(0, 420)));
     /// let res = Duration::try_from_secs_f32(2.7);
-    /// assert_eq!(res, Ok(Duration::new(2, 700_000_047)));
+    /// assert_eq!(res, Ok(Duration::new(2, 700_000_048)));
     /// let res = Duration::try_from_secs_f32(3e10);
     /// assert_eq!(res, Ok(Duration::new(30_000_001_024, 0)));
     /// // subnormal float:
     /// let res = Duration::try_from_secs_f32(f32::from_bits(1));
     /// assert_eq!(res, Ok(Duration::new(0, 0)));
-    /// // conversion uses truncation, not rounding
-    /// let res = Duration::try_from_secs_f32(0.999e-9);
-    /// assert_eq!(res, Ok(Duration::new(0, 0)));
     ///
     /// let res = Duration::try_from_secs_f32(-5.0);
     /// assert!(res.is_err());
@@ -1333,6 +1362,30 @@ impl Duration {
     /// assert!(res.is_err());
     /// let res = Duration::try_from_secs_f32(2e19);
     /// assert!(res.is_err());
+    ///
+    /// // the conversion uses rounding with tie resolution to even
+    /// let res = Duration::try_from_secs_f32(0.999e-9);
+    /// assert_eq!(res, Ok(Duration::new(0, 1)));
+    ///
+    /// // this float represents exactly 976562.5e-9
+    /// let val = f32::from_bits(0x3A80_0000);
+    /// let res = Duration::try_from_secs_f32(val);
+    /// assert_eq!(res, Ok(Duration::new(0, 976_562)));
+    ///
+    /// // this float represents exactly 2929687.5e-9
+    /// let val = f32::from_bits(0x3B40_0000);
+    /// let res = Duration::try_from_secs_f32(val);
+    /// assert_eq!(res, Ok(Duration::new(0, 2_929_688)));
+    ///
+    /// // this float represents exactly 1.000_976_562_5
+    /// let val = f32::from_bits(0x3F802000);
+    /// let res = Duration::try_from_secs_f32(val);
+    /// assert_eq!(res, Ok(Duration::new(1, 976_562)));
+    ///
+    /// // this float represents exactly 1.002_929_687_5
+    /// let val = f32::from_bits(0x3F806000);
+    /// let res = Duration::try_from_secs_f32(val);
+    /// assert_eq!(res, Ok(Duration::new(1, 2_929_688)));
     /// ```
     #[unstable(feature = "duration_checked_float", issue = "83400")]
     #[inline]
@@ -1372,9 +1425,6 @@ impl Duration {
     /// // subnormal float
     /// let res = Duration::try_from_secs_f64(f64::from_bits(1));
     /// assert_eq!(res, Ok(Duration::new(0, 0)));
-    /// // conversion uses truncation, not rounding
-    /// let res = Duration::try_from_secs_f32(0.999e-9);
-    /// assert_eq!(res, Ok(Duration::new(0, 0)));
     ///
     /// let res = Duration::try_from_secs_f64(-5.0);
     /// assert!(res.is_err());
@@ -1382,6 +1432,38 @@ impl Duration {
     /// assert!(res.is_err());
     /// let res = Duration::try_from_secs_f64(2e19);
     /// assert!(res.is_err());
+    ///
+    /// // the conversion uses rounding with tie resolution to even
+    /// let res = Duration::try_from_secs_f64(0.999e-9);
+    /// assert_eq!(res, Ok(Duration::new(0, 1)));
+    /// let res = Duration::try_from_secs_f64(0.999_999_999_499);
+    /// assert_eq!(res, Ok(Duration::new(0, 999_999_999)));
+    /// let res = Duration::try_from_secs_f64(0.999_999_999_501);
+    /// assert_eq!(res, Ok(Duration::new(1, 0)));
+    /// let res = Duration::try_from_secs_f64(42.999_999_999_499);
+    /// assert_eq!(res, Ok(Duration::new(42, 999_999_999)));
+    /// let res = Duration::try_from_secs_f64(42.999_999_999_501);
+    /// assert_eq!(res, Ok(Duration::new(43, 0)));
+    ///
+    /// // this float represents exactly 976562.5e-9
+    /// let val = f64::from_bits(0x3F50_0000_0000_0000);
+    /// let res = Duration::try_from_secs_f64(val);
+    /// assert_eq!(res, Ok(Duration::new(0, 976_562)));
+    ///
+    /// // this float represents exactly 2929687.5e-9
+    /// let val = f64::from_bits(0x3F68_0000_0000_0000);
+    /// let res = Duration::try_from_secs_f64(val);
+    /// assert_eq!(res, Ok(Duration::new(0, 2_929_688)));
+    ///
+    /// // this float represents exactly 1.000_976_562_5
+    /// let val = f64::from_bits(0x3FF0_0400_0000_0000);
+    /// let res = Duration::try_from_secs_f64(val);
+    /// assert_eq!(res, Ok(Duration::new(1, 976_562)));
+    ///
+    /// // this float represents exactly 1.002_929_687_5
+    /// let val = f64::from_bits(0x3_FF00_C000_0000_000);
+    /// let res = Duration::try_from_secs_f64(val);
+    /// assert_eq!(res, Ok(Duration::new(1, 2_929_688)));
     /// ```
     #[unstable(feature = "duration_checked_float", issue = "83400")]
     #[inline]
diff --git a/library/core/tests/asserting.rs b/library/core/tests/asserting.rs
new file mode 100644
index 00000000000..4b626ba6f2d
--- /dev/null
+++ b/library/core/tests/asserting.rs
@@ -0,0 +1,37 @@
+use core::asserting::{Capture, TryCaptureGeneric, TryCapturePrintable, Wrapper};
+
+macro_rules! test {
+    ($test_name:ident, $elem:expr, $captured_elem:expr, $output:literal) => {
+        #[test]
+        fn $test_name() {
+            let elem = $elem;
+            let mut capture = Capture::new();
+            assert!(capture.elem == None);
+            (&Wrapper(&elem)).try_capture(&mut capture);
+            assert!(capture.elem == $captured_elem);
+            assert_eq!(format!("{:?}", capture), $output);
+        }
+    };
+}
+
+#[derive(Debug, PartialEq)]
+struct NoCopy;
+
+#[derive(PartialEq)]
+struct NoCopyNoDebug;
+
+#[derive(Clone, Copy, PartialEq)]
+struct NoDebug;
+
+test!(
+    capture_with_non_copyable_and_non_debugabble_elem_has_correct_params,
+    NoCopyNoDebug,
+    None,
+    "N/A"
+);
+
+test!(capture_with_non_copyable_elem_has_correct_params, NoCopy, None, "N/A");
+
+test!(capture_with_non_debugabble_elem_has_correct_params, NoDebug, None, "N/A");
+
+test!(capture_with_copyable_and_debugabble_elem_has_correct_params, 1i32, Some(1i32), "1");
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 004589bbc31..9ea374e1045 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -35,6 +35,7 @@
 #![feature(float_minimum_maximum)]
 #![feature(future_join)]
 #![feature(future_poll_fn)]
+#![feature(generic_assert_internals)]
 #![feature(array_try_from_fn)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
@@ -104,6 +105,7 @@ mod alloc;
 mod any;
 mod array;
 mod ascii;
+mod asserting;
 mod atomic;
 mod bool;
 mod cell;
diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
index 03fe56022b0..c5242ad04de 100644
--- a/library/core/tests/ptr.rs
+++ b/library/core/tests/ptr.rs
@@ -93,6 +93,18 @@ fn test_is_null() {
 
     let nmi: *mut dyn ToString = null_mut::<isize>();
     assert!(nmi.is_null());
+
+    #[cfg(not(bootstrap))]
+    {
+        extern "C" {
+            type Extern;
+        }
+        let ec: *const Extern = null::<Extern>();
+        assert!(ec.is_null());
+
+        let em: *mut Extern = null_mut::<Extern>();
+        assert!(em.is_null());
+    }
 }
 
 #[test]
diff --git a/library/proc_macro/src/bridge/buffer.rs b/library/proc_macro/src/bridge/buffer.rs
index d82669d3e23..fb05a02dc45 100644
--- a/library/proc_macro/src/bridge/buffer.rs
+++ b/library/proc_macro/src/bridge/buffer.rs
@@ -6,37 +6,37 @@ use std::ops::{Deref, DerefMut};
 use std::slice;
 
 #[repr(C)]
-pub struct Buffer<T: Copy> {
-    data: *mut T,
+pub struct Buffer {
+    data: *mut u8,
     len: usize,
     capacity: usize,
-    reserve: extern "C" fn(Buffer<T>, usize) -> Buffer<T>,
-    drop: extern "C" fn(Buffer<T>),
+    reserve: extern "C" fn(Buffer, usize) -> Buffer,
+    drop: extern "C" fn(Buffer),
 }
 
-unsafe impl<T: Copy + Sync> Sync for Buffer<T> {}
-unsafe impl<T: Copy + Send> Send for Buffer<T> {}
+unsafe impl Sync for Buffer {}
+unsafe impl Send for Buffer {}
 
-impl<T: Copy> Default for Buffer<T> {
+impl Default for Buffer {
     fn default() -> Self {
         Self::from(vec![])
     }
 }
 
-impl<T: Copy> Deref for Buffer<T> {
-    type Target = [T];
-    fn deref(&self) -> &[T] {
-        unsafe { slice::from_raw_parts(self.data as *const T, self.len) }
+impl Deref for Buffer {
+    type Target = [u8];
+    fn deref(&self) -> &[u8] {
+        unsafe { slice::from_raw_parts(self.data as *const u8, self.len) }
     }
 }
 
-impl<T: Copy> DerefMut for Buffer<T> {
-    fn deref_mut(&mut self) -> &mut [T] {
+impl DerefMut for Buffer {
+    fn deref_mut(&mut self) -> &mut [u8] {
         unsafe { slice::from_raw_parts_mut(self.data, self.len) }
     }
 }
 
-impl<T: Copy> Buffer<T> {
+impl Buffer {
     pub(super) fn new() -> Self {
         Self::default()
     }
@@ -53,7 +53,7 @@ impl<T: Copy> Buffer<T> {
     // because in the case of small arrays, codegen can be more efficient
     // (avoiding a memmove call). With extend_from_slice, LLVM at least
     // currently is not able to make that optimization.
-    pub(super) fn extend_from_array<const N: usize>(&mut self, xs: &[T; N]) {
+    pub(super) fn extend_from_array<const N: usize>(&mut self, xs: &[u8; N]) {
         if xs.len() > (self.capacity - self.len) {
             let b = self.take();
             *self = (b.reserve)(b, xs.len());
@@ -64,7 +64,7 @@ impl<T: Copy> Buffer<T> {
         }
     }
 
-    pub(super) fn extend_from_slice(&mut self, xs: &[T]) {
+    pub(super) fn extend_from_slice(&mut self, xs: &[u8]) {
         if xs.len() > (self.capacity - self.len) {
             let b = self.take();
             *self = (b.reserve)(b, xs.len());
@@ -75,7 +75,7 @@ impl<T: Copy> Buffer<T> {
         }
     }
 
-    pub(super) fn push(&mut self, v: T) {
+    pub(super) fn push(&mut self, v: u8) {
         // The code here is taken from Vec::push, and we know that reserve()
         // will panic if we're exceeding isize::MAX bytes and so there's no need
         // to check for overflow.
@@ -90,7 +90,7 @@ impl<T: Copy> Buffer<T> {
     }
 }
 
-impl Write for Buffer<u8> {
+impl Write for Buffer {
     fn write(&mut self, xs: &[u8]) -> io::Result<usize> {
         self.extend_from_slice(xs);
         Ok(xs.len())
@@ -106,21 +106,21 @@ impl Write for Buffer<u8> {
     }
 }
 
-impl<T: Copy> Drop for Buffer<T> {
+impl Drop for Buffer {
     fn drop(&mut self) {
         let b = self.take();
         (b.drop)(b);
     }
 }
 
-impl<T: Copy> From<Vec<T>> for Buffer<T> {
-    fn from(mut v: Vec<T>) -> Self {
+impl From<Vec<u8>> for Buffer {
+    fn from(mut v: Vec<u8>) -> Self {
         let (data, len, capacity) = (v.as_mut_ptr(), v.len(), v.capacity());
         mem::forget(v);
 
         // This utility function is nested in here because it can *only*
         // be safely called on `Buffer`s created by *this* `proc_macro`.
-        fn to_vec<T: Copy>(b: Buffer<T>) -> Vec<T> {
+        fn to_vec(b: Buffer) -> Vec<u8> {
             unsafe {
                 let Buffer { data, len, capacity, .. } = b;
                 mem::forget(b);
@@ -128,13 +128,13 @@ impl<T: Copy> From<Vec<T>> for Buffer<T> {
             }
         }
 
-        extern "C" fn reserve<T: Copy>(b: Buffer<T>, additional: usize) -> Buffer<T> {
+        extern "C" fn reserve(b: Buffer, additional: usize) -> Buffer {
             let mut v = to_vec(b);
             v.reserve(additional);
             Buffer::from(v)
         }
 
-        extern "C" fn drop<T: Copy>(b: Buffer<T>) {
+        extern "C" fn drop(b: Buffer) {
             mem::drop(to_vec(b));
         }
 
diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs
index cdb2bac2607..54d92ff5767 100644
--- a/library/proc_macro/src/bridge/client.rs
+++ b/library/proc_macro/src/bridge/client.rs
@@ -49,7 +49,9 @@ macro_rules! define_handles {
             #[repr(C)]
             pub(crate) struct $oty {
                 handle: handle::Handle,
-                // Prevent Send and Sync impls
+                // Prevent Send and Sync impls. `!Send`/`!Sync` is the usual
+                // way of doing this, but that requires unstable features.
+                // rust-analyzer uses this code and avoids unstable features.
                 _marker: PhantomData<*mut ()>,
             }
 
@@ -133,7 +135,9 @@ macro_rules! define_handles {
             #[derive(Copy, Clone, PartialEq, Eq, Hash)]
             pub(crate) struct $ity {
                 handle: handle::Handle,
-                // Prevent Send and Sync impls
+                // Prevent Send and Sync impls. `!Send`/`!Sync` is the usual
+                // way of doing this, but that requires unstable features.
+                // rust-analyzer uses this code and avoids unstable features.
                 _marker: PhantomData<*mut ()>,
             }
 
@@ -191,7 +195,7 @@ define_handles! {
 // FIXME(eddyb) generate these impls by pattern-matching on the
 // names of methods - also could use the presence of `fn drop`
 // to distinguish between 'owned and 'interned, above.
-// Alternatively, special 'modes" could be listed of types in with_api
+// Alternatively, special "modes" could be listed of types in with_api
 // instead of pattern matching on methods, here and in server decl.
 
 impl Clone for TokenStream {
@@ -250,17 +254,17 @@ macro_rules! define_client_side {
         $(impl $name {
             $(pub(crate) fn $method($($arg: $arg_ty),*) $(-> $ret_ty)* {
                 Bridge::with(|bridge| {
-                    let mut b = bridge.cached_buffer.take();
+                    let mut buf = bridge.cached_buffer.take();
 
-                    b.clear();
-                    api_tags::Method::$name(api_tags::$name::$method).encode(&mut b, &mut ());
-                    reverse_encode!(b; $($arg),*);
+                    buf.clear();
+                    api_tags::Method::$name(api_tags::$name::$method).encode(&mut buf, &mut ());
+                    reverse_encode!(buf; $($arg),*);
 
-                    b = bridge.dispatch.call(b);
+                    buf = bridge.dispatch.call(buf);
 
-                    let r = Result::<_, PanicMessage>::decode(&mut &b[..], &mut ());
+                    let r = Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
 
-                    bridge.cached_buffer = b;
+                    bridge.cached_buffer = buf;
 
                     r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
                 })
@@ -367,7 +371,7 @@ pub struct Client<F> {
     // FIXME(eddyb) use a reference to the `static COUNTERS`, instead of
     // a wrapper `fn` pointer, once `const fn` can reference `static`s.
     pub(super) get_handle_counters: extern "C" fn() -> &'static HandleCounters,
-    pub(super) run: extern "C" fn(Bridge<'_>, F) -> Buffer<u8>,
+    pub(super) run: extern "C" fn(Bridge<'_>, F) -> Buffer,
     pub(super) f: F,
 }
 
@@ -377,22 +381,22 @@ pub struct Client<F> {
 fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
     mut bridge: Bridge<'_>,
     f: impl FnOnce(A) -> R,
-) -> Buffer<u8> {
+) -> Buffer {
     // The initial `cached_buffer` contains the input.
-    let mut b = bridge.cached_buffer.take();
+    let mut buf = bridge.cached_buffer.take();
 
     panic::catch_unwind(panic::AssertUnwindSafe(|| {
         bridge.enter(|| {
-            let reader = &mut &b[..];
+            let reader = &mut &buf[..];
             let input = A::decode(reader, &mut ());
 
             // Put the `cached_buffer` back in the `Bridge`, for requests.
-            Bridge::with(|bridge| bridge.cached_buffer = b.take());
+            Bridge::with(|bridge| bridge.cached_buffer = buf.take());
 
             let output = f(input);
 
             // Take the `cached_buffer` back out, for the output value.
-            b = Bridge::with(|bridge| bridge.cached_buffer.take());
+            buf = Bridge::with(|bridge| bridge.cached_buffer.take());
 
             // HACK(eddyb) Separate encoding a success value (`Ok(output)`)
             // from encoding a panic (`Err(e: PanicMessage)`) to avoid
@@ -403,16 +407,16 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
             // this is defensively trying to avoid any accidental panicking
             // reaching the `extern "C"` (which should `abort` but might not
             // at the moment, so this is also potentially preventing UB).
-            b.clear();
-            Ok::<_, ()>(output).encode(&mut b, &mut ());
+            buf.clear();
+            Ok::<_, ()>(output).encode(&mut buf, &mut ());
         })
     }))
     .map_err(PanicMessage::from)
     .unwrap_or_else(|e| {
-        b.clear();
-        Err::<(), _>(e).encode(&mut b, &mut ());
+        buf.clear();
+        Err::<(), _>(e).encode(&mut buf, &mut ());
     });
-    b
+    buf
 }
 
 impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
@@ -420,7 +424,7 @@ impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
         extern "C" fn run(
             bridge: Bridge<'_>,
             f: impl FnOnce(crate::TokenStream) -> crate::TokenStream,
-        ) -> Buffer<u8> {
+        ) -> Buffer {
             run_client(bridge, |input| f(crate::TokenStream(input)).0)
         }
         Client { get_handle_counters: HandleCounters::get, run, f }
@@ -434,7 +438,7 @@ impl Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
         extern "C" fn run(
             bridge: Bridge<'_>,
             f: impl FnOnce(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
-        ) -> Buffer<u8> {
+        ) -> Buffer {
             run_client(bridge, |(input, input2)| {
                 f(crate::TokenStream(input), crate::TokenStream(input2)).0
             })
diff --git a/library/proc_macro/src/bridge/closure.rs b/library/proc_macro/src/bridge/closure.rs
index 06f76d2fc91..d371ae3cea0 100644
--- a/library/proc_macro/src/bridge/closure.rs
+++ b/library/proc_macro/src/bridge/closure.rs
@@ -6,7 +6,11 @@ use std::marker::PhantomData;
 pub struct Closure<'a, A, R> {
     call: unsafe extern "C" fn(*mut Env, A) -> R,
     env: *mut Env,
-    // Ensure Closure is !Send and !Sync
+    // Prevent Send and Sync impls. `!Send`/`!Sync` is the usual way of doing
+    // this, but that requires unstable features. rust-analyzer uses this code
+    // and avoids unstable features.
+    //
+    // The `'a` lifetime parameter represents the lifetime of `Env`.
     _marker: PhantomData<*mut &'a mut ()>,
 }
 
diff --git a/library/proc_macro/src/bridge/handle.rs b/library/proc_macro/src/bridge/handle.rs
index bcbb8681247..7d6adda48ec 100644
--- a/library/proc_macro/src/bridge/handle.rs
+++ b/library/proc_macro/src/bridge/handle.rs
@@ -8,6 +8,8 @@ use std::sync::atomic::{AtomicUsize, Ordering};
 
 pub(super) type Handle = NonZeroU32;
 
+/// A store that associates values of type `T` with numeric handles. A value can
+/// be looked up using its handle.
 pub(super) struct OwnedStore<T: 'static> {
     counter: &'static AtomicUsize,
     data: BTreeMap<Handle, T>,
@@ -49,6 +51,7 @@ impl<T> IndexMut<Handle> for OwnedStore<T> {
     }
 }
 
+/// Like `OwnedStore`, but avoids storing any value more than once.
 pub(super) struct InternedStore<T: 'static> {
     owned: OwnedStore<T>,
     interner: HashMap<T, Handle>,
diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs
index f7c9df6564f..babb1cbac70 100644
--- a/library/proc_macro/src/bridge/mod.rs
+++ b/library/proc_macro/src/bridge/mod.rs
@@ -176,7 +176,7 @@ macro_rules! with_api {
 }
 
 // FIXME(eddyb) this calls `encode` for each argument, but in reverse,
-// to avoid borrow conflicts from borrows started by `&mut` arguments.
+// to match the ordering in `reverse_decode`.
 macro_rules! reverse_encode {
     ($writer:ident;) => {};
     ($writer:ident; $first:ident $(, $rest:ident)*) => {
@@ -224,15 +224,17 @@ use rpc::{Decode, DecodeMut, Encode, Reader, Writer};
 pub struct Bridge<'a> {
     /// Reusable buffer (only `clear`-ed, never shrunk), primarily
     /// used for making requests, but also for passing input to client.
-    cached_buffer: Buffer<u8>,
+    cached_buffer: Buffer,
 
     /// Server-side function that the client uses to make requests.
-    dispatch: closure::Closure<'a, Buffer<u8>, Buffer<u8>>,
+    dispatch: closure::Closure<'a, Buffer, Buffer>,
 
     /// If 'true', always invoke the default panic hook
     force_show_panics: bool,
 
-    // Prevent Send and Sync impls
+    // Prevent Send and Sync impls. `!Send`/`!Sync` is the usual way of doing
+    // this, but that requires unstable features. rust-analyzer uses this code
+    // and avoids unstable features.
     _marker: marker::PhantomData<*mut ()>,
 }
 
@@ -252,7 +254,6 @@ mod api_tags {
                 rpc_encode_decode!(enum $name { $($method),* });
             )*
 
-
             pub(super) enum Method {
                 $($name($name)),*
             }
diff --git a/library/proc_macro/src/bridge/rpc.rs b/library/proc_macro/src/bridge/rpc.rs
index d50564d01a5..f79e016400f 100644
--- a/library/proc_macro/src/bridge/rpc.rs
+++ b/library/proc_macro/src/bridge/rpc.rs
@@ -7,7 +7,7 @@ use std::num::NonZeroU32;
 use std::ops::Bound;
 use std::str;
 
-pub(super) type Writer = super::buffer::Buffer<u8>;
+pub(super) type Writer = super::buffer::Buffer;
 
 pub(super) trait Encode<S>: Sized {
     fn encode(self, w: &mut Writer, s: &mut S);
diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs
index 2e0400d32a0..12c754682a0 100644
--- a/library/proc_macro/src/bridge/server.rs
+++ b/library/proc_macro/src/bridge/server.rs
@@ -5,37 +5,30 @@ use super::*;
 // FIXME(eddyb) generate the definition of `HandleStore` in `server.rs`.
 use super::client::HandleStore;
 
-/// Declare an associated item of one of the traits below, optionally
-/// adjusting it (i.e., adding bounds to types and default bodies to methods).
-macro_rules! associated_item {
-    (type FreeFunctions) =>
-        (type FreeFunctions: 'static;);
-    (type TokenStream) =>
-        (type TokenStream: 'static + Clone;);
-    (type TokenStreamBuilder) =>
-        (type TokenStreamBuilder: 'static;);
-    (type TokenStreamIter) =>
-        (type TokenStreamIter: 'static + Clone;);
-    (type Group) =>
-        (type Group: 'static + Clone;);
-    (type Punct) =>
-        (type Punct: 'static + Copy + Eq + Hash;);
-    (type Ident) =>
-        (type Ident: 'static + Copy + Eq + Hash;);
-    (type Literal) =>
-        (type Literal: 'static + Clone;);
-    (type SourceFile) =>
-        (type SourceFile: 'static + Clone;);
-    (type MultiSpan) =>
-        (type MultiSpan: 'static;);
-    (type Diagnostic) =>
-        (type Diagnostic: 'static;);
-    (type Span) =>
-        (type Span: 'static + Copy + Eq + Hash;);
+pub trait Types {
+    type FreeFunctions: 'static;
+    type TokenStream: 'static + Clone;
+    type TokenStreamBuilder: 'static;
+    type TokenStreamIter: 'static + Clone;
+    type Group: 'static + Clone;
+    type Punct: 'static + Copy + Eq + Hash;
+    type Ident: 'static + Copy + Eq + Hash;
+    type Literal: 'static + Clone;
+    type SourceFile: 'static + Clone;
+    type MultiSpan: 'static;
+    type Diagnostic: 'static;
+    type Span: 'static + Copy + Eq + Hash;
+}
+
+/// Declare an associated fn of one of the traits below, adding necessary
+/// default bodies.
+macro_rules! associated_fn {
     (fn drop(&mut self, $arg:ident: $arg_ty:ty)) =>
         (fn drop(&mut self, $arg: $arg_ty) { mem::drop($arg) });
+
     (fn clone(&mut self, $arg:ident: $arg_ty:ty) -> $ret_ty:ty) =>
         (fn clone(&mut self, $arg: $arg_ty) -> $ret_ty { $arg.clone() });
+
     ($($item:tt)*) => ($($item)*;)
 }
 
@@ -43,12 +36,8 @@ macro_rules! declare_server_traits {
     ($($name:ident {
         $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)*
     }),* $(,)?) => {
-        pub trait Types {
-            $(associated_item!(type $name);)*
-        }
-
         $(pub trait $name: Types {
-            $(associated_item!(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?);)*
+            $(associated_fn!(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?);)*
         })*
 
         pub trait Server: Types $(+ $name)* {}
@@ -89,15 +78,15 @@ macro_rules! define_dispatcher_impl {
         pub trait DispatcherTrait {
             // HACK(eddyb) these are here to allow `Self::$name` to work below.
             $(type $name;)*
-            fn dispatch(&mut self, b: Buffer<u8>) -> Buffer<u8>;
+            fn dispatch(&mut self, buf: Buffer) -> Buffer;
         }
 
         impl<S: Server> DispatcherTrait for Dispatcher<MarkedTypes<S>> {
             $(type $name = <MarkedTypes<S> as Types>::$name;)*
-            fn dispatch(&mut self, mut b: Buffer<u8>) -> Buffer<u8> {
+            fn dispatch(&mut self, mut buf: Buffer) -> Buffer {
                 let Dispatcher { handle_store, server } = self;
 
-                let mut reader = &b[..];
+                let mut reader = &buf[..];
                 match api_tags::Method::decode(&mut reader, &mut ()) {
                     $(api_tags::Method::$name(m) => match m {
                         $(api_tags::$name::$method => {
@@ -116,12 +105,12 @@ macro_rules! define_dispatcher_impl {
                                     .map_err(PanicMessage::from)
                             };
 
-                            b.clear();
-                            r.encode(&mut b, handle_store);
+                            buf.clear();
+                            r.encode(&mut buf, handle_store);
                         })*
                     }),*
                 }
-                b
+                buf
             }
         }
     }
@@ -132,11 +121,11 @@ pub trait ExecutionStrategy {
     fn run_bridge_and_client<D: Copy + Send + 'static>(
         &self,
         dispatcher: &mut impl DispatcherTrait,
-        input: Buffer<u8>,
-        run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
+        input: Buffer,
+        run_client: extern "C" fn(Bridge<'_>, D) -> Buffer,
         client_data: D,
         force_show_panics: bool,
-    ) -> Buffer<u8>;
+    ) -> Buffer;
 }
 
 pub struct SameThread;
@@ -145,12 +134,12 @@ impl ExecutionStrategy for SameThread {
     fn run_bridge_and_client<D: Copy + Send + 'static>(
         &self,
         dispatcher: &mut impl DispatcherTrait,
-        input: Buffer<u8>,
-        run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
+        input: Buffer,
+        run_client: extern "C" fn(Bridge<'_>, D) -> Buffer,
         client_data: D,
         force_show_panics: bool,
-    ) -> Buffer<u8> {
-        let mut dispatch = |b| dispatcher.dispatch(b);
+    ) -> Buffer {
+        let mut dispatch = |buf| dispatcher.dispatch(buf);
 
         run_client(
             Bridge {
@@ -173,19 +162,19 @@ impl ExecutionStrategy for CrossThread1 {
     fn run_bridge_and_client<D: Copy + Send + 'static>(
         &self,
         dispatcher: &mut impl DispatcherTrait,
-        input: Buffer<u8>,
-        run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
+        input: Buffer,
+        run_client: extern "C" fn(Bridge<'_>, D) -> Buffer,
         client_data: D,
         force_show_panics: bool,
-    ) -> Buffer<u8> {
+    ) -> Buffer {
         use std::sync::mpsc::channel;
 
         let (req_tx, req_rx) = channel();
         let (res_tx, res_rx) = channel();
 
         let join_handle = thread::spawn(move || {
-            let mut dispatch = |b| {
-                req_tx.send(b).unwrap();
+            let mut dispatch = |buf| {
+                req_tx.send(buf).unwrap();
                 res_rx.recv().unwrap()
             };
 
@@ -214,11 +203,11 @@ impl ExecutionStrategy for CrossThread2 {
     fn run_bridge_and_client<D: Copy + Send + 'static>(
         &self,
         dispatcher: &mut impl DispatcherTrait,
-        input: Buffer<u8>,
-        run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
+        input: Buffer,
+        run_client: extern "C" fn(Bridge<'_>, D) -> Buffer,
         client_data: D,
         force_show_panics: bool,
-    ) -> Buffer<u8> {
+    ) -> Buffer {
         use std::sync::{Arc, Mutex};
 
         enum State<T> {
@@ -285,25 +274,25 @@ fn run_server<
     handle_counters: &'static client::HandleCounters,
     server: S,
     input: I,
-    run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
+    run_client: extern "C" fn(Bridge<'_>, D) -> Buffer,
     client_data: D,
     force_show_panics: bool,
 ) -> Result<O, PanicMessage> {
     let mut dispatcher =
         Dispatcher { handle_store: HandleStore::new(handle_counters), server: MarkedTypes(server) };
 
-    let mut b = Buffer::new();
-    input.encode(&mut b, &mut dispatcher.handle_store);
+    let mut buf = Buffer::new();
+    input.encode(&mut buf, &mut dispatcher.handle_store);
 
-    b = strategy.run_bridge_and_client(
+    buf = strategy.run_bridge_and_client(
         &mut dispatcher,
-        b,
+        buf,
         run_client,
         client_data,
         force_show_panics,
     );
 
-    Result::decode(&mut &b[..], &mut dispatcher.handle_store)
+    Result::decode(&mut &buf[..], &mut dispatcher.handle_store)
 }
 
 impl client::Client<fn(crate::TokenStream) -> crate::TokenStream> {
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index 438304e1664..c2d30616019 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -1,4 +1,140 @@
-//! Traits for working with Errors.
+//! Interfaces for working with Errors.
+//!
+//! # Error Handling In Rust
+//!
+//! The Rust language provides two complementary systems for constructing /
+//! representing, reporting, propagating, reacting to, and discarding errors.
+//! These responsibilities are collectively known as "error handling." The
+//! components of the first system, the panic runtime and interfaces, are most
+//! commonly used to represent bugs that have been detected in your program. The
+//! components of the second system, `Result`, the error traits, and user
+//! defined types, are used to represent anticipated runtime failure modes of
+//! your program.
+//!
+//! ## The Panic Interfaces
+//!
+//! The following are the primary interfaces of the panic system and the
+//! responsibilities they cover:
+//!
+//! * [`panic!`] and [`panic_any`] (Constructing, Propagated automatically)
+//! * [`PanicInfo`] (Reporting)
+//! * [`set_hook`], [`take_hook`], and [`#[panic_handler]`][panic-handler] (Reporting)
+//! * [`catch_unwind`] and [`resume_unwind`] (Discarding, Propagating)
+//!
+//! The following are the primary interfaces of the error system and the
+//! responsibilities they cover:
+//!
+//! * [`Result`] (Propagating, Reacting)
+//! * The [`Error`] trait (Reporting)
+//! * User defined types (Constructing / Representing)
+//! * [`match`] and [`downcast`] (Reacting)
+//! * The question mark operator ([`?`]) (Propagating)
+//! * The partially stable [`Try`] traits (Propagating, Constructing)
+//! * [`Termination`] (Reporting)
+//!
+//! ## Converting Errors into Panics
+//!
+//! The panic and error systems are not entirely distinct. Often times errors
+//! that are anticipated runtime failures in an API might instead represent bugs
+//! to a caller. For these situations the standard library provides APIs for
+//! constructing panics with an `Error` as it's source.
+//!
+//! * [`Result::unwrap`]
+//! * [`Result::expect`]
+//!
+//! These functions are equivalent, they either return the inner value if the
+//! `Result` is `Ok` or panic if the `Result` is `Err` printing the inner error
+//! as the source. The only difference between them is that with `expect` you
+//! provide a panic error message to be printed alongside the source, whereas
+//! `unwrap` has a default message indicating only that you unwraped an `Err`.
+//!
+//! Of the two, `expect` is generally preferred since its `msg` field allows you
+//! to convey your intent and assumptions which makes tracking down the source
+//! of a panic easier. `unwrap` on the other hand can still be a good fit in
+//! situations where you can trivially show that a piece of code will never
+//! panick, such as `"127.0.0.1".parse::<std::net::IpAddr>().unwrap()` or early
+//! prototyping.
+//!
+//! # Common Message Styles
+//!
+//! There are two common styles for how people word `expect` messages. Using
+//! the message to present information to users encountering a panic
+//! ("expect as error message") or using the message to present information
+//! to developers debugging the panic ("expect as precondition").
+//!
+//! In the former case the expect message is used to describe the error that
+//! has occurred which is considered a bug. Consider the following example:
+//!
+//! ```should_panic
+//! // Read environment variable, panic if it is not present
+//! let path = std::env::var("IMPORTANT_PATH").unwrap();
+//! ```
+//!
+//! In the "expect as error message" style we would use expect to describe
+//! that the environment variable was not set when it should have been:
+//!
+//! ```should_panic
+//! let path = std::env::var("IMPORTANT_PATH")
+//!     .expect("env variable `IMPORTANT_PATH` is not set");
+//! ```
+//!
+//! In the "expect as precondition" style, we would instead describe the
+//! reason we _expect_ the `Result` should be `Ok`. With this style we would
+//! prefer to write:
+//!
+//! ```should_panic
+//! let path = std::env::var("IMPORTANT_PATH")
+//!     .expect("env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`");
+//! ```
+//!
+//! The "expect as error message" style does not work as well with the
+//! default output of the std panic hooks, and often ends up repeating
+//! information that is already communicated by the source error being
+//! unwrapped:
+//!
+//! ```text
+//! thread 'main' panicked at 'env variable `IMPORTANT_PATH` is not set: NotPresent', src/main.rs:4:6
+//! ```
+//!
+//! In this example we end up mentioning that an env variable is not set,
+//! followed by our source message that says the env is not present, the
+//! only additional information we're communicating is the name of the
+//! environment variable being checked.
+//!
+//! The "expect as precondition" style instead focuses on source code
+//! readability, making it easier to understand what must have gone wrong in
+//! situations where panics are being used to represent bugs exclusively.
+//! Also, by framing our expect in terms of what "SHOULD" have happened to
+//! prevent the source error, we end up introducing new information that is
+//! independent from our source error.
+//!
+//! ```text
+//! thread 'main' panicked at 'env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`: NotPresent', src/main.rs:4:6
+//! ```
+//!
+//! In this example we are communicating not only the name of the
+//! environment variable that should have been set, but also an explanation
+//! for why it should have been set, and we let the source error display as
+//! a clear contradiction to our expectation.
+//!
+//! **Hint**: If you're having trouble remembering how to phrase
+//! expect-as-precondition style error messages remember to focus on the word
+//! "should" as in "env variable should be set by blah" or "the given binary
+//! should be available and executable by the current user".
+//!
+//! [`panic_any`]: crate::panic::panic_any
+//! [`PanicInfo`]: crate::panic::PanicInfo
+//! [`catch_unwind`]: crate::panic::catch_unwind
+//! [`resume_unwind`]: crate::panic::resume_unwind
+//! [`downcast`]: crate::error::Error
+//! [`Termination`]: crate::process::Termination
+//! [`Try`]: crate::ops::Try
+//! [panic hook]: crate::panic::set_hook
+//! [`set_hook`]: crate::panic::set_hook
+//! [`take_hook`]: crate::panic::take_hook
+//! [panic-handler]: <https://doc.rust-lang.org/nomicon/panic-handler.html>
+//! [`match`]: ../../std/keyword.match.html
+//! [`?`]: ../../std/result/index.html#the-question-mark-operator-
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs
index 9e31b8b32a1..ecee123a9b6 100644
--- a/library/std/src/os/unix/net/ancillary.rs
+++ b/library/std/src/os/unix/net/ancillary.rs
@@ -1,3 +1,5 @@
+// FIXME: This is currently disabled on *BSD.
+
 use super::{sockaddr_un, SocketAddr};
 use crate::io::{self, IoSlice, IoSliceMut};
 use crate::marker::PhantomData;
diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs
index 872058b36e6..0b1d9b07132 100644
--- a/library/std/src/os/unix/net/datagram.rs
+++ b/library/std/src/os/unix/net/datagram.rs
@@ -1,24 +1,7 @@
-#[cfg(any(
-    doc,
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[cfg(any(doc, target_os = "android", target_os = "linux"))]
 use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary};
 use super::{sockaddr_un, SocketAddr};
-#[cfg(any(
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[cfg(any(doc, target_os = "android", target_os = "linux"))]
 use crate::io::{IoSlice, IoSliceMut};
 use crate::net::Shutdown;
 use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
@@ -403,7 +386,8 @@ impl UnixDatagram {
     ///
     /// # Examples
     ///
-    /// ```no_run
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")]
+    #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")]
     /// #![feature(unix_socket_ancillary_data)]
     /// use std::os::unix::net::{UnixDatagram, SocketAncillary, AncillaryData};
     /// use std::io::IoSliceMut;
@@ -433,15 +417,7 @@ impl UnixDatagram {
     ///     Ok(())
     /// }
     /// ```
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(doc, target_os = "android", target_os = "linux"))]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn recv_vectored_with_ancillary_from(
         &self,
@@ -460,7 +436,8 @@ impl UnixDatagram {
     ///
     /// # Examples
     ///
-    /// ```no_run
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")]
+    #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")]
     /// #![feature(unix_socket_ancillary_data)]
     /// use std::os::unix::net::{UnixDatagram, SocketAncillary, AncillaryData};
     /// use std::io::IoSliceMut;
@@ -490,15 +467,7 @@ impl UnixDatagram {
     ///     Ok(())
     /// }
     /// ```
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(doc, target_os = "android", target_os = "linux"))]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn recv_vectored_with_ancillary(
         &self,
@@ -609,7 +578,8 @@ impl UnixDatagram {
     ///
     /// # Examples
     ///
-    /// ```no_run
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")]
+    #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")]
     /// #![feature(unix_socket_ancillary_data)]
     /// use std::os::unix::net::{UnixDatagram, SocketAncillary};
     /// use std::io::IoSlice;
@@ -633,15 +603,7 @@ impl UnixDatagram {
     ///     Ok(())
     /// }
     /// ```
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(doc, target_os = "android", target_os = "linux"))]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn send_vectored_with_ancillary_to<P: AsRef<Path>>(
         &self,
@@ -658,7 +620,8 @@ impl UnixDatagram {
     ///
     /// # Examples
     ///
-    /// ```no_run
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")]
+    #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")]
     /// #![feature(unix_socket_ancillary_data)]
     /// use std::os::unix::net::{UnixDatagram, SocketAncillary};
     /// use std::io::IoSlice;
@@ -682,15 +645,7 @@ impl UnixDatagram {
     ///     Ok(())
     /// }
     /// ```
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(doc, target_os = "android", target_os = "linux"))]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn send_vectored_with_ancillary(
         &self,
diff --git a/library/std/src/os/unix/net/mod.rs b/library/std/src/os/unix/net/mod.rs
index 8ce82208854..6da3e350bf1 100644
--- a/library/std/src/os/unix/net/mod.rs
+++ b/library/std/src/os/unix/net/mod.rs
@@ -1,27 +1,11 @@
 //! Unix-specific networking functionality.
 
+#![allow(irrefutable_let_patterns)]
 #![stable(feature = "unix_socket", since = "1.10.0")]
 
 mod addr;
-#[doc(cfg(any(
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-)))]
-#[cfg(any(
-    doc,
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[doc(cfg(any(target_os = "android", target_os = "linux")))]
+#[cfg(any(doc, target_os = "android", target_os = "linux"))]
 mod ancillary;
 mod datagram;
 mod listener;
@@ -31,16 +15,7 @@ mod tests;
 
 #[stable(feature = "unix_socket", since = "1.10.0")]
 pub use self::addr::*;
-#[cfg(any(
-    doc,
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[cfg(any(doc, target_os = "android", target_os = "linux"))]
 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
 pub use self::ancillary::*;
 #[stable(feature = "unix_socket", since = "1.10.0")]
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index cd1aa01fa0f..2a5790e9d5c 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -1,13 +1,4 @@
-#[cfg(any(
-    doc,
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[cfg(any(doc, target_os = "android", target_os = "linux"))]
 use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary};
 use super::{sockaddr_un, SocketAddr};
 use crate::fmt;
@@ -511,7 +502,8 @@ impl UnixStream {
     ///
     /// # Examples
     ///
-    /// ```no_run
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")]
+    #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")]
     /// #![feature(unix_socket_ancillary_data)]
     /// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData};
     /// use std::io::IoSliceMut;
@@ -541,15 +533,7 @@ impl UnixStream {
     ///     Ok(())
     /// }
     /// ```
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(doc, target_os = "android", target_os = "linux"))]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn recv_vectored_with_ancillary(
         &self,
@@ -567,7 +551,8 @@ impl UnixStream {
     ///
     /// # Examples
     ///
-    /// ```no_run
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")]
+    #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")]
     /// #![feature(unix_socket_ancillary_data)]
     /// use std::os::unix::net::{UnixStream, SocketAncillary};
     /// use std::io::IoSlice;
@@ -591,15 +576,7 @@ impl UnixStream {
     ///     Ok(())
     /// }
     /// ```
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(doc, target_os = "android", target_os = "linux"))]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn send_vectored_with_ancillary(
         &self,
diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs
index c1f11c56b8f..e4499f9b6a6 100644
--- a/library/std/src/os/unix/net/tests.rs
+++ b/library/std/src/os/unix/net/tests.rs
@@ -1,24 +1,7 @@
 use super::*;
 use crate::io::prelude::*;
 use crate::io::{self, ErrorKind, IoSlice, IoSliceMut};
-#[cfg(any(
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
-#[cfg(any(
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[cfg(any(target_os = "android", target_os = "linux"))]
 use crate::os::unix::io::AsRawFd;
 use crate::sys_common::io::test::tmpdir;
 use crate::thread;
@@ -618,15 +601,7 @@ fn test_unix_datagram_peek_from() {
     assert_eq!(msg, &buf[..]);
 }
 
-#[cfg(any(
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[cfg(any(target_os = "android", target_os = "linux"))]
 #[test]
 fn test_send_vectored_fds_unix_stream() {
     let (s1, s2) = or_panic!(UnixStream::pair());
@@ -664,7 +639,7 @@ fn test_send_vectored_fds_unix_stream() {
     }
 }
 
-#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux",))]
+#[cfg(any(target_os = "android", target_os = "linux",))]
 #[test]
 fn test_send_vectored_with_ancillary_to_unix_datagram() {
     fn getpid() -> libc::pid_t {
@@ -731,15 +706,7 @@ fn test_send_vectored_with_ancillary_to_unix_datagram() {
     }
 }
 
-#[cfg(any(
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[cfg(any(target_os = "android", target_os = "linux"))]
 #[test]
 fn test_send_vectored_with_ancillary_unix_datagram() {
     let dir = tmpdir();
diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs
index 9bf9607a63e..a1bbc2d87b6 100644
--- a/library/std/src/sys/unix/net.rs
+++ b/library/std/src/sys/unix/net.rs
@@ -289,15 +289,7 @@ impl Socket {
         self.recv_from_with_flags(buf, 0)
     }
 
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(target_os = "android", target_os = "linux"))]
     pub fn recv_msg(&self, msg: &mut libc::msghdr) -> io::Result<usize> {
         let n = cvt(unsafe { libc::recvmsg(self.as_raw_fd(), msg, libc::MSG_CMSG_CLOEXEC) })?;
         Ok(n as usize)
@@ -320,15 +312,7 @@ impl Socket {
         self.0.is_write_vectored()
     }
 
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(target_os = "android", target_os = "linux"))]
     pub fn send_msg(&self, msg: &mut libc::msghdr) -> io::Result<usize> {
         let n = cvt(unsafe { libc::sendmsg(self.as_raw_fd(), msg, 0) })?;
         Ok(n as usize)
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 761bd66b505..b804cefd3fc 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -227,7 +227,7 @@ impl StepDescription {
 
     fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
         if builder.config.exclude.iter().any(|e| pathset.has(&e.path, e.kind)) {
-            eprintln!("Skipping {:?} because it is excluded", pathset);
+            println!("Skipping {:?} because it is excluded", pathset);
             return true;
         }
 
@@ -1232,7 +1232,12 @@ impl<'a> Builder<'a> {
                 // HACK: because anyhow does feature detection in build.rs, we need to allow the backtrace feature too.
                 rustflags.arg("-Zallow-features=binary-dep-depinfo,backtrace");
             }
-            Mode::Std | Mode::Rustc | Mode::ToolStd | Mode::Codegen | Mode::ToolRustc => {}
+            Mode::ToolStd => {
+                // Right now this is just compiletest and a few other tools that build on stable.
+                // Allow them to use `feature(test)`, but nothing else.
+                rustflags.arg("-Zallow-features=binary-dep-depinfo,test,backtrace");
+            }
+            Mode::Std | Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {}
         }
 
         cargo.arg("-j").arg(self.jobs().to_string());
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 0b430f64e1e..b35eba21e6b 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -1164,14 +1164,11 @@ impl Step for Assemble {
             // for `-Z gcc-ld=lld`
             let gcc_ld_dir = libdir_bin.join("gcc-ld");
             t!(fs::create_dir(&gcc_ld_dir));
-            for flavor in ["ld", "ld64"] {
-                let lld_wrapper_exe = builder.ensure(crate::tool::LldWrapper {
-                    compiler: build_compiler,
-                    target: target_compiler.host,
-                    flavor_feature: flavor,
-                });
-                builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe(flavor, target_compiler.host)));
-            }
+            let lld_wrapper_exe = builder.ensure(crate::tool::LldWrapper {
+                compiler: build_compiler,
+                target: target_compiler.host,
+            });
+            builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe("ld", target_compiler.host)));
         }
 
         if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 843d276cd7a..b82c1505b24 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -765,7 +765,7 @@ impl Config {
             {
                 Ok(table) => table,
                 Err(err) => {
-                    println!("failed to parse TOML configuration '{}': {}", file.display(), err);
+                    eprintln!("failed to parse TOML configuration '{}': {}", file.display(), err);
                     process::exit(2);
                 }
             }
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 0be11e3fb46..cc10d67c551 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -407,11 +407,8 @@ impl Step for Rustc {
                 let gcc_lld_src_dir = src_dir.join("gcc-ld");
                 let gcc_lld_dst_dir = dst_dir.join("gcc-ld");
                 t!(fs::create_dir(&gcc_lld_dst_dir));
-                for flavor in ["ld", "ld64"] {
-                    let exe_name = exe(flavor, compiler.host);
-                    builder
-                        .copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name));
-                }
+                let exe_name = exe("ld", compiler.host);
+                builder.copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name));
             }
 
             // Man pages
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 4cd835ade64..9827a6c590b 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -367,8 +367,8 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
             }
         }
         if !pass_sanity_check {
-            println!("{}\n", subcommand_help);
-            println!(
+            eprintln!("{}\n", subcommand_help);
+            eprintln!(
                 "Sorry, I couldn't figure out which subcommand you were trying to specify.\n\
                  You may need to move some options to after the subcommand.\n"
             );
@@ -532,7 +532,7 @@ Arguments:
             Kind::Build => Subcommand::Build { paths },
             Kind::Check => {
                 if matches.opt_present("all-targets") {
-                    eprintln!(
+                    println!(
                         "Warning: --all-targets is now on by default and does not need to be passed explicitly."
                     );
                 }
@@ -606,7 +606,7 @@ Arguments:
             if matches.opt_str("keep-stage").is_some()
                 || matches.opt_str("keep-stage-std").is_some()
             {
-                println!("--keep-stage not yet supported for x.py check");
+                eprintln!("--keep-stage not yet supported for x.py check");
                 process::exit(1);
             }
         }
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index 10b846e6db2..d1a450f1bff 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -96,7 +96,7 @@ pub fn format(build: &Build, check: bool, paths: &[PathBuf]) {
                     entry.split(' ').nth(1).expect("every git status entry should list a path")
                 });
             for untracked_path in untracked_paths {
-                eprintln!("skip untracked path {} during rustfmt invocations", untracked_path);
+                println!("skip untracked path {} during rustfmt invocations", untracked_path);
                 // The leading `/` makes it an exact match against the
                 // repository root, rather than a glob. Without that, if you
                 // have `foo.rs` in the repository root it will also match
@@ -105,10 +105,10 @@ pub fn format(build: &Build, check: bool, paths: &[PathBuf]) {
                 ignore_fmt.add(&format!("!/{}", untracked_path)).expect(&untracked_path);
             }
         } else {
-            eprintln!("Not in git tree. Skipping git-aware format checks");
+            println!("Not in git tree. Skipping git-aware format checks");
         }
     } else {
-        eprintln!("Could not find usable git. Skipping git-aware format checks");
+        println!("Could not find usable git. Skipping git-aware format checks");
     }
     let ignore_fmt = ignore_fmt.build().unwrap();
 
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 591f9a1ca50..0f0cf0762ab 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -689,9 +689,9 @@ impl Build {
         // Check for postponed failures from `test --no-fail-fast`.
         let failures = self.delayed_failures.borrow();
         if failures.len() > 0 {
-            println!("\n{} command(s) did not execute successfully:\n", failures.len());
+            eprintln!("\n{} command(s) did not execute successfully:\n", failures.len());
             for failure in failures.iter() {
-                println!("  - {}\n", failure);
+                eprintln!("  - {}\n", failure);
             }
             process::exit(1);
         }
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 09b8cbe9014..7bfcfcdef2c 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -138,10 +138,10 @@ pub(crate) fn maybe_download_ci_llvm(builder: &Builder<'_>) {
     let llvm_sha = llvm_sha.trim();
 
     if llvm_sha == "" {
-        println!("error: could not find commit hash for downloading LLVM");
-        println!("help: maybe your repository history is too shallow?");
-        println!("help: consider disabling `download-ci-llvm`");
-        println!("help: or fetch enough history to include one upstream commit");
+        eprintln!("error: could not find commit hash for downloading LLVM");
+        eprintln!("help: maybe your repository history is too shallow?");
+        eprintln!("help: consider disabling `download-ci-llvm`");
+        eprintln!("help: or fetch enough history to include one upstream commit");
         panic!();
     }
 
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index b730730854f..82f55440ce5 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -85,12 +85,12 @@ pub fn setup(config: &Config, profile: Profile) {
     let path = &config.config;
 
     if path.exists() {
-        println!(
+        eprintln!(
             "error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
             path.display()
         );
-        println!("help: try adding `profile = \"{}\"` at the top of {}", profile, path.display());
-        println!(
+        eprintln!("help: try adding `profile = \"{}\"` at the top of {}", profile, path.display());
+        eprintln!(
             "note: this will use the configuration in {}",
             profile.include_path(&config.src).display()
         );
@@ -115,7 +115,7 @@ pub fn setup(config: &Config, profile: Profile) {
     println!();
 
     if !rustup_installed() && profile != Profile::User {
-        println!("`rustup` is not installed; cannot link `stage1` toolchain");
+        eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
     } else if stage_dir_exists(&stage_path[..]) {
         attempt_toolchain_link(&stage_path[..]);
     }
@@ -173,7 +173,7 @@ fn attempt_toolchain_link(stage_path: &str) {
     }
 
     if !ensure_stage1_toolchain_placeholder_exists(stage_path) {
-        println!(
+        eprintln!(
             "Failed to create a template for stage 1 toolchain or confirm that it already exists"
         );
         return;
@@ -184,8 +184,8 @@ fn attempt_toolchain_link(stage_path: &str) {
             "Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain"
         );
     } else {
-        println!("`rustup` failed to link stage 1 build to `stage1` toolchain");
-        println!(
+        eprintln!("`rustup` failed to link stage 1 build to `stage1` toolchain");
+        eprintln!(
             "To manually link stage 1 build to `stage1` toolchain, run:\n
             `rustup toolchain link stage1 {}`",
             &stage_path
@@ -292,8 +292,8 @@ pub fn interactive_path() -> io::Result<Profile> {
         break match parse_with_abbrev(&input) {
             Ok(profile) => profile,
             Err(err) => {
-                println!("error: {}", err);
-                println!("note: press Ctrl+C to exit");
+                eprintln!("error: {}", err);
+                eprintln!("note: press Ctrl+C to exit");
                 continue;
             }
         };
@@ -320,8 +320,8 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
             "y" | "yes" => true,
             "n" | "no" | "" => false,
             _ => {
-                println!("error: unrecognized option '{}'", input.trim());
-                println!("note: press Ctrl+C to exit");
+                eprintln!("error: unrecognized option '{}'", input.trim());
+                eprintln!("note: press Ctrl+C to exit");
                 continue;
             }
         };
@@ -337,7 +337,7 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
         ));
         let dst = git.join("hooks").join("pre-push");
         match fs::hard_link(src, &dst) {
-            Err(e) => println!(
+            Err(e) => eprintln!(
                 "error: could not create hook {}: do you already have the git hook installed?\n{}",
                 dst.display(),
                 e
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 3b30e6de12a..f39cbb57b82 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -152,43 +152,43 @@ impl Step for ToolBuild {
         });
 
         if is_expected && !duplicates.is_empty() {
-            println!(
+            eprintln!(
                 "duplicate artifacts found when compiling a tool, this \
                       typically means that something was recompiled because \
                       a transitive dependency has different features activated \
                       than in a previous build:\n"
             );
-            println!(
+            eprintln!(
                 "the following dependencies are duplicated although they \
                       have the same features enabled:"
             );
             let (same, different): (Vec<_>, Vec<_>) =
                 duplicates.into_iter().partition(|(_, cur, prev)| cur.2 == prev.2);
             for (id, cur, prev) in same {
-                println!("  {}", id);
+                eprintln!("  {}", id);
                 // same features
-                println!("    `{}` ({:?})\n    `{}` ({:?})", cur.0, cur.1, prev.0, prev.1);
+                eprintln!("    `{}` ({:?})\n    `{}` ({:?})", cur.0, cur.1, prev.0, prev.1);
             }
-            println!("the following dependencies have different features:");
+            eprintln!("the following dependencies have different features:");
             for (id, cur, prev) in different {
-                println!("  {}", id);
+                eprintln!("  {}", id);
                 let cur_features: HashSet<_> = cur.2.into_iter().collect();
                 let prev_features: HashSet<_> = prev.2.into_iter().collect();
-                println!(
+                eprintln!(
                     "    `{}` additionally enabled features {:?} at {:?}",
                     cur.0,
                     &cur_features - &prev_features,
                     cur.1
                 );
-                println!(
+                eprintln!(
                     "    `{}` additionally enabled features {:?} at {:?}",
                     prev.0,
                     &prev_features - &cur_features,
                     prev.1
                 );
             }
-            println!();
-            println!(
+            eprintln!();
+            eprintln!(
                 "to fix this you will probably want to edit the local \
                       src/tools/rustc-workspace-hack/Cargo.toml crate, as \
                       that will update the dependency graph to ensure that \
@@ -656,7 +656,6 @@ impl Step for Cargo {
 pub struct LldWrapper {
     pub compiler: Compiler,
     pub target: TargetSelection,
-    pub flavor_feature: &'static str,
 }
 
 impl Step for LldWrapper {
@@ -676,7 +675,7 @@ impl Step for LldWrapper {
                 path: "src/tools/lld-wrapper",
                 is_optional_tool: false,
                 source_type: SourceType::InTree,
-                extra_features: vec![self.flavor_feature.to_owned()],
+                extra_features: Vec::new(),
             })
             .expect("expected to build -- essential tool");
 
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 710b3588b84..848d9a7dc92 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -455,7 +455,7 @@ fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
 }
 
 fn fail(s: &str) -> ! {
-    println!("\n\n{}\n\n", s);
+    eprintln!("\n\n{}\n\n", s);
     std::process::exit(1);
 }
 
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index b3ec1638fda..03834411d15 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.9.3
\ No newline at end of file
+0.9.5
\ No newline at end of file
diff --git a/src/doc/book b/src/doc/book
-Subproject d9415b7cbfcb4b24062683f429bd0ff53539636
+Subproject b4dd5f00b87190ad5ef42cbc2a88a783c6ae57e
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 8e36971959ff238b5aa2575fbc7a2e09e1313e8
+Subproject b74825d8f88b685e239ade00f00de68ba4cd63d
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject e9f93cfcf410bc092c9107b8a41a82f144c761f
+Subproject 2ed26865e8c29ef939dc913a97bd321cadd72a9
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 0c02acdb6f48f03907a02ea8e537c3272b4fde9
+Subproject 554c00e4805df7f7bffac7db408437d62d6dfb9
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index e10c61901d0..99b4eacedc2 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -525,7 +525,7 @@ impl Item {
                 if let Ok((mut href, ..)) = href(*did, cx) {
                     debug!(?href);
                     if let Some(ref fragment) = *fragment {
-                        fragment.render(&mut href, cx.tcx()).unwrap()
+                        fragment.render(&mut href, cx.tcx())
                     }
                     Some(RenderedLink {
                         original_text: s.clone(),
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index a4ec4052e05..86c58cd79dc 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -795,7 +795,9 @@ fn partition_source(s: &str, edition: Edition) -> (String, String, String) {
                         // If not, then we append the new line into the pending attribute to check
                         // if this time it's complete...
                         mod_attr_pending.push_str(line);
-                        if !trimline.is_empty() && check_if_attr_is_complete(line, edition) {
+                        if !trimline.is_empty()
+                            && check_if_attr_is_complete(&mod_attr_pending, edition)
+                        {
                             // If it's complete, then we can clear the pending content.
                             mod_attr_pending.clear();
                         }
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index da4273345cb..c5dbf8aa754 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -55,9 +55,9 @@ pub(crate) struct Context<'tcx> {
     pub(super) render_redirect_pages: bool,
     /// Tracks section IDs for `Deref` targets so they match in both the main
     /// body and the sidebar.
-    pub(super) deref_id_map: RefCell<FxHashMap<DefId, String>>,
+    pub(super) deref_id_map: FxHashMap<DefId, String>,
     /// The map used to ensure all generated 'id=' attributes are unique.
-    pub(super) id_map: RefCell<IdMap>,
+    pub(super) id_map: IdMap,
     /// Shared mutable state.
     ///
     /// Issue for improving the situation: [#82381][]
@@ -72,7 +72,7 @@ pub(crate) struct Context<'tcx> {
 
 // `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Context<'_>, 144);
+rustc_data_structures::static_assert_size!(Context<'_>, 128);
 
 /// Shared mutable state used in [`Context`] and elsewhere.
 pub(crate) struct SharedContext<'tcx> {
@@ -155,9 +155,8 @@ impl<'tcx> Context<'tcx> {
         self.shared.tcx.sess
     }
 
-    pub(super) fn derive_id(&self, id: String) -> String {
-        let mut map = self.id_map.borrow_mut();
-        map.derive(id)
+    pub(super) fn derive_id(&mut self, id: String) -> String {
+        self.id_map.derive(id)
     }
 
     /// String representation of how to get back to the root path of the 'doc/'
@@ -166,7 +165,7 @@ impl<'tcx> Context<'tcx> {
         "../".repeat(self.current.len())
     }
 
-    fn render_item(&self, it: &clean::Item, is_module: bool) -> String {
+    fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
         let mut title = String::new();
         if !is_module {
             title.push_str(it.name.unwrap().as_str());
@@ -203,23 +202,26 @@ impl<'tcx> Context<'tcx> {
         };
 
         if !self.render_redirect_pages {
+            let clone_shared = Rc::clone(&self.shared);
             let page = layout::Page {
                 css_class: tyname_s,
                 root_path: &self.root_path(),
-                static_root_path: self.shared.static_root_path.as_deref(),
+                static_root_path: clone_shared.static_root_path.as_deref(),
                 title: &title,
                 description: &desc,
                 keywords: &keywords,
-                resource_suffix: &self.shared.resource_suffix,
+                resource_suffix: &clone_shared.resource_suffix,
                 extra_scripts: &[],
                 static_extra_scripts: &[],
             };
+            let mut page_buffer = Buffer::html();
+            print_item(self, it, &mut page_buffer, &page);
             layout::render(
-                &self.shared.layout,
+                &clone_shared.layout,
                 &page,
                 |buf: &mut _| print_sidebar(self, it, buf),
-                |buf: &mut _| print_item(self, it, buf, &page),
-                &self.shared.style_files,
+                move |buf: &mut Buffer| buf.push_buffer(page_buffer),
+                &clone_shared.style_files,
             )
         } else {
             if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) {
@@ -512,8 +514,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             current: Vec::new(),
             dst,
             render_redirect_pages: false,
-            id_map: RefCell::new(id_map),
-            deref_id_map: RefCell::new(FxHashMap::default()),
+            id_map,
+            deref_id_map: FxHashMap::default(),
             shared: Rc::new(scx),
             include_sources,
         };
@@ -528,7 +530,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
 
             // Write shared runs within a flock; disable thread dispatching of IO temporarily.
             Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true);
-            write_shared(&cx, &krate, index, &md_opts)?;
+            write_shared(&mut cx, &krate, index, &md_opts)?;
             Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false);
         }
 
@@ -540,8 +542,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             current: self.current.clone(),
             dst: self.dst.clone(),
             render_redirect_pages: self.render_redirect_pages,
-            deref_id_map: RefCell::new(FxHashMap::default()),
-            id_map: RefCell::new(IdMap::new()),
+            deref_id_map: FxHashMap::default(),
+            id_map: IdMap::new(),
             shared: Rc::clone(&self.shared),
             include_sources: self.include_sources,
         }
@@ -557,31 +559,32 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         if !root_path.ends_with('/') {
             root_path.push('/');
         }
+        let shared = Rc::clone(&self.shared);
         let mut page = layout::Page {
             title: "List of all items in this crate",
             css_class: "mod",
             root_path: "../",
-            static_root_path: self.shared.static_root_path.as_deref(),
+            static_root_path: shared.static_root_path.as_deref(),
             description: "List of all items in this crate",
             keywords: BASIC_KEYWORDS,
-            resource_suffix: &self.shared.resource_suffix,
+            resource_suffix: &shared.resource_suffix,
             extra_scripts: &[],
             static_extra_scripts: &[],
         };
-        let sidebar = if self.shared.cache.crate_version.is_some() {
+        let sidebar = if shared.cache.crate_version.is_some() {
             format!("<h2 class=\"location\">Crate {}</h2>", crate_name)
         } else {
             String::new()
         };
-        let all = self.shared.all.replace(AllTypes::new());
+        let all = shared.all.replace(AllTypes::new());
         let v = layout::render(
-            &self.shared.layout,
+            &shared.layout,
             &page,
             sidebar,
             |buf: &mut Buffer| all.print(buf),
-            &self.shared.style_files,
+            &shared.style_files,
         );
-        self.shared.fs.write(final_file, v)?;
+        shared.fs.write(final_file, v)?;
 
         // Generating settings page.
         page.title = "Rustdoc settings";
@@ -590,7 +593,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
 
         let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
         let v = layout::render(
-            &self.shared.layout,
+            &shared.layout,
             &page,
             sidebar,
             |buf: &mut Buffer| {
@@ -613,33 +616,36 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
                     suffix = page.resource_suffix,
                 )
             },
-            &self.shared.style_files,
+            &shared.style_files,
         );
-        self.shared.fs.write(settings_file, v)?;
+        shared.fs.write(settings_file, v)?;
 
-        if self.shared.layout.scrape_examples_extension {
+        if shared.layout.scrape_examples_extension {
             page.title = "About scraped examples";
             page.description = "How the scraped examples feature works in Rustdoc";
             let v = layout::render(
-                &self.shared.layout,
+                &shared.layout,
                 &page,
                 "",
-                scrape_examples_help(&*self.shared),
-                &self.shared.style_files,
+                scrape_examples_help(&*shared),
+                &shared.style_files,
             );
-            self.shared.fs.write(scrape_examples_help_file, v)?;
+            shared.fs.write(scrape_examples_help_file, v)?;
         }
 
-        if let Some(ref redirections) = self.shared.redirections {
+        if let Some(ref redirections) = shared.redirections {
             if !redirections.borrow().is_empty() {
                 let redirect_map_path =
                     self.dst.join(crate_name.as_str()).join("redirect-map.json");
                 let paths = serde_json::to_string(&*redirections.borrow()).unwrap();
-                self.shared.ensure_dir(&self.dst.join(crate_name.as_str()))?;
-                self.shared.fs.write(redirect_map_path, paths)?;
+                shared.ensure_dir(&self.dst.join(crate_name.as_str()))?;
+                shared.fs.write(redirect_map_path, paths)?;
             }
         }
 
+        // No need for it anymore.
+        drop(shared);
+
         // Flush pending errors.
         Rc::get_mut(&mut self.shared).unwrap().fs.close();
         let nb_errors =
@@ -662,7 +668,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         if !self.render_redirect_pages {
             self.render_redirect_pages = item.is_stripped();
         }
-        let scx = &self.shared;
         let item_name = item.name.unwrap();
         self.dst.push(&*item_name.as_str());
         self.current.push(item_name);
@@ -674,7 +679,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         if !buf.is_empty() {
             self.shared.ensure_dir(&self.dst)?;
             let joint_dst = self.dst.join("index.html");
-            scx.fs.write(joint_dst, buf)?;
+            self.shared.fs.write(joint_dst, buf)?;
         }
 
         // Render sidebar-items.js used throughout this module.
@@ -684,7 +689,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             let items = self.build_sidebar_items(module);
             let js_dst = self.dst.join(&format!("sidebar-items{}.js", self.shared.resource_suffix));
             let v = format!("initSidebarItems({});", serde_json::to_string(&items).unwrap());
-            scx.fs.write(js_dst, v)?;
+            self.shared.fs.write(js_dst, v)?;
         }
         Ok(())
     }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 3809738cc33..eefb2c2358f 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -42,6 +42,7 @@ use std::fmt;
 use std::fs;
 use std::iter::Peekable;
 use std::path::PathBuf;
+use std::rc::Rc;
 use std::str;
 use std::string::ToString;
 
@@ -364,7 +365,7 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String {
 
 fn document(
     w: &mut Buffer,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     item: &clean::Item,
     parent: Option<&clean::Item>,
     heading_offset: HeadingOffset,
@@ -383,19 +384,18 @@ fn document(
 /// Render md_text as markdown.
 fn render_markdown(
     w: &mut Buffer,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     md_text: &str,
     links: Vec<RenderedLink>,
     heading_offset: HeadingOffset,
 ) {
-    let mut ids = cx.id_map.borrow_mut();
     write!(
         w,
         "<div class=\"docblock\">{}</div>",
         Markdown {
             content: md_text,
             links: &links,
-            ids: &mut ids,
+            ids: &mut cx.id_map,
             error_codes: cx.shared.codes,
             edition: cx.shared.edition(),
             playground: &cx.shared.playground,
@@ -410,7 +410,7 @@ fn render_markdown(
 fn document_short(
     w: &mut Buffer,
     item: &clean::Item,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     link: AssocItemLink<'_>,
     parent: &clean::Item,
     show_def_docs: bool,
@@ -439,7 +439,7 @@ fn document_short(
 fn document_full_collapsible(
     w: &mut Buffer,
     item: &clean::Item,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     heading_offset: HeadingOffset,
 ) {
     document_full_inner(w, item, cx, true, heading_offset);
@@ -448,7 +448,7 @@ fn document_full_collapsible(
 fn document_full(
     w: &mut Buffer,
     item: &clean::Item,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     heading_offset: HeadingOffset,
 ) {
     document_full_inner(w, item, cx, false, heading_offset);
@@ -457,7 +457,7 @@ fn document_full(
 fn document_full_inner(
     w: &mut Buffer,
     item: &clean::Item,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     is_collapsible: bool,
     heading_offset: HeadingOffset,
 ) {
@@ -493,7 +493,7 @@ fn document_full_inner(
 /// * Required features (through the `doc_cfg` feature)
 fn document_item_info(
     w: &mut Buffer,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     item: &clean::Item,
     parent: Option<&clean::Item>,
 ) {
@@ -522,7 +522,7 @@ fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option<Strin
 /// the item's documentation.
 fn short_item_info(
     item: &clean::Item,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     parent: Option<&clean::Item>,
 ) -> Vec<String> {
     let mut extra_info = vec![];
@@ -550,10 +550,9 @@ fn short_item_info(
 
         if let Some(note) = note {
             let note = note.as_str();
-            let mut ids = cx.id_map.borrow_mut();
             let html = MarkdownHtml(
                 note,
-                &mut ids,
+                &mut cx.id_map,
                 error_codes,
                 cx.shared.edition(),
                 &cx.shared.playground,
@@ -601,7 +600,7 @@ fn short_item_info(
 // Render the list of items inside one of the sections "Trait Implementations",
 // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages).
 fn render_impls(
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     w: &mut Buffer,
     impls: &[&&Impl],
     containing_item: &clean::Item,
@@ -994,7 +993,7 @@ impl<'a> AssocItemLink<'a> {
 
 fn render_assoc_items(
     w: &mut Buffer,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     containing_item: &clean::Item,
     it: DefId,
     what: AssocItemRender<'_>,
@@ -1006,14 +1005,15 @@ fn render_assoc_items(
 
 fn render_assoc_items_inner(
     w: &mut Buffer,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     containing_item: &clean::Item,
     it: DefId,
     what: AssocItemRender<'_>,
     derefs: &mut FxHashSet<DefId>,
 ) {
     info!("Documenting associated items of {:?}", containing_item.name);
-    let cache = cx.cache();
+    let shared = Rc::clone(&cx.shared);
+    let cache = &shared.cache;
     let Some(v) = cache.impls.get(&it) else { return };
     let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
     if !non_trait.is_empty() {
@@ -1032,7 +1032,7 @@ fn render_assoc_items_inner(
                 let id =
                     cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx))));
                 if let Some(def_id) = type_.def_id(cx.cache()) {
-                    cx.deref_id_map.borrow_mut().insert(def_id, id.clone());
+                    cx.deref_id_map.insert(def_id, id.clone());
                 }
                 write!(
                     tmp_buf,
@@ -1138,7 +1138,7 @@ fn render_assoc_items_inner(
 
 fn render_deref_methods(
     w: &mut Buffer,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     impl_: &Impl,
     container_item: &clean::Item,
     deref_mut: bool,
@@ -1285,7 +1285,7 @@ struct ImplRenderingParameters {
 
 fn render_impl(
     w: &mut Buffer,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     i: &Impl,
     parent: &clean::Item,
     link: AssocItemLink<'_>,
@@ -1294,7 +1294,8 @@ fn render_impl(
     aliases: &[String],
     rendering_params: ImplRenderingParameters,
 ) {
-    let cache = cx.cache();
+    let shared = Rc::clone(&cx.shared);
+    let cache = &shared.cache;
     let traits = &cache.traits;
     let trait_ = i.trait_did().map(|did| &traits[&did]);
     let mut close_tags = String::new();
@@ -1307,7 +1308,7 @@ fn render_impl(
     fn doc_impl_item(
         boring: &mut Buffer,
         interesting: &mut Buffer,
-        cx: &Context<'_>,
+        cx: &mut Context<'_>,
         item: &clean::Item,
         parent: &clean::Item,
         containing_item: &clean::Item,
@@ -1520,7 +1521,7 @@ fn render_impl(
     fn render_default_items(
         boring: &mut Buffer,
         interesting: &mut Buffer,
-        cx: &Context<'_>,
+        cx: &mut Context<'_>,
         t: &clean::Trait,
         i: &clean::Impl,
         parent: &clean::Item,
@@ -1599,14 +1600,13 @@ fn render_impl(
         }
 
         if let Some(ref dox) = i.impl_item.collapsed_doc_value() {
-            let mut ids = cx.id_map.borrow_mut();
             write!(
                 w,
                 "<div class=\"docblock\">{}</div>",
                 Markdown {
                     content: &*dox,
                     links: &i.impl_item.links(cx),
-                    ids: &mut ids,
+                    ids: &mut cx.id_map,
                     error_codes: cx.shared.codes,
                     edition: cx.shared.edition(),
                     playground: &cx.shared.playground,
@@ -1664,7 +1664,7 @@ fn render_rightside(
 
 pub(crate) fn render_impl_summary(
     w: &mut Buffer,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     i: &Impl,
     parent: &clean::Item,
     containing_item: &clean::Item,
@@ -2092,10 +2092,8 @@ fn sidebar_deref_methods(
                 })
                 .collect::<Vec<_>>();
             if !ret.is_empty() {
-                let map;
                 let id = if let Some(target_def_id) = real_target.def_id(c) {
-                    map = cx.deref_id_map.borrow();
-                    map.get(&target_def_id).expect("Deref section without derived id")
+                    cx.deref_id_map.get(&target_def_id).expect("Deref section without derived id")
                 } else {
                     "deref-methods"
                 };
@@ -2641,14 +2639,14 @@ const MAX_FULL_EXAMPLES: usize = 5;
 const NUM_VISIBLE_LINES: usize = 10;
 
 /// Generates the HTML for example call locations generated via the --scrape-examples flag.
-fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
+fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item) {
     let tcx = cx.tcx();
     let def_id = item.item_id.expect_def_id();
     let key = tcx.def_path_hash(def_id);
     let Some(call_locations) = cx.shared.call_locations.get(&key) else { return };
 
     // Generate a unique ID so users can link to this section for a given method
-    let id = cx.id_map.borrow_mut().derive("scraped-examples");
+    let id = cx.id_map.derive("scraped-examples");
     write!(
         w,
         "<div class=\"docblock scraped-example-list\">\
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index ed41b95e73f..dcf36b5e865 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -2,6 +2,7 @@ use clean::AttributesExt;
 
 use std::cmp::Ordering;
 use std::fmt;
+use std::rc::Rc;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
@@ -60,7 +61,12 @@ struct ItemVars<'a> {
     src_href: Option<&'a str>,
 }
 
-pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, page: &Page<'_>) {
+pub(super) fn print_item(
+    cx: &mut Context<'_>,
+    item: &clean::Item,
+    buf: &mut Buffer,
+    page: &Page<'_>,
+) {
     debug_assert!(!item.is_stripped());
     let typ = match *item.kind {
         clean::ModuleItem(_) => {
@@ -187,7 +193,7 @@ fn toggle_close(w: &mut Buffer) {
     w.write_str("</details>");
 }
 
-fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) {
+fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) {
     document(w, cx, item, None, HeadingOffset::H2);
 
     let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::<Vec<usize>>();
@@ -344,6 +350,12 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
                 let add = if stab.is_some() { " " } else { "" };
 
                 w.write_str(ITEM_TABLE_ROW_OPEN);
+                let id = match import.kind {
+                    clean::ImportKind::Simple(s) => {
+                        format!(" id=\"{}\"", cx.derive_id(format!("reexport.{}", s)))
+                    }
+                    clean::ImportKind::Glob => String::new(),
+                };
                 write!(
                     w,
                     "<div class=\"item-left {stab}{add}import-item\"{id}>\
@@ -351,15 +363,9 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
                      </div>\
                      <div class=\"item-right docblock-short\">{stab_tags}</div>",
                     stab = stab.unwrap_or_default(),
-                    add = add,
                     vis = myitem.visibility.print_with_space(myitem.item_id, cx),
                     imp = import.print(cx),
                     stab_tags = stab_tags.unwrap_or_default(),
-                    id = match import.kind {
-                        clean::ImportKind::Simple(s) =>
-                            format!(" id=\"{}\"", cx.derive_id(format!("reexport.{}", s))),
-                        clean::ImportKind::Glob => String::new(),
-                    },
                 );
                 w.write_str(ITEM_TABLE_ROW_CLOSE);
             }
@@ -464,7 +470,7 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) ->
     tags
 }
 
-fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) {
+fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &clean::Function) {
     let header = it.fn_header(cx.tcx()).expect("printing a function which isn't a function");
     let constness = print_constness_with_space(&header.constness, it.const_stability(cx.tcx()));
     let unsafety = header.unsafety.print_with_space();
@@ -507,7 +513,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
     document(w, cx, it, None, HeadingOffset::H2)
 }
 
-fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) {
+fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Trait) {
     let bounds = bounds(&t.bounds, false, cx);
     let required_types = t.items.iter().filter(|m| m.is_ty_associated_type()).collect::<Vec<_>>();
     let provided_types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
@@ -674,7 +680,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
         )
     }
 
-    fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item) {
+    fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::Item) {
         let name = m.name.unwrap();
         info!("Documenting {} on {:?}", name, t.name);
         let item_type = m.type_();
@@ -791,14 +797,15 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
     // If there are methods directly on this trait object, render them here.
     render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All);
 
-    let cache = cx.cache();
+    let cloned_shared = Rc::clone(&cx.shared);
+    let cache = &cloned_shared.cache;
     let mut extern_crates = FxHashSet::default();
     if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) {
         // The DefId is for the first Type found with that name. The bool is
         // if any Types with the same name but different DefId have been found.
         let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
         for implementor in implementors {
-            if let Some(did) = implementor.inner_impl().for_.without_borrowed_ref().def_id(cx.cache()) &&
+            if let Some(did) = implementor.inner_impl().for_.without_borrowed_ref().def_id(cache) &&
                 !did.is_local() {
                 extern_crates.insert(did.krate);
             }
@@ -996,7 +1003,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
     );
 }
 
-fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TraitAlias) {
+fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TraitAlias) {
     wrap_into_docblock(w, |w| {
         wrap_item(w, "trait-alias", |w| {
             render_attributes_in_pre(w, it, "");
@@ -1020,7 +1027,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
     render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
 }
 
-fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
+fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
     wrap_into_docblock(w, |w| {
         wrap_item(w, "opaque", |w| {
             render_attributes_in_pre(w, it, "");
@@ -1044,7 +1051,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
     render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
 }
 
-fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
+fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Typedef) {
     fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
         wrap_item(w, "typedef", |w| {
             render_attributes_in_pre(w, it, "");
@@ -1073,7 +1080,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T
     document_type_layout(w, cx, def_id);
 }
 
-fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) {
+fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) {
     wrap_into_docblock(w, |w| {
         wrap_item(w, "union", |w| {
             render_attributes_in_pre(w, it, "");
@@ -1135,7 +1142,7 @@ fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]
     }
 }
 
-fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) {
+fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) {
     let count_variants = e.variants().count();
     wrap_into_docblock(w, |w| {
         wrap_item(w, "enum", |w| {
@@ -1283,7 +1290,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
     document_type_layout(w, cx, def_id);
 }
 
-fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) {
+fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) {
     wrap_into_docblock(w, |w| {
         highlight::render_with_highlighting(
             &t.source,
@@ -1300,7 +1307,7 @@ fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Mac
     document(w, cx, it, None, HeadingOffset::H2)
 }
 
-fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean::ProcMacro) {
+fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &clean::ProcMacro) {
     wrap_into_docblock(w, |w| {
         let name = it.name.expect("proc-macros always have names");
         match m.kind {
@@ -1332,12 +1339,12 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean
     document(w, cx, it, None, HeadingOffset::H2)
 }
 
-fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
+fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
     document(w, cx, it, None, HeadingOffset::H2);
     render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
 }
 
-fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::Constant) {
+fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) {
     wrap_into_docblock(w, |w| {
         wrap_item(w, "const", |w| {
             render_attributes_in_code(w, it);
@@ -1377,7 +1384,7 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::
     document(w, cx, it, None, HeadingOffset::H2)
 }
 
-fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) {
+fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) {
     wrap_into_docblock(w, |w| {
         wrap_item(w, "struct", |w| {
             render_attributes_in_code(w, it);
@@ -1430,7 +1437,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
     document_type_layout(w, cx, def_id);
 }
 
-fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Static) {
+fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) {
     wrap_into_docblock(w, |w| {
         wrap_item(w, "static", |w| {
             render_attributes_in_code(w, it);
@@ -1447,7 +1454,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
     document(w, cx, it, None, HeadingOffset::H2)
 }
 
-fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
+fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
     wrap_into_docblock(w, |w| {
         wrap_item(w, "foreigntype", |w| {
             w.write_str("extern {\n");
@@ -1466,7 +1473,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
     render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
 }
 
-fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
+fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
     document(w, cx, it, None, HeadingOffset::H2)
 }
 
@@ -1579,7 +1586,7 @@ fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl, cx: &Context<'_>) -> O
 }
 
 fn render_implementor(
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     implementor: &Impl,
     trait_: &clean::Item,
     w: &mut Buffer,
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index ece659284d1..325d3a31434 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -5,6 +5,7 @@ use std::io::prelude::*;
 use std::io::{self, BufReader};
 use std::lazy::SyncLazy as Lazy;
 use std::path::{Component, Path, PathBuf};
+use std::rc::Rc;
 
 use itertools::Itertools;
 use rustc_data_structures::flock;
@@ -135,7 +136,7 @@ impl Context<'_> {
 }
 
 pub(super) fn write_shared(
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     krate: &Crate,
     search_index: String,
     options: &RenderOptions,
@@ -462,15 +463,16 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
             crate::markdown::render(&index_page, md_opts, cx.shared.edition())
                 .map_err(|e| Error::new(e, &index_page))?;
         } else {
+            let shared = Rc::clone(&cx.shared);
             let dst = cx.dst.join("index.html");
             let page = layout::Page {
                 title: "Index of crates",
                 css_class: "mod",
                 root_path: "./",
-                static_root_path: cx.shared.static_root_path.as_deref(),
+                static_root_path: shared.static_root_path.as_deref(),
                 description: "List of crates",
                 keywords: BASIC_KEYWORDS,
-                resource_suffix: &cx.shared.resource_suffix,
+                resource_suffix: &shared.resource_suffix,
                 extra_scripts: &[],
                 static_extra_scripts: &[],
             };
@@ -490,8 +492,8 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
                     })
                     .collect::<String>()
             );
-            let v = layout::render(&cx.shared.layout, &page, "", content, &cx.shared.style_files);
-            cx.shared.fs.write(dst, v)?;
+            let v = layout::render(&shared.layout, &page, "", content, &shared.style_files);
+            shared.fs.write(dst, v)?;
         }
     }
 
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 0bbdc37ea89..524c90e1f4d 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -6,15 +6,18 @@ use crate::html::highlight;
 use crate::html::layout;
 use crate::html::render::{Context, BASIC_KEYWORDS};
 use crate::visit::DocVisitor;
+
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::FileName;
+
 use std::ffi::OsStr;
 use std::fs;
 use std::path::{Component, Path, PathBuf};
+use std::rc::Rc;
 
 pub(crate) fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), Error> {
     info!("emitting source files");
@@ -174,15 +177,16 @@ impl SourceCollector<'_, '_> {
         // Remove the utf-8 BOM if any
         let contents = contents.strip_prefix('\u{feff}').unwrap_or(&contents);
 
+        let shared = Rc::clone(&self.cx.shared);
         // Create the intermediate directories
         let mut cur = self.dst.clone();
         let mut root_path = String::from("../../");
-        clean_path(&self.cx.shared.src_root, &p, false, |component| {
+        clean_path(&shared.src_root, &p, false, |component| {
             cur.push(component);
             root_path.push_str("../");
         });
 
-        self.cx.shared.ensure_dir(&cur)?;
+        shared.ensure_dir(&cur)?;
 
         let src_fname = p.file_name().expect("source has no filename").to_os_string();
         let mut fname = src_fname.clone();
@@ -195,32 +199,33 @@ impl SourceCollector<'_, '_> {
             title: &title,
             css_class: "source",
             root_path: &root_path,
-            static_root_path: self.cx.shared.static_root_path.as_deref(),
+            static_root_path: shared.static_root_path.as_deref(),
             description: &desc,
             keywords: BASIC_KEYWORDS,
-            resource_suffix: &self.cx.shared.resource_suffix,
-            extra_scripts: &[&format!("source-files{}", self.cx.shared.resource_suffix)],
-            static_extra_scripts: &[&format!("source-script{}", self.cx.shared.resource_suffix)],
+            resource_suffix: &shared.resource_suffix,
+            extra_scripts: &[&format!("source-files{}", shared.resource_suffix)],
+            static_extra_scripts: &[&format!("source-script{}", shared.resource_suffix)],
         };
         let v = layout::render(
-            &self.cx.shared.layout,
+            &shared.layout,
             &page,
             "",
             |buf: &mut _| {
+                let cx = &mut self.cx;
                 print_src(
                     buf,
                     contents,
-                    self.cx.shared.edition(),
+                    cx.shared.edition(),
                     file_span,
-                    self.cx,
+                    cx,
                     &root_path,
                     None,
                     SourceContext::Standalone,
                 )
             },
-            &self.cx.shared.style_files,
+            &shared.style_files,
         );
-        self.cx.shared.fs.write(cur, v)?;
+        shared.fs.write(cur, v)?;
         self.emitted_local_sources.insert(p);
         Ok(())
     }
diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js
index bf962303b3a..997def1657f 100644
--- a/src/librustdoc/html/static/.eslintrc.js
+++ b/src/librustdoc/html/static/.eslintrc.js
@@ -47,5 +47,21 @@ module.exports = {
             { "beforeColon": false, "afterColon": true, "mode": "strict" }
         ],
         "func-call-spacing": ["error", "never"],
+        "space-infix-ops": "error",
+        "space-before-function-paren": ["error", "never"],
+        "space-before-blocks": "error",
+        "comma-dangle": ["error", "always-multiline"],
+        "comma-style": ["error", "last"],
+        "max-len": ["error", { "code": 100, "tabWidth": 4 }],
+        "eol-last": ["error", "always"],
+        "arrow-parens": ["error", "as-needed"],
+        "no-unused-vars": [
+            "error",
+            {
+                "argsIgnorePattern": "^_",
+                "varsIgnorePattern": "^_"
+            }
+        ],
+        "eqeqeq": "error",
     }
 };
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 4eb8029ee2d..d0229bdb5f2 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1415,30 +1415,6 @@ pre.rust {
 #settings-menu.rotate > a img {
 	animation: rotating 2s linear infinite;
 }
-#settings-menu #settings {
-	position: absolute;
-	right: 0;
-	z-index: 1;
-	display: block;
-	margin-top: 7px;
-	border-radius: 3px;
-	border: 1px solid;
-}
-#settings-menu #settings .setting-line {
-	margin: 0.6em;
-}
-/* This rule is to draw the little arrow connecting the settings menu to the gear icon. */
-#settings-menu #settings::before {
-	content: '';
-	position: absolute;
-	right: 11px;
-	border: solid;
-	border-width: 1px 1px 0 0;
-	display: inline-block;
-	padding: 4px;
-	transform: rotate(-45deg);
-	top: -5px;
-}
 
 #help-button {
 	font-family: "Fira Sans", Arial, sans-serif;
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index 07588748ad6..c69ff04236d 100644
--- a/src/librustdoc/html/static/css/settings.css
+++ b/src/librustdoc/html/static/css/settings.css
@@ -46,9 +46,12 @@
 .toggle {
 	position: relative;
 	display: inline-block;
-	width: 45px;
+	width: 100%;
 	height: 27px;
 	margin-right: 20px;
+	display: flex;
+	align-items: center;
+	cursor: pointer;
 }
 
 .toggle input {
@@ -57,12 +60,12 @@
 }
 
 .slider {
-	position: absolute;
+	position: relative;
+	width: 45px;
+	display: block;
+	height: 28px;
+	margin-right: 20px;
 	cursor: pointer;
-	top: 0;
-	left: 0;
-	right: 0;
-	bottom: 0;
 	background-color: #ccc;
 	transition: .3s;
 }
@@ -95,3 +98,28 @@ input:checked + .slider:before {
 	width: 100%;
 	display: block;
 }
+
+div#settings {
+	position: absolute;
+	right: 0;
+	z-index: 1;
+	display: block;
+	margin-top: 7px;
+	border-radius: 3px;
+	border: 1px solid;
+}
+#settings .setting-line {
+	margin: 1.2em 0.6em;
+}
+/* This rule is to draw the little arrow connecting the settings menu to the gear icon. */
+div#settings::before {
+	content: '';
+	position: absolute;
+	right: 11px;
+	border: solid;
+	border-width: 1px 1px 0 0;
+	display: inline-block;
+	padding: 4px;
+	transform: rotate(-45deg);
+	top: -5px;
+}
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 454c7f557b9..548aeedd033 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -63,7 +63,7 @@ function showMain() {
     removeClass(document.getElementById(MAIN_ID), "hidden");
 }
 
-(function () {
+(function() {
     window.rootPath = getVar("root-path");
     window.currentCrate = getVar("current-crate");
     window.searchJS =  resourcePath("search", ".js");
@@ -97,12 +97,12 @@ function showMain() {
 //
 // So I guess you could say things are getting pretty interoperable.
 function getVirtualKey(ev) {
-    if ("key" in ev && typeof ev.key != "undefined") {
+    if ("key" in ev && typeof ev.key !== "undefined") {
         return ev.key;
     }
 
     const c = ev.charCode || ev.keyCode;
-    if (c == 27) {
+    if (c === 27) {
         return "Escape";
     }
     return String.fromCharCode(c);
@@ -929,7 +929,7 @@ function loadCss(cssFileName) {
     searchState.setup();
 }());
 
-(function () {
+(function() {
     let reset_button_timeout = null;
 
     window.copy_path = but => {
diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js
index 7b9d86a851b..fd7a1449763 100644
--- a/src/librustdoc/html/static/js/scrape-examples.js
+++ b/src/librustdoc/html/static/js/scrape-examples.js
@@ -2,7 +2,7 @@
 
 "use strict";
 
-(function () {
+(function() {
     // Number of lines shown when code viewer is not expanded
     const MAX_LINES = 10;
 
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index c784d69dcd6..c726aeeff47 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -70,7 +70,7 @@ function printTab(nb) {
     });
     if (foundCurrentTab && foundCurrentResultSet) {
         searchState.currentTab = nb;
-    } else if (nb != 0) {
+    } else if (nb !== 0) {
         printTab(0);
     }
 }
@@ -200,7 +200,7 @@ function initSearch(rawSearchIndex) {
      * @return {boolean}
      */
     function isPathStart(parserState) {
-        return parserState.userQuery.slice(parserState.pos, parserState.pos + 2) == "::";
+        return parserState.userQuery.slice(parserState.pos, parserState.pos + 2) === "::";
     }
 
     /**
@@ -211,7 +211,7 @@ function initSearch(rawSearchIndex) {
      * @return {boolean}
      */
     function isReturnArrow(parserState) {
-        return parserState.userQuery.slice(parserState.pos, parserState.pos + 2) == "->";
+        return parserState.userQuery.slice(parserState.pos, parserState.pos + 2) === "->";
     }
 
     /**
@@ -1726,7 +1726,7 @@ function initSearch(rawSearchIndex) {
             crates = " in <select id=\"crate-search\"><option value=\"All crates\">" +
                 "All crates</option>";
             for (const c of window.ALL_CRATES) {
-                crates += `<option value="${c}" ${c == filterCrates && "selected"}>${c}</option>`;
+                crates += `<option value="${c}" ${c === filterCrates && "selected"}>${c}</option>`;
             }
             crates += "</select>";
         }
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 8770cc3f3b1..3d1d942eaa9 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -5,7 +5,7 @@
 
 "use strict";
 
-(function () {
+(function() {
     const isSettingsPage = window.location.pathname.endsWith("/settings.html");
 
     function changeSetting(settingName, value) {
@@ -130,12 +130,11 @@
             } else {
                 // This is a toggle.
                 const checked = setting["default"] === true ? " checked" : "";
-                output += `
-                    <label class="toggle">
-                        <input type="checkbox" id="${js_data_name}"${checked}>
-                        <span class="slider"></span>
-                    </label>
-                    <div>${setting_name}</div>`;
+                output += `<label class="toggle">\
+                        <input type="checkbox" id="${js_data_name}"${checked}>\
+                        <span class="slider"></span>\
+                        <span class="label">${setting_name}</span>\
+                    </label>`;
             }
             output += "</div>";
         }
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index 15e3bdf47b2..aaac878d3a3 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -187,7 +187,7 @@ function highlightSourceLines(match) {
     }
 }
 
-const handleSourceHighlight = (function () {
+const handleSourceHighlight = (function() {
     let prev_line_id = 0;
 
     const set_fragment = name => {
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index 3fcf66a817e..4fcf0499234 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -4,7 +4,7 @@ const darkThemes = ["dark", "ayu"];
 window.currentTheme = document.getElementById("themeStyle");
 window.mainTheme = document.getElementById("mainThemeStyle");
 
-const settingsDataset = (function () {
+const settingsDataset = (function() {
     const settingsElement = document.getElementById("default-settings");
     if (settingsElement === null) {
         return null;
@@ -163,7 +163,7 @@ function useSystemTheme(value) {
     }
 }
 
-const updateSystemTheme = (function () {
+const updateSystemTheme = (function() {
     if (!window.matchMedia) {
         // fallback to the CSS computed value
         return () => {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 61acf2de90d..8b3edfd2135 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -70,9 +70,7 @@ extern crate test;
 // See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs
 // about jemalloc.
 #[cfg(feature = "jemalloc")]
-extern crate tikv_jemalloc_sys;
-#[cfg(feature = "jemalloc")]
-use tikv_jemalloc_sys as jemalloc_sys;
+extern crate jemalloc_sys;
 
 use std::default::Default;
 use std::env::{self, VarError};
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index ab57005abc4..83d8fe9ef11 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -20,7 +20,6 @@ use rustc_span::BytePos;
 use smallvec::{smallvec, SmallVec};
 
 use std::borrow::Cow;
-use std::fmt::Write;
 use std::mem;
 use std::ops::Range;
 
@@ -220,80 +219,43 @@ enum MalformedGenerics {
 
 #[derive(Clone, Debug, Hash, PartialEq, Eq)]
 pub(crate) enum UrlFragment {
-    Item(ItemFragment),
+    Item(DefId),
     UserWritten(String),
 }
 
 impl UrlFragment {
     /// Render the fragment, including the leading `#`.
-    pub(crate) fn render(&self, s: &mut String, tcx: TyCtxt<'_>) -> std::fmt::Result {
+    pub(crate) fn render(&self, s: &mut String, tcx: TyCtxt<'_>) {
+        s.push('#');
         match self {
-            UrlFragment::Item(frag) => frag.render(s, tcx),
-            UrlFragment::UserWritten(raw) => write!(s, "#{}", raw),
-        }
-    }
-}
-
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub(crate) struct ItemFragment(FragmentKind, DefId);
-
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub(crate) enum FragmentKind {
-    Method,
-    TyMethod,
-    AssociatedConstant,
-    AssociatedType,
-
-    StructField,
-    Variant,
-    VariantField,
-}
-
-impl FragmentKind {
-    fn from_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> FragmentKind {
-        match tcx.def_kind(def_id) {
-            DefKind::AssocFn => {
-                if tcx.associated_item(def_id).defaultness.has_value() {
-                    FragmentKind::Method
-                } else {
-                    FragmentKind::TyMethod
-                }
-            }
-            DefKind::AssocConst => FragmentKind::AssociatedConstant,
-            DefKind::AssocTy => FragmentKind::AssociatedType,
-            DefKind::Variant => FragmentKind::Variant,
-            DefKind::Field => {
-                if tcx.def_kind(tcx.parent(def_id)) == DefKind::Variant {
-                    FragmentKind::VariantField
-                } else {
-                    FragmentKind::StructField
-                }
-            }
-            kind => bug!("unexpected associated item kind: {:?}", kind),
-        }
-    }
-}
-
-impl ItemFragment {
-    /// Render the fragment, including the leading `#`.
-    pub(crate) fn render(&self, s: &mut String, tcx: TyCtxt<'_>) -> std::fmt::Result {
-        write!(s, "#")?;
-        match *self {
-            ItemFragment(kind, def_id) => {
-                let name = tcx.item_name(def_id);
-                match kind {
-                    FragmentKind::Method => write!(s, "method.{}", name),
-                    FragmentKind::TyMethod => write!(s, "tymethod.{}", name),
-                    FragmentKind::AssociatedConstant => write!(s, "associatedconstant.{}", name),
-                    FragmentKind::AssociatedType => write!(s, "associatedtype.{}", name),
-                    FragmentKind::StructField => write!(s, "structfield.{}", name),
-                    FragmentKind::Variant => write!(s, "variant.{}", name),
-                    FragmentKind::VariantField => {
-                        let variant = tcx.item_name(tcx.parent(def_id));
-                        write!(s, "variant.{}.field.{}", variant, name)
+            &UrlFragment::Item(def_id) => {
+                let kind = match tcx.def_kind(def_id) {
+                    DefKind::AssocFn => {
+                        if tcx.associated_item(def_id).defaultness.has_value() {
+                            "method."
+                        } else {
+                            "tymethod."
+                        }
                     }
-                }
+                    DefKind::AssocConst => "associatedconstant.",
+                    DefKind::AssocTy => "associatedtype.",
+                    DefKind::Variant => "variant.",
+                    DefKind::Field => {
+                        let parent_id = tcx.parent(def_id);
+                        if tcx.def_kind(parent_id) == DefKind::Variant {
+                            s.push_str("variant.");
+                            s.push_str(tcx.item_name(parent_id).as_str());
+                            ".field."
+                        } else {
+                            "structfield."
+                        }
+                    }
+                    kind => bug!("unexpected associated item kind: {:?}", kind),
+                };
+                s.push_str(kind);
+                s.push_str(tcx.item_name(def_id).as_str());
             }
+            UrlFragment::UserWritten(raw) => s.push_str(&raw),
         }
     }
 }
@@ -315,11 +277,6 @@ struct DiagnosticInfo<'a> {
     link_range: Range<usize>,
 }
 
-#[derive(Clone, Debug, Hash)]
-struct CachedLink {
-    res: (Res, Option<UrlFragment>),
-}
-
 struct LinkCollector<'a, 'tcx> {
     cx: &'a mut DocContext<'tcx>,
     /// A stack of modules used to decide what scope to resolve in.
@@ -329,7 +286,7 @@ struct LinkCollector<'a, 'tcx> {
     mod_ids: Vec<DefId>,
     /// 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>>,
+    visited_links: FxHashMap<ResolutionInfo, Option<(Res, Option<UrlFragment>)>>,
 }
 
 impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
@@ -1097,6 +1054,9 @@ impl LinkCollector<'_, '_> {
                 extra_fragment: extra_fragment.clone(),
             },
             diag_info.clone(), // this struct should really be Copy, but Range is not :(
+            // For reference-style links we want to report only one error so unsuccessful
+            // resolutions are cached, for other links we want to report an error every
+            // time so they are not cached.
             matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut),
         )?;
 
@@ -1123,7 +1083,7 @@ impl LinkCollector<'_, '_> {
 
         match res {
             Res::Primitive(prim) => {
-                if let Some(UrlFragment::Item(ItemFragment(_, id))) = fragment {
+                if let Some(UrlFragment::Item(id)) = fragment {
                     // 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,
@@ -1171,12 +1131,11 @@ impl LinkCollector<'_, '_> {
                 })
             }
             Res::Def(kind, id) => {
-                let (kind_for_dis, id_for_dis) =
-                    if let Some(UrlFragment::Item(ItemFragment(_, id))) = fragment {
-                        (self.cx.tcx.def_kind(id), id)
-                    } else {
-                        (kind, id)
-                    };
+                let (kind_for_dis, id_for_dis) = if let Some(UrlFragment::Item(id)) = fragment {
+                    (self.cx.tcx.def_kind(id), id)
+                } else {
+                    (kind, id)
+                };
                 self.verify_disambiguator(
                     path_str,
                     ori_link,
@@ -1294,53 +1253,33 @@ impl LinkCollector<'_, '_> {
         &mut self,
         key: ResolutionInfo,
         diag: DiagnosticInfo<'_>,
-        cache_resolution_failure: bool,
+        // If errors are cached then they are only reported on first ocurrence
+        // which we want in some cases but not in others.
+        cache_errors: bool,
     ) -> Option<(Res, Option<UrlFragment>)> {
-        if let Some(ref cached) = self.visited_links.get(&key) {
-            match cached {
-                Some(cached) => {
-                    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.
-                }
+        if let Some(res) = self.visited_links.get(&key) {
+            if res.is_some() || cache_errors {
+                return res.clone();
             }
         }
 
         let res = self.resolve_with_disambiguator(&key, diag.clone()).and_then(|(res, def_id)| {
             let fragment = match (&key.extra_fragment, def_id) {
                 (Some(_), Some(def_id)) => {
-                    report_anchor_conflict(self.cx, diag, Res::from_def_id(self.cx.tcx, def_id));
+                    report_anchor_conflict(self.cx, diag, def_id);
                     return None;
                 }
                 (Some(u_frag), None) => Some(UrlFragment::UserWritten(u_frag.clone())),
-                (None, Some(def_id)) => Some(UrlFragment::Item(ItemFragment(
-                    FragmentKind::from_def_id(self.cx.tcx, def_id),
-                    def_id,
-                ))),
+                (None, Some(def_id)) => Some(UrlFragment::Item(def_id)),
                 (None, None) => None,
             };
             Some((res, fragment))
         });
 
-        // Cache only if resolved successfully - don't silence duplicate errors
-        if let Some(res) = res {
-            // Store result for the actual namespace
-            self.visited_links.insert(key, Some(CachedLink { res: res.clone() }));
-
-            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
+        if res.is_some() || cache_errors {
+            self.visited_links.insert(key, res.clone());
         }
+        res
     }
 
     /// After parsing the disambiguator, resolve the main part of the link.
@@ -1916,8 +1855,8 @@ fn report_multiple_anchors(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>) {
     anchor_failure(cx, diag_info, &msg, 1)
 }
 
-fn report_anchor_conflict(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, res: Res) {
-    let (link, kind) = (diag_info.ori_link, res.descr());
+fn report_anchor_conflict(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, def_id: DefId) {
+    let (link, kind) = (diag_info.ori_link, Res::from_def_id(cx.tcx, def_id).descr());
     let msg = format!("`{link}` contains an anchor, but links to {kind}s are already anchored");
     anchor_failure(cx, diag_info, &msg, 0)
 }
diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml
index 9a9c45a9b7f..1b2d1e31f52 100644
--- a/src/test/rustdoc-gui/settings.goml
+++ b/src/test/rustdoc-gui/settings.goml
@@ -34,7 +34,7 @@ wait-for: "#settings"
 
 // We check that the "Use system theme" is disabled.
 assert-property: ("#use-system-theme", {"checked": "false"})
-assert: "//*[@class='setting-line']/*[text()='Use system theme']"
+assert: "//*[@class='setting-line']//span[text()='Use system theme']"
 // Meaning that only the "theme" menu is showing up.
 assert: ".setting-line:not(.hidden) #theme"
 assert: ".setting-line.hidden #preferred-dark-theme"
@@ -55,7 +55,13 @@ assert: ".setting-line.hidden #theme"
 assert-text: ("#preferred-dark-theme .setting-name", "Preferred dark theme")
 assert-text: ("#preferred-light-theme .setting-name", "Preferred light theme")
 
+// We now check that clicking on the "sliders"' text is like clicking on the slider.
+// To test it, we use the "Disable keyboard shortcuts".
+local-storage: {"rustdoc-disable-shortcuts": "false"}
+click: ".setting-line:last-child .toggle .label"
+assert-local-storage: {"rustdoc-disable-shortcuts": "true"}
+
 // Now we go to the settings page to check that the CSS is loaded as expected.
 goto: file://|DOC_PATH|/settings.html
 wait-for: "#settings"
-assert-css: (".setting-line .toggle", {"width": "45px", "margin-right": "20px"})
+assert-css: (".setting-line .toggle .slider", {"width": "45px", "margin-right": "20px"})
diff --git a/src/test/rustdoc-ui/doc-comment-multi-line-attr.rs b/src/test/rustdoc-ui/doc-comment-multi-line-attr.rs
new file mode 100644
index 00000000000..97259f782bd
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-comment-multi-line-attr.rs
@@ -0,0 +1,11 @@
+// Regression test for #97440: Multiline inner attribute triggers ICE during doctest
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// check-pass
+
+//! ```rust
+//! #![deny(
+//! unused_parens,
+//! )]
+//! ```
diff --git a/src/test/rustdoc-ui/doc-comment-multi-line-attr.stdout b/src/test/rustdoc-ui/doc-comment-multi-line-attr.stdout
new file mode 100644
index 00000000000..e47edbd2a81
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-comment-multi-line-attr.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/doc-comment-multi-line-attr.rs - (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/ui/asm/aarch64/bad-reg.rs b/src/test/ui/asm/aarch64/bad-reg.rs
index 1a314101916..2b6a9b71cd5 100644
--- a/src/test/ui/asm/aarch64/bad-reg.rs
+++ b/src/test/ui/asm/aarch64/bad-reg.rs
@@ -36,9 +36,11 @@ fn main() {
 
         asm!("", in("p0") foo);
         //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output
+        //~| ERROR type `i32` cannot be used with this register class
         asm!("", out("p0") _);
         asm!("{}", in(preg) foo);
         //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output
+        //~| ERROR type `i32` cannot be used with this register class
         asm!("{}", out(preg) _);
         //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output
 
diff --git a/src/test/ui/asm/aarch64/bad-reg.stderr b/src/test/ui/asm/aarch64/bad-reg.stderr
index e3316b85193..0ba627dac30 100644
--- a/src/test/ui/asm/aarch64/bad-reg.stderr
+++ b/src/test/ui/asm/aarch64/bad-reg.stderr
@@ -87,19 +87,19 @@ LL |         asm!("", in("p0") foo);
    |                  ^^^^^^^^^^^^
 
 error: register class `preg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:40:20
+  --> $DIR/bad-reg.rs:41:20
    |
 LL |         asm!("{}", in(preg) foo);
    |                    ^^^^^^^^^^^^
 
 error: register class `preg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:42:20
+  --> $DIR/bad-reg.rs:44:20
    |
 LL |         asm!("{}", out(preg) _);
    |                    ^^^^^^^^^^^
 
 error: register `x0` conflicts with register `x0`
-  --> $DIR/bad-reg.rs:48:32
+  --> $DIR/bad-reg.rs:50:32
    |
 LL |         asm!("", in("x0") foo, in("w0") bar);
    |                  ------------  ^^^^^^^^^^^^ register `x0`
@@ -107,7 +107,7 @@ LL |         asm!("", in("x0") foo, in("w0") bar);
    |                  register `x0`
 
 error: register `x0` conflicts with register `x0`
-  --> $DIR/bad-reg.rs:50:32
+  --> $DIR/bad-reg.rs:52:32
    |
 LL |         asm!("", in("x0") foo, out("x0") bar);
    |                  ------------  ^^^^^^^^^^^^^ register `x0`
@@ -115,13 +115,13 @@ LL |         asm!("", in("x0") foo, out("x0") bar);
    |                  register `x0`
    |
 help: use `lateout` instead of `out` to avoid conflict
-  --> $DIR/bad-reg.rs:50:18
+  --> $DIR/bad-reg.rs:52:18
    |
 LL |         asm!("", in("x0") foo, out("x0") bar);
    |                  ^^^^^^^^^^^^
 
 error: register `v0` conflicts with register `v0`
-  --> $DIR/bad-reg.rs:53:32
+  --> $DIR/bad-reg.rs:55:32
    |
 LL |         asm!("", in("v0") foo, in("q0") bar);
    |                  ------------  ^^^^^^^^^^^^ register `v0`
@@ -129,7 +129,7 @@ LL |         asm!("", in("v0") foo, in("q0") bar);
    |                  register `v0`
 
 error: register `v0` conflicts with register `v0`
-  --> $DIR/bad-reg.rs:55:32
+  --> $DIR/bad-reg.rs:57:32
    |
 LL |         asm!("", in("v0") foo, out("q0") bar);
    |                  ------------  ^^^^^^^^^^^^^ register `v0`
@@ -137,10 +137,26 @@ LL |         asm!("", in("v0") foo, out("q0") bar);
    |                  register `v0`
    |
 help: use `lateout` instead of `out` to avoid conflict
-  --> $DIR/bad-reg.rs:55:18
+  --> $DIR/bad-reg.rs:57:18
    |
 LL |         asm!("", in("v0") foo, out("q0") bar);
    |                  ^^^^^^^^^^^^
 
-error: aborting due to 18 previous errors
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:37:27
+   |
+LL |         asm!("", in("p0") foo);
+   |                           ^^^
+   |
+   = note: register class `preg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:41:29
+   |
+LL |         asm!("{}", in(preg) foo);
+   |                             ^^^
+   |
+   = note: register class `preg` supports these types: 
+
+error: aborting due to 20 previous errors
 
diff --git a/src/test/ui/asm/aarch64/type-check-2-2.rs b/src/test/ui/asm/aarch64/type-check-2-2.rs
new file mode 100644
index 00000000000..e4d29754556
--- /dev/null
+++ b/src/test/ui/asm/aarch64/type-check-2-2.rs
@@ -0,0 +1,37 @@
+// only-aarch64
+
+#![feature(repr_simd, never_type, asm_sym)]
+
+use std::arch::{asm, global_asm};
+
+#[repr(simd)]
+#[derive(Clone, Copy)]
+struct SimdType(f32, f32, f32, f32);
+
+#[repr(simd)]
+struct SimdNonCopy(f32, f32, f32, f32);
+
+fn main() {
+    unsafe {
+        // Inputs must be initialized
+
+        let x: u64;
+        asm!("{}", in(reg) x);
+        //~^ ERROR use of possibly-uninitialized variable: `x`
+        let mut y: u64;
+        asm!("{}", inout(reg) y);
+        //~^ ERROR use of possibly-uninitialized variable: `y`
+        let _ = y;
+
+        // Outputs require mutable places
+
+        let v: Vec<u64> = vec![0, 1, 2];
+        asm!("{}", in(reg) v[0]);
+        asm!("{}", out(reg) v[0]);
+        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+        asm!("{}", inout(reg) v[0]);
+        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+
+        // Sym operands must point to a function or static
+    }
+}
diff --git a/src/test/ui/asm/aarch64/type-check-2-2.stderr b/src/test/ui/asm/aarch64/type-check-2-2.stderr
new file mode 100644
index 00000000000..37bbe394994
--- /dev/null
+++ b/src/test/ui/asm/aarch64/type-check-2-2.stderr
@@ -0,0 +1,34 @@
+error[E0381]: use of possibly-uninitialized variable: `x`
+  --> $DIR/type-check-2-2.rs:19:28
+   |
+LL |         asm!("{}", in(reg) x);
+   |                            ^ use of possibly-uninitialized `x`
+
+error[E0381]: use of possibly-uninitialized variable: `y`
+  --> $DIR/type-check-2-2.rs:22:9
+   |
+LL |         asm!("{}", inout(reg) y);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y`
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+  --> $DIR/type-check-2-2.rs:30:29
+   |
+LL |         let v: Vec<u64> = vec![0, 1, 2];
+   |             - help: consider changing this to be mutable: `mut v`
+LL |         asm!("{}", in(reg) v[0]);
+LL |         asm!("{}", out(reg) v[0]);
+   |                             ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+  --> $DIR/type-check-2-2.rs:32:31
+   |
+LL |         let v: Vec<u64> = vec![0, 1, 2];
+   |             - help: consider changing this to be mutable: `mut v`
+...
+LL |         asm!("{}", inout(reg) v[0]);
+   |                               ^ cannot borrow as mutable
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0381, E0596.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/asm/aarch64/type-check-2.rs b/src/test/ui/asm/aarch64/type-check-2.rs
index 9e53a2e0c52..fdafe63c7b0 100644
--- a/src/test/ui/asm/aarch64/type-check-2.rs
+++ b/src/test/ui/asm/aarch64/type-check-2.rs
@@ -15,23 +15,6 @@ fn main() {
     unsafe {
         // Inputs must be initialized
 
-        let x: u64;
-        asm!("{}", in(reg) x);
-        //~^ ERROR use of possibly-uninitialized variable: `x`
-        let mut y: u64;
-        asm!("{}", inout(reg) y);
-        //~^ ERROR use of possibly-uninitialized variable: `y`
-        let _ = y;
-
-        // Outputs require mutable places
-
-        let v: Vec<u64> = vec![0, 1, 2];
-        asm!("{}", in(reg) v[0]);
-        asm!("{}", out(reg) v[0]);
-        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
-        asm!("{}", inout(reg) v[0]);
-        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
-
         // Sym operands must point to a function or static
 
         const C: i32 = 0;
diff --git a/src/test/ui/asm/aarch64/type-check-2.stderr b/src/test/ui/asm/aarch64/type-check-2.stderr
index 6047bed6e78..4b99652cd20 100644
--- a/src/test/ui/asm/aarch64/type-check-2.stderr
+++ b/src/test/ui/asm/aarch64/type-check-2.stderr
@@ -1,13 +1,29 @@
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:75:19
+   |
+LL | global_asm!("{}", sym C);
+   |                   ^^^^^ is an `i32`
+   |
+   = help: `sym` operands must refer to either a function or a static
+
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:24:20
+   |
+LL |         asm!("{}", sym C);
+   |                    ^^^^^ is an `i32`
+   |
+   = help: `sym` operands must refer to either a function or a static
+
 error: arguments for inline assembly must be copyable
-  --> $DIR/type-check-2.rs:46:31
+  --> $DIR/type-check-2.rs:29:31
    |
 LL |         asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `SimdNonCopy` does not implement the Copy trait
 
-error: cannot use value of type `[closure@$DIR/type-check-2.rs:58:28: 58:38]` for inline assembly
-  --> $DIR/type-check-2.rs:58:28
+error: cannot use value of type `[closure@$DIR/type-check-2.rs:41:28: 41:38]` for inline assembly
+  --> $DIR/type-check-2.rs:41:28
    |
 LL |         asm!("{}", in(reg) |x: i32| x);
    |                            ^^^^^^^^^^
@@ -15,7 +31,7 @@ LL |         asm!("{}", in(reg) |x: i32| x);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `Vec<i32>` for inline assembly
-  --> $DIR/type-check-2.rs:60:28
+  --> $DIR/type-check-2.rs:43:28
    |
 LL |         asm!("{}", in(reg) vec![0]);
    |                            ^^^^^^^
@@ -24,7 +40,7 @@ LL |         asm!("{}", in(reg) vec![0]);
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: cannot use value of type `(i32, i32, i32)` for inline assembly
-  --> $DIR/type-check-2.rs:62:28
+  --> $DIR/type-check-2.rs:45:28
    |
 LL |         asm!("{}", in(reg) (1, 2, 3));
    |                            ^^^^^^^^^
@@ -32,7 +48,7 @@ LL |         asm!("{}", in(reg) (1, 2, 3));
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `[i32; 3]` for inline assembly
-  --> $DIR/type-check-2.rs:64:28
+  --> $DIR/type-check-2.rs:47:28
    |
 LL |         asm!("{}", in(reg) [1, 2, 3]);
    |                            ^^^^^^^^^
@@ -40,7 +56,7 @@ LL |         asm!("{}", in(reg) [1, 2, 3]);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `fn() {main}` for inline assembly
-  --> $DIR/type-check-2.rs:72:31
+  --> $DIR/type-check-2.rs:55:31
    |
 LL |         asm!("{}", inout(reg) f);
    |                               ^
@@ -48,60 +64,12 @@ LL |         asm!("{}", inout(reg) f);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `&mut i32` for inline assembly
-  --> $DIR/type-check-2.rs:75:31
+  --> $DIR/type-check-2.rs:58:31
    |
 LL |         asm!("{}", inout(reg) r);
    |                               ^
    |
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
-error: invalid `sym` operand
-  --> $DIR/type-check-2.rs:41:20
-   |
-LL |         asm!("{}", sym C);
-   |                    ^^^^^ is an `i32`
-   |
-   = help: `sym` operands must refer to either a function or a static
-
-error: invalid `sym` operand
-  --> $DIR/type-check-2.rs:92:19
-   |
-LL | global_asm!("{}", sym C);
-   |                   ^^^^^ is an `i32`
-   |
-   = help: `sym` operands must refer to either a function or a static
-
-error[E0381]: use of possibly-uninitialized variable: `x`
-  --> $DIR/type-check-2.rs:19:28
-   |
-LL |         asm!("{}", in(reg) x);
-   |                            ^ use of possibly-uninitialized `x`
-
-error[E0381]: use of possibly-uninitialized variable: `y`
-  --> $DIR/type-check-2.rs:22:9
-   |
-LL |         asm!("{}", inout(reg) y);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y`
-
-error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
-  --> $DIR/type-check-2.rs:30:29
-   |
-LL |         let v: Vec<u64> = vec![0, 1, 2];
-   |             - help: consider changing this to be mutable: `mut v`
-LL |         asm!("{}", in(reg) v[0]);
-LL |         asm!("{}", out(reg) v[0]);
-   |                             ^ cannot borrow as mutable
-
-error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
-  --> $DIR/type-check-2.rs:32:31
-   |
-LL |         let v: Vec<u64> = vec![0, 1, 2];
-   |             - help: consider changing this to be mutable: `mut v`
-...
-LL |         asm!("{}", inout(reg) v[0]);
-   |                               ^ cannot borrow as mutable
-
-error: aborting due to 13 previous errors
+error: aborting due to 9 previous errors
 
-Some errors have detailed explanations: E0381, E0596.
-For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/asm/aarch64/type-check-3.rs b/src/test/ui/asm/aarch64/type-check-3.rs
index 8cac18b8052..623f6593d79 100644
--- a/src/test/ui/asm/aarch64/type-check-3.rs
+++ b/src/test/ui/asm/aarch64/type-check-3.rs
@@ -95,21 +95,3 @@ fn main() {
         asm!("{:x}", inout(reg) main => val_u64);
     }
 }
-
-// Constants must be... constant
-
-static S: i32 = 1;
-const fn const_foo(x: i32) -> i32 {
-    x
-}
-const fn const_bar<T>(x: T) -> T {
-    x
-}
-global_asm!("{}", const S);
-//~^ ERROR constants cannot refer to statics
-global_asm!("{}", const const_foo(0));
-global_asm!("{}", const const_foo(S));
-//~^ ERROR constants cannot refer to statics
-global_asm!("{}", const const_bar(0));
-global_asm!("{}", const const_bar(S));
-//~^ ERROR constants cannot refer to statics
diff --git a/src/test/ui/asm/aarch64/type-check-3.stderr b/src/test/ui/asm/aarch64/type-check-3.stderr
index c31a62ae791..b320abdc01b 100644
--- a/src/test/ui/asm/aarch64/type-check-3.stderr
+++ b/src/test/ui/asm/aarch64/type-check-3.stderr
@@ -143,30 +143,5 @@ LL |         asm!("{:x}", inout(reg) main => val_u32);
    |
    = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
 
-error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:108:25
-   |
-LL | global_asm!("{}", const S);
-   |                         ^
-   |
-   = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:111:35
-   |
-LL | global_asm!("{}", const const_foo(S));
-   |                                   ^
-   |
-   = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:114:35
-   |
-LL | global_asm!("{}", const const_bar(S));
-   |                                   ^
-   |
-   = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error: aborting due to 9 previous errors; 10 warnings emitted
+error: aborting due to 6 previous errors; 10 warnings emitted
 
-For more information about this error, try `rustc --explain E0013`.
diff --git a/src/test/ui/asm/aarch64/type-check-4.rs b/src/test/ui/asm/aarch64/type-check-4.rs
new file mode 100644
index 00000000000..bd23755c023
--- /dev/null
+++ b/src/test/ui/asm/aarch64/type-check-4.rs
@@ -0,0 +1,32 @@
+// only-aarch64
+// compile-flags: -C target-feature=+neon
+
+#![feature(repr_simd, stdsimd, asm_const)]
+
+use std::arch::aarch64::float64x2_t;
+use std::arch::{asm, global_asm};
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct Simd256bit(f64, f64, f64, f64);
+
+fn main() {
+}
+
+// Constants must be... constant
+
+static S: i32 = 1;
+const fn const_foo(x: i32) -> i32 {
+    x
+}
+const fn const_bar<T>(x: T) -> T {
+    x
+}
+global_asm!("{}", const S);
+//~^ ERROR constants cannot refer to statics
+global_asm!("{}", const const_foo(0));
+global_asm!("{}", const const_foo(S));
+//~^ ERROR constants cannot refer to statics
+global_asm!("{}", const const_bar(0));
+global_asm!("{}", const const_bar(S));
+//~^ ERROR constants cannot refer to statics
diff --git a/src/test/ui/asm/aarch64/type-check-4.stderr b/src/test/ui/asm/aarch64/type-check-4.stderr
new file mode 100644
index 00000000000..4837e647bea
--- /dev/null
+++ b/src/test/ui/asm/aarch64/type-check-4.stderr
@@ -0,0 +1,27 @@
+error[E0013]: constants cannot refer to statics
+  --> $DIR/type-check-4.rs:25:25
+   |
+LL | global_asm!("{}", const S);
+   |                         ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+  --> $DIR/type-check-4.rs:28:35
+   |
+LL | global_asm!("{}", const const_foo(S));
+   |                                   ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+  --> $DIR/type-check-4.rs:31:35
+   |
+LL | global_asm!("{}", const const_bar(S));
+   |                                   ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0013`.
diff --git a/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr b/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr
index 11c4e01f418..7ef93e15f5b 100644
--- a/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr
+++ b/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr
@@ -89,7 +89,7 @@ LL |         asm!("{:foo}", in(reg) foo);
    |                 ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:52:18
+  --> $DIR/bad-template.rs:53:18
    |
 LL |         asm!("", in(reg) 0, in(reg) 1);
    |                  ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -99,7 +99,7 @@ LL |         asm!("", in(reg) 0, in(reg) 1);
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:58:14
+  --> $DIR/bad-template.rs:59:14
    |
 LL | global_asm!("{}");
    |              ^^ from here
@@ -107,7 +107,7 @@ LL | global_asm!("{}");
    = note: no arguments were given
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:60:14
+  --> $DIR/bad-template.rs:61:14
    |
 LL | global_asm!("{1}", const FOO);
    |              ^^^ from here
@@ -115,7 +115,7 @@ LL | global_asm!("{1}", const FOO);
    = note: there is 1 argument
 
 error: argument never used
-  --> $DIR/bad-template.rs:60:20
+  --> $DIR/bad-template.rs:61:20
    |
 LL | global_asm!("{1}", const FOO);
    |                    ^^^^^^^^^ argument never used
@@ -123,13 +123,13 @@ LL | global_asm!("{1}", const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
 
 error: there is no argument named `a`
-  --> $DIR/bad-template.rs:63:15
+  --> $DIR/bad-template.rs:64:15
    |
 LL | global_asm!("{a}");
    |               ^
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:65:14
+  --> $DIR/bad-template.rs:66:14
    |
 LL | global_asm!("{}", a = const FOO);
    |              ^^   ------------- named argument
@@ -138,13 +138,13 @@ LL | global_asm!("{}", a = const FOO);
    |
    = note: no positional arguments were given
 note: named arguments cannot be referenced by position
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^
 
 error: named argument never used
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^ named argument never used
@@ -152,7 +152,7 @@ LL | global_asm!("{}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:68:14
+  --> $DIR/bad-template.rs:69:14
    |
 LL | global_asm!("{1}", a = const FOO);
    |              ^^^ from here
@@ -160,7 +160,7 @@ LL | global_asm!("{1}", a = const FOO);
    = note: no positional arguments were given
 
 error: named argument never used
-  --> $DIR/bad-template.rs:68:20
+  --> $DIR/bad-template.rs:69:20
    |
 LL | global_asm!("{1}", a = const FOO);
    |                    ^^^^^^^^^^^^^ named argument never used
@@ -168,13 +168,13 @@ LL | global_asm!("{1}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: asm template modifier must be a single character
-  --> $DIR/bad-template.rs:71:16
+  --> $DIR/bad-template.rs:72:16
    |
 LL | global_asm!("{:foo}", const FOO);
    |                ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:73:17
+  --> $DIR/bad-template.rs:74:17
    |
 LL | global_asm!("", const FOO, const FOO);
    |                 ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -183,5 +183,15 @@ LL | global_asm!("", const FOO, const FOO);
    |
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
-error: aborting due to 21 previous errors
+warning: formatting may not be suitable for sub-register argument
+  --> $DIR/bad-template.rs:50:15
+   |
+LL |         asm!("{:foo}", in(reg) foo);
+   |               ^^^^^^           --- for this argument
+   |
+   = note: `#[warn(asm_sub_register)]` on by default
+   = help: use the `w` modifier to have the register formatted as `w0`
+   = help: or use the `x` modifier to keep the default formatting of `x0`
+
+error: aborting due to 21 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr b/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr
index 11c4e01f418..7ef93e15f5b 100644
--- a/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr
+++ b/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr
@@ -89,7 +89,7 @@ LL |         asm!("{:foo}", in(reg) foo);
    |                 ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:52:18
+  --> $DIR/bad-template.rs:53:18
    |
 LL |         asm!("", in(reg) 0, in(reg) 1);
    |                  ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -99,7 +99,7 @@ LL |         asm!("", in(reg) 0, in(reg) 1);
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:58:14
+  --> $DIR/bad-template.rs:59:14
    |
 LL | global_asm!("{}");
    |              ^^ from here
@@ -107,7 +107,7 @@ LL | global_asm!("{}");
    = note: no arguments were given
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:60:14
+  --> $DIR/bad-template.rs:61:14
    |
 LL | global_asm!("{1}", const FOO);
    |              ^^^ from here
@@ -115,7 +115,7 @@ LL | global_asm!("{1}", const FOO);
    = note: there is 1 argument
 
 error: argument never used
-  --> $DIR/bad-template.rs:60:20
+  --> $DIR/bad-template.rs:61:20
    |
 LL | global_asm!("{1}", const FOO);
    |                    ^^^^^^^^^ argument never used
@@ -123,13 +123,13 @@ LL | global_asm!("{1}", const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
 
 error: there is no argument named `a`
-  --> $DIR/bad-template.rs:63:15
+  --> $DIR/bad-template.rs:64:15
    |
 LL | global_asm!("{a}");
    |               ^
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:65:14
+  --> $DIR/bad-template.rs:66:14
    |
 LL | global_asm!("{}", a = const FOO);
    |              ^^   ------------- named argument
@@ -138,13 +138,13 @@ LL | global_asm!("{}", a = const FOO);
    |
    = note: no positional arguments were given
 note: named arguments cannot be referenced by position
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^
 
 error: named argument never used
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^ named argument never used
@@ -152,7 +152,7 @@ LL | global_asm!("{}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:68:14
+  --> $DIR/bad-template.rs:69:14
    |
 LL | global_asm!("{1}", a = const FOO);
    |              ^^^ from here
@@ -160,7 +160,7 @@ LL | global_asm!("{1}", a = const FOO);
    = note: no positional arguments were given
 
 error: named argument never used
-  --> $DIR/bad-template.rs:68:20
+  --> $DIR/bad-template.rs:69:20
    |
 LL | global_asm!("{1}", a = const FOO);
    |                    ^^^^^^^^^^^^^ named argument never used
@@ -168,13 +168,13 @@ LL | global_asm!("{1}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: asm template modifier must be a single character
-  --> $DIR/bad-template.rs:71:16
+  --> $DIR/bad-template.rs:72:16
    |
 LL | global_asm!("{:foo}", const FOO);
    |                ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:73:17
+  --> $DIR/bad-template.rs:74:17
    |
 LL | global_asm!("", const FOO, const FOO);
    |                 ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -183,5 +183,15 @@ LL | global_asm!("", const FOO, const FOO);
    |
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
-error: aborting due to 21 previous errors
+warning: formatting may not be suitable for sub-register argument
+  --> $DIR/bad-template.rs:50:15
+   |
+LL |         asm!("{:foo}", in(reg) foo);
+   |               ^^^^^^           --- for this argument
+   |
+   = note: `#[warn(asm_sub_register)]` on by default
+   = help: use the `w` modifier to have the register formatted as `w0`
+   = help: or use the `x` modifier to keep the default formatting of `x0`
+
+error: aborting due to 21 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/asm/bad-template.rs b/src/test/ui/asm/bad-template.rs
index b062c45e6ea..55637174792 100644
--- a/src/test/ui/asm/bad-template.rs
+++ b/src/test/ui/asm/bad-template.rs
@@ -49,6 +49,7 @@ fn main() {
         //[aarch64_thirunsafeck,aarch64_mirunsafeck]~^ ERROR invalid reference to argument at index 0
         asm!("{:foo}", in(reg) foo);
         //~^ ERROR asm template modifier must be a single character
+        //~| WARN formatting may not be suitable for sub-register argument [asm_sub_register]
         asm!("", in(reg) 0, in(reg) 1);
         //~^ ERROR multiple unused asm arguments
     }
diff --git a/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr b/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr
index c198e0a69dd..250bc3be42e 100644
--- a/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr
+++ b/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr
@@ -89,7 +89,7 @@ LL |         asm!("{:foo}", in(reg) foo);
    |                 ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:52:18
+  --> $DIR/bad-template.rs:53:18
    |
 LL |         asm!("", in(reg) 0, in(reg) 1);
    |                  ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -99,7 +99,7 @@ LL |         asm!("", in(reg) 0, in(reg) 1);
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:58:14
+  --> $DIR/bad-template.rs:59:14
    |
 LL | global_asm!("{}");
    |              ^^ from here
@@ -107,7 +107,7 @@ LL | global_asm!("{}");
    = note: no arguments were given
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:60:14
+  --> $DIR/bad-template.rs:61:14
    |
 LL | global_asm!("{1}", const FOO);
    |              ^^^ from here
@@ -115,7 +115,7 @@ LL | global_asm!("{1}", const FOO);
    = note: there is 1 argument
 
 error: argument never used
-  --> $DIR/bad-template.rs:60:20
+  --> $DIR/bad-template.rs:61:20
    |
 LL | global_asm!("{1}", const FOO);
    |                    ^^^^^^^^^ argument never used
@@ -123,13 +123,13 @@ LL | global_asm!("{1}", const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
 
 error: there is no argument named `a`
-  --> $DIR/bad-template.rs:63:15
+  --> $DIR/bad-template.rs:64:15
    |
 LL | global_asm!("{a}");
    |               ^
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:65:14
+  --> $DIR/bad-template.rs:66:14
    |
 LL | global_asm!("{}", a = const FOO);
    |              ^^   ------------- named argument
@@ -138,13 +138,13 @@ LL | global_asm!("{}", a = const FOO);
    |
    = note: no positional arguments were given
 note: named arguments cannot be referenced by position
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^
 
 error: named argument never used
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^ named argument never used
@@ -152,7 +152,7 @@ LL | global_asm!("{}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:68:14
+  --> $DIR/bad-template.rs:69:14
    |
 LL | global_asm!("{1}", a = const FOO);
    |              ^^^ from here
@@ -160,7 +160,7 @@ LL | global_asm!("{1}", a = const FOO);
    = note: no positional arguments were given
 
 error: named argument never used
-  --> $DIR/bad-template.rs:68:20
+  --> $DIR/bad-template.rs:69:20
    |
 LL | global_asm!("{1}", a = const FOO);
    |                    ^^^^^^^^^^^^^ named argument never used
@@ -168,13 +168,13 @@ LL | global_asm!("{1}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: asm template modifier must be a single character
-  --> $DIR/bad-template.rs:71:16
+  --> $DIR/bad-template.rs:72:16
    |
 LL | global_asm!("{:foo}", const FOO);
    |                ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:73:17
+  --> $DIR/bad-template.rs:74:17
    |
 LL | global_asm!("", const FOO, const FOO);
    |                 ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -183,5 +183,15 @@ LL | global_asm!("", const FOO, const FOO);
    |
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
-error: aborting due to 21 previous errors
+warning: formatting may not be suitable for sub-register argument
+  --> $DIR/bad-template.rs:50:15
+   |
+LL |         asm!("{:foo}", in(reg) foo);
+   |               ^^^^^^           --- for this argument
+   |
+   = note: `#[warn(asm_sub_register)]` on by default
+   = help: use the `e` modifier to have the register formatted as `eax`
+   = help: or use the `r` modifier to keep the default formatting of `rax`
+
+error: aborting due to 21 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr b/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr
index c198e0a69dd..250bc3be42e 100644
--- a/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr
+++ b/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr
@@ -89,7 +89,7 @@ LL |         asm!("{:foo}", in(reg) foo);
    |                 ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:52:18
+  --> $DIR/bad-template.rs:53:18
    |
 LL |         asm!("", in(reg) 0, in(reg) 1);
    |                  ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -99,7 +99,7 @@ LL |         asm!("", in(reg) 0, in(reg) 1);
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:58:14
+  --> $DIR/bad-template.rs:59:14
    |
 LL | global_asm!("{}");
    |              ^^ from here
@@ -107,7 +107,7 @@ LL | global_asm!("{}");
    = note: no arguments were given
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:60:14
+  --> $DIR/bad-template.rs:61:14
    |
 LL | global_asm!("{1}", const FOO);
    |              ^^^ from here
@@ -115,7 +115,7 @@ LL | global_asm!("{1}", const FOO);
    = note: there is 1 argument
 
 error: argument never used
-  --> $DIR/bad-template.rs:60:20
+  --> $DIR/bad-template.rs:61:20
    |
 LL | global_asm!("{1}", const FOO);
    |                    ^^^^^^^^^ argument never used
@@ -123,13 +123,13 @@ LL | global_asm!("{1}", const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
 
 error: there is no argument named `a`
-  --> $DIR/bad-template.rs:63:15
+  --> $DIR/bad-template.rs:64:15
    |
 LL | global_asm!("{a}");
    |               ^
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:65:14
+  --> $DIR/bad-template.rs:66:14
    |
 LL | global_asm!("{}", a = const FOO);
    |              ^^   ------------- named argument
@@ -138,13 +138,13 @@ LL | global_asm!("{}", a = const FOO);
    |
    = note: no positional arguments were given
 note: named arguments cannot be referenced by position
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^
 
 error: named argument never used
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^ named argument never used
@@ -152,7 +152,7 @@ LL | global_asm!("{}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:68:14
+  --> $DIR/bad-template.rs:69:14
    |
 LL | global_asm!("{1}", a = const FOO);
    |              ^^^ from here
@@ -160,7 +160,7 @@ LL | global_asm!("{1}", a = const FOO);
    = note: no positional arguments were given
 
 error: named argument never used
-  --> $DIR/bad-template.rs:68:20
+  --> $DIR/bad-template.rs:69:20
    |
 LL | global_asm!("{1}", a = const FOO);
    |                    ^^^^^^^^^^^^^ named argument never used
@@ -168,13 +168,13 @@ LL | global_asm!("{1}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: asm template modifier must be a single character
-  --> $DIR/bad-template.rs:71:16
+  --> $DIR/bad-template.rs:72:16
    |
 LL | global_asm!("{:foo}", const FOO);
    |                ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:73:17
+  --> $DIR/bad-template.rs:74:17
    |
 LL | global_asm!("", const FOO, const FOO);
    |                 ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -183,5 +183,15 @@ LL | global_asm!("", const FOO, const FOO);
    |
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
-error: aborting due to 21 previous errors
+warning: formatting may not be suitable for sub-register argument
+  --> $DIR/bad-template.rs:50:15
+   |
+LL |         asm!("{:foo}", in(reg) foo);
+   |               ^^^^^^           --- for this argument
+   |
+   = note: `#[warn(asm_sub_register)]` on by default
+   = help: use the `e` modifier to have the register formatted as `eax`
+   = help: or use the `r` modifier to keep the default formatting of `rax`
+
+error: aborting due to 21 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/asm/naked-functions.rs b/src/test/ui/asm/naked-functions.rs
index 2a57afa1a6a..9e626f5711d 100644
--- a/src/test/ui/asm/naked-functions.rs
+++ b/src/test/ui/asm/naked-functions.rs
@@ -37,6 +37,7 @@ pub unsafe extern "C" fn inc(a: u32) -> u32 {
 }
 
 #[naked]
+#[allow(asm_sub_register)]
 pub unsafe extern "C" fn inc_asm(a: u32) -> u32 {
     asm!("/* {0} */", in(reg) a, options(noreturn));
     //~^ ERROR referencing function parameters is not allowed in naked functions
diff --git a/src/test/ui/asm/naked-functions.stderr b/src/test/ui/asm/naked-functions.stderr
index 8a610b25f00..1828066b692 100644
--- a/src/test/ui/asm/naked-functions.stderr
+++ b/src/test/ui/asm/naked-functions.stderr
@@ -1,23 +1,23 @@
 error: asm with the `pure` option must have at least one output
-  --> $DIR/naked-functions.rs:110:14
+  --> $DIR/naked-functions.rs:111:14
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^
 
 error: this is a user specified error
-  --> $DIR/naked-functions.rs:202:5
+  --> $DIR/naked-functions.rs:203:5
    |
 LL |     compile_error!("this is a user specified error")
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this is a user specified error
-  --> $DIR/naked-functions.rs:208:5
+  --> $DIR/naked-functions.rs:209:5
    |
 LL |     compile_error!("this is a user specified error");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: asm template must be a string literal
-  --> $DIR/naked-functions.rs:215:10
+  --> $DIR/naked-functions.rs:216:10
    |
 LL |     asm!(invalid_syntax)
    |          ^^^^^^^^^^^^^^
@@ -66,7 +66,7 @@ LL | | }
    | |_^
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:41:31
+  --> $DIR/naked-functions.rs:42:31
    |
 LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    |                               ^
@@ -74,13 +74,13 @@ LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    = help: follow the calling convention in asm block to use parameters
 
 error[E0787]: only `const` and `sym` operands are supported in naked functions
-  --> $DIR/naked-functions.rs:41:23
+  --> $DIR/naked-functions.rs:42:23
    |
 LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    |                       ^^^^^^^^^
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:47:1
+  --> $DIR/naked-functions.rs:48:1
    |
 LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
 LL | |
@@ -90,7 +90,7 @@ LL | | }
    | |_^
 
 error[E0787]: only `const` and `sym` operands are supported in naked functions
-  --> $DIR/naked-functions.rs:64:10
+  --> $DIR/naked-functions.rs:65:10
    |
 LL |          in(reg) a,
    |          ^^^^^^^^^
@@ -105,7 +105,7 @@ LL |          out(reg) e,
    |          ^^^^^^^^^^
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:62:5
+  --> $DIR/naked-functions.rs:63:5
    |
 LL | /     asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
 LL | |
@@ -122,7 +122,7 @@ LL |          sym G, options(noreturn),
    |               +++++++++++++++++++
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:53:1
+  --> $DIR/naked-functions.rs:54:1
    |
 LL | / pub unsafe extern "C" fn unsupported_operands() {
 LL | |
@@ -142,7 +142,7 @@ LL | | }
    | |_^
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:76:1
+  --> $DIR/naked-functions.rs:77:1
    |
 LL | / pub extern "C" fn missing_assembly() {
 LL | |
@@ -150,7 +150,7 @@ LL | | }
    | |_^
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:83:5
+  --> $DIR/naked-functions.rs:84:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
@@ -161,7 +161,7 @@ LL |     asm!("", options(noreturn));
    |            +++++++++++++++++++
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:85:5
+  --> $DIR/naked-functions.rs:86:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
@@ -172,7 +172,7 @@ LL |     asm!("", options(noreturn));
    |            +++++++++++++++++++
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:87:5
+  --> $DIR/naked-functions.rs:88:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
@@ -183,7 +183,7 @@ LL |     asm!("", options(noreturn));
    |            +++++++++++++++++++
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:81:1
+  --> $DIR/naked-functions.rs:82:1
    |
 LL | / pub extern "C" fn too_many_asm_blocks() {
 LL | |
@@ -201,7 +201,7 @@ LL | | }
    | |_^
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:96:11
+  --> $DIR/naked-functions.rs:97:11
    |
 LL |         *&y
    |           ^
@@ -209,7 +209,7 @@ LL |         *&y
    = help: follow the calling convention in asm block to use parameters
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:94:5
+  --> $DIR/naked-functions.rs:95:5
    |
 LL | /     pub extern "C" fn inner(y: usize) -> usize {
 LL | |
@@ -220,19 +220,19 @@ LL | |     }
    | |_____^
 
 error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_flags`
-  --> $DIR/naked-functions.rs:104:5
+  --> $DIR/naked-functions.rs:105:5
    |
 LL |     asm!("", options(nomem, preserves_flags, noreturn));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0787]: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
-  --> $DIR/naked-functions.rs:110:5
+  --> $DIR/naked-functions.rs:111:5
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:110:5
+  --> $DIR/naked-functions.rs:111:5
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -243,13 +243,13 @@ LL |     asm!("", options(noreturn), options(readonly, nostack), options(pure));
    |            +++++++++++++++++++
 
 error[E0787]: asm options unsupported in naked functions: `may_unwind`
-  --> $DIR/naked-functions.rs:118:5
+  --> $DIR/naked-functions.rs:119:5
    |
 LL |     asm!("", options(noreturn, may_unwind));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: Rust ABI is unsupported in naked functions
-  --> $DIR/naked-functions.rs:123:15
+  --> $DIR/naked-functions.rs:124:15
    |
 LL | pub unsafe fn default_abi() {
    |               ^^^^^^^^^^^
@@ -257,43 +257,43 @@ LL | pub unsafe fn default_abi() {
    = note: `#[warn(undefined_naked_function_abi)]` on by default
 
 warning: Rust ABI is unsupported in naked functions
-  --> $DIR/naked-functions.rs:129:15
+  --> $DIR/naked-functions.rs:130:15
    |
 LL | pub unsafe fn rust_abi() {
    |               ^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:169:1
+  --> $DIR/naked-functions.rs:170:1
    |
 LL | #[inline]
    | ^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:176:1
+  --> $DIR/naked-functions.rs:177:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:183:1
+  --> $DIR/naked-functions.rs:184:1
    |
 LL | #[inline(never)]
    | ^^^^^^^^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:190:1
+  --> $DIR/naked-functions.rs:191:1
    |
 LL | #[inline]
    | ^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:192:1
+  --> $DIR/naked-functions.rs:193:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:194:1
+  --> $DIR/naked-functions.rs:195:1
    |
 LL | #[inline(never)]
    | ^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/asm/type-check-1.rs b/src/test/ui/asm/type-check-1.rs
index 367a035387b..50b369ae045 100644
--- a/src/test/ui/asm/type-check-1.rs
+++ b/src/test/ui/asm/type-check-1.rs
@@ -22,10 +22,13 @@ fn main() {
         let v: [u64; 3] = [0, 1, 2];
         asm!("{}", in(reg) v[..]);
         //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
+        //~| ERROR cannot use value of type `[u64]` for inline assembly
         asm!("{}", out(reg) v[..]);
         //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
+        //~| ERROR cannot use value of type `[u64]` for inline assembly
         asm!("{}", inout(reg) v[..]);
         //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
+        //~| ERROR cannot use value of type `[u64]` for inline assembly
 
         // Constants must be... constant
 
diff --git a/src/test/ui/asm/type-check-1.stderr b/src/test/ui/asm/type-check-1.stderr
index bf5ea1befb6..52d814ce682 100644
--- a/src/test/ui/asm/type-check-1.stderr
+++ b/src/test/ui/asm/type-check-1.stderr
@@ -1,5 +1,5 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/type-check-1.rs:39:26
+  --> $DIR/type-check-1.rs:42:26
    |
 LL |         let x = 0;
    |         ----- help: consider using `const` instead of `let`: `const x`
@@ -8,7 +8,7 @@ LL |         asm!("{}", const x);
    |                          ^ non-constant value
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/type-check-1.rs:42:36
+  --> $DIR/type-check-1.rs:45:36
    |
 LL |         let x = 0;
    |         ----- help: consider using `const` instead of `let`: `const x`
@@ -17,7 +17,7 @@ LL |         asm!("{}", const const_foo(x));
    |                                    ^ non-constant value
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/type-check-1.rs:45:36
+  --> $DIR/type-check-1.rs:48:36
    |
 LL |         let x = 0;
    |         ----- help: consider using `const` instead of `let`: `const x`
@@ -26,7 +26,7 @@ LL |         asm!("{}", const const_bar(x));
    |                                    ^ non-constant value
 
 error: invalid `sym` operand
-  --> $DIR/type-check-1.rs:47:24
+  --> $DIR/type-check-1.rs:50:24
    |
 LL |         asm!("{}", sym x);
    |                        ^ is a local variable
@@ -34,13 +34,13 @@ LL |         asm!("{}", sym x);
    = help: `sym` operands must refer to either a function or a static
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:55:26
+  --> $DIR/type-check-1.rs:58:26
    |
 LL |         asm!("{}", const 0f32);
    |                          ^^^^ expected integer, found `f32`
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:57:26
+  --> $DIR/type-check-1.rs:60:26
    |
 LL |         asm!("{}", const 0 as *mut u8);
    |                          ^^^^^^^^^^^^ expected integer, found *-ptr
@@ -49,7 +49,7 @@ LL |         asm!("{}", const 0 as *mut u8);
            found raw pointer `*mut u8`
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:59:26
+  --> $DIR/type-check-1.rs:62:26
    |
 LL |         asm!("{}", const &0);
    |                          ^^ expected integer, found `&{integer}`
@@ -82,7 +82,7 @@ LL |         asm!("{}", in(reg) v[..]);
    = note: all inline asm arguments must have a statically known size
 
 error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
-  --> $DIR/type-check-1.rs:25:29
+  --> $DIR/type-check-1.rs:26:29
    |
 LL |         asm!("{}", out(reg) v[..]);
    |                             ^^^^^ doesn't have a size known at compile-time
@@ -91,7 +91,7 @@ LL |         asm!("{}", out(reg) v[..]);
    = note: all inline asm arguments must have a statically known size
 
 error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
-  --> $DIR/type-check-1.rs:27:31
+  --> $DIR/type-check-1.rs:29:31
    |
 LL |         asm!("{}", inout(reg) v[..]);
    |                               ^^^^^ doesn't have a size known at compile-time
@@ -99,14 +99,38 @@ LL |         asm!("{}", inout(reg) v[..]);
    = help: the trait `Sized` is not implemented for `[u64]`
    = note: all inline asm arguments must have a statically known size
 
+error: cannot use value of type `[u64]` for inline assembly
+  --> $DIR/type-check-1.rs:23:28
+   |
+LL |         asm!("{}", in(reg) v[..]);
+   |                            ^^^^^
+   |
+   = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `[u64]` for inline assembly
+  --> $DIR/type-check-1.rs:26:29
+   |
+LL |         asm!("{}", out(reg) v[..]);
+   |                             ^^^^^
+   |
+   = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `[u64]` for inline assembly
+  --> $DIR/type-check-1.rs:29:31
+   |
+LL |         asm!("{}", inout(reg) v[..]);
+   |                               ^^^^^
+   |
+   = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:73:25
+  --> $DIR/type-check-1.rs:76:25
    |
 LL | global_asm!("{}", const 0f32);
    |                         ^^^^ expected integer, found `f32`
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:75:25
+  --> $DIR/type-check-1.rs:78:25
    |
 LL | global_asm!("{}", const 0 as *mut u8);
    |                         ^^^^^^^^^^^^ expected integer, found *-ptr
@@ -114,7 +138,7 @@ LL | global_asm!("{}", const 0 as *mut u8);
    = note:     expected type `{integer}`
            found raw pointer `*mut u8`
 
-error: aborting due to 14 previous errors
+error: aborting due to 17 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0435.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/asm/x86_64/bad-reg.rs b/src/test/ui/asm/x86_64/bad-reg.rs
index 272372ebedc..a4f50a534a1 100644
--- a/src/test/ui/asm/x86_64/bad-reg.rs
+++ b/src/test/ui/asm/x86_64/bad-reg.rs
@@ -32,16 +32,21 @@ fn main() {
 
         asm!("", in("st(2)") foo);
         //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+        //~| ERROR `i32` cannot be used with this register class
         asm!("", in("mm0") foo);
         //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+        //~| ERROR `i32` cannot be used with this register class
         asm!("", in("k0") foo);
         //~^ ERROR register class `kreg0` can only be used as a clobber, not as an input or output
+        //~| ERROR `i32` cannot be used with this register class
         asm!("", out("st(2)") _);
         asm!("", out("mm0") _);
         asm!("{}", in(x87_reg) foo);
         //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+        //~| ERROR `i32` cannot be used with this register class
         asm!("{}", in(mmx_reg) foo);
         //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+        //~| ERROR `i32` cannot be used with this register class
         asm!("{}", out(x87_reg) _);
         //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
         asm!("{}", out(mmx_reg) _);
@@ -52,9 +57,12 @@ fn main() {
 
         asm!("", in("eax") foo, in("al") bar);
         //~^ ERROR register `al` conflicts with register `ax`
+        //~| ERROR `i32` cannot be used with this register class
         asm!("", in("rax") foo, out("rax") bar);
         //~^ ERROR register `ax` conflicts with register `ax`
         asm!("", in("al") foo, lateout("al") bar);
+        //~^ ERROR `i32` cannot be used with this register class
+        //~| ERROR `i32` cannot be used with this register class
         asm!("", in("xmm0") foo, in("ymm0") bar);
         //~^ ERROR register `ymm0` conflicts with register `xmm0`
         asm!("", in("xmm0") foo, out("ymm0") bar);
diff --git a/src/test/ui/asm/x86_64/bad-reg.stderr b/src/test/ui/asm/x86_64/bad-reg.stderr
index 84b8b5ec285..82b7ebd0fb0 100644
--- a/src/test/ui/asm/x86_64/bad-reg.stderr
+++ b/src/test/ui/asm/x86_64/bad-reg.stderr
@@ -71,43 +71,43 @@ LL |         asm!("", in("st(2)") foo);
    |                  ^^^^^^^^^^^^^^^
 
 error: register class `mmx_reg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:35:18
+  --> $DIR/bad-reg.rs:36:18
    |
 LL |         asm!("", in("mm0") foo);
    |                  ^^^^^^^^^^^^^
 
 error: register class `kreg0` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:37:18
+  --> $DIR/bad-reg.rs:39:18
    |
 LL |         asm!("", in("k0") foo);
    |                  ^^^^^^^^^^^^
 
 error: register class `x87_reg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:41:20
+  --> $DIR/bad-reg.rs:44:20
    |
 LL |         asm!("{}", in(x87_reg) foo);
    |                    ^^^^^^^^^^^^^^^
 
 error: register class `mmx_reg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:43:20
+  --> $DIR/bad-reg.rs:47:20
    |
 LL |         asm!("{}", in(mmx_reg) foo);
    |                    ^^^^^^^^^^^^^^^
 
 error: register class `x87_reg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:45:20
+  --> $DIR/bad-reg.rs:50:20
    |
 LL |         asm!("{}", out(x87_reg) _);
    |                    ^^^^^^^^^^^^^^
 
 error: register class `mmx_reg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:47:20
+  --> $DIR/bad-reg.rs:52:20
    |
 LL |         asm!("{}", out(mmx_reg) _);
    |                    ^^^^^^^^^^^^^^
 
 error: register `al` conflicts with register `ax`
-  --> $DIR/bad-reg.rs:53:33
+  --> $DIR/bad-reg.rs:58:33
    |
 LL |         asm!("", in("eax") foo, in("al") bar);
    |                  -------------  ^^^^^^^^^^^^ register `al`
@@ -115,7 +115,7 @@ LL |         asm!("", in("eax") foo, in("al") bar);
    |                  register `ax`
 
 error: register `ax` conflicts with register `ax`
-  --> $DIR/bad-reg.rs:55:33
+  --> $DIR/bad-reg.rs:61:33
    |
 LL |         asm!("", in("rax") foo, out("rax") bar);
    |                  -------------  ^^^^^^^^^^^^^^ register `ax`
@@ -123,13 +123,13 @@ LL |         asm!("", in("rax") foo, out("rax") bar);
    |                  register `ax`
    |
 help: use `lateout` instead of `out` to avoid conflict
-  --> $DIR/bad-reg.rs:55:18
+  --> $DIR/bad-reg.rs:61:18
    |
 LL |         asm!("", in("rax") foo, out("rax") bar);
    |                  ^^^^^^^^^^^^^
 
 error: register `ymm0` conflicts with register `xmm0`
-  --> $DIR/bad-reg.rs:58:34
+  --> $DIR/bad-reg.rs:66:34
    |
 LL |         asm!("", in("xmm0") foo, in("ymm0") bar);
    |                  --------------  ^^^^^^^^^^^^^^ register `ymm0`
@@ -137,7 +137,7 @@ LL |         asm!("", in("xmm0") foo, in("ymm0") bar);
    |                  register `xmm0`
 
 error: register `ymm0` conflicts with register `xmm0`
-  --> $DIR/bad-reg.rs:60:34
+  --> $DIR/bad-reg.rs:68:34
    |
 LL |         asm!("", in("xmm0") foo, out("ymm0") bar);
    |                  --------------  ^^^^^^^^^^^^^^^ register `ymm0`
@@ -145,10 +145,74 @@ LL |         asm!("", in("xmm0") foo, out("ymm0") bar);
    |                  register `xmm0`
    |
 help: use `lateout` instead of `out` to avoid conflict
-  --> $DIR/bad-reg.rs:60:18
+  --> $DIR/bad-reg.rs:68:18
    |
 LL |         asm!("", in("xmm0") foo, out("ymm0") bar);
    |                  ^^^^^^^^^^^^^^
 
-error: aborting due to 20 previous errors
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:33:30
+   |
+LL |         asm!("", in("st(2)") foo);
+   |                              ^^^
+   |
+   = note: register class `x87_reg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:36:28
+   |
+LL |         asm!("", in("mm0") foo);
+   |                            ^^^
+   |
+   = note: register class `mmx_reg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:39:27
+   |
+LL |         asm!("", in("k0") foo);
+   |                           ^^^
+   |
+   = note: register class `kreg0` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:44:32
+   |
+LL |         asm!("{}", in(x87_reg) foo);
+   |                                ^^^
+   |
+   = note: register class `x87_reg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:47:32
+   |
+LL |         asm!("{}", in(mmx_reg) foo);
+   |                                ^^^
+   |
+   = note: register class `mmx_reg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:58:42
+   |
+LL |         asm!("", in("eax") foo, in("al") bar);
+   |                                          ^^^
+   |
+   = note: register class `reg_byte` supports these types: i8
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:63:27
+   |
+LL |         asm!("", in("al") foo, lateout("al") bar);
+   |                           ^^^
+   |
+   = note: register class `reg_byte` supports these types: i8
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:63:46
+   |
+LL |         asm!("", in("al") foo, lateout("al") bar);
+   |                                              ^^^
+   |
+   = note: register class `reg_byte` supports these types: i8
+
+error: aborting due to 28 previous errors
 
diff --git a/src/test/ui/asm/x86_64/type-check-2.rs b/src/test/ui/asm/x86_64/type-check-2.rs
index eb87ea91085..59d8cde3fb6 100644
--- a/src/test/ui/asm/x86_64/type-check-2.rs
+++ b/src/test/ui/asm/x86_64/type-check-2.rs
@@ -13,10 +13,8 @@ fn main() {
 
         let x: u64;
         asm!("{}", in(reg) x);
-        //~^ ERROR use of possibly-uninitialized variable: `x`
         let mut y: u64;
         asm!("{}", inout(reg) y);
-        //~^ ERROR use of possibly-uninitialized variable: `y`
         let _ = y;
 
         // Outputs require mutable places
@@ -24,9 +22,7 @@ fn main() {
         let v: Vec<u64> = vec![0, 1, 2];
         asm!("{}", in(reg) v[0]);
         asm!("{}", out(reg) v[0]);
-        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
         asm!("{}", inout(reg) v[0]);
-        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
 
         // Sym operands must point to a function or static
 
@@ -36,6 +32,8 @@ fn main() {
         asm!("{}", sym main);
         asm!("{}", sym C);
         //~^ ERROR invalid `sym` operand
+        asm!("{}", sym x);
+        //~^ ERROR invalid `sym` operand
 
         // Register operands must be Copy
 
diff --git a/src/test/ui/asm/x86_64/type-check-2.stderr b/src/test/ui/asm/x86_64/type-check-2.stderr
index cb3960acdf9..46baeb511ca 100644
--- a/src/test/ui/asm/x86_64/type-check-2.stderr
+++ b/src/test/ui/asm/x86_64/type-check-2.stderr
@@ -1,13 +1,37 @@
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:35:24
+   |
+LL |         asm!("{}", sym x);
+   |                        ^ is a local variable
+   |
+   = help: `sym` operands must refer to either a function or a static
+
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:86:19
+   |
+LL | global_asm!("{}", sym C);
+   |                   ^^^^^ is an `i32`
+   |
+   = help: `sym` operands must refer to either a function or a static
+
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:33:20
+   |
+LL |         asm!("{}", sym C);
+   |                    ^^^^^ is an `i32`
+   |
+   = help: `sym` operands must refer to either a function or a static
+
 error: arguments for inline assembly must be copyable
-  --> $DIR/type-check-2.rs:42:32
+  --> $DIR/type-check-2.rs:40:32
    |
 LL |         asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `SimdNonCopy` does not implement the Copy trait
 
-error: cannot use value of type `[closure@$DIR/type-check-2.rs:54:28: 54:38]` for inline assembly
-  --> $DIR/type-check-2.rs:54:28
+error: cannot use value of type `[closure@$DIR/type-check-2.rs:52:28: 52:38]` for inline assembly
+  --> $DIR/type-check-2.rs:52:28
    |
 LL |         asm!("{}", in(reg) |x: i32| x);
    |                            ^^^^^^^^^^
@@ -15,7 +39,7 @@ LL |         asm!("{}", in(reg) |x: i32| x);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `Vec<i32>` for inline assembly
-  --> $DIR/type-check-2.rs:56:28
+  --> $DIR/type-check-2.rs:54:28
    |
 LL |         asm!("{}", in(reg) vec![0]);
    |                            ^^^^^^^
@@ -24,7 +48,7 @@ LL |         asm!("{}", in(reg) vec![0]);
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: cannot use value of type `(i32, i32, i32)` for inline assembly
-  --> $DIR/type-check-2.rs:58:28
+  --> $DIR/type-check-2.rs:56:28
    |
 LL |         asm!("{}", in(reg) (1, 2, 3));
    |                            ^^^^^^^^^
@@ -32,7 +56,7 @@ LL |         asm!("{}", in(reg) (1, 2, 3));
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `[i32; 3]` for inline assembly
-  --> $DIR/type-check-2.rs:60:28
+  --> $DIR/type-check-2.rs:58:28
    |
 LL |         asm!("{}", in(reg) [1, 2, 3]);
    |                            ^^^^^^^^^
@@ -40,7 +64,7 @@ LL |         asm!("{}", in(reg) [1, 2, 3]);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `fn() {main}` for inline assembly
-  --> $DIR/type-check-2.rs:68:31
+  --> $DIR/type-check-2.rs:66:31
    |
 LL |         asm!("{}", inout(reg) f);
    |                               ^
@@ -48,60 +72,12 @@ LL |         asm!("{}", inout(reg) f);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `&mut i32` for inline assembly
-  --> $DIR/type-check-2.rs:71:31
+  --> $DIR/type-check-2.rs:69:31
    |
 LL |         asm!("{}", inout(reg) r);
    |                               ^
    |
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
-error: invalid `sym` operand
-  --> $DIR/type-check-2.rs:37:20
-   |
-LL |         asm!("{}", sym C);
-   |                    ^^^^^ is an `i32`
-   |
-   = help: `sym` operands must refer to either a function or a static
-
-error: invalid `sym` operand
-  --> $DIR/type-check-2.rs:88:19
-   |
-LL | global_asm!("{}", sym C);
-   |                   ^^^^^ is an `i32`
-   |
-   = help: `sym` operands must refer to either a function or a static
-
-error[E0381]: use of possibly-uninitialized variable: `x`
-  --> $DIR/type-check-2.rs:15:28
-   |
-LL |         asm!("{}", in(reg) x);
-   |                            ^ use of possibly-uninitialized `x`
-
-error[E0381]: use of possibly-uninitialized variable: `y`
-  --> $DIR/type-check-2.rs:18:9
-   |
-LL |         asm!("{}", inout(reg) y);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y`
-
-error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
-  --> $DIR/type-check-2.rs:26:29
-   |
-LL |         let v: Vec<u64> = vec![0, 1, 2];
-   |             - help: consider changing this to be mutable: `mut v`
-LL |         asm!("{}", in(reg) v[0]);
-LL |         asm!("{}", out(reg) v[0]);
-   |                             ^ cannot borrow as mutable
-
-error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
-  --> $DIR/type-check-2.rs:28:31
-   |
-LL |         let v: Vec<u64> = vec![0, 1, 2];
-   |             - help: consider changing this to be mutable: `mut v`
-...
-LL |         asm!("{}", inout(reg) v[0]);
-   |                               ^ cannot borrow as mutable
-
-error: aborting due to 13 previous errors
+error: aborting due to 10 previous errors
 
-Some errors have detailed explanations: E0381, E0596.
-For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/asm/x86_64/type-check-3.rs b/src/test/ui/asm/x86_64/type-check-3.rs
index 595de55fd8b..89c849c7523 100644
--- a/src/test/ui/asm/x86_64/type-check-3.rs
+++ b/src/test/ui/asm/x86_64/type-check-3.rs
@@ -71,21 +71,3 @@ fn main() {
         asm!("{:r}", inout(reg) main => val_u64);
     }
 }
-
-// Constants must be... constant
-
-static S: i32 = 1;
-const fn const_foo(x: i32) -> i32 {
-    x
-}
-const fn const_bar<T>(x: T) -> T {
-    x
-}
-global_asm!("{}", const S);
-//~^ ERROR constants cannot refer to statics
-global_asm!("{}", const const_foo(0));
-global_asm!("{}", const const_foo(S));
-//~^ ERROR constants cannot refer to statics
-global_asm!("{}", const const_bar(0));
-global_asm!("{}", const const_bar(S));
-//~^ ERROR constants cannot refer to statics
diff --git a/src/test/ui/asm/x86_64/type-check-3.stderr b/src/test/ui/asm/x86_64/type-check-3.stderr
index aeb638d6949..b38ea8cc4d8 100644
--- a/src/test/ui/asm/x86_64/type-check-3.stderr
+++ b/src/test/ui/asm/x86_64/type-check-3.stderr
@@ -114,30 +114,5 @@ LL |         asm!("{:r}", inout(reg) main => val_u32);
    |
    = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
 
-error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:84:25
-   |
-LL | global_asm!("{}", const S);
-   |                         ^
-   |
-   = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:87:35
-   |
-LL | global_asm!("{}", const const_foo(S));
-   |                                   ^
-   |
-   = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:90:35
-   |
-LL | global_asm!("{}", const const_bar(S));
-   |                                   ^
-   |
-   = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error: aborting due to 12 previous errors; 4 warnings emitted
+error: aborting due to 9 previous errors; 4 warnings emitted
 
-For more information about this error, try `rustc --explain E0013`.
diff --git a/src/test/ui/asm/x86_64/type-check-4.rs b/src/test/ui/asm/x86_64/type-check-4.rs
new file mode 100644
index 00000000000..da3b76c3d23
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-4.rs
@@ -0,0 +1,29 @@
+// only-x86_64
+// compile-flags: -C target-feature=+avx512f
+
+#![feature(asm_const, asm_sym)]
+
+use std::arch::{asm, global_asm};
+
+use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps};
+
+fn main() {
+}
+
+// Constants must be... constant
+
+static S: i32 = 1;
+const fn const_foo(x: i32) -> i32 {
+    x
+}
+const fn const_bar<T>(x: T) -> T {
+    x
+}
+global_asm!("{}", const S);
+//~^ ERROR constants cannot refer to statics
+global_asm!("{}", const const_foo(0));
+global_asm!("{}", const const_foo(S));
+//~^ ERROR constants cannot refer to statics
+global_asm!("{}", const const_bar(0));
+global_asm!("{}", const const_bar(S));
+//~^ ERROR constants cannot refer to statics
diff --git a/src/test/ui/asm/x86_64/type-check-4.stderr b/src/test/ui/asm/x86_64/type-check-4.stderr
new file mode 100644
index 00000000000..33f4638fb4b
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-4.stderr
@@ -0,0 +1,27 @@
+error[E0013]: constants cannot refer to statics
+  --> $DIR/type-check-4.rs:22:25
+   |
+LL | global_asm!("{}", const S);
+   |                         ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+  --> $DIR/type-check-4.rs:25:35
+   |
+LL | global_asm!("{}", const const_foo(S));
+   |                                   ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+  --> $DIR/type-check-4.rs:28:35
+   |
+LL | global_asm!("{}", const const_bar(S));
+   |                                   ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0013`.
diff --git a/src/test/ui/asm/x86_64/type-check-5.rs b/src/test/ui/asm/x86_64/type-check-5.rs
new file mode 100644
index 00000000000..474478f6a88
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-5.rs
@@ -0,0 +1,63 @@
+// only-x86_64
+
+#![feature(repr_simd, never_type, asm_sym)]
+
+use std::arch::asm;
+
+#[repr(simd)]
+struct SimdNonCopy(f32, f32, f32, f32);
+
+fn main() {
+    unsafe {
+        // Inputs must be initialized
+
+        let x: u64;
+        asm!("{}", in(reg) x);
+        //~^ ERROR use of possibly-uninitialized variable: `x`
+        let mut y: u64;
+        asm!("{}", inout(reg) y);
+        //~^ ERROR use of possibly-uninitialized variable: `y`
+        let _ = y;
+
+        // Outputs require mutable places
+
+        let v: Vec<u64> = vec![0, 1, 2];
+        asm!("{}", in(reg) v[0]);
+        asm!("{}", out(reg) v[0]);
+        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+        asm!("{}", inout(reg) v[0]);
+        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+
+        // Sym operands must point to a function or static
+
+        const C: i32 = 0;
+        static S: i32 = 0;
+        asm!("{}", sym S);
+        asm!("{}", sym main);
+
+        // Register operands must be Copy
+
+        // Register operands must be integers, floats, SIMD vectors, pointers or
+        // function pointers.
+
+        asm!("{}", in(reg) 0i64);
+        asm!("{}", in(reg) 0f64);
+        asm!("{}", in(xmm_reg) std::arch::x86_64::_mm_setzero_ps());
+        asm!("{}", in(reg) 0 as *const u8);
+        asm!("{}", in(reg) 0 as *mut u8);
+        asm!("{}", in(reg) main as fn());
+
+        // Register inputs (but not outputs) allow references and function types
+
+        let mut f = main;
+        let mut r = &mut 0;
+        asm!("{}", in(reg) f);
+        asm!("{}", in(reg) r);
+        let _ = (f, r);
+
+        // Type checks ignore never type
+
+        let u: ! = unreachable!();
+        asm!("{}", in(reg) u);
+    }
+}
diff --git a/src/test/ui/asm/x86_64/type-check-5.stderr b/src/test/ui/asm/x86_64/type-check-5.stderr
new file mode 100644
index 00000000000..181ecaf5855
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-5.stderr
@@ -0,0 +1,34 @@
+error[E0381]: use of possibly-uninitialized variable: `x`
+  --> $DIR/type-check-5.rs:15:28
+   |
+LL |         asm!("{}", in(reg) x);
+   |                            ^ use of possibly-uninitialized `x`
+
+error[E0381]: use of possibly-uninitialized variable: `y`
+  --> $DIR/type-check-5.rs:18:9
+   |
+LL |         asm!("{}", inout(reg) y);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y`
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+  --> $DIR/type-check-5.rs:26:29
+   |
+LL |         let v: Vec<u64> = vec![0, 1, 2];
+   |             - help: consider changing this to be mutable: `mut v`
+LL |         asm!("{}", in(reg) v[0]);
+LL |         asm!("{}", out(reg) v[0]);
+   |                             ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+  --> $DIR/type-check-5.rs:28:31
+   |
+LL |         let v: Vec<u64> = vec![0, 1, 2];
+   |             - help: consider changing this to be mutable: `mut v`
+...
+LL |         asm!("{}", inout(reg) v[0]);
+   |                               ^ cannot borrow as mutable
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0381, E0596.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr
index 36b7f2e4558..28d94b14ac9 100644
--- a/src/test/ui/async-await/issue-68112.stderr
+++ b/src/test/ui/async-await/issue-68112.stderr
@@ -43,13 +43,13 @@ LL |     require_send(send_fut);
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
    = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36]`
-   = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>`
+   = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>`
    = note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
    = note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
    = note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
    = note: required because it appears within the type `{ResumeTy, impl Future<Output = Arc<RefCell<i32>>>, (), i32, Ready<i32>}`
    = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6]`
-   = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>`
+   = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>`
    = note: required because it appears within the type `impl Future<Output = ()>`
 note: required by a bound in `require_send`
   --> $DIR/issue-68112.rs:11:25
diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.stderr
index 7c074b07c3d..a1c4957e984 100644
--- a/src/test/ui/async-await/partial-drop-partial-reinit.stderr
+++ b/src/test/ui/async-await/partial-drop-partial-reinit.stderr
@@ -13,7 +13,7 @@ LL | async fn foo() {
    = note: required because it appears within the type `(NotSend,)`
    = note: required because it appears within the type `{ResumeTy, (NotSend,), impl Future<Output = ()>, ()}`
    = note: required because it appears within the type `[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]`
-   = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]>`
+   = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]>`
    = note: required because it appears within the type `impl Future<Output = ()>`
    = note: required because it appears within the type `impl Future<Output = ()>`
 note: required by a bound in `gimme_send`
diff --git a/src/test/ui/borrowck/issue-81899.rs b/src/test/ui/borrowck/issue-81899.rs
new file mode 100644
index 00000000000..356517745ff
--- /dev/null
+++ b/src/test/ui/borrowck/issue-81899.rs
@@ -0,0 +1,13 @@
+// Regression test for #81899.
+// The `panic!()` below is important to trigger the fixed ICE.
+
+const _CONST: &[u8] = &f(&[], |_| {});
+
+const fn f<F>(_: &[u8], _: F) -> &[u8]
+where
+    F: FnMut(&u8),
+{
+    panic!() //~ ERROR: evaluation of constant value failed
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-81899.stderr b/src/test/ui/borrowck/issue-81899.stderr
new file mode 100644
index 00000000000..59bf00d0012
--- /dev/null
+++ b/src/test/ui/borrowck/issue-81899.stderr
@@ -0,0 +1,17 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-81899.rs:10:5
+   |
+LL | const _CONST: &[u8] = &f(&[], |_| {});
+   |                        -------------- inside `_CONST` at $DIR/issue-81899.rs:4:24
+...
+LL |     panic!()
+   |     ^^^^^^^^
+   |     |
+   |     the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:10:5
+   |     inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/cast/casts-issue-46365.rs b/src/test/ui/cast/casts-issue-46365.rs
index 3d0fea245c0..a2205b718c1 100644
--- a/src/test/ui/cast/casts-issue-46365.rs
+++ b/src/test/ui/cast/casts-issue-46365.rs
@@ -3,5 +3,5 @@ struct Lorem {
 }
 
 fn main() {
-    let _foo: *mut Lorem = core::ptr::null_mut(); // no error here
+    let _foo: *mut Lorem = core::ptr::NonNull::dangling().as_ptr(); // no error here
 }
diff --git a/src/test/ui/cfg/cfg-target-compact-errors.rs b/src/test/ui/cfg/cfg-target-compact-errors.rs
new file mode 100644
index 00000000000..bca2275b1a9
--- /dev/null
+++ b/src/test/ui/cfg/cfg-target-compact-errors.rs
@@ -0,0 +1,17 @@
+// check-fail
+
+#![feature(cfg_target_compact)]
+
+#[cfg(target(o::o))]
+//~^ ERROR `cfg` predicate key must be an identifier
+fn one() {}
+
+#[cfg(target(os = 8))]
+//~^ ERROR literal in `cfg` predicate value must be a string
+fn two() {}
+
+#[cfg(target(os = "linux", pointer(width = "64")))]
+//~^ ERROR invalid predicate `target_pointer`
+fn three() {}
+
+fn main() {}
diff --git a/src/test/ui/cfg/cfg-target-compact-errors.stderr b/src/test/ui/cfg/cfg-target-compact-errors.stderr
new file mode 100644
index 00000000000..bb858301eb5
--- /dev/null
+++ b/src/test/ui/cfg/cfg-target-compact-errors.stderr
@@ -0,0 +1,22 @@
+error: `cfg` predicate key must be an identifier
+  --> $DIR/cfg-target-compact-errors.rs:5:14
+   |
+LL | #[cfg(target(o::o))]
+   |              ^^^^
+
+error[E0565]: literal in `cfg` predicate value must be a string
+  --> $DIR/cfg-target-compact-errors.rs:9:19
+   |
+LL | #[cfg(target(os = 8))]
+   |                   ^
+
+error[E0537]: invalid predicate `target_pointer`
+  --> $DIR/cfg-target-compact-errors.rs:13:28
+   |
+LL | #[cfg(target(os = "linux", pointer(width = "64")))]
+   |                            ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0537, E0565.
+For more information about an error, try `rustc --explain E0537`.
diff --git a/src/test/ui/cfg/cfg-target-compact.rs b/src/test/ui/cfg/cfg-target-compact.rs
new file mode 100644
index 00000000000..dc95a80915c
--- /dev/null
+++ b/src/test/ui/cfg/cfg-target-compact.rs
@@ -0,0 +1,10 @@
+// run-pass
+#![feature(cfg_target_compact)]
+
+#[cfg(target(os = "linux", pointer_width = "64"))]
+pub fn main() {
+}
+
+#[cfg(not(target(os = "linux", pointer_width = "64")))]
+pub fn main() {
+}
diff --git a/src/test/ui/chalkify/bugs/async.stderr b/src/test/ui/chalkify/bugs/async.stderr
index e6a72c72dd3..5b7ca8d46cf 100644
--- a/src/test/ui/chalkify/bugs/async.stderr
+++ b/src/test/ui/chalkify/bugs/async.stderr
@@ -7,11 +7,11 @@ LL | |     x
 LL | | }
    | |_^ the trait `Generator<ResumeTy>` is not implemented for `[static generator@$DIR/async.rs:7:29: 9:2]`
    |
-note: required by a bound in `from_generator`
+note: required by a bound in `std::future::from_generator`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
 LL |     T: Generator<ResumeTy, Yield = ()>,
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `from_generator`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `std::future::from_generator`
 
 error[E0280]: the requirement `<[static generator@$DIR/async.rs:7:29: 9:2] as Generator<ResumeTy>>::Yield == ()` is not satisfied
   --> $DIR/async.rs:7:29
@@ -22,11 +22,11 @@ LL | |     x
 LL | | }
    | |_^
    |
-note: required by a bound in `from_generator`
+note: required by a bound in `std::future::from_generator`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
 LL |     T: Generator<ResumeTy, Yield = ()>,
-   |                            ^^^^^^^^^^ required by this bound in `from_generator`
+   |                            ^^^^^^^^^^ required by this bound in `std::future::from_generator`
 
 error[E0280]: the requirement `<impl Future<Output = u32> as Future>::Output == u32` is not satisfied
   --> $DIR/async.rs:7:29
diff --git a/src/test/ui/check-cfg/compact-names.rs b/src/test/ui/check-cfg/compact-names.rs
new file mode 100644
index 00000000000..bff80740039
--- /dev/null
+++ b/src/test/ui/check-cfg/compact-names.rs
@@ -0,0 +1,15 @@
+// This test check that we correctly emit an warning for compact cfg
+//
+// check-pass
+// compile-flags:--check-cfg=names() -Z unstable-options
+
+#![feature(cfg_target_compact)]
+
+#[cfg(target(os = "linux", arch = "arm"))]
+pub fn expected() {}
+
+#[cfg(target(os = "linux", architecture = "arm"))]
+//~^ WARNING unexpected `cfg` condition name
+pub fn unexpected() {}
+
+fn main() {}
diff --git a/src/test/ui/check-cfg/compact-names.stderr b/src/test/ui/check-cfg/compact-names.stderr
new file mode 100644
index 00000000000..f1fc4285a71
--- /dev/null
+++ b/src/test/ui/check-cfg/compact-names.stderr
@@ -0,0 +1,10 @@
+warning: unexpected `cfg` condition name
+  --> $DIR/compact-names.rs:11:28
+   |
+LL | #[cfg(target(os = "linux", architecture = "arm"))]
+   |                            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/check-cfg/compact-values.rs b/src/test/ui/check-cfg/compact-values.rs
new file mode 100644
index 00000000000..1f17057840c
--- /dev/null
+++ b/src/test/ui/check-cfg/compact-values.rs
@@ -0,0 +1,15 @@
+// This test check that we correctly emit an warning for compact cfg
+//
+// check-pass
+// compile-flags:--check-cfg=values() -Z unstable-options
+
+#![feature(cfg_target_compact)]
+
+#[cfg(target(os = "linux", arch = "arm"))]
+pub fn expected() {}
+
+#[cfg(target(os = "linux", arch = "X"))]
+//~^ WARNING unexpected `cfg` condition value
+pub fn unexpected() {}
+
+fn main() {}
diff --git a/src/test/ui/check-cfg/compact-values.stderr b/src/test/ui/check-cfg/compact-values.stderr
new file mode 100644
index 00000000000..a196e1537df
--- /dev/null
+++ b/src/test/ui/check-cfg/compact-values.stderr
@@ -0,0 +1,11 @@
+warning: unexpected `cfg` condition value
+  --> $DIR/compact-values.rs:11:28
+   |
+LL | #[cfg(target(os = "linux", arch = "X"))]
+   |                            ^^^^^^^^^^
+   |
+   = note: `#[warn(unexpected_cfgs)]` on by default
+   = note: expected values for `target_arch` are: aarch64, arm, avr, bpf, hexagon, m68k, mips, mips64, msp430, nvptx64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, wasm32, wasm64, x86, x86_64
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
index e1c20e6ae78..16fabd1e88f 100644
--- a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
+++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
@@ -1,8 +1,8 @@
-error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
+error[E0741]: `(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
    |
 LL | fn test<const T: &'static dyn A>() {
-   |                  ^^^^^^^^^^^^^^ `&'static (dyn A + 'static)` doesn't derive both `PartialEq` and `Eq`
+   |                  ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-97278.rs b/src/test/ui/const-generics/issues/issue-97278.rs
new file mode 100644
index 00000000000..da0a9776fd4
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-97278.rs
@@ -0,0 +1,14 @@
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
+
+use std::sync::Arc;
+
+#[derive(PartialEq, Eq)]
+enum Bar {
+    Bar(Arc<i32>)
+}
+
+fn test<const BAR: Bar>() {}
+//~^ ERROR `Arc<i32>` must be annotated with `#[derive(PartialEq, Eq)]`
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-97278.stderr b/src/test/ui/const-generics/issues/issue-97278.stderr
new file mode 100644
index 00000000000..ff13cb505ab
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-97278.stderr
@@ -0,0 +1,9 @@
+error[E0741]: `Arc<i32>` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
+  --> $DIR/issue-97278.rs:11:20
+   |
+LL | fn test<const BAR: Bar>() {}
+   |                    ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0741`.
diff --git a/src/test/ui/consts/issue-91434.rs b/src/test/ui/consts/issue-91434.rs
index fc7731291b3..001dc708f89 100644
--- a/src/test/ui/consts/issue-91434.rs
+++ b/src/test/ui/consts/issue-91434.rs
@@ -2,5 +2,4 @@ fn main() {
     [9; [[9E; h]]];
     //~^ ERROR: expected at least one digit in exponent
     //~| ERROR: cannot find value `h` in this scope [E0425]
-    //~| ERROR: constant expression depends on a generic parameter
 }
diff --git a/src/test/ui/consts/issue-91434.stderr b/src/test/ui/consts/issue-91434.stderr
index 9d3fe5f2016..08d3ad77053 100644
--- a/src/test/ui/consts/issue-91434.stderr
+++ b/src/test/ui/consts/issue-91434.stderr
@@ -10,14 +10,6 @@ error[E0425]: cannot find value `h` in this scope
 LL |     [9; [[9E; h]]];
    |               ^ not found in this scope
 
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-91434.rs:2:9
-   |
-LL |     [9; [[9E; h]]];
-   |         ^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/consts/nested_erroneous_ctfe.rs b/src/test/ui/consts/nested_erroneous_ctfe.rs
new file mode 100644
index 00000000000..1ec271401fb
--- /dev/null
+++ b/src/test/ui/consts/nested_erroneous_ctfe.rs
@@ -0,0 +1,4 @@
+fn main() {
+    [9; || [9; []]];
+    //~^ ERROR: mismatched types
+}
diff --git a/src/test/ui/consts/nested_erroneous_ctfe.stderr b/src/test/ui/consts/nested_erroneous_ctfe.stderr
new file mode 100644
index 00000000000..d579a54e983
--- /dev/null
+++ b/src/test/ui/consts/nested_erroneous_ctfe.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/nested_erroneous_ctfe.rs:2:16
+   |
+LL |     [9; || [9; []]];
+   |                ^^ expected `usize`, found array of 0 elements
+   |
+   = note: expected type `usize`
+             found array `[_; 0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs b/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs
index 2e1d5d26b5c..852a5b3b46a 100644
--- a/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs
+++ b/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs
@@ -5,15 +5,9 @@
 
 fn main() {
     match &b""[..] {
-        ZST => {} //~ ERROR could not evaluate constant pattern
-                  //~| ERROR could not evaluate constant pattern
+        ZST => {}
     }
 }
 
 const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
-//~^ ERROR any use of this value will cause an error
-//~| ERROR cannot transmute between types of different sizes
-//~| WARN this was previously accepted by the compiler but is being phased out
-
-// Once the `any use of this value will cause an error` disappears in this test, make sure to
-// remove the `TransmuteSizeDiff` error variant and make its emitter site an assertion again.
+//~^ ERROR cannot transmute between types of different sizes
diff --git a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
index 27cc2f5e66a..4e8470173a1 100644
--- a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
+++ b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
@@ -1,23 +1,5 @@
-error: any use of this value will cause an error
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:13:29
-   |
-LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
-   | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                             |
-   |                             transmuting `usize` to `&[u8]` is not possible, because these types do not have the same size
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: could not evaluate constant pattern
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:8:9
-   |
-LL |         ZST => {}
-   |         ^^^
-
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:13:29
+  --> $DIR/transmute-size-mismatch-before-typeck.rs:12:29
    |
 LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    |                             ^^^^^^^^^^^^^^^^^^^
@@ -25,12 +7,6 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    = note: source type: `usize` (word size)
    = note: target type: `&[u8]` (2 * word size)
 
-error: could not evaluate constant pattern
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:8:9
-   |
-LL |         ZST => {}
-   |         ^^^
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/derives/issue-97343.rs b/src/test/ui/derives/issue-97343.rs
new file mode 100644
index 00000000000..adec6c7a5c5
--- /dev/null
+++ b/src/test/ui/derives/issue-97343.rs
@@ -0,0 +1,8 @@
+use std::fmt::Debug;
+
+#[derive(Debug)]
+pub struct Irrelevant<Irrelevant> { //~ ERROR type arguments are not allowed for this type
+    irrelevant: Irrelevant,
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/issue-97343.stderr b/src/test/ui/derives/issue-97343.stderr
new file mode 100644
index 00000000000..eedd54f1e9f
--- /dev/null
+++ b/src/test/ui/derives/issue-97343.stderr
@@ -0,0 +1,13 @@
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/issue-97343.rs:4:23
+   |
+LL | #[derive(Debug)]
+   |          ----- in this derive macro expansion
+LL | pub struct Irrelevant<Irrelevant> {
+   |                       ^^^^^^^^^^ type argument not allowed
+   |
+   = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/drop/repeat-drop-2.rs b/src/test/ui/drop/repeat-drop-2.rs
new file mode 100644
index 00000000000..2e7855328ec
--- /dev/null
+++ b/src/test/ui/drop/repeat-drop-2.rs
@@ -0,0 +1,15 @@
+fn borrowck_catch() {
+    let foo = String::new();
+    let _bar = foo;
+    let _baz = [foo; 0]; //~ ERROR use of moved value: `foo` [E0382]
+}
+
+const _: [String; 0] = [String::new(); 0];
+//~^ ERROR destructors cannot be evaluated at compile-time [E0493]
+
+fn must_be_init() {
+    let x: u8;
+    let _ = [x; 0]; //~ ERROR: use of possibly-uninitialized variable: `x`
+}
+
+fn main() {}
diff --git a/src/test/ui/drop/repeat-drop-2.stderr b/src/test/ui/drop/repeat-drop-2.stderr
new file mode 100644
index 00000000000..cdc58180c37
--- /dev/null
+++ b/src/test/ui/drop/repeat-drop-2.stderr
@@ -0,0 +1,29 @@
+error[E0382]: use of moved value: `foo`
+  --> $DIR/repeat-drop-2.rs:4:17
+   |
+LL |     let foo = String::new();
+   |         --- move occurs because `foo` has type `String`, which does not implement the `Copy` trait
+LL |     let _bar = foo;
+   |                --- value moved here
+LL |     let _baz = [foo; 0];
+   |                 ^^^ value used here after move
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/repeat-drop-2.rs:7:25
+   |
+LL | const _: [String; 0] = [String::new(); 0];
+   |                        -^^^^^^^^^^^^^----
+   |                        ||
+   |                        |constants cannot evaluate destructors
+   |                        value is dropped here
+
+error[E0381]: use of possibly-uninitialized variable: `x`
+  --> $DIR/repeat-drop-2.rs:12:14
+   |
+LL |     let _ = [x; 0];
+   |              ^ use of possibly-uninitialized `x`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0381, E0382, E0493.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/drop/repeat-drop.rs b/src/test/ui/drop/repeat-drop.rs
new file mode 100644
index 00000000000..03e832adb3b
--- /dev/null
+++ b/src/test/ui/drop/repeat-drop.rs
@@ -0,0 +1,120 @@
+// run-pass
+// ignore-wasm32-bare no unwinding panic
+// ignore-avr no unwinding panic
+// ignore-nvptx64 no unwinding panic
+
+static mut CHECK: usize = 0;
+
+struct DropChecker(usize);
+
+impl Drop for DropChecker {
+    fn drop(&mut self) {
+        unsafe {
+            if CHECK != self.0 - 1 {
+                panic!("Found {}, should have found {}", CHECK, self.0 - 1);
+            }
+            CHECK = self.0;
+        }
+    }
+}
+
+macro_rules! check_drops {
+    ($l:literal) => {
+        unsafe { assert_eq!(CHECK, $l) }
+    };
+}
+
+struct DropPanic;
+
+impl Drop for DropPanic {
+    fn drop(&mut self) {
+        panic!()
+    }
+}
+
+fn value_zero() {
+    unsafe { CHECK = 0 };
+    let foo = DropChecker(1);
+    let v: [DropChecker; 0] = [foo; 0];
+    check_drops!(1);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+fn value_one() {
+    unsafe { CHECK = 0 };
+    let foo = DropChecker(1);
+    let v: [DropChecker; 1] = [foo; 1];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+const DROP_CHECKER: DropChecker = DropChecker(1);
+
+fn const_zero() {
+    unsafe { CHECK = 0 };
+    let v: [DropChecker; 0] = [DROP_CHECKER; 0];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(0);
+}
+
+fn const_one() {
+    unsafe { CHECK = 0 };
+    let v: [DropChecker; 1] = [DROP_CHECKER; 1];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+fn const_generic_zero<const N: usize>() {
+    unsafe { CHECK = 0 };
+    let v: [DropChecker; N] = [DROP_CHECKER; N];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(0);
+}
+
+fn const_generic_one<const N: usize>() {
+    unsafe { CHECK = 0 };
+    let v: [DropChecker; N] = [DROP_CHECKER; N];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+// Make sure that things are allowed to promote as expected
+
+fn allow_promote() {
+    unsafe { CHECK = 0 };
+    let foo = DropChecker(1);
+    let v: &'static [DropChecker; 0] = &[foo; 0];
+    check_drops!(1);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+// Verify that unwinding in the drop causes the right things to drop in the right order
+fn on_unwind() {
+    unsafe { CHECK = 0 };
+    std::panic::catch_unwind(|| {
+        let panic = DropPanic;
+        let _local = DropChecker(2);
+        let _v = (DropChecker(1), [panic; 0]);
+        std::process::abort();
+    })
+    .unwrap_err();
+    check_drops!(2);
+}
+
+fn main() {
+    value_zero();
+    value_one();
+    const_zero();
+    const_one();
+    const_generic_zero::<0>();
+    const_generic_one::<1>();
+    allow_promote();
+    on_unwind();
+}
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-compact.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-compact.rs
new file mode 100644
index 00000000000..df81b7d2297
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-compact.rs
@@ -0,0 +1,13 @@
+#[cfg(target(os = "x"))] //~ ERROR compact `cfg(target(..))` is experimental
+struct Foo(u64, u64);
+
+#[cfg_attr(target(os = "x"), x)] //~ ERROR compact `cfg(target(..))` is experimental
+struct Bar(u64, u64);
+
+#[cfg(not(any(all(target(os = "x")))))] //~ ERROR compact `cfg(target(..))` is experimental
+fn foo() {}
+
+fn main() {
+    cfg!(target(os = "x"));
+    //~^ ERROR compact `cfg(target(..))` is experimental and subject to change
+}
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-compact.stderr b/src/test/ui/feature-gates/feature-gate-cfg-target-compact.stderr
new file mode 100644
index 00000000000..be6fe23ded1
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-compact.stderr
@@ -0,0 +1,39 @@
+error[E0658]: compact `cfg(target(..))` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-compact.rs:1:7
+   |
+LL | #[cfg(target(os = "x"))]
+   |       ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information
+   = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable
+
+error[E0658]: compact `cfg(target(..))` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-compact.rs:4:12
+   |
+LL | #[cfg_attr(target(os = "x"), x)]
+   |            ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information
+   = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable
+
+error[E0658]: compact `cfg(target(..))` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-compact.rs:7:19
+   |
+LL | #[cfg(not(any(all(target(os = "x")))))]
+   |                   ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information
+   = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable
+
+error[E0658]: compact `cfg(target(..))` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-compact.rs:11:10
+   |
+LL |     cfg!(target(os = "x"));
+   |          ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information
+   = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/native-library-link-flags/modifiers-override-3.rs b/src/test/ui/native-library-link-flags/modifiers-override-3.rs
new file mode 100644
index 00000000000..b28c53c6b0a
--- /dev/null
+++ b/src/test/ui/native-library-link-flags/modifiers-override-3.rs
@@ -0,0 +1,7 @@
+// Regression test for issue #97299, one command line library with modifiers
+// overrides another command line library with modifiers.
+
+// compile-flags:-lstatic:+whole-archive=foo -lstatic:+whole-archive=foo
+// error-pattern: overriding linking modifiers from command line is not supported
+
+fn main() {}
diff --git a/src/test/ui/native-library-link-flags/modifiers-override-3.stderr b/src/test/ui/native-library-link-flags/modifiers-override-3.stderr
new file mode 100644
index 00000000000..365e5618100
--- /dev/null
+++ b/src/test/ui/native-library-link-flags/modifiers-override-3.stderr
@@ -0,0 +1,4 @@
+error: overriding linking modifiers from command line is not supported
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/else-no-if.stderr b/src/test/ui/parser/else-no-if.stderr
index 27abbadd7ad..b9c1a75276c 100644
--- a/src/test/ui/parser/else-no-if.stderr
+++ b/src/test/ui/parser/else-no-if.stderr
@@ -6,14 +6,10 @@ LL |     } else false {
    |       |
    |       expected an `if` or a block after this `else`
    |
-help: add an `if` if this is the condition to an chained `if` statement after the `else`
+help: add an `if` if this is the condition of a chained `else if` statement
    |
 LL |     } else if false {
    |            ++
-help: ... otherwise, place this expression inside of a block if it is not an `if` condition
-   |
-LL |     } else { false } {
-   |            +       +
 
 error: expected `{`, found `falsy`
   --> $DIR/else-no-if.rs:10:12
@@ -23,14 +19,10 @@ LL |     } else falsy() {
    |       |
    |       expected an `if` or a block after this `else`
    |
-help: add an `if` if this is the condition to an chained `if` statement after the `else`
+help: add an `if` if this is the condition of a chained `else if` statement
    |
 LL |     } else if falsy() {
    |            ++
-help: ... otherwise, place this expression inside of a block if it is not an `if` condition
-   |
-LL |     } else { falsy() } {
-   |            +         +
 
 error: expected `{`, found `falsy`
   --> $DIR/else-no-if.rs:17:12
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
index 0045d608133..43e33cbb120 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
+++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
@@ -4,6 +4,7 @@
 use std::arch::asm;
 
 #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
+//~^ ERROR `#[track_caller]` requires Rust ABI
 #[naked]
 extern "C" fn f() {
     asm!("", options(noreturn));
@@ -13,6 +14,7 @@ struct S;
 
 impl S {
     #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
+    //~^ ERROR `#[track_caller]` requires Rust ABI
     #[naked]
     extern "C" fn g() {
         asm!("", options(noreturn));
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
index d33aecc0f97..3f7d0df42a0 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
+++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
@@ -5,11 +5,24 @@ LL | #[track_caller]
    | ^^^^^^^^^^^^^^^
 
 error[E0736]: cannot use `#[track_caller]` with `#[naked]`
-  --> $DIR/error-with-naked.rs:15:5
+  --> $DIR/error-with-naked.rs:16:5
    |
 LL |     #[track_caller]
    |     ^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error[E0737]: `#[track_caller]` requires Rust ABI
+  --> $DIR/error-with-naked.rs:6:1
+   |
+LL | #[track_caller]
+   | ^^^^^^^^^^^^^^^
+
+error[E0737]: `#[track_caller]` requires Rust ABI
+  --> $DIR/error-with-naked.rs:16:5
+   |
+LL |     #[track_caller]
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0736`.
+Some errors have detailed explanations: E0736, E0737.
+For more information about an error, try `rustc --explain E0736`.
diff --git a/src/test/ui/traits/issue-82830.rs b/src/test/ui/traits/issue-82830.rs
new file mode 100644
index 00000000000..c8289b2e30b
--- /dev/null
+++ b/src/test/ui/traits/issue-82830.rs
@@ -0,0 +1,16 @@
+trait A<Y, N> {
+    type B;
+}
+
+type MaybeBox<T> = <T as A<T, Box<T>>>::B;
+struct P {
+    t: MaybeBox<P>, //~ ERROR: overflow evaluating the requirement `P: Sized`
+}
+
+impl<Y, N> A<Y, N> for P {
+    type B = N;
+}
+
+fn main() {
+    let t: MaybeBox<P>;
+}
diff --git a/src/test/ui/traits/issue-82830.stderr b/src/test/ui/traits/issue-82830.stderr
new file mode 100644
index 00000000000..f863143c738
--- /dev/null
+++ b/src/test/ui/traits/issue-82830.stderr
@@ -0,0 +1,15 @@
+error[E0275]: overflow evaluating the requirement `P: Sized`
+  --> $DIR/issue-82830.rs:7:8
+   |
+LL |     t: MaybeBox<P>,
+   |        ^^^^^^^^^^^
+   |
+note: required because of the requirements on the impl of `A<P, Box<P>>` for `P`
+  --> $DIR/issue-82830.rs:10:12
+   |
+LL | impl<Y, N> A<Y, N> for P {
+   |            ^^^^^^^     ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-53092-2.rs b/src/test/ui/type-alias-impl-trait/issue-53092-2.rs
new file mode 100644
index 00000000000..438ac35fdea
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-53092-2.rs
@@ -0,0 +1,15 @@
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+type Bug<T, U> = impl Fn(T) -> U + Copy; //~ ERROR cycle detected
+
+const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+//~^ ERROR: cannot transmute
+
+fn make_bug<T, U: From<T>>() -> Bug<T, U> {
+    |x| x.into() //~ ERROR the trait bound `U: From<T>` is not satisfied
+}
+
+fn main() {
+    CONST_BUG(0);
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr b/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr
new file mode 100644
index 00000000000..f4a0cdb1625
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr
@@ -0,0 +1,55 @@
+error[E0391]: cycle detected when computing type of `Bug::{opaque#0}`
+  --> $DIR/issue-53092-2.rs:4:18
+   |
+LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires type-checking `CONST_BUG`...
+  --> $DIR/issue-53092-2.rs:6:1
+   |
+LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing layout of `Bug<u8, ()>`...
+   = note: ...which requires normalizing `Bug<u8, ()>`...
+   = note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/issue-53092-2.rs:1:1
+   |
+LL | / #![feature(type_alias_impl_trait)]
+LL | | #![allow(dead_code)]
+LL | |
+LL | | type Bug<T, U> = impl Fn(T) -> U + Copy;
+...  |
+LL | |     CONST_BUG(0);
+LL | | }
+   | |_^
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/issue-53092-2.rs:6:41
+   |
+LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+   |                                         ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[closure@$DIR/issue-53092-2.rs:6:61: 6:71]` (0 bits)
+   = note: target type: `Bug<u8, ()>` (size can vary because of [type error])
+
+error[E0277]: the trait bound `U: From<T>` is not satisfied
+  --> $DIR/issue-53092-2.rs:10:5
+   |
+LL |     |x| x.into()
+   |     ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U`
+   |
+note: required by a bound in `make_bug`
+  --> $DIR/issue-53092-2.rs:9:19
+   |
+LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> {
+   |                   ^^^^^^^ required by this bound in `make_bug`
+help: consider restricting type parameter `U`
+   |
+LL | type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy;
+   |              +++++++++++++++++++++++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0391, E0512.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-53092.rs b/src/test/ui/type-alias-impl-trait/issue-53092.rs
index 45792ba97a7..1be5b46d6df 100644
--- a/src/test/ui/type-alias-impl-trait/issue-53092.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-53092.rs
@@ -3,7 +3,12 @@
 
 type Bug<T, U> = impl Fn(T) -> U + Copy;
 
-const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+union Moo {
+    x: Bug<u8, ()>,
+    y: (),
+}
+
+const CONST_BUG: Bug<u8, ()> = unsafe { Moo { y: () }.x };
 
 fn make_bug<T, U: From<T>>() -> Bug<T, U> {
     |x| x.into() //~ ERROR the trait bound `U: From<T>` is not satisfied
diff --git a/src/test/ui/type-alias-impl-trait/issue-53092.stderr b/src/test/ui/type-alias-impl-trait/issue-53092.stderr
index 2d423a0c0df..2109cf8a784 100644
--- a/src/test/ui/type-alias-impl-trait/issue-53092.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-53092.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `U: From<T>` is not satisfied
-  --> $DIR/issue-53092.rs:9:5
+  --> $DIR/issue-53092.rs:14:5
    |
 LL |     |x| x.into()
    |     ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U`
    |
 note: required by a bound in `make_bug`
-  --> $DIR/issue-53092.rs:8:19
+  --> $DIR/issue-53092.rs:13:19
    |
 LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> {
    |                   ^^^^^^^ required by this bound in `make_bug`
diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
index fa578eced5f..46621362e4f 100644
--- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
+++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
@@ -3,13 +3,17 @@
 
 #![feature(type_alias_impl_trait)]
 
-type Foo = impl Copy; //~ unconstrained opaque type
+mod foo {
+    pub type Foo = impl Copy;
+    //~^ ERROR unconstrained opaque type
 
-// make compiler happy about using 'Foo'
-fn bar(x: Foo) -> Foo {
-    x
+    // make compiler happy about using 'Foo'
+    pub fn bar(x: Foo) -> Foo {
+        x
+    }
 }
 
 fn main() {
-    let _: Foo = std::mem::transmute(0u8);
+    let _: foo::Foo = std::mem::transmute(0u8);
+    //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
 }
diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
index 009935347e6..337708b8765 100644
--- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
+++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
@@ -1,10 +1,20 @@
 error: unconstrained opaque type
-  --> $DIR/no_inferrable_concrete_type.rs:6:12
+  --> $DIR/no_inferrable_concrete_type.rs:7:20
    |
-LL | type Foo = impl Copy;
-   |            ^^^^^^^^^
+LL |     pub type Foo = impl Copy;
+   |                    ^^^^^^^^^
    |
    = note: `Foo` must be used in combination with a concrete type within the same module
 
-error: aborting due to previous error
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/no_inferrable_concrete_type.rs:17:23
+   |
+LL |     let _: foo::Foo = std::mem::transmute(0u8);
+   |                       ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `u8` (8 bits)
+   = note: target type: `Foo` (size can vary because of [type error])
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/type/type-check/unknown_type_for_closure.rs b/src/test/ui/type/type-check/unknown_type_for_closure.rs
index 0dbf82453a2..0089d86e340 100644
--- a/src/test/ui/type/type-check/unknown_type_for_closure.rs
+++ b/src/test/ui/type/type-check/unknown_type_for_closure.rs
@@ -1,3 +1,17 @@
-fn main() {
-    let x = |_| {    }; //~ ERROR type annotations needed
+fn infer_in_arg() {
+    let x = |b: Vec<_>| {}; //~ ERROR E0282
 }
+
+fn empty_pattern() {
+    let x = |_| {}; //~ ERROR type annotations needed
+}
+
+fn infer_ty() {
+    let x = |k: _| {}; //~ ERROR type annotations needed
+}
+
+fn ambig_return() {
+    let x = || -> Vec<_> { Vec::new() }; //~ ERROR type annotations needed for the closure `fn() -> Vec<_>`
+}
+
+fn main() {}
diff --git a/src/test/ui/type/type-check/unknown_type_for_closure.stderr b/src/test/ui/type/type-check/unknown_type_for_closure.stderr
index 5971f56c97f..c3accad5f25 100644
--- a/src/test/ui/type/type-check/unknown_type_for_closure.stderr
+++ b/src/test/ui/type/type-check/unknown_type_for_closure.stderr
@@ -1,9 +1,32 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `Vec<_>`
   --> $DIR/unknown_type_for_closure.rs:2:14
    |
-LL |     let x = |_| {    };
+LL |     let x = |b: Vec<_>| {};
    |              ^ consider giving this closure parameter a type
 
-error: aborting due to previous error
+error[E0282]: type annotations needed
+  --> $DIR/unknown_type_for_closure.rs:6:14
+   |
+LL |     let x = |_| {};
+   |              ^ consider giving this closure parameter a type
+
+error[E0282]: type annotations needed
+  --> $DIR/unknown_type_for_closure.rs:10:14
+   |
+LL |     let x = |k: _| {};
+   |              ^ consider giving this closure parameter a type
+
+error[E0282]: type annotations needed for the closure `fn() -> Vec<_>`
+  --> $DIR/unknown_type_for_closure.rs:14:28
+   |
+LL |     let x = || -> Vec<_> { Vec::new() };
+   |                            ^^^^^^^^ cannot infer type for type parameter `T`
+   |
+help: give this closure an explicit return type without `_` placeholders
+   |
+LL |     let x = || -> Vec<_> { Vec::new() };
+   |                   ~~~~~~
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0282`.
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject a4c1cd0eb6b18082a7e693f5a665548fe1534be
+Subproject 39ad1039d9e3e1746177bf5d134af4c164f9552
diff --git a/src/tools/lld-wrapper/Cargo.toml b/src/tools/lld-wrapper/Cargo.toml
index 66a586fd6c3..bf5138b16d5 100644
--- a/src/tools/lld-wrapper/Cargo.toml
+++ b/src/tools/lld-wrapper/Cargo.toml
@@ -3,9 +3,3 @@ name = "lld-wrapper"
 version = "0.1.0"
 edition = "2021"
 license = "MIT OR Apache-2.0"
-
-[dependencies]
-
-[features]
-ld = []
-ld64 = []
\ No newline at end of file
diff --git a/src/tools/lld-wrapper/src/main.rs b/src/tools/lld-wrapper/src/main.rs
index 8d19a054a1d..90bd24a75e0 100644
--- a/src/tools/lld-wrapper/src/main.rs
+++ b/src/tools/lld-wrapper/src/main.rs
@@ -1,5 +1,4 @@
-//! Script to invoke the bundled rust-lld with the correct flavor. The flavor is selected by
-//! feature.
+//! Script to invoke the bundled rust-lld with the correct flavor.
 //!
 //! lld supports multiple command line interfaces. If `-flavor <flavor>` are passed as the first
 //! two arguments the `<flavor>` command line interface is used to process the remaining arguments.
@@ -8,59 +7,33 @@
 //! In Rust with `-Z gcc-ld=lld` we have gcc or clang invoke rust-lld. Since there is no way to
 //! make gcc/clang pass `-flavor <flavor>` as the first two arguments in the linker invocation
 //! and since Windows does not support symbolic links for files this wrapper is used in place of a
-//! symbolic link. It execs `../rust-lld -flavor ld` if the feature `ld` is enabled and
-//! `../rust-lld -flavor ld64` if `ld64` is enabled. On Windows it spawns a `..\rust-lld.exe`
+//! symbolic link. It execs `../rust-lld -flavor <flavor>` by propagating the flavor argument
+//! passed to the wrapper as the first two arguments. On Windows it spawns a `..\rust-lld.exe`
 //! child process.
 
-#[cfg(not(any(feature = "ld", feature = "ld64")))]
-compile_error!("One of the features ld and ld64 must be enabled.");
-
-#[cfg(all(feature = "ld", feature = "ld64"))]
-compile_error!("Only one of the feature ld or ld64 can be enabled.");
-
-#[cfg(feature = "ld")]
-const FLAVOR: &str = "ld";
-
-#[cfg(feature = "ld64")]
-const FLAVOR: &str = "ld64";
-
-use std::env;
 use std::fmt::Display;
 use std::path::{Path, PathBuf};
-use std::process;
+use std::{env, process};
 
-trait ResultExt<T, E> {
+trait UnwrapOrExitWith<T> {
     fn unwrap_or_exit_with(self, context: &str) -> T;
 }
 
-impl<T, E> ResultExt<T, E> for Result<T, E>
-where
-    E: Display,
-{
+impl<T> UnwrapOrExitWith<T> for Option<T> {
     fn unwrap_or_exit_with(self, context: &str) -> T {
-        match self {
-            Ok(t) => t,
-            Err(e) => {
-                eprintln!("lld-wrapper: {}: {}", context, e);
-                process::exit(1);
-            }
-        }
+        self.unwrap_or_else(|| {
+            eprintln!("lld-wrapper: {}", context);
+            process::exit(1);
+        })
     }
 }
 
-trait OptionExt<T> {
-    fn unwrap_or_exit_with(self, context: &str) -> T;
-}
-
-impl<T> OptionExt<T> for Option<T> {
+impl<T, E: Display> UnwrapOrExitWith<T> for Result<T, E> {
     fn unwrap_or_exit_with(self, context: &str) -> T {
-        match self {
-            Some(t) => t,
-            None => {
-                eprintln!("lld-wrapper: {}", context);
-                process::exit(1);
-            }
-        }
+        self.unwrap_or_else(|err| {
+            eprintln!("lld-wrapper: {}: {}", context, err);
+            process::exit(1);
+        })
     }
 }
 
@@ -81,14 +54,28 @@ fn get_rust_lld_path(current_exe_path: &Path) -> PathBuf {
 }
 
 /// Returns the command for invoking rust-lld with the correct flavor.
+/// LLD only accepts the flavor argument at the first two arguments, so move it there.
 ///
 /// Exits on error.
 fn get_rust_lld_command(current_exe_path: &Path) -> process::Command {
     let rust_lld_path = get_rust_lld_path(current_exe_path);
     let mut command = process::Command::new(rust_lld_path);
+
+    let mut flavor = None;
+    let args = env::args_os()
+        .skip(1)
+        .filter(|arg| match arg.to_str().and_then(|s| s.strip_prefix("-rustc-lld-flavor=")) {
+            Some(suffix) => {
+                flavor = Some(suffix.to_string());
+                false
+            }
+            None => true,
+        })
+        .collect::<Vec<_>>();
+
     command.arg("-flavor");
-    command.arg(FLAVOR);
-    command.args(env::args_os().skip(1));
+    command.arg(flavor.unwrap_or_exit_with("-rustc-lld-flavor=<flavor> is not passed"));
+    command.args(args);
     command
 }
 
@@ -101,20 +88,14 @@ fn exec_lld(mut command: process::Command) {
 
 #[cfg(not(unix))]
 fn exec_lld(mut command: process::Command) {
-    // Windows has no exec(), spawn a child process and wait for it
+    // Windows has no exec(), spawn a child process and wait for it.
     let exit_status = command.status().unwrap_or_exit_with("error running rust-lld child process");
-    if !exit_status.success() {
-        match exit_status.code() {
-            Some(code) => {
-                // return the original lld exit code
-                process::exit(code)
-            }
-            None => {
-                eprintln!("lld-wrapper: rust-lld child process exited with error: {}", exit_status,);
-                process::exit(1);
-            }
-        }
-    }
+    let code = exit_status
+        .code()
+        .ok_or(exit_status)
+        .unwrap_or_exit_with("rust-lld child process exited with error");
+    // Return the original lld exit code.
+    process::exit(code);
 }
 
 fn main() {
diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js
index 8532410a1bf..4599e12de5f 100644
--- a/src/tools/rustdoc-gui/tester.js
+++ b/src/tools/rustdoc-gui/tester.js
@@ -19,6 +19,7 @@ function showHelp() {
     console.log("  --help                     : show this message then quit");
     console.log("  --tests-folder [PATH]      : location of the .GOML tests folder");
     console.log("  --jobs [NUMBER]            : number of threads to run tests on");
+    console.log("  --executable-path [PATH]   : path of the browser's executable to be used");
 }
 
 function isNumeric(s) {
@@ -34,6 +35,8 @@ function parseOptions(args) {
         "show_text": false,
         "no_headless": false,
         "jobs": -1,
+        "executable_path": null,
+        "no_sandbox": false,
     };
     var correspondances = {
         "--doc-folder": "doc_folder",
@@ -41,13 +44,16 @@ function parseOptions(args) {
         "--debug": "debug",
         "--show-text": "show_text",
         "--no-headless": "no_headless",
+        "--executable-path": "executable_path",
+        "--no-sandbox": "no_sandbox",
     };
 
     for (var i = 0; i < args.length; ++i) {
         if (args[i] === "--doc-folder"
             || args[i] === "--tests-folder"
             || args[i] === "--file"
-            || args[i] === "--jobs") {
+            || args[i] === "--jobs"
+            || args[i] === "--executable-path") {
             i += 1;
             if (i >= args.length) {
                 console.log("Missing argument after `" + args[i - 1] + "` option.");
@@ -68,6 +74,9 @@ function parseOptions(args) {
         } else if (args[i] === "--help") {
             showHelp();
             process.exit(0);
+        } else if (args[i] === "--no-sandbox") {
+            console.log("`--no-sandbox` is being used. Be very careful!");
+            opts[correspondances[args[i]]] = true;
         } else if (correspondances[args[i]]) {
             opts[correspondances[args[i]]] = true;
         } else {
@@ -147,10 +156,17 @@ async function main(argv) {
         if (opts["show_text"]) {
             args.push("--show-text");
         }
+        if (opts["no_sandbox"]) {
+            args.push("--no-sandbox");
+        }
         if (opts["no_headless"]) {
             args.push("--no-headless");
             headless = false;
         }
+        if (opts["executable_path"] !== null) {
+            args.push("--executable-path");
+            args.push(opts["executable_path"]);
+        }
         options.parseArguments(args);
     } catch (error) {
         console.error(`invalid argument: ${error}`);
diff --git a/triagebot.toml b/triagebot.toml
index a5724ddfb88..e161adcd6e0 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -80,6 +80,13 @@ resolved/implemented on Fuchsia. Could one of you weigh in?
 """
 label = "O-fuchsia"
 
+[ping.macos]
+message = """\
+Hey MacOS Group! This issue or PR could use some MacOS-specific guidance. Could one
+of you weigh in? Thanks <3
+"""
+label = "O-macos"
+
 [prioritize]
 label = "I-prioritize"