about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml10
-rw-r--r--compiler/rustc_ast/src/ast.rs37
-rw-r--r--compiler/rustc_ast/src/util/comments.rs10
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs37
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs46
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs105
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs28
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs10
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs17
-rw-r--r--compiler/rustc_codegen_cranelift/src/archive.rs72
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/archive.rs76
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs35
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs42
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs181
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs23
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs27
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs2
-rw-r--r--compiler/rustc_const_eval/src/util/call_kind.rs9
-rw-r--r--compiler/rustc_hir/src/definitions.rs7
-rw-r--r--compiler/rustc_hir/src/hir.rs31
-rw-r--r--compiler/rustc_hir/src/intravisit.rs42
-rw-r--r--compiler/rustc_incremental/src/persist/dirty_clean.rs2
-rw-r--r--compiler/rustc_index/src/bit_set.rs8
-rw-r--r--compiler/rustc_index/src/bit_set/tests.rs17
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs16
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs9
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs6
-rw-r--r--compiler/rustc_interface/src/util.rs1
-rw-r--r--compiler/rustc_lexer/src/cursor.rs4
-rw-r--r--compiler/rustc_lexer/src/lib.rs89
-rw-r--r--compiler/rustc_lexer/src/tests.rs50
-rw-r--r--compiler/rustc_lint/src/builtin.rs25
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs4
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs28
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs38
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs48
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs72
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs45
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs4
-rw-r--r--compiler/rustc_middle/src/query/mod.rs12
-rw-r--r--compiler/rustc_middle/src/thir.rs18
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs2
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs63
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs4
-rw-r--r--compiler/rustc_middle/src/ty/context.rs13
-rw-r--r--compiler/rustc_middle/src/ty/error.rs5
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs2
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs4
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs26
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs9
-rw-r--r--compiler/rustc_middle/src/ty/util.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs18
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs1
-rw-r--r--compiler/rustc_mir_build/src/lints.rs21
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs1
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs2
-rw-r--r--compiler/rustc_monomorphize/src/util.rs4
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs77
-rw-r--r--compiler/rustc_parse/src/lexer/tokentrees.rs5
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs56
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs7
-rw-r--r--compiler/rustc_passes/src/check_const.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs13
-rw-r--r--compiler/rustc_query_impl/src/keys.rs10
-rw-r--r--compiler/rustc_query_system/src/query/job.rs14
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs6
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs7
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs6
-rw-r--r--compiler/rustc_session/src/config.rs14
-rw-r--r--compiler/rustc_session/src/options.rs11
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs6
-rw-r--r--compiler/rustc_target/src/abi/call/x86.rs6
-rw-r--r--compiler/rustc_target/src/abi/mod.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/codegen.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs3
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs8
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs39
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs2
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs12
-rw-r--r--compiler/rustc_typeck/src/astconv/errors.rs6
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs6
-rw-r--r--compiler/rustc_typeck/src/check/_match.rs4
-rw-r--r--compiler/rustc_typeck/src/check/callee.rs12
-rw-r--r--compiler/rustc_typeck/src/check/check.rs2
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs26
-rw-r--r--compiler/rustc_typeck/src/check/demand.rs54
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs11
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs19
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs5
-rw-r--r--compiler/rustc_typeck/src/check/inherited.rs5
-rw-r--r--compiler/rustc_typeck/src/check/method/confirm.rs13
-rw-r--r--compiler/rustc_typeck/src/check/method/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/method/prelude2021.rs7
-rw-r--r--compiler/rustc_typeck/src/check/method/probe.rs35
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs6
-rw-r--r--compiler/rustc_typeck/src/check/upvar.rs47
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs17
-rw-r--r--compiler/rustc_typeck/src/check/writeback.rs25
-rw-r--r--compiler/rustc_typeck/src/coherence/builtin.rs26
-rw-r--r--compiler/rustc_typeck/src/collect.rs6
-rw-r--r--compiler/rustc_typeck/src/collect/item_bounds.rs4
-rw-r--r--compiler/rustc_typeck/src/expr_use_visitor.rs8
-rw-r--r--compiler/rustc_typeck/src/impl_wf_check.rs2
-rw-r--r--compiler/rustc_typeck/src/outlives/implicit_infer.rs4
-rw-r--r--library/panic_unwind/src/gcc.rs4
-rw-r--r--library/std/src/error.rs74
-rw-r--r--library/std/src/error/tests.rs5
-rw-r--r--library/std/src/fs.rs81
-rw-r--r--library/std/src/net/addr.rs165
-rw-r--r--library/std/src/net/ip.rs147
-rw-r--r--library/std/src/net/ip/tests.rs23
-rw-r--r--library/std/src/net/mod.rs9
-rw-r--r--library/std/src/sys/sgx/net.rs2
-rw-r--r--library/std/src/sys/solid/net.rs4
-rw-r--r--library/std/src/sys/unix/fs.rs89
-rw-r--r--library/std/src/sys/unix/net.rs4
-rw-r--r--library/std/src/sys/unsupported/fs.rs12
-rw-r--r--library/std/src/sys/unsupported/net.rs2
-rw-r--r--library/std/src/sys/wasi/fs.rs25
-rw-r--r--library/std/src/sys/wasi/net.rs2
-rw-r--r--library/std/src/sys/wasi/time.rs4
-rw-r--r--library/std/src/sys/windows/c.rs31
-rw-r--r--library/std/src/sys/windows/compat.rs246
-rw-r--r--library/std/src/sys/windows/fs.rs31
-rw-r--r--library/std/src/sys/windows/net.rs4
-rw-r--r--library/std/src/sys/windows/time.rs7
-rw-r--r--library/std/src/sys_common/net.rs61
-rw-r--r--library/std/src/time.rs8
-rw-r--r--src/bootstrap/check.rs8
-rw-r--r--src/bootstrap/tool.rs52
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-12-stage1/Dockerfile44
-rw-r--r--src/ci/github-actions/ci.yml9
-rwxr-xr-xsrc/ci/run.sh2
-rwxr-xr-xsrc/ci/scripts/verify-channel.sh2
m---------src/doc/embedded-book0
-rw-r--r--src/doc/man/rustc.16
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/unstable-book/src/compiler-flags/check-cfg.md35
-rw-r--r--src/doc/unstable-book/src/compiler-flags/location-detail.md5
-rw-r--r--src/librustdoc/clean/inline.rs2
-rw-r--r--src/librustdoc/clean/mod.rs64
-rw-r--r--src/librustdoc/clean/types.rs55
-rw-r--r--src/librustdoc/html/highlight.rs2
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css10
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs2
-rw-r--r--src/librustdoc/scrape_examples.rs6
-rw-r--r--src/test/incremental/hashes/inherent_impls.rs8
-rw-r--r--src/test/incremental/hashes/trait_defs.rs44
-rw-r--r--src/test/incremental/hashes/trait_impls.rs26
-rw-r--r--src/test/run-make-fulldeps/symbol-visibility/Makefile21
-rw-r--r--src/test/run-make-fulldeps/symbol-visibility/a_proc_macro.rs9
-rw-r--r--src/test/run-make/raw-dylib-alt-calling-convention/Makefile11
-rw-r--r--src/test/run-make/raw-dylib-alt-calling-convention/driver.rs5
-rw-r--r--src/test/run-make/raw-dylib-alt-calling-convention/extern.c55
-rw-r--r--src/test/run-make/raw-dylib-alt-calling-convention/lib.rs76
-rw-r--r--src/test/run-make/raw-dylib-alt-calling-convention/output.msvc.txt11
-rw-r--r--src/test/rustdoc-gui/item-info-width.goml8
-rw-r--r--src/test/rustdoc-gui/item-info.goml32
-rw-r--r--src/test/rustdoc-gui/src/lib2/lib.rs3
-rw-r--r--src/test/rustdoc-ui/scrape-examples-fail-if-type-error.rs7
-rw-r--r--src/test/rustdoc-ui/scrape-examples-fail-if-type-error.stderr14
-rw-r--r--src/test/rustdoc-ui/z-help.stdout2
-rw-r--r--src/test/ui/async-await/no-const-async.stderr2
-rw-r--r--src/test/ui/borrowck/access-mode-in-closures.stderr2
-rw-r--r--src/test/ui/borrowck/borrowck-move-error-with-note.stderr2
-rw-r--r--src/test/ui/check-cfg/invalid-cfg-value.rs1
-rw-r--r--src/test/ui/check-cfg/invalid-cfg-value.stderr12
-rw-r--r--src/test/ui/check-cfg/mix.rs8
-rw-r--r--src/test/ui/check-cfg/mix.stderr80
-rw-r--r--src/test/ui/consts/issue-44415.stderr6
-rw-r--r--src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr18
-rw-r--r--src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr6
-rw-r--r--src/test/ui/did_you_mean/compatible-variants.rs5
-rw-r--r--src/test/ui/did_you_mean/compatible-variants.stderr9
-rw-r--r--src/test/ui/did_you_mean/issue-42764.rs1
-rw-r--r--src/test/ui/did_you_mean/issue-42764.stderr5
-rw-r--r--src/test/ui/hrtb/hrtb-perfect-forwarding.stderr42
-rw-r--r--src/test/ui/issues/issue-12511.stderr6
-rw-r--r--src/test/ui/layout/debug.stderr242
-rw-r--r--src/test/ui/layout/hexagon-enum.stderr326
-rw-r--r--src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr496
-rw-r--r--src/test/ui/layout/issue-96185-overaligned-enum.stderr146
-rw-r--r--src/test/ui/layout/thumb-enum.stderr326
-rw-r--r--src/test/ui/layout/zero-sized-array-enum-niche.stderr304
-rw-r--r--src/test/ui/lint/unreachable_pub.stderr14
-rw-r--r--src/test/ui/moves/issue-99470-move-out-of-some.rs9
-rw-r--r--src/test/ui/moves/issue-99470-move-out-of-some.stderr16
-rw-r--r--src/test/ui/moves/moves-based-on-type-block-bad.stderr2
-rw-r--r--src/test/ui/nll/move-errors.stderr4
-rw-r--r--src/test/ui/panics/location-detail-panic-no-location-info.rs8
-rw-r--r--src/test/ui/panics/location-detail-panic-no-location-info.run.stderr2
-rw-r--r--src/test/ui/proc-macro/auxiliary/proc-macro-panic.rs (renamed from src/test/ui-fulldeps/auxiliary/proc-macro-panic.rs)0
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-1.rs5
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-1.stderr2
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-2.rs5
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-2.stderr2
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-3.rs5
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-3.stderr2
-rw-r--r--src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs (renamed from src/test/ui-fulldeps/issue-76270-panic-in-libproc-macro.rs)5
-rw-r--r--src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr (renamed from src/test/ui-fulldeps/issue-76270-panic-in-libproc-macro.stderr)2
-rw-r--r--src/test/ui/proc-macro/load-panic-backtrace.rs10
-rw-r--r--src/test/ui/proc-macro/load-panic-backtrace.stderr2
-rw-r--r--src/test/ui/resolve/issue-23305.stderr10
-rw-r--r--src/test/ui/rfc-2294-if-let-guard/feature-gate.rs2
-rw-r--r--src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr24
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs12
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr542
-rw-r--r--src/test/ui/suggestions/dont-suggest-ref/simple.stderr48
-rw-r--r--src/test/ui/suggestions/if-then-neeing-semi.rs70
-rw-r--r--src/test/ui/suggestions/if-then-neeing-semi.stderr130
-rw-r--r--src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed19
-rw-r--r--src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs19
-rw-r--r--src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr22
-rw-r--r--src/test/ui/suggestions/missing-bound-in-manual-copy-impl.fixed9
-rw-r--r--src/test/ui/suggestions/missing-bound-in-manual-copy-impl.rs9
-rw-r--r--src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr17
-rw-r--r--src/test/ui/traits/issue-91949-hangs-on-recursion.stderr9
-rw-r--r--src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr2
-rw-r--r--src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr6
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs2
-rw-r--r--src/tools/x/src/main.rs6
-rw-r--r--triagebot.toml1
248 files changed, 4032 insertions, 3044 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6d9e249ee44..5410613548c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -79,7 +79,7 @@ jobs:
         uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
         with:
           github_token: "${{ secrets.github_token }}"
-        if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
+        if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && github.ref != 'refs/heads/try-perf'"
       - name: collect CPU statistics
         run: src/ci/scripts/collect-cpu-stats.sh
         if: success() && !env.SKIP_JOB
@@ -278,6 +278,10 @@ jobs:
             env:
               RUST_BACKTRACE: 1
             os: ubuntu-20.04-xl
+          - name: x86_64-gnu-llvm-12-stage1
+            env:
+              RUST_BACKTRACE: 1
+            os: ubuntu-20.04-xl
           - name: x86_64-gnu-nopt
             os: ubuntu-20.04-xl
             env: {}
@@ -474,7 +478,7 @@ jobs:
         uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
         with:
           github_token: "${{ secrets.github_token }}"
-        if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
+        if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && github.ref != 'refs/heads/try-perf'"
       - name: collect CPU statistics
         run: src/ci/scripts/collect-cpu-stats.sh
         if: success() && !env.SKIP_JOB
@@ -584,7 +588,7 @@ jobs:
         uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
         with:
           github_token: "${{ secrets.github_token }}"
-        if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
+        if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && github.ref != 'refs/heads/try-perf'"
       - name: collect CPU statistics
         run: src/ci/scripts/collect-cpu-stats.sh
         if: success() && !env.SKIP_JOB
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index ac2328a5824..116497109f1 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1111,10 +1111,6 @@ pub struct Expr {
     pub tokens: Option<LazyTokenStream>,
 }
 
-// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Expr, 104);
-
 impl Expr {
     /// Returns `true` if this expression would be valid somewhere that expects a value;
     /// for example, an `if` condition.
@@ -2883,9 +2879,6 @@ pub enum ItemKind {
     MacroDef(MacroDef),
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(ItemKind, 112);
-
 impl ItemKind {
     pub fn article(&self) -> &str {
         use ItemKind::*;
@@ -2957,9 +2950,6 @@ pub enum AssocItemKind {
     MacCall(MacCall),
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(AssocItemKind, 72);
-
 impl AssocItemKind {
     pub fn defaultness(&self) -> Defaultness {
         match *self {
@@ -3009,9 +2999,6 @@ pub enum ForeignItemKind {
     MacCall(MacCall),
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(ForeignItemKind, 72);
-
 impl From<ForeignItemKind> for ItemKind {
     fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
         match foreign_item_kind {
@@ -3038,3 +3025,27 @@ impl TryFrom<ItemKind> for ForeignItemKind {
 }
 
 pub type ForeignItem = Item<ForeignItemKind>;
+
+// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+    use super::*;
+    // These are in alphabetical order, which is easy to maintain.
+    rustc_data_structures::static_assert_size!(AssocItemKind, 72);
+    rustc_data_structures::static_assert_size!(Attribute, 152);
+    rustc_data_structures::static_assert_size!(Block, 48);
+    rustc_data_structures::static_assert_size!(Expr, 104);
+    rustc_data_structures::static_assert_size!(Fn, 192);
+    rustc_data_structures::static_assert_size!(ForeignItemKind, 72);
+    rustc_data_structures::static_assert_size!(GenericBound, 88);
+    rustc_data_structures::static_assert_size!(Generics, 72);
+    rustc_data_structures::static_assert_size!(Impl, 200);
+    rustc_data_structures::static_assert_size!(Item, 200);
+    rustc_data_structures::static_assert_size!(ItemKind, 112);
+    rustc_data_structures::static_assert_size!(Lit, 48);
+    rustc_data_structures::static_assert_size!(Pat, 120);
+    rustc_data_structures::static_assert_size!(Path, 40);
+    rustc_data_structures::static_assert_size!(PathSegment, 24);
+    rustc_data_structures::static_assert_size!(Stmt, 32);
+    rustc_data_structures::static_assert_size!(Ty, 96);
+}
diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs
index b4fff0022e2..c96474ccb42 100644
--- a/compiler/rustc_ast/src/util/comments.rs
+++ b/compiler/rustc_ast/src/util/comments.rs
@@ -194,7 +194,7 @@ pub fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comme
     }
 
     for token in rustc_lexer::tokenize(&text[pos..]) {
-        let token_text = &text[pos..pos + token.len];
+        let token_text = &text[pos..pos + token.len as usize];
         match token.kind {
             rustc_lexer::TokenKind::Whitespace => {
                 if let Some(mut idx) = token_text.find('\n') {
@@ -211,8 +211,10 @@ pub fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comme
             }
             rustc_lexer::TokenKind::BlockComment { doc_style, .. } => {
                 if doc_style.is_none() {
-                    let code_to_the_right =
-                        !matches!(text[pos + token.len..].chars().next(), Some('\r' | '\n'));
+                    let code_to_the_right = !matches!(
+                        text[pos + token.len as usize..].chars().next(),
+                        Some('\r' | '\n')
+                    );
                     let style = match (code_to_the_left, code_to_the_right) {
                         (_, true) => CommentStyle::Mixed,
                         (false, false) => CommentStyle::Isolated,
@@ -246,7 +248,7 @@ pub fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comme
                 code_to_the_left = true;
             }
         }
-        pos += token.len;
+        pos += token.len as usize;
     }
 
     comments
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index ddd54f7c208..d5af74d47fd 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -323,7 +323,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     fn visit_trait_item_ref(&mut self, ii: &'hir TraitItemRef) {
         // Do not visit the duplicate information in TraitItemRef. We want to
         // map the actual nodes, not the duplicate ones in the *Ref.
-        let TraitItemRef { id, ident: _, kind: _, span: _, defaultness: _ } = *ii;
+        let TraitItemRef { id, ident: _, kind: _, span: _ } = *ii;
 
         self.visit_nested_trait_item(id);
     }
@@ -331,8 +331,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) {
         // Do not visit the duplicate information in ImplItemRef. We want to
         // map the actual nodes, not the duplicate ones in the *Ref.
-        let ImplItemRef { id, ident: _, kind: _, span: _, defaultness: _, trait_item_def_id: _ } =
-            *ii;
+        let ImplItemRef { id, ident: _, kind: _, span: _, trait_item_def_id: _ } = *ii;
 
         self.visit_nested_impl_item(id);
     }
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 7da49143b46..99f81afc1e2 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -755,17 +755,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let hir_id = self.lower_node_id(i.id);
         let trait_item_def_id = hir_id.expect_owner();
 
-        let (generics, kind) = match i.kind {
+        let (generics, kind, has_default) = match i.kind {
             AssocItemKind::Const(_, ref ty, ref default) => {
                 let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
                 let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
-                (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body))
+                (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some())
             }
             AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => {
                 let names = self.lower_fn_params_to_names(&sig.decl);
                 let (generics, sig) =
                     self.lower_method_sig(generics, sig, i.id, FnDeclKind::Trait, None);
-                (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)))
+                (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
             }
             AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => {
                 let asyncness = sig.header.asyncness;
@@ -778,7 +778,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     FnDeclKind::Trait,
                     asyncness.opt_return_id(),
                 );
-                (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)))
+                (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
             }
             AssocItemKind::TyAlias(box TyAlias {
                 ref generics,
@@ -789,7 +789,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }) => {
                 let mut generics = generics.clone();
                 add_ty_alias_where_clause(&mut generics, where_clauses, false);
-                self.lower_generics(
+                let (generics, kind) = self.lower_generics(
                     &generics,
                     i.id,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
@@ -805,7 +805,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                             ty,
                         )
                     },
-                )
+                );
+                (generics, kind, ty.is_some())
             }
             AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
         };
@@ -817,28 +818,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
             generics,
             kind,
             span: self.lower_span(i.span),
+            defaultness: hir::Defaultness::Default { has_value: has_default },
         };
         self.arena.alloc(item)
     }
 
     fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
-        let (kind, has_default) = match &i.kind {
-            AssocItemKind::Const(_, _, default) => (hir::AssocItemKind::Const, default.is_some()),
-            AssocItemKind::TyAlias(box TyAlias { ty, .. }) => {
-                (hir::AssocItemKind::Type, ty.is_some())
-            }
-            AssocItemKind::Fn(box Fn { sig, body, .. }) => {
-                (hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }, body.is_some())
+        let kind = match &i.kind {
+            AssocItemKind::Const(..) => hir::AssocItemKind::Const,
+            AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type,
+            AssocItemKind::Fn(box Fn { sig, .. }) => {
+                hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
             }
             AssocItemKind::MacCall(..) => unimplemented!(),
         };
         let id = hir::TraitItemId { def_id: self.local_def_id(i.id) };
-        let defaultness = hir::Defaultness::Default { has_value: has_default };
         hir::TraitItemRef {
             id,
             ident: self.lower_ident(i.ident),
             span: self.lower_span(i.span),
-            defaultness,
             kind,
         }
     }
@@ -849,6 +847,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
+        // Since `default impl` is not yet implemented, this is always true in impls.
+        let has_value = true;
+        let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
+
         let (generics, kind) = match &i.kind {
             AssocItemKind::Const(_, ty, expr) => {
                 let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
@@ -903,19 +905,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
             kind,
             vis_span: self.lower_span(i.vis.span),
             span: self.lower_span(i.span),
+            defaultness,
         };
         self.arena.alloc(item)
     }
 
     fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
-        // Since `default impl` is not yet implemented, this is always true in impls.
-        let has_value = true;
-        let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
         hir::ImplItemRef {
             id: hir::ImplItemId { def_id: self.local_def_id(i.id) },
             ident: self.lower_ident(i.ident),
             span: self.lower_span(i.span),
-            defaultness,
             kind: match &i.kind {
                 AssocItemKind::Const(..) => hir::AssocItemKind::Const,
                 AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type,
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 255c31d0b1a..5da260f980f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -6,7 +6,6 @@ use rustc_errors::{
     struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
 };
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
 use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
 use rustc_infer::infer::TyCtxtInferExt;
@@ -21,6 +20,7 @@ use rustc_middle::ty::{
     self, subst::Subst, suggest_constraining_type_params, EarlyBinder, PredicateKind, Ty,
 };
 use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
+use rustc_span::def_id::LocalDefId;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::symbol::sym;
 use rustc_span::{BytePos, Span, Symbol};
@@ -39,7 +39,7 @@ use crate::{
 
 use super::{
     explain_borrow::{BorrowExplanation, LaterUseKind},
-    IncludingDowncast, RegionName, RegionNameSource, UseSpans,
+    DescribePlaceOpt, RegionName, RegionNameSource, UseSpans,
 };
 
 #[derive(Debug)]
@@ -137,7 +137,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 span,
                 desired_action.as_noun(),
                 partially_str,
-                self.describe_place_with_options(moved_place, IncludingDowncast(true)),
+                self.describe_place_with_options(
+                    moved_place,
+                    DescribePlaceOpt { including_downcast: true, including_tuple_field: true },
+                ),
             );
 
             let reinit_spans = maybe_reinitialized_locations
@@ -274,8 +277,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 }
             }
 
-            let opt_name =
-                self.describe_place_with_options(place.as_ref(), IncludingDowncast(true));
+            let opt_name = self.describe_place_with_options(
+                place.as_ref(),
+                DescribePlaceOpt { including_downcast: true, including_tuple_field: true },
+            );
             let note_msg = match opt_name {
                 Some(ref name) => format!("`{}`", name),
                 None => "value".to_owned(),
@@ -341,12 +346,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
         }
 
-        let (name, desc) =
-            match self.describe_place_with_options(moved_place, IncludingDowncast(true)) {
-                Some(name) => (format!("`{name}`"), format!("`{name}` ")),
-                None => ("the variable".to_string(), String::new()),
-            };
-        let path = match self.describe_place_with_options(used_place, IncludingDowncast(true)) {
+        let (name, desc) = match self.describe_place_with_options(
+            moved_place,
+            DescribePlaceOpt { including_downcast: true, including_tuple_field: true },
+        ) {
+            Some(name) => (format!("`{name}`"), format!("`{name}` ")),
+            None => ("the variable".to_string(), String::new()),
+        };
+        let path = match self.describe_place_with_options(
+            used_place,
+            DescribePlaceOpt { including_downcast: true, including_tuple_field: true },
+        ) {
             Some(name) => format!("`{name}`"),
             None => "value".to_string(),
         };
@@ -2223,7 +2233,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 let ty = self.infcx.tcx.type_of(self.mir_def_id());
                 match ty.kind() {
                     ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig(
-                        self.mir_def_id().to_def_id(),
+                        self.mir_def_id(),
                         self.infcx.tcx.fn_sig(self.mir_def_id()),
                     ),
                     _ => None,
@@ -2267,8 +2277,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         // Check if our `target` was captured by a closure.
                         if let Rvalue::Aggregate(
                             box AggregateKind::Closure(def_id, substs),
-                            operands,
-                        ) = rvalue
+                            ref operands,
+                        ) = *rvalue
                         {
                             for operand in operands {
                                 let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else {
@@ -2292,7 +2302,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                 // into a place then we should annotate the closure in
                                 // case it ends up being assigned into the return place.
                                 annotated_closure =
-                                    self.annotate_fn_sig(*def_id, substs.as_closure().sig());
+                                    self.annotate_fn_sig(def_id, substs.as_closure().sig());
                                 debug!(
                                     "annotate_argument_and_return_for_borrow: \
                                      annotated_closure={:?} assigned_from_local={:?} \
@@ -2414,12 +2424,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// references.
     fn annotate_fn_sig(
         &self,
-        did: DefId,
+        did: LocalDefId,
         sig: ty::PolyFnSig<'tcx>,
     ) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
         debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig);
-        let is_closure = self.infcx.tcx.is_closure(did);
-        let fn_hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did.as_local()?);
+        let is_closure = self.infcx.tcx.is_closure(did.to_def_id());
+        let fn_hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
         let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?;
 
         // We need to work out which arguments to highlight. We do this by looking
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 53c07a3d481..098e8de9420 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -4,10 +4,10 @@ use itertools::Itertools;
 use rustc_const_eval::util::{call_kind, CallDesugaringKind};
 use rustc_errors::{Applicability, Diagnostic};
 use rustc_hir as hir;
-use rustc_hir::def::Namespace;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::GeneratorKind;
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::{
     AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand,
     Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
@@ -15,7 +15,8 @@ use rustc_middle::mir::{
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
 use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
-use rustc_span::{symbol::sym, Span, DUMMY_SP};
+use rustc_span::def_id::LocalDefId;
+use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
 use rustc_target::abi::VariantIdx;
 use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
 
@@ -41,9 +42,16 @@ pub(crate) use outlives_suggestion::OutlivesSuggestionBuilder;
 pub(crate) use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
 pub(crate) use region_name::{RegionName, RegionNameSource};
 pub(crate) use rustc_const_eval::util::CallKind;
-use rustc_middle::mir::tcx::PlaceTy;
 
-pub(super) struct IncludingDowncast(pub(super) bool);
+pub(super) struct DescribePlaceOpt {
+    pub including_downcast: bool,
+
+    /// Enable/Disable tuple fields.
+    /// For example `x` tuple. if it's `true` `x.0`. Otherwise `x`
+    pub including_tuple_field: bool,
+}
+
+pub(super) struct IncludingTupleField(pub(super) bool);
 
 impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure
@@ -164,7 +172,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// End-user visible description of `place` if one can be found.
     /// If the place is a temporary for instance, `None` will be returned.
     pub(super) fn describe_place(&self, place_ref: PlaceRef<'tcx>) -> Option<String> {
-        self.describe_place_with_options(place_ref, IncludingDowncast(false))
+        self.describe_place_with_options(
+            place_ref,
+            DescribePlaceOpt { including_downcast: false, including_tuple_field: true },
+        )
     }
 
     /// End-user visible description of `place` if one can be found. If the place is a temporary
@@ -174,7 +185,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     pub(super) fn describe_place_with_options(
         &self,
         place: PlaceRef<'tcx>,
-        including_downcast: IncludingDowncast,
+        opt: DescribePlaceOpt,
     ) -> Option<String> {
         let local = place.local;
         let mut autoderef_index = None;
@@ -224,7 +235,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         }
                     }
                 }
-                ProjectionElem::Downcast(..) if including_downcast.0 => return None,
+                ProjectionElem::Downcast(..) if opt.including_downcast => return None,
                 ProjectionElem::Downcast(..) => (),
                 ProjectionElem::Field(field, _ty) => {
                     // FIXME(project-rfc_2229#36): print capture precisely here.
@@ -238,9 +249,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         let field_name = self.describe_field(
                             PlaceRef { local, projection: place.projection.split_at(index).0 },
                             *field,
+                            IncludingTupleField(opt.including_tuple_field),
                         );
-                        buf.push('.');
-                        buf.push_str(&field_name);
+                        if let Some(field_name_str) = field_name {
+                            buf.push('.');
+                            buf.push_str(&field_name_str);
+                        }
                     }
                 }
                 ProjectionElem::Index(index) => {
@@ -261,6 +275,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         ok.ok().map(|_| buf)
     }
 
+    fn describe_name(&self, place: PlaceRef<'tcx>) -> Option<Symbol> {
+        for elem in place.projection.into_iter() {
+            match elem {
+                ProjectionElem::Downcast(Some(name), _) => {
+                    return Some(*name);
+                }
+                _ => {}
+            }
+        }
+        None
+    }
+
     /// Appends end-user visible description of the `local` place to `buf`. If `local` doesn't have
     /// a name, or its name was generated by the compiler, then `Err` is returned
     fn append_local_to_string(&self, local: Local, buf: &mut String) -> Result<(), ()> {
@@ -275,7 +301,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     }
 
     /// End-user visible description of the `field`nth field of `base`
-    fn describe_field(&self, place: PlaceRef<'tcx>, field: Field) -> String {
+    fn describe_field(
+        &self,
+        place: PlaceRef<'tcx>,
+        field: Field,
+        including_tuple_field: IncludingTupleField,
+    ) -> Option<String> {
         let place_ty = match place {
             PlaceRef { local, projection: [] } => PlaceTy::from_ty(self.body.local_decls[local].ty),
             PlaceRef { local, projection: [proj_base @ .., elem] } => match elem {
@@ -289,7 +320,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
             },
         };
-        self.describe_field_from_ty(place_ty.ty, field, place_ty.variant_index)
+        self.describe_field_from_ty(
+            place_ty.ty,
+            field,
+            place_ty.variant_index,
+            including_tuple_field,
+        )
     }
 
     /// End-user visible description of the `field_index`nth field of `ty`
@@ -298,10 +334,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         ty: Ty<'_>,
         field: Field,
         variant_index: Option<VariantIdx>,
-    ) -> String {
+        including_tuple_field: IncludingTupleField,
+    ) -> Option<String> {
         if ty.is_box() {
             // If the type is a box, the field is described from the boxed type
-            self.describe_field_from_ty(ty.boxed_ty(), field, variant_index)
+            self.describe_field_from_ty(ty.boxed_ty(), field, variant_index, including_tuple_field)
         } else {
             match *ty.kind() {
                 ty::Adt(def, _) => {
@@ -311,30 +348,34 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     } else {
                         def.non_enum_variant()
                     };
-                    variant.fields[field.index()].name.to_string()
+                    if !including_tuple_field.0 && variant.ctor_kind == CtorKind::Fn {
+                        return None;
+                    }
+                    Some(variant.fields[field.index()].name.to_string())
                 }
-                ty::Tuple(_) => field.index().to_string(),
+                ty::Tuple(_) => Some(field.index().to_string()),
                 ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
-                    self.describe_field_from_ty(ty, field, variant_index)
+                    self.describe_field_from_ty(ty, field, variant_index, including_tuple_field)
                 }
                 ty::Array(ty, _) | ty::Slice(ty) => {
-                    self.describe_field_from_ty(ty, field, variant_index)
+                    self.describe_field_from_ty(ty, field, variant_index, including_tuple_field)
                 }
                 ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
                     // We won't be borrowck'ing here if the closure came from another crate,
                     // so it's safe to call `expect_local`.
                     //
                     // We know the field exists so it's safe to call operator[] and `unwrap` here.
+                    let def_id = def_id.expect_local();
                     let var_id = self
                         .infcx
                         .tcx
-                        .typeck(def_id.expect_local())
+                        .typeck(def_id)
                         .closure_min_captures_flattened(def_id)
                         .nth(field.index())
                         .unwrap()
                         .get_root_variable();
 
-                    self.infcx.tcx.hir().name(var_id).to_string()
+                    Some(self.infcx.tcx.hir().name(var_id).to_string())
                 }
                 _ => {
                     // Might need a revision when the fields in trait RFC is implemented
@@ -715,12 +756,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
         debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
         if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind {
-            match kind {
-                box AggregateKind::Closure(def_id, _)
-                | box AggregateKind::Generator(def_id, _, _) => {
+            match **kind {
+                AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => {
                     debug!("move_spans: def_id={:?} places={:?}", def_id, places);
                     if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
-                        self.closure_span(*def_id, moved_place, places)
+                        self.closure_span(def_id, moved_place, places)
                     {
                         return ClosureUse {
                             generator_kind,
@@ -847,7 +887,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) =
                 stmt.kind
             {
-                let (def_id, is_generator) = match kind {
+                let (&def_id, is_generator) = match kind {
                     box AggregateKind::Closure(def_id, _) => (def_id, false),
                     box AggregateKind::Generator(def_id, _, _) => (def_id, true),
                     _ => continue,
@@ -858,7 +898,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     def_id, is_generator, places
                 );
                 if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
-                    self.closure_span(*def_id, Place::from(target).as_ref(), places)
+                    self.closure_span(def_id, Place::from(target).as_ref(), places)
                 {
                     return ClosureUse { generator_kind, args_span, capture_kind_span, path_span };
                 } else {
@@ -879,7 +919,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// The second span is the location the use resulting in the captured path of the capture
     fn closure_span(
         &self,
-        def_id: DefId,
+        def_id: LocalDefId,
         target_place: PlaceRef<'tcx>,
         places: &[Operand<'tcx>],
     ) -> Option<(Span, Option<GeneratorKind>, Span, Span)> {
@@ -887,17 +927,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             "closure_span: def_id={:?} target_place={:?} places={:?}",
             def_id, target_place, places
         );
-        let local_did = def_id.as_local()?;
-        let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(local_did);
+        let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(def_id);
         let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
         debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
         if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = expr {
-            for (captured_place, place) in self
-                .infcx
-                .tcx
-                .typeck(def_id.expect_local())
-                .closure_min_captures_flattened(def_id)
-                .zip(places)
+            for (captured_place, place) in
+                self.infcx.tcx.typeck(def_id).closure_min_captures_flattened(def_id).zip(places)
             {
                 match place {
                     Operand::Copy(place) | Operand::Move(place)
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index becb81b2e26..cb3cd479ae2 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -6,7 +6,7 @@ use rustc_mir_dataflow::move_paths::{
 };
 use rustc_span::Span;
 
-use crate::diagnostics::UseSpans;
+use crate::diagnostics::{DescribePlaceOpt, UseSpans};
 use crate::prefixes::PrefixSet;
 use crate::MirBorrowckCtxt;
 
@@ -368,13 +368,31 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             }
             _ => {
                 let source = self.borrowed_content_source(deref_base);
-                match (self.describe_place(move_place.as_ref()), source.describe_for_named_place())
-                {
-                    (Some(place_desc), Some(source_desc)) => self.cannot_move_out_of(
+                let move_place_ref = move_place.as_ref();
+                match (
+                    self.describe_place_with_options(
+                        move_place_ref,
+                        DescribePlaceOpt {
+                            including_downcast: false,
+                            including_tuple_field: false,
+                        },
+                    ),
+                    self.describe_name(move_place_ref),
+                    source.describe_for_named_place(),
+                ) {
+                    (Some(place_desc), Some(name), Some(source_desc)) => self.cannot_move_out_of(
+                        span,
+                        &format!("`{place_desc}` as enum variant `{name}` which is behind a {source_desc}"),
+                    ),
+                    (Some(place_desc), Some(name), None) => self.cannot_move_out_of(
+                        span,
+                        &format!("`{place_desc}` as enum variant `{name}`"),
+                    ),
+                    (Some(place_desc), _, Some(source_desc)) => self.cannot_move_out_of(
                         span,
                         &format!("`{place_desc}` which is behind a {source_desc}"),
                     ),
-                    (_, _) => self.cannot_move_out_of(
+                    (_, _, _) => self.cannot_move_out_of(
                         span,
                         &source.describe_for_unnamed_place(self.infcx.tcx),
                     ),
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index ac26bc9c7f4..0ad4abbce20 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -343,7 +343,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 );
                 let tcx = self.infcx.tcx;
                 if let ty::Closure(id, _) = *the_place_err.ty(self.body, tcx).ty.kind() {
-                    self.show_mutating_upvar(tcx, id, the_place_err, &mut err);
+                    self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err);
                 }
             }
 
@@ -382,7 +382,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 if let ty::Ref(_, ty, Mutability::Mut) = the_place_err.ty(self.body, tcx).ty.kind()
                     && let ty::Closure(id, _) = *ty.kind()
                 {
-                    self.show_mutating_upvar(tcx, id, the_place_err, &mut err);
+                    self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err);
                 }
             }
 
@@ -685,11 +685,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     fn show_mutating_upvar(
         &self,
         tcx: TyCtxt<'_>,
-        id: hir::def_id::DefId,
+        closure_local_def_id: hir::def_id::LocalDefId,
         the_place_err: PlaceRef<'tcx>,
         err: &mut Diagnostic,
     ) {
-        let closure_local_def_id = id.expect_local();
         let tables = tcx.typeck(closure_local_def_id);
         let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_local_def_id);
         if let Some((span, closure_kind_origin)) =
@@ -699,7 +698,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 let upvar = ty::place_to_string_for_capture(tcx, closure_kind_origin);
                 let root_hir_id = upvar_id.var_path.hir_id;
                 // we have an origin for this closure kind starting at this root variable so it's safe to unwrap here
-                let captured_places = tables.closure_min_captures[&id].get(&root_hir_id).unwrap();
+                let captured_places =
+                    tables.closure_min_captures[&closure_local_def_id].get(&root_hir_id).unwrap();
 
                 let origin_projection = closure_kind_origin
                     .projections
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 0662d4d882f..f68358ecfe6 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -189,7 +189,7 @@ impl Display for RegionName {
 
 impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
     pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId {
-        self.body.source.def_id().as_local().unwrap()
+        self.body.source.def_id().expect_local()
     }
 
     pub(crate) fn mir_hir_id(&self) -> hir::HirId {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 3e2d57ae00c..4f2a7bccefb 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -189,7 +189,7 @@ fn do_mir_borrowck<'a, 'tcx>(
         errors.set_tainted_by_errors();
     }
     let upvars: Vec<_> = tables
-        .closure_min_captures_flattened(def.did.to_def_id())
+        .closure_min_captures_flattened(def.did)
         .map(|captured_place| {
             let capture = captured_place.info.capture_kind;
             let by_ref = match capture {
@@ -1295,7 +1295,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 match **aggregate_kind {
                     AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => {
                         let BorrowCheckResult { used_mut_upvars, .. } =
-                            self.infcx.tcx.mir_borrowck(def_id.expect_local());
+                            self.infcx.tcx.mir_borrowck(def_id);
                         debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars);
                         for field in used_mut_upvars {
                             self.propagate_closure_used_mut_upvar(&operands[field.index()]);
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index cf2140097e6..f7d35da0259 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1847,14 +1847,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     let tcx = self.tcx();
                     let def_id = uv.def.def_id_for_type_of();
                     if tcx.def_kind(def_id) == DefKind::InlineConst {
-                        let predicates = self.prove_closure_bounds(
-                            tcx,
-                            def_id.expect_local(),
-                            uv.substs,
-                            location,
-                        );
+                        let def_id = def_id.expect_local();
+                        let predicates =
+                            self.prove_closure_bounds(tcx, def_id, uv.substs, location);
                         self.normalize_and_prove_instantiated_predicates(
-                            def_id,
+                            def_id.to_def_id(),
                             predicates,
                             location.to_locations(),
                         );
@@ -2514,9 +2511,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             aggregate_kind, location
         );
 
-        let (def_id, instantiated_predicates) = match aggregate_kind {
+        let (def_id, instantiated_predicates) = match *aggregate_kind {
             AggregateKind::Adt(adt_did, _, substs, _, _) => {
-                (*adt_did, tcx.predicates_of(*adt_did).instantiate(tcx, substs))
+                (adt_did, tcx.predicates_of(adt_did).instantiate(tcx, substs))
             }
 
             // For closures, we have some **extra requirements** we
@@ -2541,7 +2538,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             // clauses on the struct.
             AggregateKind::Closure(def_id, substs)
             | AggregateKind::Generator(def_id, substs, _) => {
-                (*def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location))
+                (def_id.to_def_id(), self.prove_closure_bounds(tcx, def_id, substs, location))
             }
 
             AggregateKind::Array(_) | AggregateKind::Tuple => {
diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs
index c92c1051139..b4c79096170 100644
--- a/compiler/rustc_codegen_cranelift/src/archive.rs
+++ b/compiler/rustc_codegen_cranelift/src/archive.rs
@@ -5,7 +5,7 @@ use std::fs::File;
 use std::io::{self, Read, Seek};
 use std::path::{Path, PathBuf};
 
-use rustc_codegen_ssa::back::archive::ArchiveBuilder;
+use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
 use rustc_session::Session;
 
 use object::read::archive::ArchiveFile;
@@ -17,9 +17,34 @@ enum ArchiveEntry {
     File(PathBuf),
 }
 
+pub(crate) struct ArArchiveBuilderBuilder;
+
+impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
+    fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
+        Box::new(ArArchiveBuilder {
+            sess,
+            use_gnu_style_archive: sess.target.archive_format == "gnu",
+            // FIXME fix builtin ranlib on macOS
+            no_builtin_ranlib: sess.target.is_like_osx,
+
+            src_archives: vec![],
+            entries: vec![],
+        })
+    }
+
+    fn create_dll_import_lib(
+        &self,
+        _sess: &Session,
+        _lib_name: &str,
+        _dll_imports: &[rustc_session::cstore::DllImport],
+        _tmpdir: &Path,
+    ) -> PathBuf {
+        bug!("creating dll imports is not supported");
+    }
+}
+
 pub(crate) struct ArArchiveBuilder<'a> {
     sess: &'a Session,
-    dst: PathBuf,
     use_gnu_style_archive: bool,
     no_builtin_ranlib: bool,
 
@@ -30,19 +55,6 @@ pub(crate) struct ArArchiveBuilder<'a> {
 }
 
 impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
-    fn new(sess: &'a Session, output: &Path) -> Self {
-        ArArchiveBuilder {
-            sess,
-            dst: output.to_path_buf(),
-            use_gnu_style_archive: sess.target.archive_format == "gnu",
-            // FIXME fix builtin ranlib on macOS
-            no_builtin_ranlib: sess.target.is_like_osx,
-
-            src_archives: vec![],
-            entries: vec![],
-        }
-    }
-
     fn add_file(&mut self, file: &Path) {
         self.entries.push((
             file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(),
@@ -50,10 +62,11 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
         ));
     }
 
-    fn add_archive<F>(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()>
-    where
-        F: FnMut(&str) -> bool + 'static,
-    {
+    fn add_archive(
+        &mut self,
+        archive_path: &Path,
+        mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
+    ) -> std::io::Result<()> {
         let read_cache = ReadCache::new(std::fs::File::open(&archive_path)?);
         let archive = ArchiveFile::parse(&read_cache).unwrap();
         let archive_index = self.src_archives.len();
@@ -74,7 +87,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
         Ok(())
     }
 
-    fn build(mut self) -> bool {
+    fn build(mut self: Box<Self>, output: &Path) -> bool {
         enum BuilderKind {
             Bsd(ar::Builder<File>),
             Gnu(ar::GnuBuilder<File>),
@@ -163,7 +176,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
         let mut builder = if self.use_gnu_style_archive {
             BuilderKind::Gnu(
                 ar::GnuBuilder::new(
-                    File::create(&self.dst).unwrap_or_else(|err| {
+                    File::create(output).unwrap_or_else(|err| {
                         sess.fatal(&format!(
                             "error opening destination during archive building: {}",
                             err
@@ -178,7 +191,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
         } else {
             BuilderKind::Bsd(
                 ar::Builder::new(
-                    File::create(&self.dst).unwrap_or_else(|err| {
+                    File::create(output).unwrap_or_else(|err| {
                         sess.fatal(&format!(
                             "error opening destination during archive building: {}",
                             err
@@ -209,7 +222,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
 
             // Run ranlib to be able to link the archive
             let status = std::process::Command::new(ranlib)
-                .arg(self.dst)
+                .arg(output)
                 .status()
                 .expect("Couldn't run ranlib");
 
@@ -220,17 +233,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
 
         any_members
     }
-
-    fn sess(&self) -> &Session {
-        self.sess
-    }
-
-    fn create_dll_import_lib(
-        _sess: &Session,
-        _lib_name: &str,
-        _dll_imports: &[rustc_session::cstore::DllImport],
-        _tmpdir: &Path,
-    ) -> PathBuf {
-        bug!("creating dll imports is not supported");
-    }
 }
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 568bb20a3f4..bb0793b1deb 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -226,7 +226,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
     ) -> Result<(), ErrorGuaranteed> {
         use rustc_codegen_ssa::back::link::link_binary;
 
-        link_binary::<crate::archive::ArArchiveBuilder<'_>>(sess, &codegen_results, outputs)
+        link_binary(sess, &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs)
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs
index 21f62a6b009..f863abdcc97 100644
--- a/compiler/rustc_codegen_gcc/src/archive.rs
+++ b/compiler/rustc_codegen_gcc/src/archive.rs
@@ -1,14 +1,13 @@
 use std::fs::File;
 use std::path::{Path, PathBuf};
 
-use rustc_codegen_ssa::back::archive::ArchiveBuilder;
+use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
 use rustc_session::Session;
 
 use rustc_session::cstore::DllImport;
 
 struct ArchiveConfig<'a> {
     sess: &'a Session,
-    dst: PathBuf,
     use_native_ar: bool,
     use_gnu_style_archive: bool,
 }
@@ -22,31 +21,44 @@ enum ArchiveEntry {
     File(PathBuf),
 }
 
-pub struct ArArchiveBuilder<'a> {
-    config: ArchiveConfig<'a>,
-    src_archives: Vec<(PathBuf, ar::Archive<File>)>,
-    // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
-    // the end of an archive for linkers to not get confused.
-    entries: Vec<(String, ArchiveEntry)>,
-}
+pub struct ArArchiveBuilderBuilder;
 
-impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
-    fn new(sess: &'a Session, output: &Path) -> Self {
+impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
+    fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
         let config = ArchiveConfig {
             sess,
-            dst: output.to_path_buf(),
             use_native_ar: false,
             // FIXME test for linux and System V derivatives instead
             use_gnu_style_archive: sess.target.options.archive_format == "gnu",
         };
 
-        ArArchiveBuilder {
+        Box::new(ArArchiveBuilder {
             config,
             src_archives: vec![],
             entries: vec![],
-        }
+        })
+    }
+
+    fn create_dll_import_lib(
+        &self,
+        _sess: &Session,
+        _lib_name: &str,
+        _dll_imports: &[DllImport],
+        _tmpdir: &Path,
+    ) -> PathBuf {
+        unimplemented!();
     }
+}
 
+pub struct ArArchiveBuilder<'a> {
+    config: ArchiveConfig<'a>,
+    src_archives: Vec<(PathBuf, ar::Archive<File>)>,
+    // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
+    // the end of an archive for linkers to not get confused.
+    entries: Vec<(String, ArchiveEntry)>,
+}
+
+impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
     fn add_file(&mut self, file: &Path) {
         self.entries.push((
             file.file_name().unwrap().to_str().unwrap().to_string(),
@@ -54,10 +66,11 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
         ));
     }
 
-    fn add_archive<F>(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()>
-    where
-        F: FnMut(&str) -> bool + 'static,
-    {
+    fn add_archive(
+        &mut self,
+        archive_path: &Path,
+        mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
+    ) -> std::io::Result<()> {
         let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
         let archive_index = self.src_archives.len();
 
@@ -77,7 +90,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
         Ok(())
     }
 
-    fn build(mut self) -> bool {
+    fn build(mut self: Box<Self>, output: &Path) -> bool {
         use std::process::Command;
 
         fn add_file_using_ar(archive: &Path, file: &Path) {
@@ -97,17 +110,17 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
         }
 
         let mut builder = if self.config.use_native_ar {
-            BuilderKind::NativeAr(&self.config.dst)
+            BuilderKind::NativeAr(output)
         } else if self.config.use_gnu_style_archive {
             BuilderKind::Gnu(ar::GnuBuilder::new(
-                File::create(&self.config.dst).unwrap(),
+                File::create(output).unwrap(),
                 self.entries
                     .iter()
                     .map(|(name, _)| name.as_bytes().to_vec())
                     .collect(),
             ))
         } else {
-            BuilderKind::Bsd(ar::Builder::new(File::create(&self.config.dst).unwrap()))
+            BuilderKind::Bsd(ar::Builder::new(File::create(output).unwrap()))
         };
 
         let any_members = !self.entries.is_empty();
@@ -164,10 +177,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
         std::mem::drop(builder);
 
         // Run ranlib to be able to link the archive
-        let status = std::process::Command::new("ranlib")
-            .arg(self.config.dst)
-            .status()
-            .expect("Couldn't run ranlib");
+        let status =
+            std::process::Command::new("ranlib").arg(output).status().expect("Couldn't run ranlib");
 
         if !status.success() {
             self.config.sess.fatal(&format!("Ranlib exited with code {:?}", status.code()));
@@ -175,17 +186,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
 
         any_members
     }
-
-    fn sess(&self) -> &Session {
-        self.config.sess
-    }
-
-    fn create_dll_import_lib(
-        _sess: &Session,
-        _lib_name: &str,
-        _dll_imports: &[DllImport],
-        _tmpdir: &Path,
-    ) -> PathBuf {
-        unimplemented!();
-    }
 }
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index c21e0c5a35b..8a206c0368f 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -133,8 +133,9 @@ impl CodegenBackend for GccCodegenBackend {
     fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorGuaranteed> {
         use rustc_codegen_ssa::back::link::link_binary;
 
-        link_binary::<crate::archive::ArArchiveBuilder<'_>>(
+        link_binary(
             sess,
+            &crate::archive::ArArchiveBuilderBuilder,
             &codegen_results,
             outputs,
         )
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index baa858709a0..27039cda253 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -10,7 +10,7 @@ use std::str;
 
 use crate::llvm::archive_ro::{ArchiveRO, Child};
 use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
-use rustc_codegen_ssa::back::archive::ArchiveBuilder;
+use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
 use rustc_session::cstore::{DllCallingConvention, DllImport};
 use rustc_session::Session;
 
@@ -18,7 +18,6 @@ use rustc_session::Session;
 #[must_use = "must call build() to finish building the archive"]
 pub struct LlvmArchiveBuilder<'a> {
     sess: &'a Session,
-    dst: PathBuf,
     additions: Vec<Addition>,
 }
 
@@ -54,16 +53,11 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
 }
 
 impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
-    /// Creates a new static archive, ready for modifying the archive specified
-    /// by `config`.
-    fn new(sess: &'a Session, output: &Path) -> LlvmArchiveBuilder<'a> {
-        LlvmArchiveBuilder { sess, dst: output.to_path_buf(), additions: Vec::new() }
-    }
-
-    fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
-    where
-        F: FnMut(&str) -> bool + 'static,
-    {
+    fn add_archive(
+        &mut self,
+        archive: &Path,
+        skip: Box<dyn FnMut(&str) -> bool + 'static>,
+    ) -> io::Result<()> {
         let archive_ro = match ArchiveRO::open(archive) {
             Ok(ar) => ar,
             Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
@@ -88,18 +82,23 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
 
     /// Combine the provided files, rlibs, and native libraries into a single
     /// `Archive`.
-    fn build(mut self) -> bool {
-        match self.build_with_llvm() {
+    fn build(mut self: Box<Self>, output: &Path) -> bool {
+        match self.build_with_llvm(output) {
             Ok(any_members) => any_members,
             Err(e) => self.sess.fatal(&format!("failed to build archive: {}", e)),
         }
     }
+}
+
+pub struct LlvmArchiveBuilderBuilder;
 
-    fn sess(&self) -> &Session {
-        self.sess
+impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
+    fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
+        Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() })
     }
 
     fn create_dll_import_lib(
+        &self,
         sess: &Session,
         lib_name: &str,
         dll_imports: &[DllImport],
@@ -241,7 +240,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
 }
 
 impl<'a> LlvmArchiveBuilder<'a> {
-    fn build_with_llvm(&mut self) -> io::Result<bool> {
+    fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> {
         let kind = &*self.sess.target.archive_format;
         let kind = kind.parse::<ArchiveKind>().map_err(|_| kind).unwrap_or_else(|kind| {
             self.sess.fatal(&format!("Don't know how to build archive of type: {}", kind))
@@ -251,7 +250,7 @@ impl<'a> LlvmArchiveBuilder<'a> {
         let mut strings = Vec::new();
         let mut members = Vec::new();
 
-        let dst = CString::new(self.dst.to_str().unwrap())?;
+        let dst = CString::new(output.to_str().unwrap())?;
 
         unsafe {
             for addition in &mut additions {
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 25ce1cef944..eeb1ed61f28 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -370,12 +370,12 @@ impl CodegenBackend for LlvmCodegenBackend {
         codegen_results: CodegenResults,
         outputs: &OutputFilenames,
     ) -> Result<(), ErrorGuaranteed> {
-        use crate::back::archive::LlvmArchiveBuilder;
+        use crate::back::archive::LlvmArchiveBuilderBuilder;
         use rustc_codegen_ssa::back::link::link_binary;
 
         // Run the linker on any artifacts that resulted from the LLVM run.
         // This should produce either a finished executable or library.
-        link_binary::<LlvmArchiveBuilder<'_>>(sess, &codegen_results, outputs)
+        link_binary(sess, &LlvmArchiveBuilderBuilder, &codegen_results, outputs)
     }
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index 53550b049db..0d2aa483d3d 100644
--- a/compiler/rustc_codegen_ssa/src/back/archive.rs
+++ b/compiler/rustc_codegen_ssa/src/back/archive.rs
@@ -1,4 +1,3 @@
-use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_session::cstore::DllImport;
 use rustc_session::Session;
 
@@ -40,18 +39,8 @@ pub(super) fn find_library(
     ));
 }
 
-pub trait ArchiveBuilder<'a> {
-    fn new(sess: &'a Session, output: &Path) -> Self;
-
-    fn add_file(&mut self, path: &Path);
-
-    fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
-    where
-        F: FnMut(&str) -> bool + 'static;
-
-    fn build(self) -> bool;
-
-    fn sess(&self) -> &Session;
+pub trait ArchiveBuilderBuilder {
+    fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a>;
 
     /// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>.
     /// and returns the path on disk to that import library.
@@ -59,29 +48,22 @@ pub trait ArchiveBuilder<'a> {
     /// `linker_with_args`, which is specialized on `ArchiveBuilder` but
     /// doesn't take or create an instance of that type.
     fn create_dll_import_lib(
+        &self,
         sess: &Session,
         lib_name: &str,
         dll_imports: &[DllImport],
         tmpdir: &Path,
     ) -> PathBuf;
+}
 
-    /// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>
-    /// and adds it to the current compilation's set of archives.
-    fn inject_dll_import_lib(
+pub trait ArchiveBuilder<'a> {
+    fn add_file(&mut self, path: &Path);
+
+    fn add_archive(
         &mut self,
-        lib_name: &str,
-        dll_imports: &[DllImport],
-        tmpdir: &MaybeTempDir,
-    ) {
-        let output_path =
-            Self::create_dll_import_lib(self.sess(), lib_name, dll_imports, tmpdir.as_ref());
+        archive: &Path,
+        skip: Box<dyn FnMut(&str) -> bool + 'static>,
+    ) -> io::Result<()>;
 
-        self.add_archive(&output_path, |_| false).unwrap_or_else(|e| {
-            self.sess().fatal(&format!(
-                "failed to add native library {}: {}",
-                output_path.display(),
-                e
-            ));
-        });
-    }
+    fn build(self: Box<Self>, output: &Path) -> bool;
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index c26e8d99bbb..13a7b6be947 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -24,7 +24,7 @@ use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
 use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo};
 use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target};
 
-use super::archive::{find_library, ArchiveBuilder};
+use super::archive::{find_library, ArchiveBuilder, ArchiveBuilderBuilder};
 use super::command::Command;
 use super::linker::{self, Linker};
 use super::metadata::{create_rmeta_file, MetadataPosition};
@@ -56,8 +56,9 @@ pub fn ensure_removed(diag_handler: &Handler, path: &Path) {
 
 /// Performs the linkage portion of the compilation phase. This will generate all
 /// of the requested outputs for this compilation session.
-pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
+pub fn link_binary<'a>(
     sess: &'a Session,
+    archive_builder_builder: &dyn ArchiveBuilderBuilder,
     codegen_results: &CodegenResults,
     outputs: &OutputFilenames,
 ) -> Result<(), ErrorGuaranteed> {
@@ -101,21 +102,29 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
             match crate_type {
                 CrateType::Rlib => {
                     let _timer = sess.timer("link_rlib");
-                    link_rlib::<B>(
+                    info!("preparing rlib to {:?}", out_filename);
+                    link_rlib(
                         sess,
+                        archive_builder_builder,
                         codegen_results,
                         RlibFlavor::Normal,
-                        &out_filename,
                         &path,
                     )?
-                    .build();
+                    .build(&out_filename);
                 }
                 CrateType::Staticlib => {
-                    link_staticlib::<B>(sess, codegen_results, &out_filename, &path)?;
+                    link_staticlib(
+                        sess,
+                        archive_builder_builder,
+                        codegen_results,
+                        &out_filename,
+                        &path,
+                    )?;
                 }
                 _ => {
-                    link_natively::<B>(
+                    link_natively(
                         sess,
+                        archive_builder_builder,
                         crate_type,
                         &out_filename,
                         codegen_results,
@@ -245,18 +254,16 @@ pub fn each_linked_rlib(
 /// the object file of the crate, but it also contains all of the object files from native
 /// libraries. This is done by unzipping native libraries and inserting all of the contents into
 /// this archive.
-fn link_rlib<'a, B: ArchiveBuilder<'a>>(
+fn link_rlib<'a>(
     sess: &'a Session,
+    archive_builder_builder: &dyn ArchiveBuilderBuilder,
     codegen_results: &CodegenResults,
     flavor: RlibFlavor,
-    out_filename: &Path,
     tmpdir: &MaybeTempDir,
-) -> Result<B, ErrorGuaranteed> {
-    info!("preparing rlib to {:?}", out_filename);
-
+) -> Result<Box<dyn ArchiveBuilder<'a> + 'a>, ErrorGuaranteed> {
     let lib_search_paths = archive_search_paths(sess);
 
-    let mut ab = <B as ArchiveBuilder>::new(sess, out_filename);
+    let mut ab = archive_builder_builder.new_archive_builder(sess);
 
     let trailing_metadata = match flavor {
         RlibFlavor::Normal => {
@@ -342,7 +349,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
         if let Some(name) = lib.name {
             let location =
                 find_library(name.as_str(), lib.verbatim.unwrap_or(false), &lib_search_paths, sess);
-            ab.add_archive(&location, |_| false).unwrap_or_else(|e| {
+            ab.add_archive(&location, Box::new(|_| false)).unwrap_or_else(|e| {
                 sess.fatal(&format!(
                     "failed to add native library {}: {}",
                     location.to_string_lossy(),
@@ -355,7 +362,16 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
     for (raw_dylib_name, raw_dylib_imports) in
         collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)?
     {
-        ab.inject_dll_import_lib(&raw_dylib_name, &raw_dylib_imports, tmpdir);
+        let output_path = archive_builder_builder.create_dll_import_lib(
+            sess,
+            &raw_dylib_name,
+            &raw_dylib_imports,
+            tmpdir.as_ref(),
+        );
+
+        ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|e| {
+            sess.fatal(&format!("failed to add native library {}: {}", output_path.display(), e));
+        });
     }
 
     if let Some(trailing_metadata) = trailing_metadata {
@@ -446,14 +462,21 @@ fn collate_raw_dylibs(
 ///
 /// There's no need to include metadata in a static archive, so ensure to not link in the metadata
 /// object file (and also don't prepare the archive with a metadata file).
-fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
+fn link_staticlib<'a>(
     sess: &'a Session,
+    archive_builder_builder: &dyn ArchiveBuilderBuilder,
     codegen_results: &CodegenResults,
     out_filename: &Path,
     tempdir: &MaybeTempDir,
 ) -> Result<(), ErrorGuaranteed> {
-    let mut ab =
-        link_rlib::<B>(sess, codegen_results, RlibFlavor::StaticlibBase, out_filename, tempdir)?;
+    info!("preparing staticlib to {:?}", out_filename);
+    let mut ab = link_rlib(
+        sess,
+        archive_builder_builder,
+        codegen_results,
+        RlibFlavor::StaticlibBase,
+        tempdir,
+    )?;
     let mut all_native_libs = vec![];
 
     let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| {
@@ -487,26 +510,29 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
         // might be also an extra name suffix
         let obj_start = name.as_str().to_owned();
 
-        ab.add_archive(path, move |fname: &str| {
-            // Ignore metadata files, no matter the name.
-            if fname == METADATA_FILENAME {
-                return true;
-            }
+        ab.add_archive(
+            path,
+            Box::new(move |fname: &str| {
+                // Ignore metadata files, no matter the name.
+                if fname == METADATA_FILENAME {
+                    return true;
+                }
 
-            // Don't include Rust objects if LTO is enabled
-            if lto && looks_like_rust_object_file(fname) {
-                return true;
-            }
+                // Don't include Rust objects if LTO is enabled
+                if lto && looks_like_rust_object_file(fname) {
+                    return true;
+                }
 
-            // Otherwise if this is *not* a rust object and we're skipping
-            // objects then skip this file
-            if skip_object_files && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
-                return true;
-            }
+                // Otherwise if this is *not* a rust object and we're skipping
+                // objects then skip this file
+                if skip_object_files && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
+                    return true;
+                }
 
-            // ok, don't skip this
-            false
-        })
+                // ok, don't skip this
+                false
+            }),
+        )
         .unwrap();
 
         all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
@@ -515,7 +541,7 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
         sess.fatal(&e);
     }
 
-    ab.build();
+    ab.build(out_filename);
 
     if !all_native_libs.is_empty() {
         if sess.opts.prints.contains(&PrintRequest::NativeStaticLibs) {
@@ -645,8 +671,9 @@ fn link_dwarf_object<'a>(
 ///
 /// This will invoke the system linker/cc to create the resulting file. This links to all upstream
 /// files as well.
-fn link_natively<'a, B: ArchiveBuilder<'a>>(
+fn link_natively<'a>(
     sess: &'a Session,
+    archive_builder_builder: &dyn ArchiveBuilderBuilder,
     crate_type: CrateType,
     out_filename: &Path,
     codegen_results: &CodegenResults,
@@ -654,10 +681,11 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
 ) -> Result<(), ErrorGuaranteed> {
     info!("preparing {:?} to {:?}", crate_type, out_filename);
     let (linker_path, flavor) = linker_and_flavor(sess);
-    let mut cmd = linker_with_args::<B>(
+    let mut cmd = linker_with_args(
         &linker_path,
         flavor,
         sess,
+        archive_builder_builder,
         crate_type,
         tmpdir,
         out_filename,
@@ -1844,10 +1872,11 @@ fn add_rpath_args(
 /// to the linking process as a whole.
 /// Order-independent options may still override each other in order-dependent fashion,
 /// e.g `--foo=yes --foo=no` may be equivalent to `--foo=no`.
-fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
+fn linker_with_args<'a>(
     path: &Path,
     flavor: LinkerFlavor,
     sess: &'a Session,
+    archive_builder_builder: &dyn ArchiveBuilderBuilder,
     crate_type: CrateType,
     tmpdir: &Path,
     out_filename: &Path,
@@ -1948,7 +1977,14 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
     }
 
     // Upstream rust libraries and their non-bundled static libraries
-    add_upstream_rust_crates::<B>(cmd, sess, codegen_results, crate_type, tmpdir);
+    add_upstream_rust_crates(
+        cmd,
+        sess,
+        archive_builder_builder,
+        codegen_results,
+        crate_type,
+        tmpdir,
+    );
 
     // Upstream dynamic native libraries linked with `#[link]` attributes at and `-l`
     // command line options.
@@ -1963,7 +1999,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
     for (raw_dylib_name, raw_dylib_imports) in
         collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)?
     {
-        cmd.add_object(&B::create_dll_import_lib(
+        cmd.add_object(&archive_builder_builder.create_dll_import_lib(
             sess,
             &raw_dylib_name,
             &raw_dylib_imports,
@@ -2256,9 +2292,10 @@ fn add_local_native_libraries(
 ///
 /// Rust crates are not considered at all when creating an rlib output. All dependencies will be
 /// linked when producing the final output (instead of the intermediate rlib version).
-fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
+fn add_upstream_rust_crates<'a>(
     cmd: &mut dyn Linker,
     sess: &'a Session,
+    archive_builder_builder: &dyn ArchiveBuilderBuilder,
     codegen_results: &CodegenResults,
     crate_type: CrateType,
     tmpdir: &Path,
@@ -2347,7 +2384,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
         let src = &codegen_results.crate_info.used_crate_source[&cnum];
         match data[cnum.as_usize() - 1] {
             _ if codegen_results.crate_info.profiler_runtime == Some(cnum) => {
-                add_static_crate::<B>(cmd, sess, codegen_results, tmpdir, cnum);
+                add_static_crate(cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum);
             }
             // compiler-builtins are always placed last to ensure that they're
             // linked correctly.
@@ -2357,7 +2394,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
             }
             Linkage::NotLinked | Linkage::IncludedFromDylib => {}
             Linkage::Static => {
-                add_static_crate::<B>(cmd, sess, codegen_results, tmpdir, cnum);
+                add_static_crate(cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum);
 
                 // Link static native libs with "-bundle" modifier only if the crate they originate from
                 // is being linked statically to the current crate.  If it's linked dynamically
@@ -2431,7 +2468,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
     // was already "included" in a dylib (e.g., `libstd` when `-C prefer-dynamic`
     // is used)
     if let Some(cnum) = compiler_builtins {
-        add_static_crate::<B>(cmd, sess, codegen_results, tmpdir, cnum);
+        add_static_crate(cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum);
     }
 
     // Converts a library file-stem into a cc -l argument
@@ -2457,9 +2494,10 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
     // Note, however, that if we're not doing LTO we can just pass the rlib
     // blindly to the linker (fast) because it's fine if it's not actually
     // included as we're at the end of the dependency chain.
-    fn add_static_crate<'a, B: ArchiveBuilder<'a>>(
+    fn add_static_crate<'a>(
         cmd: &mut dyn Linker,
         sess: &'a Session,
+        archive_builder_builder: &dyn ArchiveBuilderBuilder,
         codegen_results: &CodegenResults,
         tmpdir: &Path,
         cnum: CrateNum,
@@ -2499,38 +2537,41 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
             let is_builtins = sess.target.no_builtins
                 || !codegen_results.crate_info.is_no_builtins.contains(&cnum);
 
-            let mut archive = <B as ArchiveBuilder>::new(sess, &dst);
-            if let Err(e) = archive.add_archive(cratepath, move |f| {
-                if f == METADATA_FILENAME {
-                    return true;
-                }
+            let mut archive = archive_builder_builder.new_archive_builder(sess);
+            if let Err(e) = archive.add_archive(
+                cratepath,
+                Box::new(move |f| {
+                    if f == METADATA_FILENAME {
+                        return true;
+                    }
 
-                let canonical = f.replace('-', "_");
+                    let canonical = f.replace('-', "_");
 
-                let is_rust_object =
-                    canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f);
+                    let is_rust_object =
+                        canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f);
 
-                // If we've been requested to skip all native object files
-                // (those not generated by the rust compiler) then we can skip
-                // this file. See above for why we may want to do this.
-                let skip_because_cfg_say_so = skip_native && !is_rust_object;
+                    // If we've been requested to skip all native object files
+                    // (those not generated by the rust compiler) then we can skip
+                    // this file. See above for why we may want to do this.
+                    let skip_because_cfg_say_so = skip_native && !is_rust_object;
 
-                // If we're performing LTO and this is a rust-generated object
-                // file, then we don't need the object file as it's part of the
-                // LTO module. Note that `#![no_builtins]` is excluded from LTO,
-                // though, so we let that object file slide.
-                let skip_because_lto =
-                    upstream_rust_objects_already_included && is_rust_object && is_builtins;
+                    // If we're performing LTO and this is a rust-generated object
+                    // file, then we don't need the object file as it's part of the
+                    // LTO module. Note that `#![no_builtins]` is excluded from LTO,
+                    // though, so we let that object file slide.
+                    let skip_because_lto =
+                        upstream_rust_objects_already_included && is_rust_object && is_builtins;
 
-                if skip_because_cfg_say_so || skip_because_lto {
-                    return true;
-                }
+                    if skip_because_cfg_say_so || skip_because_lto {
+                        return true;
+                    }
 
-                false
-            }) {
+                    false
+                }),
+            ) {
                 sess.fatal(&format!("failed to build archive from rlib: {}", e));
             }
-            if archive.build() {
+            if archive.build(&dst) {
                 link_upstream(&dst);
             }
         });
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index a4bbdefbb87..ce51b2e9531 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -656,9 +656,7 @@ impl<'a> Linker for GccLinker<'a> {
             return;
         }
 
-        if crate_type == CrateType::ProcMacro {
-            return;
-        }
+        // FIXME(#99978) hide #[no_mangle] symbols for proc-macros
 
         let is_windows = self.sess.target.is_like_windows;
         let path = tmpdir.join(if is_windows { "list.def" } else { "list" });
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index d1a267f7643..e6b6055759d 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -257,16 +257,18 @@ fn exported_symbols_provider_local<'tcx>(
         }));
     }
 
-    if tcx.sess.crate_types().contains(&CrateType::Dylib) {
+    if tcx.sess.crate_types().contains(&CrateType::Dylib)
+        || tcx.sess.crate_types().contains(&CrateType::ProcMacro)
+    {
         let symbol_name = metadata_symbol_name(tcx);
         let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));
 
         symbols.push((
             exported_symbol,
             SymbolExportInfo {
-                level: SymbolExportLevel::Rust,
+                level: SymbolExportLevel::C,
                 kind: SymbolExportKind::Data,
-                used: false,
+                used: true,
             },
         ));
     }
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index de284bd3bae..94ba62c160c 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -37,9 +37,6 @@ pub enum Immediate<Prov: Provenance = AllocId> {
     Uninit,
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Immediate, 56);
-
 impl<Prov: Provenance> From<ScalarMaybeUninit<Prov>> for Immediate<Prov> {
     #[inline(always)]
     fn from(val: ScalarMaybeUninit<Prov>) -> Self {
@@ -117,9 +114,6 @@ pub struct ImmTy<'tcx, Prov: Provenance = AllocId> {
     pub layout: TyAndLayout<'tcx>,
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(ImmTy<'_>, 72);
-
 impl<Prov: Provenance> std::fmt::Display for ImmTy<'_, Prov> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         /// Helper function for printing a scalar to a FmtPrinter
@@ -187,9 +181,6 @@ pub enum Operand<Prov: Provenance = AllocId> {
     Indirect(MemPlace<Prov>),
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Operand, 64);
-
 #[derive(Clone, Debug)]
 pub struct OpTy<'tcx, Prov: Provenance = AllocId> {
     op: Operand<Prov>, // Keep this private; it helps enforce invariants.
@@ -204,9 +195,6 @@ pub struct OpTy<'tcx, Prov: Provenance = AllocId> {
     pub align: Option<Align>,
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(OpTy<'_>, 88);
-
 impl<'tcx, Prov: Provenance> std::ops::Deref for OpTy<'tcx, Prov> {
     type Target = Operand<Prov>;
     #[inline(always)]
@@ -830,3 +818,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         })
     }
 }
+
+// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+    use super::*;
+    // These are in alphabetical order, which is easy to maintain.
+    rustc_data_structures::static_assert_size!(Immediate, 56);
+    rustc_data_structures::static_assert_size!(ImmTy<'_>, 72);
+    rustc_data_structures::static_assert_size!(Operand, 64);
+    rustc_data_structures::static_assert_size!(OpTy<'_>, 88);
+}
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 473da71a0ab..f4571a1ca3d 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -25,9 +25,6 @@ pub enum MemPlaceMeta<Prov: Provenance = AllocId> {
     None,
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(MemPlaceMeta, 24);
-
 impl<Prov: Provenance> MemPlaceMeta<Prov> {
     pub fn unwrap_meta(self) -> Scalar<Prov> {
         match self {
@@ -56,9 +53,6 @@ pub struct MemPlace<Prov: Provenance = AllocId> {
     pub meta: MemPlaceMeta<Prov>,
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(MemPlace, 40);
-
 /// A MemPlace with its layout. Constructing it is only possible in this module.
 #[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
 pub struct MPlaceTy<'tcx, Prov: Provenance = AllocId> {
@@ -71,9 +65,6 @@ pub struct MPlaceTy<'tcx, Prov: Provenance = AllocId> {
     pub align: Align,
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(MPlaceTy<'_>, 64);
-
 #[derive(Copy, Clone, Debug)]
 pub enum Place<Prov: Provenance = AllocId> {
     /// A place referring to a value allocated in the `Memory` system.
@@ -84,9 +75,6 @@ pub enum Place<Prov: Provenance = AllocId> {
     Local { frame: usize, local: mir::Local },
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Place, 48);
-
 #[derive(Clone, Debug)]
 pub struct PlaceTy<'tcx, Prov: Provenance = AllocId> {
     place: Place<Prov>, // Keep this private; it helps enforce invariants.
@@ -98,9 +86,6 @@ pub struct PlaceTy<'tcx, Prov: Provenance = AllocId> {
     pub align: Align,
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(PlaceTy<'_>, 72);
-
 impl<'tcx, Prov: Provenance> std::ops::Deref for PlaceTy<'tcx, Prov> {
     type Target = Place<Prov>;
     #[inline(always)]
@@ -901,3 +886,15 @@ where
         Ok(mplace)
     }
 }
+
+// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+    use super::*;
+    // These are in alphabetical order, which is easy to maintain.
+    rustc_data_structures::static_assert_size!(MemPlaceMeta, 24);
+    rustc_data_structures::static_assert_size!(MemPlace, 40);
+    rustc_data_structures::static_assert_size!(MPlaceTy<'_>, 64);
+    rustc_data_structures::static_assert_size!(Place, 48);
+    rustc_data_structures::static_assert_size!(PlaceTy<'_>, 72);
+}
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index d20f16755c3..6f6717721fb 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -238,7 +238,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 if let Some(local_def_id) = def_id.as_local() {
                     let tables = self.ecx.tcx.typeck(local_def_id);
                     if let Some(captured_place) =
-                        tables.closure_min_captures_flattened(*def_id).nth(field)
+                        tables.closure_min_captures_flattened(local_def_id).nth(field)
                     {
                         // Sometimes the index is beyond the number of upvars (seen
                         // for a generator).
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 628298df473..0adb88a180f 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -772,7 +772,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                             let mut nonconst_call_permission = false;
                             if let Some(callee_trait) = tcx.trait_of_item(callee)
                                 && tcx.has_attr(callee_trait, sym::const_trait)
-                                && Some(callee_trait) == tcx.trait_of_item(caller)
+                                && Some(callee_trait) == tcx.trait_of_item(caller.to_def_id())
                                 // Can only call methods when it's `<Self as TheTrait>::f`.
                                 && tcx.types.self_param == substs.type_at(0)
                             {
diff --git a/compiler/rustc_const_eval/src/util/call_kind.rs b/compiler/rustc_const_eval/src/util/call_kind.rs
index a7a480dd1d7..af9d83f0609 100644
--- a/compiler/rustc_const_eval/src/util/call_kind.rs
+++ b/compiler/rustc_const_eval/src/util/call_kind.rs
@@ -66,9 +66,12 @@ pub fn call_kind<'tcx>(
     from_hir_call: bool,
     self_arg: Option<Ident>,
 ) -> CallKind<'tcx> {
-    let parent = tcx.opt_associated_item(method_did).and_then(|assoc| match assoc.container {
-        AssocItemContainer::ImplContainer(impl_did) => tcx.trait_id_of_impl(impl_did),
-        AssocItemContainer::TraitContainer(trait_did) => Some(trait_did),
+    let parent = tcx.opt_associated_item(method_did).and_then(|assoc| {
+        let container_id = assoc.container_id(tcx);
+        match assoc.container {
+            AssocItemContainer::ImplContainer => tcx.trait_id_of_impl(container_id),
+            AssocItemContainer::TraitContainer => Some(container_id),
+        }
     });
 
     let fn_call = parent
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 5f8801cc4e2..c2c551e78a4 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -338,7 +338,12 @@ impl Definitions {
 
     /// Adds a definition with a parent definition.
     pub fn create_def(&mut self, parent: LocalDefId, data: DefPathData) -> LocalDefId {
-        debug!("create_def(parent={:?}, data={:?})", parent, data);
+        // We can't use `Debug` implementation for `LocalDefId` here, since it tries to acquire a
+        // reference to `Definitions` and we're already holding a mutable reference.
+        debug!(
+            "create_def(parent={}, data={data:?})",
+            self.def_path(parent).to_string_no_crate_verbose(),
+        );
 
         // The root node must be created with `create_root_def()`.
         assert!(data != DefPathData::CrateRoot);
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index f71400898e6..617433a9803 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2222,6 +2222,7 @@ pub struct TraitItem<'hir> {
     pub generics: &'hir Generics<'hir>,
     pub kind: TraitItemKind<'hir>,
     pub span: Span,
+    pub defaultness: Defaultness,
 }
 
 impl TraitItem<'_> {
@@ -2281,6 +2282,7 @@ pub struct ImplItem<'hir> {
     pub def_id: LocalDefId,
     pub generics: &'hir Generics<'hir>,
     pub kind: ImplItemKind<'hir>,
+    pub defaultness: Defaultness,
     pub span: Span,
     pub vis_span: Span,
 }
@@ -3083,7 +3085,6 @@ pub struct TraitItemRef {
     pub ident: Ident,
     pub kind: AssocItemKind,
     pub span: Span,
-    pub defaultness: Defaultness,
 }
 
 /// A reference from an impl to one of its associated items. This
@@ -3098,7 +3099,6 @@ pub struct ImplItemRef {
     pub ident: Ident,
     pub kind: AssocItemKind,
     pub span: Span,
-    pub defaultness: Defaultness,
     /// When we are in a trait impl, link to the trait-item's id.
     pub trait_item_def_id: Option<DefId>,
 }
@@ -3489,17 +3489,18 @@ impl<'hir> Node<'hir> {
 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 mod size_asserts {
-    rustc_data_structures::static_assert_size!(super::Block<'static>, 48);
-    rustc_data_structures::static_assert_size!(super::Expr<'static>, 56);
-    rustc_data_structures::static_assert_size!(super::Pat<'static>, 88);
-    rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
-    rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);
-    rustc_data_structures::static_assert_size!(super::GenericBound<'_>, 48);
-    rustc_data_structures::static_assert_size!(super::Generics<'static>, 56);
-    rustc_data_structures::static_assert_size!(super::Impl<'static>, 80);
-
-    rustc_data_structures::static_assert_size!(super::Item<'static>, 80);
-    rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 88);
-    rustc_data_structures::static_assert_size!(super::ImplItem<'static>, 80);
-    rustc_data_structures::static_assert_size!(super::ForeignItem<'static>, 72);
+    use super::*;
+    // These are in alphabetical order, which is easy to maintain.
+    rustc_data_structures::static_assert_size!(Block<'static>, 48);
+    rustc_data_structures::static_assert_size!(Expr<'static>, 56);
+    rustc_data_structures::static_assert_size!(ForeignItem<'static>, 72);
+    rustc_data_structures::static_assert_size!(GenericBound<'_>, 48);
+    rustc_data_structures::static_assert_size!(Generics<'static>, 56);
+    rustc_data_structures::static_assert_size!(ImplItem<'static>, 88);
+    rustc_data_structures::static_assert_size!(Impl<'static>, 80);
+    rustc_data_structures::static_assert_size!(Item<'static>, 80);
+    rustc_data_structures::static_assert_size!(Pat<'static>, 88);
+    rustc_data_structures::static_assert_size!(QPath<'static>, 24);
+    rustc_data_structures::static_assert_size!(TraitItem<'static>, 96);
+    rustc_data_structures::static_assert_size!(Ty<'static>, 72);
 }
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 640974115b9..e676acebe35 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -946,32 +946,30 @@ pub fn walk_fn<'v, V: Visitor<'v>>(
 }
 
 pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) {
-    visitor.visit_ident(trait_item.ident);
-    visitor.visit_generics(&trait_item.generics);
-    match trait_item.kind {
+    // N.B., deliberately force a compilation error if/when new fields are added.
+    let TraitItem { ident, generics, ref defaultness, ref kind, span, def_id: _ } = *trait_item;
+    let hir_id = trait_item.hir_id();
+    visitor.visit_ident(ident);
+    visitor.visit_generics(&generics);
+    visitor.visit_defaultness(&defaultness);
+    match *kind {
         TraitItemKind::Const(ref ty, default) => {
-            visitor.visit_id(trait_item.hir_id());
+            visitor.visit_id(hir_id);
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_nested_body, default);
         }
         TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
-            visitor.visit_id(trait_item.hir_id());
+            visitor.visit_id(hir_id);
             visitor.visit_fn_decl(&sig.decl);
             for &param_name in param_names {
                 visitor.visit_ident(param_name);
             }
         }
         TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
-            visitor.visit_fn(
-                FnKind::Method(trait_item.ident, sig),
-                &sig.decl,
-                body_id,
-                trait_item.span,
-                trait_item.hir_id(),
-            );
+            visitor.visit_fn(FnKind::Method(ident, sig), &sig.decl, body_id, span, hir_id);
         }
         TraitItemKind::Type(bounds, ref default) => {
-            visitor.visit_id(trait_item.hir_id());
+            visitor.visit_id(hir_id);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, default);
         }
@@ -980,19 +978,27 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
 
 pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: &'v TraitItemRef) {
     // N.B., deliberately force a compilation error if/when new fields are added.
-    let TraitItemRef { id, ident, ref kind, span: _, ref defaultness } = *trait_item_ref;
+    let TraitItemRef { id, ident, ref kind, span: _ } = *trait_item_ref;
     visitor.visit_nested_trait_item(id);
     visitor.visit_ident(ident);
     visitor.visit_associated_item_kind(kind);
-    visitor.visit_defaultness(defaultness);
 }
 
 pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) {
     // N.B., deliberately force a compilation error if/when new fields are added.
-    let ImplItem { def_id: _, ident, ref generics, ref kind, span: _, vis_span: _ } = *impl_item;
+    let ImplItem {
+        def_id: _,
+        ident,
+        ref generics,
+        ref kind,
+        ref defaultness,
+        span: _,
+        vis_span: _,
+    } = *impl_item;
 
     visitor.visit_ident(ident);
     visitor.visit_generics(generics);
+    visitor.visit_defaultness(defaultness);
     match *kind {
         ImplItemKind::Const(ref ty, body) => {
             visitor.visit_id(impl_item.hir_id());
@@ -1027,12 +1033,10 @@ pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>(
 
 pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef) {
     // N.B., deliberately force a compilation error if/when new fields are added.
-    let ImplItemRef { id, ident, ref kind, span: _, ref defaultness, trait_item_def_id: _ } =
-        *impl_item_ref;
+    let ImplItemRef { id, ident, ref kind, span: _, trait_item_def_id: _ } = *impl_item_ref;
     visitor.visit_nested_impl_item(id);
     visitor.visit_ident(ident);
     visitor.visit_associated_item_kind(kind);
-    visitor.visit_defaultness(defaultness);
 }
 
 pub fn walk_struct_def<'v, V: Visitor<'v>>(
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index 35a278e6c92..710c4a01b24 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -80,7 +80,7 @@ const BASE_STRUCT: &[&str] =
 /// Extra `DepNode`s for functions and methods.
 const EXTRA_ASSOCIATED: &[&str] = &[label_strs::associated_item];
 
-const EXTRA_TRAIT: &[&str] = &[label_strs::trait_of_item];
+const EXTRA_TRAIT: &[&str] = &[];
 
 // Fully Built Labels
 
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index 5b664e19c18..777112442f0 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -1061,12 +1061,8 @@ impl<T> Clone for BitSet<T> {
     }
 
     fn clone_from(&mut self, from: &Self) {
-        if self.domain_size != from.domain_size {
-            self.words.resize(from.domain_size, 0);
-            self.domain_size = from.domain_size;
-        }
-
-        self.words.copy_from_slice(&from.words);
+        self.domain_size = from.domain_size;
+        self.words.clone_from(&from.words);
     }
 }
 
diff --git a/compiler/rustc_index/src/bit_set/tests.rs b/compiler/rustc_index/src/bit_set/tests.rs
index a58133e4aed..351d62feed9 100644
--- a/compiler/rustc_index/src/bit_set/tests.rs
+++ b/compiler/rustc_index/src/bit_set/tests.rs
@@ -41,6 +41,23 @@ fn bitset_iter_works_2() {
 }
 
 #[test]
+fn bitset_clone_from() {
+    let mut a: BitSet<usize> = BitSet::new_empty(10);
+    a.insert(4);
+    a.insert(7);
+    a.insert(9);
+
+    let mut b = BitSet::new_empty(2);
+    b.clone_from(&a);
+    assert_eq!(b.domain_size(), 10);
+    assert_eq!(b.iter().collect::<Vec<_>>(), [4, 7, 9]);
+
+    b.clone_from(&BitSet::new_empty(40));
+    assert_eq!(b.domain_size(), 40);
+    assert_eq!(b.iter().collect::<Vec<_>>(), []);
+}
+
+#[test]
 fn union_two_sets() {
     let mut set1: BitSet<usize> = BitSet::new_empty(65);
     let mut set2: BitSet<usize> = BitSet::new_empty(65);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 39faed0bf36..20864c657ff 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -712,7 +712,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 opt_suggest_box_span,
             }) => {
                 let then_span = self.find_block_span_from_hir_id(then_id);
-                let else_span = self.find_block_span_from_hir_id(then_id);
+                let else_span = self.find_block_span_from_hir_id(else_id);
                 err.span_label(then_span, "expected because of this");
                 if let Some(sp) = outer_span {
                     err.span_label(sp, "`if` and `else` have incompatible types");
@@ -760,11 +760,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         second_ty: Ty<'tcx>,
         second_span: Span,
     ) {
-        let remove_semicolon =
-            [(first_id, second_ty), (second_id, first_ty)].into_iter().find_map(|(id, ty)| {
-                let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None };
-                self.could_remove_semicolon(blk, ty)
-            });
+        let remove_semicolon = [
+            (first_id, self.resolve_vars_if_possible(second_ty)),
+            (second_id, self.resolve_vars_if_possible(first_ty)),
+        ]
+        .into_iter()
+        .find_map(|(id, ty)| {
+            let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None };
+            self.could_remove_semicolon(blk, ty)
+        });
         match remove_semicolon {
             Some((sp, StatementAsExpression::NeedsBoxing)) => {
                 err.multipart_suggestion(
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 246d27be71c..9886c572a8a 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -76,10 +76,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                             "...is used and required to live as long as `'static` here \
                              because of an implicit lifetime bound on the {}",
                             match ctxt.assoc_item.container {
-                                AssocItemContainer::TraitContainer(id) =>
-                                    format!("`impl` of `{}`", tcx.def_path_str(id)),
-                                AssocItemContainer::ImplContainer(_) =>
-                                    "inherent `impl`".to_string(),
+                                AssocItemContainer::TraitContainer => {
+                                    let id = ctxt.assoc_item.container_id(tcx);
+                                    format!("`impl` of `{}`", tcx.def_path_str(id))
+                                }
+                                AssocItemContainer::ImplContainer => "inherent `impl`".to_string(),
                             },
                         ),
                     );
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 6d5f4993d8d..0424b5a7c44 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -8,7 +8,7 @@ pub use self::ValuePairs::*;
 use self::opaque_types::OpaqueTypeStorage;
 pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
 
-use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine};
+use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine, TraitEngineExt};
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
@@ -645,9 +645,7 @@ impl<'tcx, T> InferOk<'tcx, T> {
         fulfill_cx: &mut dyn TraitEngine<'tcx>,
     ) -> T {
         let InferOk { value, obligations } = self;
-        for obligation in obligations {
-            fulfill_cx.register_predicate_obligation(infcx, obligation);
-        }
+        fulfill_cx.register_predicate_obligations(infcx, obligations);
         value
     }
 }
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 4c64e679b95..5e5596f13c8 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -117,7 +117,6 @@ pub fn create_session(
 
     let mut check_cfg = config::to_crate_check_config(check_cfg);
     check_cfg.fill_well_known();
-    check_cfg.fill_actual(&cfg);
 
     sess.parse_sess.config = cfg;
     sess.parse_sess.check_config = check_cfg;
diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs
index 0ba6c56dbb5..21557a9c854 100644
--- a/compiler/rustc_lexer/src/cursor.rs
+++ b/compiler/rustc_lexer/src/cursor.rs
@@ -61,8 +61,8 @@ impl<'a> Cursor<'a> {
     }
 
     /// Returns amount of already consumed symbols.
-    pub(crate) fn len_consumed(&self) -> usize {
-        self.initial_len - self.chars.as_str().len()
+    pub(crate) fn len_consumed(&self) -> u32 {
+        (self.initial_len - self.chars.as_str().len()) as u32
     }
 
     /// Resets the number of bytes consumed to 0.
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index a41e0374f41..6d311af9007 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -38,18 +38,17 @@ use std::convert::TryFrom;
 #[derive(Debug)]
 pub struct Token {
     pub kind: TokenKind,
-    pub len: usize,
+    pub len: u32,
 }
 
 impl Token {
-    fn new(kind: TokenKind, len: usize) -> Token {
+    fn new(kind: TokenKind, len: u32) -> Token {
         Token { kind, len }
     }
 }
 
 /// Enum representing common lexeme types.
-// perf note: Changing all `usize` to `u32` doesn't change performance. See #77629
-#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum TokenKind {
     // Multi-char tokens:
     /// "// comment"
@@ -76,7 +75,7 @@ pub enum TokenKind {
     /// tokens.
     UnknownPrefix,
     /// "12_u8", "1.0e-40", "b"123"". See `LiteralKind` for more details.
-    Literal { kind: LiteralKind, suffix_start: usize },
+    Literal { kind: LiteralKind, suffix_start: u32 },
     /// "'a"
     Lifetime { starts_with_number: bool },
 
@@ -160,26 +159,24 @@ pub enum LiteralKind {
     Str { terminated: bool },
     /// "b"abc"", "b"abc"
     ByteStr { terminated: bool },
-    /// "r"abc"", "r#"abc"#", "r####"ab"###"c"####", "r#"a"
-    RawStr { n_hashes: u8, err: Option<RawStrError> },
-    /// "br"abc"", "br#"abc"#", "br####"ab"###"c"####", "br#"a"
-    RawByteStr { n_hashes: u8, err: Option<RawStrError> },
+    /// "r"abc"", "r#"abc"#", "r####"ab"###"c"####", "r#"a". `None` indicates
+    /// an invalid literal.
+    RawStr { n_hashes: Option<u8> },
+    /// "br"abc"", "br#"abc"#", "br####"ab"###"c"####", "br#"a". `None`
+    /// indicates an invalid literal.
+    RawByteStr { n_hashes: Option<u8> },
 }
 
-/// Error produced validating a raw string. Represents cases like:
-/// - `r##~"abcde"##`: `InvalidStarter`
-/// - `r###"abcde"##`: `NoTerminator { expected: 3, found: 2, possible_terminator_offset: Some(11)`
-/// - Too many `#`s (>255): `TooManyDelimiters`
-// perf note: It doesn't matter that this makes `Token` 36 bytes bigger. See #77629
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub enum RawStrError {
-    /// Non `#` characters exist between `r` and `"` eg. `r#~"..`
+    /// Non `#` characters exist between `r` and `"`, e.g. `r##~"abcde"##`
     InvalidStarter { bad_char: char },
-    /// The string was never terminated. `possible_terminator_offset` is the number of characters after `r` or `br` where they
-    /// may have intended to terminate it.
-    NoTerminator { expected: usize, found: usize, possible_terminator_offset: Option<usize> },
+    /// The string was not terminated, e.g. `r###"abcde"##`.
+    /// `possible_terminator_offset` is the number of characters after `r` or
+    /// `br` where they may have intended to terminate it.
+    NoTerminator { expected: u32, found: u32, possible_terminator_offset: Option<u32> },
     /// More than 255 `#`s exist.
-    TooManyDelimiters { found: usize },
+    TooManyDelimiters { found: u32 },
 }
 
 /// Base of numeric literal encoding according to its prefix.
@@ -221,11 +218,25 @@ pub fn strip_shebang(input: &str) -> Option<usize> {
 }
 
 /// Parses the first token from the provided input string.
+#[inline]
 pub fn first_token(input: &str) -> Token {
     debug_assert!(!input.is_empty());
     Cursor::new(input).advance_token()
 }
 
+/// Validates a raw string literal. Used for getting more information about a
+/// problem with a `RawStr`/`RawByteStr` with a `None` field.
+#[inline]
+pub fn validate_raw_str(input: &str, prefix_len: u32) -> Result<(), RawStrError> {
+    debug_assert!(!input.is_empty());
+    let mut cursor = Cursor::new(input);
+    // Move past the leading `r` or `br`.
+    for _ in 0..prefix_len {
+        cursor.bump().unwrap();
+    }
+    cursor.raw_double_quoted_string(prefix_len).map(|_| ())
+}
+
 /// Creates an iterator that produces tokens from the input string.
 pub fn tokenize(input: &str) -> impl Iterator<Item = Token> + '_ {
     let mut cursor = Cursor::new(input);
@@ -315,12 +326,12 @@ impl Cursor<'_> {
             'r' => match (self.first(), self.second()) {
                 ('#', c1) if is_id_start(c1) => self.raw_ident(),
                 ('#', _) | ('"', _) => {
-                    let (n_hashes, err) = self.raw_double_quoted_string(1);
+                    let res = self.raw_double_quoted_string(1);
                     let suffix_start = self.len_consumed();
-                    if err.is_none() {
+                    if res.is_ok() {
                         self.eat_literal_suffix();
                     }
-                    let kind = RawStr { n_hashes, err };
+                    let kind = RawStr { n_hashes: res.ok() };
                     Literal { kind, suffix_start }
                 }
                 _ => self.ident_or_unknown_prefix(),
@@ -350,12 +361,12 @@ impl Cursor<'_> {
                 }
                 ('r', '"') | ('r', '#') => {
                     self.bump();
-                    let (n_hashes, err) = self.raw_double_quoted_string(2);
+                    let res = self.raw_double_quoted_string(2);
                     let suffix_start = self.len_consumed();
-                    if err.is_none() {
+                    if res.is_ok() {
                         self.eat_literal_suffix();
                     }
-                    let kind = RawByteStr { n_hashes, err };
+                    let kind = RawByteStr { n_hashes: res.ok() };
                     Literal { kind, suffix_start }
                 }
                 _ => self.ident_or_unknown_prefix(),
@@ -698,19 +709,18 @@ impl Cursor<'_> {
     }
 
     /// Eats the double-quoted string and returns `n_hashes` and an error if encountered.
-    fn raw_double_quoted_string(&mut self, prefix_len: usize) -> (u8, Option<RawStrError>) {
+    fn raw_double_quoted_string(&mut self, prefix_len: u32) -> Result<u8, RawStrError> {
         // Wrap the actual function to handle the error with too many hashes.
         // This way, it eats the whole raw string.
-        let (n_hashes, err) = self.raw_string_unvalidated(prefix_len);
+        let n_hashes = self.raw_string_unvalidated(prefix_len)?;
         // Only up to 255 `#`s are allowed in raw strings
         match u8::try_from(n_hashes) {
-            Ok(num) => (num, err),
-            // We lie about the number of hashes here :P
-            Err(_) => (0, Some(RawStrError::TooManyDelimiters { found: n_hashes })),
+            Ok(num) => Ok(num),
+            Err(_) => Err(RawStrError::TooManyDelimiters { found: n_hashes }),
         }
     }
 
-    fn raw_string_unvalidated(&mut self, prefix_len: usize) -> (usize, Option<RawStrError>) {
+    fn raw_string_unvalidated(&mut self, prefix_len: u32) -> Result<u32, RawStrError> {
         debug_assert!(self.prev() == 'r');
         let start_pos = self.len_consumed();
         let mut possible_terminator_offset = None;
@@ -729,7 +739,7 @@ impl Cursor<'_> {
             Some('"') => (),
             c => {
                 let c = c.unwrap_or(EOF_CHAR);
-                return (n_start_hashes, Some(RawStrError::InvalidStarter { bad_char: c }));
+                return Err(RawStrError::InvalidStarter { bad_char: c });
             }
         }
 
@@ -739,14 +749,11 @@ impl Cursor<'_> {
             self.eat_while(|c| c != '"');
 
             if self.is_eof() {
-                return (
-                    n_start_hashes,
-                    Some(RawStrError::NoTerminator {
-                        expected: n_start_hashes,
-                        found: max_hashes,
-                        possible_terminator_offset,
-                    }),
-                );
+                return Err(RawStrError::NoTerminator {
+                    expected: n_start_hashes,
+                    found: max_hashes,
+                    possible_terminator_offset,
+                });
             }
 
             // Eat closing double quote.
@@ -764,7 +771,7 @@ impl Cursor<'_> {
             }
 
             if n_end_hashes == n_start_hashes {
-                return (n_start_hashes, None);
+                return Ok(n_start_hashes);
             } else if n_end_hashes > max_hashes {
                 // Keep track of possible terminators to give a hint about
                 // where there might be a missing terminator
diff --git a/compiler/rustc_lexer/src/tests.rs b/compiler/rustc_lexer/src/tests.rs
index 07daee06f0f..e4c1787f2cc 100644
--- a/compiler/rustc_lexer/src/tests.rs
+++ b/compiler/rustc_lexer/src/tests.rs
@@ -2,42 +2,39 @@ use super::*;
 
 use expect_test::{expect, Expect};
 
-fn check_raw_str(s: &str, expected_hashes: u8, expected_err: Option<RawStrError>) {
+fn check_raw_str(s: &str, expected: Result<u8, RawStrError>) {
     let s = &format!("r{}", s);
     let mut cursor = Cursor::new(s);
     cursor.bump();
-    let (n_hashes, err) = cursor.raw_double_quoted_string(0);
-    assert_eq!(n_hashes, expected_hashes);
-    assert_eq!(err, expected_err);
+    let res = cursor.raw_double_quoted_string(0);
+    assert_eq!(res, expected);
 }
 
 #[test]
 fn test_naked_raw_str() {
-    check_raw_str(r#""abc""#, 0, None);
+    check_raw_str(r#""abc""#, Ok(0));
 }
 
 #[test]
 fn test_raw_no_start() {
-    check_raw_str(r##""abc"#"##, 0, None);
+    check_raw_str(r##""abc"#"##, Ok(0));
 }
 
 #[test]
 fn test_too_many_terminators() {
     // this error is handled in the parser later
-    check_raw_str(r###"#"abc"##"###, 1, None);
+    check_raw_str(r###"#"abc"##"###, Ok(1));
 }
 
 #[test]
 fn test_unterminated() {
     check_raw_str(
         r#"#"abc"#,
-        1,
-        Some(RawStrError::NoTerminator { expected: 1, found: 0, possible_terminator_offset: None }),
+        Err(RawStrError::NoTerminator { expected: 1, found: 0, possible_terminator_offset: None }),
     );
     check_raw_str(
         r###"##"abc"#"###,
-        2,
-        Some(RawStrError::NoTerminator {
+        Err(RawStrError::NoTerminator {
             expected: 2,
             found: 1,
             possible_terminator_offset: Some(7),
@@ -46,14 +43,13 @@ fn test_unterminated() {
     // We're looking for "# not just any #
     check_raw_str(
         r###"##"abc#"###,
-        2,
-        Some(RawStrError::NoTerminator { expected: 2, found: 0, possible_terminator_offset: None }),
+        Err(RawStrError::NoTerminator { expected: 2, found: 0, possible_terminator_offset: None }),
     )
 }
 
 #[test]
 fn test_invalid_start() {
-    check_raw_str(r##"#~"abc"#"##, 1, Some(RawStrError::InvalidStarter { bad_char: '~' }));
+    check_raw_str(r##"#~"abc"#"##, Err(RawStrError::InvalidStarter { bad_char: '~' }));
 }
 
 #[test]
@@ -61,26 +57,24 @@ fn test_unterminated_no_pound() {
     // https://github.com/rust-lang/rust/issues/70677
     check_raw_str(
         r#"""#,
-        0,
-        Some(RawStrError::NoTerminator { expected: 0, found: 0, possible_terminator_offset: None }),
+        Err(RawStrError::NoTerminator { expected: 0, found: 0, possible_terminator_offset: None }),
     );
 }
 
 #[test]
 fn test_too_many_hashes() {
     let max_count = u8::MAX;
-    let mut hashes: String = "#".repeat(max_count.into());
+    let hashes1 = "#".repeat(max_count as usize);
+    let hashes2 = "#".repeat(max_count as usize + 1);
+    let middle = "\"abc\"";
+    let s1 = [&hashes1, middle, &hashes1].join("");
+    let s2 = [&hashes2, middle, &hashes2].join("");
 
-    // Valid number of hashes (255 = 2^8 - 1 = u8::MAX), but invalid string.
-    check_raw_str(&hashes, max_count, Some(RawStrError::InvalidStarter { bad_char: '\u{0}' }));
+    // Valid number of hashes (255 = 2^8 - 1 = u8::MAX).
+    check_raw_str(&s1, Ok(255));
 
     // One more hash sign (256 = 2^8) becomes too many.
-    hashes.push('#');
-    check_raw_str(
-        &hashes,
-        0,
-        Some(RawStrError::TooManyDelimiters { found: usize::from(max_count) + 1 }),
-    );
+    check_raw_str(&s2, Err(RawStrError::TooManyDelimiters { found: u32::from(max_count) + 1 }));
 }
 
 #[test]
@@ -251,7 +245,7 @@ fn raw_string() {
     check_lexing(
         "r###\"\"#a\\b\x00c\"\"###",
         expect![[r#"
-            Token { kind: Literal { kind: RawStr { n_hashes: 3, err: None }, suffix_start: 17 }, len: 17 }
+            Token { kind: Literal { kind: RawStr { n_hashes: Some(3) }, suffix_start: 17 }, len: 17 }
         "#]],
     )
 }
@@ -295,9 +289,9 @@ br###"raw"###suffix
             Token { kind: Whitespace, len: 1 }
             Token { kind: Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 }, len: 3 }
             Token { kind: Whitespace, len: 1 }
-            Token { kind: Literal { kind: RawStr { n_hashes: 3, err: None }, suffix_start: 12 }, len: 18 }
+            Token { kind: Literal { kind: RawStr { n_hashes: Some(3) }, suffix_start: 12 }, len: 18 }
             Token { kind: Whitespace, len: 1 }
-            Token { kind: Literal { kind: RawByteStr { n_hashes: 3, err: None }, suffix_start: 13 }, len: 19 }
+            Token { kind: Literal { kind: RawByteStr { n_hashes: Some(3) }, suffix_start: 13 }, len: 19 }
             Token { kind: Whitespace, len: 1 }
         "#]],
     )
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index ca3e6ce4d60..bd58021f78f 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1364,7 +1364,6 @@ impl UnreachablePub {
         cx: &LateContext<'_>,
         what: &str,
         def_id: LocalDefId,
-        span: Span,
         vis_span: Span,
         exportable: bool,
     ) {
@@ -1373,7 +1372,7 @@ impl UnreachablePub {
             if vis_span.from_expansion() {
                 applicability = Applicability::MaybeIncorrect;
             }
-            let def_span = cx.tcx.sess.source_map().guess_head_span(span);
+            let def_span = cx.tcx.def_span(def_id);
             cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| {
                 let mut err = lint.build(fluent::lint::builtin_unreachable_pub);
                 err.set_arg("what", what);
@@ -1399,36 +1398,22 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
         if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind {
             return;
         }
-        self.perform_lint(cx, "item", item.def_id, item.span, item.vis_span, true);
+        self.perform_lint(cx, "item", item.def_id, item.vis_span, true);
     }
 
     fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) {
-        self.perform_lint(
-            cx,
-            "item",
-            foreign_item.def_id,
-            foreign_item.span,
-            foreign_item.vis_span,
-            true,
-        );
+        self.perform_lint(cx, "item", foreign_item.def_id, foreign_item.vis_span, true);
     }
 
     fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
         let def_id = cx.tcx.hir().local_def_id(field.hir_id);
-        self.perform_lint(cx, "field", def_id, field.span, field.vis_span, false);
+        self.perform_lint(cx, "field", def_id, field.vis_span, false);
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
         // Only lint inherent impl items.
         if cx.tcx.associated_item(impl_item.def_id).trait_item_def_id.is_none() {
-            self.perform_lint(
-                cx,
-                "item",
-                impl_item.def_id,
-                impl_item.span,
-                impl_item.vis_span,
-                false,
-            );
+            self.perform_lint(cx, "item", impl_item.def_id, impl_item.vis_span, false);
         }
     }
 }
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 33ac2ed02aa..8d04d68bf1c 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -22,8 +22,8 @@ pub fn method_context(cx: &LateContext<'_>, id: hir::HirId) -> MethodLateContext
     let def_id = cx.tcx.hir().local_def_id(id);
     let item = cx.tcx.associated_item(def_id);
     match item.container {
-        ty::TraitContainer(..) => MethodLateContext::TraitAutoImpl,
-        ty::ImplContainer(cid) => match cx.tcx.impl_trait_ref(cid) {
+        ty::TraitContainer => MethodLateContext::TraitAutoImpl,
+        ty::ImplContainer => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) {
             Some(_) => MethodLateContext::TraitImpl,
             None => MethodLateContext::PlainImpl,
         },
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index c33219e4700..9f6079ecba4 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -472,7 +472,9 @@ impl<'tcx> Collector<'tcx> {
                 Abi::Fastcall { .. } => {
                     DllCallingConvention::Fastcall(self.i686_arg_list_size(item))
                 }
-                // Vectorcall is intentionally not supported at this time.
+                Abi::Vectorcall { .. } => {
+                    DllCallingConvention::Vectorcall(self.i686_arg_list_size(item))
+                }
                 _ => {
                     self.tcx.sess.span_fatal(
                         item.span,
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 6b0b5ac7da9..40dc4fb052d 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1114,7 +1114,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
 
     fn get_fn_has_self_parameter(self, id: DefIndex) -> bool {
         match self.kind(id) {
-            EntryKind::AssocFn(data) => data.decode(self).has_self,
+            EntryKind::AssocFn { has_self, .. } => has_self,
             _ => false,
         }
     }
@@ -1134,28 +1134,21 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_associated_item(self, id: DefIndex) -> ty::AssocItem {
-        let def_key = self.def_key(id);
-        let parent = self.local_def_id(def_key.parent.unwrap());
         let name = self.item_name(id);
 
         let (kind, container, has_self) = match self.kind(id) {
             EntryKind::AssocConst(container) => (ty::AssocKind::Const, container, false),
-            EntryKind::AssocFn(data) => {
-                let data = data.decode(self);
-                (ty::AssocKind::Fn, data.container, data.has_self)
-            }
+            EntryKind::AssocFn { container, has_self } => (ty::AssocKind::Fn, container, has_self),
             EntryKind::AssocType(container) => (ty::AssocKind::Type, container, false),
-            _ => bug!("cannot get associated-item of `{:?}`", def_key),
+            _ => bug!("cannot get associated-item of `{:?}`", id),
         };
 
         ty::AssocItem {
             name,
             kind,
-            vis: self.get_visibility(id),
-            defaultness: container.defaultness(),
             def_id: self.local_def_id(id),
             trait_item_def_id: self.get_trait_item_def_id(id),
-            container: container.with_def_id(parent),
+            container,
             fn_has_self_parameter: has_self,
         }
     }
@@ -1310,19 +1303,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn get_trait_of_item(self, id: DefIndex) -> Option<DefId> {
-        let def_key = self.def_key(id);
-        match def_key.disambiguated_data.data {
-            DefPathData::TypeNs(..) | DefPathData::ValueNs(..) => (),
-            // Not an associated item
-            _ => return None,
-        }
-        def_key.parent.and_then(|parent_index| match self.kind(parent_index) {
-            EntryKind::Trait | EntryKind::TraitAlias => Some(self.local_def_id(parent_index)),
-            _ => None,
-        })
-    }
-
     fn get_native_libraries(self, sess: &'a Session) -> impl Iterator<Item = NativeLib> + 'a {
         self.root.native_libraries.decode((self, sess))
     }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 6bf237b8ed5..38ce50e8323 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -235,7 +235,6 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
     is_foreign_item => { cdata.is_foreign_item(def_id.index) }
     item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) }
-    trait_of_item => { cdata.get_trait_of_item(def_id.index) }
     is_mir_available => { cdata.is_item_mir_available(def_id.index) }
     is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
 
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index f0886036899..33278367ce3 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1212,14 +1212,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let tcx = self.tcx;
 
         let ast_item = tcx.hir().expect_trait_item(def_id.expect_local());
+        self.tables.impl_defaultness.set(def_id.index, ast_item.defaultness);
         let trait_item = tcx.associated_item(def_id);
 
-        let container = match trait_item.defaultness {
-            hir::Defaultness::Default { has_value: true } => AssocContainer::TraitWithDefault,
-            hir::Defaultness::Default { has_value: false } => AssocContainer::TraitRequired,
-            hir::Defaultness::Final => span_bug!(ast_item.span, "traits cannot have final items"),
-        };
-
         match trait_item.kind {
             ty::AssocKind::Const => {
                 let rendered = rustc_hir_pretty::to_string(
@@ -1227,7 +1222,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     |s| s.print_trait_item(ast_item),
                 );
 
-                record!(self.tables.kind[def_id] <- EntryKind::AssocConst(container));
+                record!(self.tables.kind[def_id] <- EntryKind::AssocConst(ty::AssocItemContainer::TraitContainer));
                 record!(self.tables.mir_const_qualif[def_id] <- mir::ConstQualifs::default());
                 record!(self.tables.rendered_const[def_id] <- rendered);
             }
@@ -1243,14 +1238,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 };
                 self.tables.asyncness.set(def_id.index, m_sig.header.asyncness);
                 self.tables.constness.set(def_id.index, hir::Constness::NotConst);
-                record!(self.tables.kind[def_id] <- EntryKind::AssocFn(self.lazy(AssocFnData {
-                    container,
+                record!(self.tables.kind[def_id] <- EntryKind::AssocFn {
+                    container: ty::AssocItemContainer::TraitContainer,
                     has_self: trait_item.fn_has_self_parameter,
-                })));
+                });
             }
             ty::AssocKind::Type => {
                 self.encode_explicit_item_bounds(def_id);
-                record!(self.tables.kind[def_id] <- EntryKind::AssocType(container));
+                record!(self.tables.kind[def_id] <- EntryKind::AssocType(ty::AssocItemContainer::TraitContainer));
             }
         }
         match trait_item.kind {
@@ -1258,7 +1253,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 self.encode_item_type(def_id);
             }
             ty::AssocKind::Type => {
-                if trait_item.defaultness.has_value() {
+                if ast_item.defaultness.has_value() {
                     self.encode_item_type(def_id);
                 }
             }
@@ -1273,23 +1268,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let tcx = self.tcx;
 
         let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local());
+        self.tables.impl_defaultness.set(def_id.index, ast_item.defaultness);
         let impl_item = self.tcx.associated_item(def_id);
 
-        let container = match impl_item.defaultness {
-            hir::Defaultness::Default { has_value: true } => AssocContainer::ImplDefault,
-            hir::Defaultness::Final => AssocContainer::ImplFinal,
-            hir::Defaultness::Default { has_value: false } => {
-                span_bug!(ast_item.span, "impl items always have values (currently)")
-            }
-        };
-
         match impl_item.kind {
             ty::AssocKind::Const => {
                 if let hir::ImplItemKind::Const(_, body_id) = ast_item.kind {
                     let qualifs = self.tcx.at(ast_item.span).mir_const_qualif(def_id);
                     let const_data = self.encode_rendered_const_for_body(body_id);
 
-                    record!(self.tables.kind[def_id] <- EntryKind::AssocConst(container));
+                    record!(self.tables.kind[def_id] <- EntryKind::AssocConst(ty::AssocItemContainer::ImplContainer));
                     record!(self.tables.mir_const_qualif[def_id] <- qualifs);
                     record!(self.tables.rendered_const[def_id] <- const_data);
                 } else {
@@ -1307,13 +1295,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     hir::Constness::NotConst
                 };
                 self.tables.constness.set(def_id.index, constness);
-                record!(self.tables.kind[def_id] <- EntryKind::AssocFn(self.lazy(AssocFnData {
-                    container,
+                record!(self.tables.kind[def_id] <- EntryKind::AssocFn {
+                    container: ty::AssocItemContainer::ImplContainer,
                     has_self: impl_item.fn_has_self_parameter,
-                })));
+                });
             }
             ty::AssocKind::Type => {
-                record!(self.tables.kind[def_id] <- EntryKind::AssocType(container));
+                record!(self.tables.kind[def_id] <- EntryKind::AssocType(ty::AssocItemContainer::ImplContainer));
             }
         }
         self.encode_item_type(def_id);
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 23198a85369..66bdecc30db 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -419,9 +419,9 @@ enum EntryKind {
     Generator,
     Trait,
     Impl,
-    AssocFn(LazyValue<AssocFnData>),
-    AssocType(AssocContainer),
-    AssocConst(AssocContainer),
+    AssocFn { container: ty::AssocItemContainer, has_self: bool },
+    AssocType(ty::AssocItemContainer),
+    AssocConst(ty::AssocItemContainer),
     TraitAlias,
 }
 
@@ -434,47 +434,6 @@ struct VariantData {
     is_non_exhaustive: bool,
 }
 
-/// Describes whether the container of an associated item
-/// is a trait or an impl and whether, in a trait, it has
-/// a default, or an in impl, whether it's marked "default".
-#[derive(Copy, Clone, TyEncodable, TyDecodable)]
-enum AssocContainer {
-    TraitRequired,
-    TraitWithDefault,
-    ImplDefault,
-    ImplFinal,
-}
-
-impl AssocContainer {
-    fn with_def_id(&self, def_id: DefId) -> ty::AssocItemContainer {
-        match *self {
-            AssocContainer::TraitRequired | AssocContainer::TraitWithDefault => {
-                ty::TraitContainer(def_id)
-            }
-
-            AssocContainer::ImplDefault | AssocContainer::ImplFinal => ty::ImplContainer(def_id),
-        }
-    }
-
-    fn defaultness(&self) -> hir::Defaultness {
-        match *self {
-            AssocContainer::TraitRequired => hir::Defaultness::Default { has_value: false },
-
-            AssocContainer::TraitWithDefault | AssocContainer::ImplDefault => {
-                hir::Defaultness::Default { has_value: true }
-            }
-
-            AssocContainer::ImplFinal => hir::Defaultness::Final,
-        }
-    }
-}
-
-#[derive(MetadataEncodable, MetadataDecodable)]
-struct AssocFnData {
-    container: AssocContainer,
-    has_self: bool,
-}
-
 #[derive(TyEncodable, TyDecodable)]
 struct GeneratorData<'tcx> {
     layout: mir::GeneratorLayout<'tcx>,
@@ -492,7 +451,6 @@ pub fn provide(providers: &mut Providers) {
 
 trivially_parameterized_over_tcx! {
     VariantData,
-    AssocFnData,
     EntryKind,
     RawDefId,
     TraitImpls,
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index f7311ebdabf..64e158ba348 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1983,53 +1983,45 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                     }
 
                     AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| {
-                        if let Some(def_id) = def_id.as_local() {
-                            let name = if tcx.sess.opts.unstable_opts.span_free_formats {
-                                let substs = tcx.lift(substs).unwrap();
-                                format!(
-                                    "[closure@{}]",
-                                    tcx.def_path_str_with_substs(def_id.to_def_id(), substs),
-                                )
-                            } else {
-                                let span = tcx.def_span(def_id);
-                                format!(
-                                    "[closure@{}]",
-                                    tcx.sess.source_map().span_to_diagnostic_string(span)
-                                )
-                            };
-                            let mut struct_fmt = fmt.debug_struct(&name);
-
-                            // FIXME(project-rfc-2229#48): This should be a list of capture names/places
-                            if let Some(upvars) = tcx.upvars_mentioned(def_id) {
-                                for (&var_id, place) in iter::zip(upvars.keys(), places) {
-                                    let var_name = tcx.hir().name(var_id);
-                                    struct_fmt.field(var_name.as_str(), place);
-                                }
-                            }
-
-                            struct_fmt.finish()
+                        let name = if tcx.sess.opts.unstable_opts.span_free_formats {
+                            let substs = tcx.lift(substs).unwrap();
+                            format!(
+                                "[closure@{}]",
+                                tcx.def_path_str_with_substs(def_id.to_def_id(), substs),
+                            )
                         } else {
-                            write!(fmt, "[closure]")
+                            let span = tcx.def_span(def_id);
+                            format!(
+                                "[closure@{}]",
+                                tcx.sess.source_map().span_to_diagnostic_string(span)
+                            )
+                        };
+                        let mut struct_fmt = fmt.debug_struct(&name);
+
+                        // FIXME(project-rfc-2229#48): This should be a list of capture names/places
+                        if let Some(upvars) = tcx.upvars_mentioned(def_id) {
+                            for (&var_id, place) in iter::zip(upvars.keys(), places) {
+                                let var_name = tcx.hir().name(var_id);
+                                struct_fmt.field(var_name.as_str(), place);
+                            }
                         }
+
+                        struct_fmt.finish()
                     }),
 
                     AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| {
-                        if let Some(def_id) = def_id.as_local() {
-                            let name = format!("[generator@{:?}]", tcx.def_span(def_id));
-                            let mut struct_fmt = fmt.debug_struct(&name);
-
-                            // FIXME(project-rfc-2229#48): This should be a list of capture names/places
-                            if let Some(upvars) = tcx.upvars_mentioned(def_id) {
-                                for (&var_id, place) in iter::zip(upvars.keys(), places) {
-                                    let var_name = tcx.hir().name(var_id);
-                                    struct_fmt.field(var_name.as_str(), place);
-                                }
+                        let name = format!("[generator@{:?}]", tcx.def_span(def_id));
+                        let mut struct_fmt = fmt.debug_struct(&name);
+
+                        // FIXME(project-rfc-2229#48): This should be a list of capture names/places
+                        if let Some(upvars) = tcx.upvars_mentioned(def_id) {
+                            for (&var_id, place) in iter::zip(upvars.keys(), places) {
+                                let var_name = tcx.hir().name(var_id);
+                                struct_fmt.field(var_name.as_str(), place);
                             }
-
-                            struct_fmt.finish()
-                        } else {
-                            write!(fmt, "[generator]")
                         }
+
+                        struct_fmt.finish()
                     }),
                 }
             }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 510316c778b..eb90169d0e3 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -18,6 +18,7 @@ use rustc_hir::{self, GeneratorKind};
 use rustc_target::abi::VariantIdx;
 
 use rustc_ast::Mutability;
+use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use rustc_target::asm::InlineAsmRegOrRegClass;
@@ -340,8 +341,11 @@ pub enum FakeReadCause {
     /// If a closure pattern matches a Place starting with an Upvar, then we introduce a
     /// FakeRead for that Place outside the closure, in such a case this option would be
     /// Some(closure_def_id).
-    /// Otherwise, the value of the optional DefId will be None.
-    ForMatchedPlace(Option<DefId>),
+    /// Otherwise, the value of the optional LocalDefId will be None.
+    //
+    // We can use LocaDefId here since fake read statements are removed
+    // before codegen in the `CleanupNonCodegenStatements` pass.
+    ForMatchedPlace(Option<LocalDefId>),
 
     /// A fake read of the RefWithinGuard version of a bind-by-value variable
     /// in a match guard to ensure that its value hasn't change by the time
@@ -365,7 +369,7 @@ pub enum FakeReadCause {
     /// FakeRead for that Place outside the closure, in such a case this option would be
     /// Some(closure_def_id).
     /// Otherwise, the value of the optional DefId will be None.
-    ForLet(Option<DefId>),
+    ForLet(Option<LocalDefId>),
 
     /// If we have an index expression like
     ///
@@ -796,9 +800,6 @@ pub struct Place<'tcx> {
     pub projection: &'tcx List<PlaceElem<'tcx>>,
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(Place<'_>, 16);
-
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[derive(TyEncodable, TyDecodable, HashStable)]
 pub enum ProjectionElem<V, T> {
@@ -862,11 +863,6 @@ pub enum ProjectionElem<V, T> {
 /// and the index is a local.
 pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
 
-// This type is fairly frequently used, so we shouldn't unintentionally increase
-// its size.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(PlaceElem<'_>, 24);
-
 ///////////////////////////////////////////////////////////////////////////
 // Operands
 
@@ -909,9 +905,6 @@ pub enum Operand<'tcx> {
     Constant(Box<Constant<'tcx>>),
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(Operand<'_>, 24);
-
 ///////////////////////////////////////////////////////////////////////////
 // Rvalues
 
@@ -1063,9 +1056,6 @@ pub enum Rvalue<'tcx> {
     CopyForDeref(Place<'tcx>),
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(Rvalue<'_>, 40);
-
 #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
 pub enum CastKind {
     /// An exposing pointer to address cast. A cast between a pointer and an integer type, or
@@ -1095,13 +1085,12 @@ pub enum AggregateKind<'tcx> {
     /// active field index would identity the field `c`
     Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<usize>),
 
-    Closure(DefId, SubstsRef<'tcx>),
-    Generator(DefId, SubstsRef<'tcx>, hir::Movability),
+    // Note: We can use LocalDefId since closures and generators a deaggregated
+    // before codegen.
+    Closure(LocalDefId, SubstsRef<'tcx>),
+    Generator(LocalDefId, SubstsRef<'tcx>, hir::Movability),
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(AggregateKind<'_>, 48);
-
 #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
 pub enum NullOp {
     /// Returns the size of a value of that type
@@ -1165,3 +1154,15 @@ pub enum BinOp {
     /// The `ptr.offset` operator
     Offset,
 }
+
+// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+    use super::*;
+    // These are in alphabetical order, which is easy to maintain.
+    static_assert_size!(AggregateKind<'_>, 48);
+    static_assert_size!(Operand<'_>, 24);
+    static_assert_size!(Place<'_>, 16);
+    static_assert_size!(PlaceElem<'_>, 24);
+    static_assert_size!(Rvalue<'_>, 40);
+}
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index fd3359ea80f..405003156c4 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -205,9 +205,9 @@ impl<'tcx> Rvalue<'tcx> {
                 AggregateKind::Adt(did, _, substs, _, _) => {
                     tcx.bound_type_of(did).subst(tcx, substs)
                 }
-                AggregateKind::Closure(did, substs) => tcx.mk_closure(did, substs),
+                AggregateKind::Closure(did, substs) => tcx.mk_closure(did.to_def_id(), substs),
                 AggregateKind::Generator(did, substs, movability) => {
-                    tcx.mk_generator(did, substs, movability)
+                    tcx.mk_generator(did.to_def_id(), substs, movability)
                 }
             },
             Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty),
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 466a0fc25f7..d8483e7e409 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -413,12 +413,12 @@ rustc_queries! {
     }
 
     query symbols_for_closure_captures(
-        key: (LocalDefId, DefId)
+        key: (LocalDefId, LocalDefId)
     ) -> Vec<rustc_span::Symbol> {
         storage(ArenaCacheSelector<'tcx>)
         desc {
             |tcx| "symbols for captures of closure `{}` in `{}`",
-            tcx.def_path_str(key.1),
+            tcx.def_path_str(key.1.to_def_id()),
             tcx.def_path_str(key.0.to_def_id())
         }
     }
@@ -1147,14 +1147,6 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    /// Given an `associated_item`, find the trait it belongs to.
-    /// Return `None` if the `DefId` is not an associated item.
-    query trait_of_item(associated_item: DefId) -> Option<DefId> {
-        desc { |tcx| "finding trait defining `{}`", tcx.def_path_str(associated_item) }
-        cache_on_disk_if { associated_item.is_local() }
-        separate_provide_extern
-    }
-
     query is_ctfe_mir_available(key: DefId) -> bool {
         desc { |tcx| "checking if item has ctfe mir available: `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 36db8d04918..b856af1d8f8 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -27,6 +27,7 @@ use rustc_span::{Span, Symbol, DUMMY_SP};
 use rustc_target::abi::VariantIdx;
 use rustc_target::asm::InlineAsmRegOrRegClass;
 
+use rustc_span::def_id::LocalDefId;
 use std::fmt;
 use std::ops::Index;
 
@@ -189,10 +190,6 @@ pub enum StmtKind<'tcx> {
     },
 }
 
-// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Expr<'_>, 104);
-
 #[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct LocalVarId(pub hir::HirId);
@@ -405,7 +402,7 @@ pub enum ExprKind<'tcx> {
     },
     /// A closure definition.
     Closure {
-        closure_id: DefId,
+        closure_id: LocalDefId,
         substs: UpvarSubsts<'tcx>,
         upvars: Box<[ExprId]>,
         movability: Option<hir::Movability>,
@@ -811,3 +808,14 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
         }
     }
 }
+
+// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+    use super::*;
+    // These are in alphabetical order, which is easy to maintain.
+    rustc_data_structures::static_assert_size!(Block, 56);
+    rustc_data_structures::static_assert_size!(Expr<'_>, 104);
+    rustc_data_structures::static_assert_size!(Pat<'_>, 24);
+    rustc_data_structures::static_assert_size!(Stmt<'_>, 120);
+}
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index 3c1d0061ae1..2465f8e2533 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -217,7 +217,7 @@ impl<'tcx> Ancestors<'tcx> {
         self.find_map(|node| {
             if let Some(item) = node.item(tcx, trait_item_def_id) {
                 if finalizing_node.is_none() {
-                    let is_specializable = item.defaultness.is_default()
+                    let is_specializable = item.defaultness(tcx).is_default()
                         || tcx.impl_defaultness(node.def_id()).is_default();
 
                     if !is_specializable {
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index eb732148e3e..c97156ac17f 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -1,6 +1,6 @@
 pub use self::AssocItemContainer::*;
 
-use crate::ty;
+use crate::ty::{self, DefIdTree};
 use rustc_data_structures::sorted_map::SortedIndexMultiMap;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace};
@@ -11,33 +11,8 @@ use super::{TyCtxt, Visibility};
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash, Encodable, Decodable)]
 pub enum AssocItemContainer {
-    TraitContainer(DefId),
-    ImplContainer(DefId),
-}
-
-impl AssocItemContainer {
-    pub fn impl_def_id(&self) -> Option<DefId> {
-        match *self {
-            ImplContainer(id) => Some(id),
-            _ => None,
-        }
-    }
-
-    /// Asserts that this is the `DefId` of an associated item declared
-    /// in a trait, and returns the trait `DefId`.
-    pub fn assert_trait(&self) -> DefId {
-        match *self {
-            TraitContainer(id) => id,
-            _ => bug!("associated item has wrong container type: {:?}", self),
-        }
-    }
-
-    pub fn id(&self) -> DefId {
-        match *self {
-            TraitContainer(id) => id,
-            ImplContainer(id) => id,
-        }
-    }
+    TraitContainer,
+    ImplContainer,
 }
 
 /// Information about an associated item
@@ -46,8 +21,6 @@ pub struct AssocItem {
     pub def_id: DefId,
     pub name: Symbol,
     pub kind: AssocKind,
-    pub vis: Visibility,
-    pub defaultness: hir::Defaultness,
     pub container: AssocItemContainer,
 
     /// If this is an item in an impl of a trait then this is the `DefId` of
@@ -64,6 +37,36 @@ impl AssocItem {
         Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
     }
 
+    pub fn defaultness(&self, tcx: TyCtxt<'_>) -> hir::Defaultness {
+        tcx.impl_defaultness(self.def_id)
+    }
+
+    #[inline]
+    pub fn visibility(&self, tcx: TyCtxt<'_>) -> Visibility {
+        tcx.visibility(self.def_id)
+    }
+
+    #[inline]
+    pub fn container_id(&self, tcx: TyCtxt<'_>) -> DefId {
+        tcx.parent(self.def_id)
+    }
+
+    #[inline]
+    pub fn trait_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
+        match self.container {
+            AssocItemContainer::ImplContainer => None,
+            AssocItemContainer::TraitContainer => Some(tcx.parent(self.def_id)),
+        }
+    }
+
+    #[inline]
+    pub fn impl_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
+        match self.container {
+            AssocItemContainer::ImplContainer => Some(tcx.parent(self.def_id)),
+            AssocItemContainer::TraitContainer => None,
+        }
+    }
+
     pub fn signature(&self, tcx: TyCtxt<'_>) -> String {
         match self.kind {
             ty::AssocKind::Fn => {
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 27b9d27b8bb..0d6c26a5822 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -59,7 +59,7 @@ pub type UpvarCaptureMap = FxHashMap<UpvarId, UpvarCapture>;
 
 /// Given the closure DefId this map provides a map of root variables to minimum
 /// set of `CapturedPlace`s that need to be tracked to support all captures of that closure.
-pub type MinCaptureInformationMap<'tcx> = FxHashMap<DefId, RootVariableMinCaptureList<'tcx>>;
+pub type MinCaptureInformationMap<'tcx> = FxHashMap<LocalDefId, RootVariableMinCaptureList<'tcx>>;
 
 /// Part of `MinCaptureInformationMap`; Maps a root variable to the list of `CapturedPlace`.
 /// Used to track the minimum set of `Place`s that need to be captured to support all
@@ -253,7 +253,7 @@ impl<'tcx> CapturedPlace<'tcx> {
 
 fn symbols_for_closure_captures<'tcx>(
     tcx: TyCtxt<'tcx>,
-    def_id: (LocalDefId, DefId),
+    def_id: (LocalDefId, LocalDefId),
 ) -> Vec<Symbol> {
     let typeck_results = tcx.typeck(def_id.0);
     let captures = typeck_results.closure_min_captures_flattened(def_id.1);
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 0f98d19820e..0a0f45ce1a0 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -570,7 +570,7 @@ pub struct TypeckResults<'tcx> {
     /// we never capture `t`. This becomes an issue when we build MIR as we require
     /// information on `t` in order to create place `t.0` and `t.1`. We can solve this
     /// issue by fake reading `t`.
-    pub closure_fake_reads: FxHashMap<DefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
+    pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
 
     /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
     /// by applying extended parameter rules.
@@ -589,7 +589,7 @@ pub struct TypeckResults<'tcx> {
 
     /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
     /// on closure size.
-    pub closure_size_eval: FxHashMap<DefId, ClosureSizeProfileData<'tcx>>,
+    pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
 }
 
 impl<'tcx> TypeckResults<'tcx> {
@@ -811,7 +811,7 @@ impl<'tcx> TypeckResults<'tcx> {
     /// by the closure.
     pub fn closure_min_captures_flattened(
         &self,
-        closure_def_id: DefId,
+        closure_def_id: LocalDefId,
     ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
         self.closure_min_captures
             .get(&closure_def_id)
@@ -1459,11 +1459,11 @@ impl<'tcx> TyCtxt<'tcx> {
         };
 
         format!(
-            "{}[{}]{}",
+            "{}[{:04x}]{}",
             crate_name,
             // Don't print the whole stable crate id. That's just
             // annoying in debug output.
-            &(format!("{:08x}", stable_crate_id.to_u64()))[..4],
+            stable_crate_id.to_u64() >> 8 * 6,
             self.def_path(def_id).to_string_no_crate_verbose()
         )
     }
@@ -1668,8 +1668,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     // Checks if the bound region is in Impl Item.
     pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool {
-        let container_id =
-            self.associated_item(suitable_region_binding_scope.to_def_id()).container.id();
+        let container_id = self.parent(suitable_region_binding_scope.to_def_id());
         if self.impl_trait_ref(container_id).is_some() {
             // For now, we do not try to target impls of traits. This is
             // because this message is going to suggest that the user
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 91246051316..4b0bc3c1114 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -673,7 +673,7 @@ impl<T> Trait<T> for X {
             // the associated type or calling a method that returns the associated type".
             let point_at_assoc_fn = self.point_at_methods_that_satisfy_associated_type(
                 diag,
-                assoc.container.id(),
+                assoc.container_id(self),
                 current_method_ident,
                 proj_ty.item_def_id,
                 values.expected,
@@ -844,7 +844,8 @@ fn foo(&self) -> Self::T { String::new() }
                         hir::AssocItemKind::Type => {
                             // FIXME: account for returning some type in a trait fn impl that has
                             // an assoc type as a return type (#72076).
-                            if let hir::Defaultness::Default { has_value: true } = item.defaultness
+                            if let hir::Defaultness::Default { has_value: true } =
+                                self.impl_defaultness(item.id.def_id)
                             {
                                 if self.type_of(item.id.def_id) == found {
                                     diag.span_label(
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 33a46f809b0..53218225d53 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -460,7 +460,7 @@ impl<'tcx> Instance<'tcx> {
                             && !matches!(
                                 tcx.opt_associated_item(def.did),
                                 Some(ty::AssocItem {
-                                    container: ty::AssocItemContainer::TraitContainer(_),
+                                    container: ty::AssocItemContainer::TraitContainer,
                                     ..
                                 })
                             )
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 833edd22805..ad78d24e954 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -232,6 +232,10 @@ fn sanity_check_layout<'tcx>(
         assert!(layout.abi.is_uninhabited());
     }
 
+    if layout.size.bytes() % layout.align.abi.bytes() != 0 {
+        bug!("size is not a multiple of align, in the following layout:\n{layout:#?}");
+    }
+
     if cfg!(debug_assertions) {
         fn check_layout_abi<'tcx>(tcx: TyCtxt<'tcx>, layout: Layout<'tcx>) {
             match layout.abi() {
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index da9d51a29b1..1978f84c137 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1945,7 +1945,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator<Item = &'tcx AssocItem> {
         self.associated_items(id)
             .in_definition_order()
-            .filter(|item| item.kind == AssocKind::Fn && item.defaultness.has_value())
+            .filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value())
     }
 
     /// Look up the name of a definition across crates. This does not look at HIR.
@@ -2191,13 +2191,29 @@ impl<'tcx> TyCtxt<'tcx> {
         self.impl_trait_ref(def_id).map(|tr| tr.def_id)
     }
 
+    /// If the given `DefId` describes an item belonging to a trait,
+    /// returns the `DefId` of the trait that the trait item belongs to;
+    /// otherwise, returns `None`.
+    pub fn trait_of_item(self, def_id: DefId) -> Option<DefId> {
+        if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
+            let parent = self.parent(def_id);
+            if let DefKind::Trait | DefKind::TraitAlias = self.def_kind(parent) {
+                return Some(parent);
+            }
+        }
+        None
+    }
+
     /// If the given `DefId` describes a method belonging to an impl, returns the
     /// `DefId` of the impl that the method belongs to; otherwise, returns `None`.
     pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
-        self.opt_associated_item(def_id).and_then(|trait_item| match trait_item.container {
-            TraitContainer(_) => None,
-            ImplContainer(def_id) => Some(def_id),
-        })
+        if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
+            let parent = self.parent(def_id);
+            if let DefKind::Impl = self.def_kind(parent) {
+                return Some(parent);
+            }
+        }
+        None
     }
 
     /// If the given `DefId` belongs to a trait that was automatically derived, returns `true`.
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 411d5c55829..fb0a4b4e8f4 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1179,13 +1179,14 @@ pub struct ProjectionTy<'tcx> {
     /// The `DefId` of the `TraitItem` for the associated type `N`.
     ///
     /// Note that this is not the `DefId` of the `TraitRef` containing this
-    /// associated type, which is in `tcx.associated_item(item_def_id).container`.
+    /// associated type, which is in `tcx.associated_item(item_def_id).container`,
+    /// aka. `tcx.parent(item_def_id).unwrap()`.
     pub item_def_id: DefId,
 }
 
 impl<'tcx> ProjectionTy<'tcx> {
     pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
-        tcx.associated_item(self.item_def_id).container.id()
+        tcx.parent(self.item_def_id)
     }
 
     /// Extracts the underlying trait reference and own substs from this projection.
@@ -1195,7 +1196,7 @@ impl<'tcx> ProjectionTy<'tcx> {
         &self,
         tcx: TyCtxt<'tcx>,
     ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
-        let def_id = tcx.associated_item(self.item_def_id).container.id();
+        let def_id = tcx.parent(self.item_def_id);
         let trait_generics = tcx.generics_of(def_id);
         (
             ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) },
@@ -1433,7 +1434,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
     /// then this function would return an `exists T. T: Iterator` existential trait
     /// reference.
     pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
-        let def_id = tcx.associated_item(self.item_def_id).container.id();
+        let def_id = tcx.parent(self.item_def_id);
         let subst_count = tcx.generics_of(def_id).count() - 1;
         let substs = tcx.intern_substs(&self.substs[..subst_count]);
         ty::ExistentialTraitRef { def_id, substs }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 4d2f69b23fa..4b5bf80c071 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -402,7 +402,7 @@ impl<'tcx> TyCtxt<'tcx> {
             Some(dtor) => dtor.did,
         };
 
-        let impl_def_id = self.associated_item(dtor).container.id();
+        let impl_def_id = self.parent(dtor);
         let impl_generics = self.generics_of(impl_def_id);
 
         // We have a destructor - all the parameters that are not
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index e88f9dc1f08..0c06aad4e44 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -3,7 +3,7 @@
 use crate::build::expr::category::Category;
 use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::LocalDefId;
 use rustc_middle::hir::place::Projection as HirProjection;
 use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
 use rustc_middle::middle::region;
@@ -58,7 +58,7 @@ pub(crate) enum PlaceBase {
         /// HirId of the upvar
         var_hir_id: LocalVarId,
         /// DefId of the closure
-        closure_def_id: DefId,
+        closure_def_id: LocalDefId,
         /// The trait closure implements, `Fn`, `FnMut`, `FnOnce`
         closure_kind: ty::ClosureKind,
     },
@@ -176,7 +176,7 @@ fn compute_capture_idx<'tcx>(
 fn find_capture_matching_projections<'a, 'tcx>(
     typeck_results: &'a ty::TypeckResults<'tcx>,
     var_hir_id: LocalVarId,
-    closure_def_id: DefId,
+    closure_def_id: LocalDefId,
     projections: &[PlaceElem<'tcx>],
 ) -> Option<(usize, &'a ty::CapturedPlace<'tcx>)> {
     let closure_min_captures = typeck_results.closure_min_captures.get(&closure_def_id)?;
@@ -242,7 +242,7 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>(
             };
 
             // We won't be building MIR if the closure wasn't local
-            let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
+            let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id);
             let closure_ty = typeck_results.node_type(closure_hir_id);
 
             let substs = match closure_ty.kind() {
@@ -626,11 +626,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     fn lower_captured_upvar(
         &mut self,
         block: BasicBlock,
-        closure_expr_id: LocalDefId,
+        closure_def_id: LocalDefId,
         var_hir_id: LocalVarId,
     ) -> BlockAnd<PlaceBuilder<'tcx>> {
         let closure_ty =
-            self.typeck_results.node_type(self.tcx.hir().local_def_id_to_hir_id(closure_expr_id));
+            self.typeck_results.node_type(self.tcx.hir().local_def_id_to_hir_id(closure_def_id));
 
         let closure_kind = if let ty::Closure(_, closure_substs) = closure_ty.kind() {
             self.infcx.closure_kind(closure_substs).unwrap()
@@ -639,11 +639,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             ty::ClosureKind::FnOnce
         };
 
-        block.and(PlaceBuilder::from(PlaceBase::Upvar {
-            var_hir_id,
-            closure_def_id: closure_expr_id.to_def_id(),
-            closure_kind,
-        }))
+        block.and(PlaceBuilder::from(PlaceBase::Upvar { var_hir_id, closure_def_id, closure_kind }))
     }
 
     /// Lower an index expression
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 7ae26cccb38..12b8ceede0f 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -672,7 +672,7 @@ where
                 Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
                     builder.args_and_body(
                         START_BLOCK,
-                        fn_def.did.to_def_id(),
+                        fn_def.did,
                         &arguments,
                         arg_scope,
                         &thir[expr],
@@ -895,7 +895,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     fn args_and_body(
         &mut self,
         mut block: BasicBlock,
-        fn_def_id: DefId,
+        fn_def_id: LocalDefId,
         arguments: &[ArgInfo<'tcx>],
         argument_scope: region::Scope,
         expr: &Expr<'tcx>,
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 55ad83f8975..864caf0ba31 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -408,7 +408,6 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                 movability: _,
                 fake_reads: _,
             } => {
-                let closure_id = closure_id.expect_local();
                 let closure_def = if let Some((did, const_param_id)) =
                     ty::WithOptConstParam::try_lookup(closure_id, self.tcx)
                 {
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index d21a8c4f9b9..54d549fd66c 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -1,10 +1,10 @@
 use rustc_data_structures::graph::iterate::{
     NodeStatus, TriColorDepthFirstSearch, TriColorVisitor,
 };
-use rustc_hir::intravisit::FnKind;
+use rustc_hir::def::DefKind;
 use rustc_middle::mir::{BasicBlock, BasicBlocks, Body, Operand, TerminatorKind};
 use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
-use rustc_middle::ty::{self, AssocItem, AssocItemContainer, Instance, TyCtxt};
+use rustc_middle::ty::{self, Instance, TyCtxt};
 use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION;
 use rustc_span::Span;
 use std::ops::ControlFlow;
@@ -12,18 +12,11 @@ use std::ops::ControlFlow;
 pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
     let def_id = body.source.def_id().expect_local();
 
-    if let Some(fn_kind) = tcx.hir().get_by_def_id(def_id).fn_kind() {
-        if let FnKind::Closure = fn_kind {
-            // closures can't recur, so they don't matter.
-            return;
-        }
-
+    if let DefKind::Fn | DefKind::AssocFn = tcx.def_kind(def_id) {
         // If this is trait/impl method, extract the trait's substs.
-        let trait_substs = match tcx.opt_associated_item(def_id.to_def_id()) {
-            Some(AssocItem {
-                container: AssocItemContainer::TraitContainer(trait_def_id), ..
-            }) => {
-                let trait_substs_count = tcx.generics_of(*trait_def_id).count();
+        let trait_substs = match tcx.trait_of_item(def_id.to_def_id()) {
+            Some(trait_def_id) => {
+                let trait_substs_count = tcx.generics_of(trait_def_id).count();
                 &InternalSubsts::identity_for_item(tcx, def_id.to_def_id())[..trait_substs_count]
             }
             _ => &[],
@@ -41,8 +34,8 @@ pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
 
         vis.reachable_recursive_calls.sort();
 
+        let sp = tcx.def_span(def_id);
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-        let sp = tcx.sess.source_map().guess_head_span(tcx.hir().span_with_body(hir_id));
         tcx.struct_span_lint_hir(UNCONDITIONAL_RECURSION, hir_id, sp, |lint| {
             let mut db = lint.build("function cannot return without recursing");
             db.span_label(sp, "cannot return without recursing");
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 4eb3607e9cc..985601712c4 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -523,6 +523,7 @@ impl<'tcx> Cx<'tcx> {
                         span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty);
                     }
                 };
+                let def_id = def_id.expect_local();
 
                 let upvars = self
                     .typeck_results
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index 13ae8a1cd3e..d564f480166 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -129,7 +129,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
                 }
                 &AggregateKind::Closure(def_id, _) | &AggregateKind::Generator(def_id, _, _) => {
                     let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
-                        self.tcx.unsafety_check_result(def_id.expect_local());
+                        self.tcx.unsafety_check_result(def_id);
                     self.register_violations(
                         violations,
                         used_unsafe_blocks.iter().map(|(&h, &d)| (h, d)),
diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs
index d3aaad46015..847e64dc2a2 100644
--- a/compiler/rustc_monomorphize/src/util.rs
+++ b/compiler/rustc_monomorphize/src/util.rs
@@ -17,8 +17,8 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
         return;
     };
 
-    let closure_def_id = closure_instance.def_id();
-    let typeck_results = tcx.typeck(closure_def_id.expect_local());
+    let closure_def_id = closure_instance.def_id().expect_local();
+    let typeck_results = tcx.typeck(closure_def_id);
 
     if typeck_results.closure_size_eval.contains_key(&closure_def_id) {
         let param_env = ty::ParamEnv::reveal_all();
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index e9701ec2d7f..848e142e59c 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -22,6 +22,13 @@ mod unicode_chars;
 
 use unescape_error_reporting::{emit_unescape_error, escaped_char};
 
+// This type is used a lot. Make sure it doesn't unintentionally get bigger.
+//
+// This assertion is in this crate, rather than in `rustc_lexer`, because that
+// crate cannot depend on `rustc_data_structures`.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(rustc_lexer::Token, 12);
+
 #[derive(Clone, Debug)]
 pub struct UnmatchedBrace {
     pub expected_delim: Delimiter,
@@ -37,8 +44,7 @@ pub(crate) fn parse_token_trees<'a>(
     start_pos: BytePos,
     override_span: Option<Span>,
 ) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
-    StringReader { sess, start_pos, pos: start_pos, end_src_index: src.len(), src, override_span }
-        .into_token_trees()
+    StringReader { sess, start_pos, pos: start_pos, src, override_span }.into_token_trees()
 }
 
 struct StringReader<'a> {
@@ -47,8 +53,6 @@ struct StringReader<'a> {
     start_pos: BytePos,
     /// The absolute offset within the source_map of the current character.
     pos: BytePos,
-    /// Stop reading src at this index.
-    end_src_index: usize,
     /// Source text to tokenize.
     src: &'a str,
     override_span: Option<Span>,
@@ -64,20 +68,17 @@ impl<'a> StringReader<'a> {
         let mut spacing = Spacing::Joint;
 
         // Skip `#!` at the start of the file
-        let start_src_index = self.src_index(self.pos);
-        let text: &str = &self.src[start_src_index..self.end_src_index];
-        let is_beginning_of_file = self.pos == self.start_pos;
-        if is_beginning_of_file {
-            if let Some(shebang_len) = rustc_lexer::strip_shebang(text) {
-                self.pos = self.pos + BytePos::from_usize(shebang_len);
-                spacing = Spacing::Alone;
-            }
+        if self.pos == self.start_pos
+            && let Some(shebang_len) = rustc_lexer::strip_shebang(self.src)
+        {
+            self.pos = self.pos + BytePos::from_usize(shebang_len);
+            spacing = Spacing::Alone;
         }
 
         // Skip trivial (whitespace & comments) tokens
         loop {
             let start_src_index = self.src_index(self.pos);
-            let text: &str = &self.src[start_src_index..self.end_src_index];
+            let text: &str = &self.src[start_src_index..];
 
             if text.is_empty() {
                 let span = self.mk_sp(self.pos, self.pos);
@@ -87,7 +88,7 @@ impl<'a> StringReader<'a> {
             let token = rustc_lexer::first_token(text);
 
             let start = self.pos;
-            self.pos = self.pos + BytePos::from_usize(token.len);
+            self.pos = self.pos + BytePos(token.len);
 
             debug!("next_token: {:?}({:?})", token.kind, self.str_from(start));
 
@@ -239,7 +240,7 @@ impl<'a> StringReader<'a> {
                 token::Ident(sym, false)
             }
             rustc_lexer::TokenKind::Literal { kind, suffix_start } => {
-                let suffix_start = start + BytePos(suffix_start as u32);
+                let suffix_start = start + BytePos(suffix_start);
                 let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind);
                 let suffix = if suffix_start < self.pos {
                     let string = self.str_from(suffix_start);
@@ -404,15 +405,21 @@ impl<'a> StringReader<'a> {
                 }
                 (token::ByteStr, Mode::ByteStr, 2, 1) // b" "
             }
-            rustc_lexer::LiteralKind::RawStr { n_hashes, err } => {
-                self.report_raw_str_error(start, err);
-                let n = u32::from(n_hashes);
-                (token::StrRaw(n_hashes), Mode::RawStr, 2 + n, 1 + n) // r##" "##
+            rustc_lexer::LiteralKind::RawStr { n_hashes } => {
+                if let Some(n_hashes) = n_hashes {
+                    let n = u32::from(n_hashes);
+                    (token::StrRaw(n_hashes), Mode::RawStr, 2 + n, 1 + n) // r##" "##
+                } else {
+                    self.report_raw_str_error(start, 1);
+                }
             }
-            rustc_lexer::LiteralKind::RawByteStr { n_hashes, err } => {
-                self.report_raw_str_error(start, err);
-                let n = u32::from(n_hashes);
-                (token::ByteStrRaw(n_hashes), Mode::RawByteStr, 3 + n, 1 + n) // br##" "##
+            rustc_lexer::LiteralKind::RawByteStr { n_hashes } => {
+                if let Some(n_hashes) = n_hashes {
+                    let n = u32::from(n_hashes);
+                    (token::ByteStrRaw(n_hashes), Mode::RawByteStr, 3 + n, 1 + n) // br##" "##
+                } else {
+                    self.report_raw_str_error(start, 2);
+                }
             }
             rustc_lexer::LiteralKind::Int { base, empty_int } => {
                 return if empty_int {
@@ -483,17 +490,17 @@ impl<'a> StringReader<'a> {
         &self.src[self.src_index(start)..self.src_index(end)]
     }
 
-    fn report_raw_str_error(&self, start: BytePos, opt_err: Option<RawStrError>) {
-        match opt_err {
-            Some(RawStrError::InvalidStarter { bad_char }) => {
+    fn report_raw_str_error(&self, start: BytePos, prefix_len: u32) -> ! {
+        match rustc_lexer::validate_raw_str(self.str_from(start), prefix_len) {
+            Err(RawStrError::InvalidStarter { bad_char }) => {
                 self.report_non_started_raw_string(start, bad_char)
             }
-            Some(RawStrError::NoTerminator { expected, found, possible_terminator_offset }) => self
+            Err(RawStrError::NoTerminator { expected, found, possible_terminator_offset }) => self
                 .report_unterminated_raw_string(start, expected, possible_terminator_offset, found),
-            Some(RawStrError::TooManyDelimiters { found }) => {
+            Err(RawStrError::TooManyDelimiters { found }) => {
                 self.report_too_many_hashes(start, found)
             }
-            None => (),
+            Ok(()) => panic!("no error found for supposedly invalid raw string literal"),
         }
     }
 
@@ -510,9 +517,9 @@ impl<'a> StringReader<'a> {
     fn report_unterminated_raw_string(
         &self,
         start: BytePos,
-        n_hashes: usize,
-        possible_offset: Option<usize>,
-        found_terminators: usize,
+        n_hashes: u32,
+        possible_offset: Option<u32>,
+        found_terminators: u32,
     ) -> ! {
         let mut err = self.sess.span_diagnostic.struct_span_fatal_with_code(
             self.mk_sp(start, start),
@@ -525,7 +532,7 @@ impl<'a> StringReader<'a> {
         if n_hashes > 0 {
             err.note(&format!(
                 "this raw string should be terminated with `\"{}`",
-                "#".repeat(n_hashes)
+                "#".repeat(n_hashes as usize)
             ));
         }
 
@@ -536,7 +543,7 @@ impl<'a> StringReader<'a> {
             err.span_suggestion(
                 span,
                 "consider terminating the string here",
-                "#".repeat(n_hashes),
+                "#".repeat(n_hashes as usize),
                 Applicability::MaybeIncorrect,
             );
         }
@@ -637,7 +644,7 @@ impl<'a> StringReader<'a> {
         }
     }
 
-    fn report_too_many_hashes(&self, start: BytePos, found: usize) -> ! {
+    fn report_too_many_hashes(&self, start: BytePos, found: u32) -> ! {
         self.fatal_span_(
             start,
             self.pos,
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index 0816bc8deb6..aa70912dcde 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -277,6 +277,7 @@ struct TokenStreamBuilder {
 }
 
 impl TokenStreamBuilder {
+    #[inline(always)]
     fn push(&mut self, tree: TokenTree) {
         if let Some(TokenTree::Token(prev_token, Spacing::Joint)) = self.buf.last()
             && let TokenTree::Token(token, joint) = &tree
@@ -284,9 +285,9 @@ impl TokenStreamBuilder {
         {
             self.buf.pop();
             self.buf.push(TokenTree::Token(glued, *joint));
-            return;
+        } else {
+            self.buf.push(tree)
         }
-        self.buf.push(tree);
     }
 
     fn into_token_stream(self) -> TokenStream {
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index c0f661f7dbb..e473f4d30cf 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1391,8 +1391,6 @@ impl<'a> Parser<'a> {
         } else if self.is_do_yeet() {
             self.parse_yeet_expr(attrs)
         } else if self.check_keyword(kw::Let) {
-            self.manage_let_chains_context();
-            self.bump();
             self.parse_let_expr(attrs)
         } else if self.eat_keyword(kw::Underscore) {
             Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore, attrs))
@@ -2342,32 +2340,24 @@ impl<'a> Parser<'a> {
 
     /// Parses the condition of a `if` or `while` expression.
     fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
-        self.with_let_management(true, |local_self| {
-            local_self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)
-        })
+        self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)
     }
 
-    // Checks if `let` is in an invalid position like `let x = let y = 1;` or
-    // if the current `let` is in a let_chains context but nested in another
-    // expression like `if let Some(_) = _opt && [1, 2, 3][let _ = ()] = 1`.
-    //
-    // This method expects that the current token is `let`.
-    fn manage_let_chains_context(&mut self) {
-        debug_assert!(matches!(self.token.kind, TokenKind::Ident(kw::Let, _)));
-        let is_in_a_let_chains_context_but_nested_in_other_expr = self.let_expr_allowed
-            && !matches!(
-                self.prev_token.kind,
-                TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _)
-            );
-        if !self.let_expr_allowed || is_in_a_let_chains_context_but_nested_in_other_expr {
+    /// Parses a `let $pat = $expr` pseudo-expression.
+    fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
+        // This is a *approximate* heuristic that detects if `let` chains are
+        // being parsed in the right position. It's approximate because it
+        // doesn't deny all invalid `let` expressions, just completely wrong usages.
+        let not_in_chain = !matches!(
+            self.prev_token.kind,
+            TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _)
+        );
+        if !self.restrictions.contains(Restrictions::ALLOW_LET) || not_in_chain {
             self.struct_span_err(self.token.span, "expected expression, found `let` statement")
                 .emit();
         }
-    }
 
-    /// Parses a `let $pat = $expr` pseudo-expression.
-    /// The `let` token has already been eaten.
-    fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
+        self.bump(); // Eat `let` token
         let lo = self.prev_token.span;
         let pat = self.parse_pat_allow_top_alt(
             None,
@@ -2687,7 +2677,9 @@ impl<'a> Parser<'a> {
         // `&&` tokens.
         fn check_let_expr(expr: &Expr) -> bool {
             match expr.kind {
-                ExprKind::Binary(_, ref lhs, ref rhs) => check_let_expr(lhs) || check_let_expr(rhs),
+                ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, ref lhs, ref rhs) => {
+                    check_let_expr(lhs) || check_let_expr(rhs)
+                }
                 ExprKind::Let(..) => true,
                 _ => false,
             }
@@ -2703,9 +2695,8 @@ impl<'a> Parser<'a> {
             )?;
             let guard = if this.eat_keyword(kw::If) {
                 let if_span = this.prev_token.span;
-                let cond = this.with_let_management(true, |local_this| local_this.parse_expr())?;
-                let has_let_expr = check_let_expr(&cond);
-                if has_let_expr {
+                let cond = this.parse_expr_res(Restrictions::ALLOW_LET, None)?;
+                if check_let_expr(&cond) {
                     let span = if_span.to(cond.span);
                     this.sess.gated_spans.gate(sym::if_let_guard, span);
                 }
@@ -3279,17 +3270,4 @@ impl<'a> Parser<'a> {
             Ok((res, trailing))
         })
     }
-
-    // Calls `f` with the internal `let_expr_allowed` set to `let_expr_allowed` and then
-    // sets the internal `let_expr_allowed` back to its original value.
-    fn with_let_management<T>(
-        &mut self,
-        let_expr_allowed: bool,
-        f: impl FnOnce(&mut Self) -> T,
-    ) -> T {
-        let last_let_expr_allowed = mem::replace(&mut self.let_expr_allowed, let_expr_allowed);
-        let rslt = f(self);
-        self.let_expr_allowed = last_let_expr_allowed;
-        rslt
-    }
 }
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 1ac8b224248..0c523ad22c2 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -47,6 +47,7 @@ bitflags::bitflags! {
         const STMT_EXPR         = 1 << 0;
         const NO_STRUCT_LITERAL = 1 << 1;
         const CONST_EXPR        = 1 << 2;
+        const ALLOW_LET         = 1 << 3;
     }
 }
 
@@ -147,15 +148,12 @@ pub struct Parser<'a> {
     /// This allows us to recover when the user forget to add braces around
     /// multiple statements in the closure body.
     pub current_closure: Option<ClosureSpans>,
-    /// Used to track where `let`s are allowed. For example, `if true && let 1 = 1` is valid
-    /// but `[1, 2, 3][let _ = ()]` is not.
-    let_expr_allowed: bool,
 }
 
 // This type is used a lot, e.g. it's cloned when matching many declarative macro rules. Make sure
 // it doesn't unintentionally get bigger.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Parser<'_>, 336);
+rustc_data_structures::static_assert_size!(Parser<'_>, 328);
 
 /// Stores span information about a closure.
 #[derive(Clone)]
@@ -462,7 +460,6 @@ impl<'a> Parser<'a> {
                 inner_attr_ranges: Default::default(),
             },
             current_closure: None,
-            let_expr_allowed: false,
         };
 
         // Make parser point to the first token.
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index f1a81b65329..70518284cf9 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -97,7 +97,7 @@ impl<'tcx> CheckConstVisitor<'tcx> {
 
             // If the function belongs to a trait, then it must enable the const_trait_impl
             // feature to use that trait function (with a const default body).
-            if tcx.trait_of_item(def_id).is_some() {
+            if tcx.trait_of_item(def_id.to_def_id()).is_some() {
                 return true;
             }
 
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index eed3e1579a2..461dd52b9f2 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -519,7 +519,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn new(ir: &'a mut IrMaps<'tcx>, body_owner: LocalDefId) -> Liveness<'a, 'tcx> {
         let typeck_results = ir.tcx.typeck(body_owner);
         let param_env = ir.tcx.param_env(body_owner);
-        let closure_min_captures = typeck_results.closure_min_captures.get(&body_owner.to_def_id());
+        let closure_min_captures = typeck_results.closure_min_captures.get(&body_owner);
         let closure_ln = ir.add_live_node(ClosureNode);
         let exit_ln = ir.add_live_node(ExitNode);
 
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 390d6f5a856..7d4ee832974 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -212,7 +212,7 @@ where
                 // `impl Pub<Priv> { pub fn my_method() {} }` is considered a private type,
                 // so we need to visit the self type additionally.
                 if let Some(assoc_item) = tcx.opt_associated_item(def_id) {
-                    if let ty::ImplContainer(impl_def_id) = assoc_item.container {
+                    if let Some(impl_def_id) = assoc_item.impl_container(tcx) {
                         tcx.type_of(impl_def_id).visit_with(self)?;
                     }
                 }
@@ -734,11 +734,12 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
                     self.reach(item.def_id, item_level).generics().predicates();
 
                     for trait_item_ref in trait_item_refs {
+                        let tcx = self.tcx;
                         let mut reach = self.reach(trait_item_ref.id.def_id, item_level);
                         reach.generics().predicates();
 
                         if trait_item_ref.kind == AssocItemKind::Type
-                            && !trait_item_ref.defaultness.has_value()
+                            && !tcx.impl_defaultness(trait_item_ref.id.def_id).has_value()
                         {
                             // No type to visit.
                         } else {
@@ -1754,8 +1755,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
                 || self.in_assoc_ty
                 || self.tcx.resolutions(()).has_pub_restricted
             {
-                let vis_span =
-                    self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id));
+                let vis_span = self.tcx.def_span(def_id);
                 if kind == "trait" {
                     self.tcx.sess.emit_err(InPublicInterfaceTraits {
                         span,
@@ -1840,14 +1840,13 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
         &self,
         def_id: LocalDefId,
         assoc_item_kind: AssocItemKind,
-        defaultness: hir::Defaultness,
         vis: ty::Visibility,
     ) {
         let mut check = self.check(def_id, vis);
 
         let (check_ty, is_assoc_ty) = match assoc_item_kind {
             AssocItemKind::Const | AssocItemKind::Fn { .. } => (true, false),
-            AssocItemKind::Type => (defaultness.has_value(), true),
+            AssocItemKind::Type => (self.tcx.impl_defaultness(def_id).has_value(), true),
         };
         check.in_assoc_ty = is_assoc_ty;
         check.generics().predicates();
@@ -1879,7 +1878,6 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
                         self.check_assoc_item(
                             trait_item_ref.id.def_id,
                             trait_item_ref.kind,
-                            trait_item_ref.defaultness,
                             item_visibility,
                         );
 
@@ -1952,7 +1950,6 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
                         self.check_assoc_item(
                             impl_item_ref.id.def_id,
                             impl_item_ref.kind,
-                            impl_item_ref.defaultness,
                             impl_item_vis,
                         );
                     }
diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs
index 54774314313..49175e97f41 100644
--- a/compiler/rustc_query_impl/src/keys.rs
+++ b/compiler/rustc_query_impl/src/keys.rs
@@ -191,6 +191,16 @@ impl Key for (LocalDefId, DefId) {
     }
 }
 
+impl Key for (LocalDefId, LocalDefId) {
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
+    }
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        self.0.default_span(tcx)
+    }
+}
+
 impl Key for (DefId, Option<Ident>) {
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index 9f5779194af..6d2aff38172 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -1,4 +1,3 @@
-use crate::dep_graph::DepContext;
 use crate::query::plumbing::CycleError;
 use crate::query::{QueryContext, QueryStackFrame};
 use rustc_hir::def::DefKind;
@@ -536,17 +535,13 @@ pub(crate) fn report_cycle<'a>(
 ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
     assert!(!stack.is_empty());
 
-    let fix_span = |span: Span, query: &QueryStackFrame| {
-        sess.source_map().guess_head_span(query.default_span(span))
-    };
-
-    let span = fix_span(stack[1 % stack.len()].span, &stack[0].query);
+    let span = stack[0].query.default_span(stack[1 % stack.len()].span);
     let mut err =
         struct_span_err!(sess, span, E0391, "cycle detected when {}", stack[0].query.description);
 
     for i in 1..stack.len() {
         let query = &stack[i].query;
-        let span = fix_span(stack[(i + 1) % stack.len()].span, query);
+        let span = query.default_span(stack[(i + 1) % stack.len()].span);
         err.span_note(span, &format!("...which requires {}...", query.description));
     }
 
@@ -577,7 +572,7 @@ pub(crate) fn report_cycle<'a>(
     }
 
     if let Some((span, query)) = usage {
-        err.span_note(fix_span(span, &query), &format!("cycle used when {}", query.description));
+        err.span_note(query.default_span(span), &format!("cycle used when {}", query.description));
     }
 
     err
@@ -606,8 +601,7 @@ pub fn print_query_stack<CTX: QueryContext>(
             Level::FailureNote,
             &format!("#{} [{}] {}", i, query_info.query.name, query_info.query.description),
         );
-        diag.span =
-            tcx.dep_context().sess().source_map().guess_head_span(query_info.job.span).into();
+        diag.span = query_info.job.span.into();
         handler.force_print_diagnostic(diag);
 
         current_query = query_info.job.parent;
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 22a307a15ed..8839fb1a151 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1587,11 +1587,7 @@ impl<'a> Resolver<'a> {
         };
         let def_span = suggestion.res.opt_def_id().and_then(|def_id| match def_id.krate {
             LOCAL_CRATE => self.opt_span(def_id),
-            _ => Some(
-                self.session
-                    .source_map()
-                    .guess_head_span(self.cstore().get_span_untracked(def_id, self.session)),
-            ),
+            _ => Some(self.cstore().get_span_untracked(def_id, self.session)),
         });
         if let Some(def_span) = def_span {
             if span.overlaps(def_span) {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 6b49c6b1ac6..2b1f2b88ec4 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -136,12 +136,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
     fn def_span(&self, def_id: DefId) -> Option<Span> {
         match def_id.krate {
             LOCAL_CRATE => self.r.opt_span(def_id),
-            _ => Some(
-                self.r
-                    .session
-                    .source_map()
-                    .guess_head_span(self.r.cstore().get_span_untracked(def_id, self.r.session)),
-            ),
+            _ => Some(self.r.cstore().get_span_untracked(def_id, self.r.session)),
         }
     }
 
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index 0a0c674d179..a1a2040bbca 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -564,8 +564,8 @@ impl<'tcx> SaveContext<'tcx> {
                     return None;
                 };
                 let (def_id, decl_id) = match self.tcx.associated_item(method_id).container {
-                    ty::ImplContainer(_) => (Some(method_id), None),
-                    ty::TraitContainer(_) => (None, Some(method_id)),
+                    ty::ImplContainer => (Some(method_id), None),
+                    ty::TraitContainer => (None, Some(method_id)),
                 };
                 let sub_span = seg.ident.span;
                 filter!(self.span_utils, sub_span);
@@ -697,7 +697,7 @@ impl<'tcx> SaveContext<'tcx> {
             }
             Res::Def(HirDefKind::AssocFn, decl_id) => {
                 let def_id = if decl_id.is_local() {
-                    if self.tcx.associated_item(decl_id).defaultness.has_value() {
+                    if self.tcx.impl_defaultness(decl_id).has_value() {
                         Some(decl_id)
                     } else {
                         None
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 70f942a6508..6a8298605a2 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1159,20 +1159,6 @@ impl CrateCheckConfig {
         self.fill_well_known_names();
         self.fill_well_known_values();
     }
-
-    /// Fills a `CrateCheckConfig` with configuration names and values that are actually active.
-    pub fn fill_actual(&mut self, cfg: &CrateConfig) {
-        for &(k, v) in cfg {
-            if let Some(names_valid) = &mut self.names_valid {
-                names_valid.insert(k);
-            }
-            if let Some(v) = v {
-                self.values_valid.entry(k).and_modify(|values| {
-                    values.insert(v);
-                });
-            }
-        }
-    }
 }
 
 pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateConfig {
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 6495339eaf1..1827f1c208d 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -393,8 +393,7 @@ mod desc {
         "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted";
     pub const parse_linker_plugin_lto: &str =
         "either a boolean (`yes`, `no`, `on`, `off`, etc), or the path to the linker plugin";
-    pub const parse_location_detail: &str =
-        "comma separated list of location details to track: `file`, `line`, or `column`";
+    pub const parse_location_detail: &str = "either `none`, or a comma separated list of location details to track: `file`, `line`, or `column`";
     pub const parse_switch_with_opt_path: &str =
         "an optional path to the profiling data output directory";
     pub const parse_merge_functions: &str = "one of: `disabled`, `trampolines`, or `aliases`";
@@ -551,6 +550,9 @@ mod parse {
             ld.line = false;
             ld.file = false;
             ld.column = false;
+            if v == "none" {
+                return true;
+            }
             for s in v.split(',') {
                 match s {
                     "file" => ld.file = true,
@@ -1374,8 +1376,9 @@ options! {
     llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],
         "generate JSON tracing data file from LLVM data (default: no)"),
     location_detail: LocationDetail = (LocationDetail::all(), parse_location_detail, [TRACKED],
-        "comma separated list of location details to be tracked when using caller_location \
-        valid options are `file`, `line`, and `column` (default: all)"),
+        "what location details should be tracked when using caller_location, either \
+        `none`, or a comma separated list of location details, for which \
+        valid options are `file`, `line`, and `column` (default: `file,line,column`)"),
     ls: bool = (false, parse_bool, [UNTRACKED],
         "list the symbols defined by a library crate (default: no)"),
     macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index ca1d1302ec6..577126a95cc 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -669,8 +669,10 @@ impl<'a, Ty> FnAbi<'a, Ty> {
 
         match &cx.target_spec().arch[..] {
             "x86" => {
-                let flavor = if let spec::abi::Abi::Fastcall { .. } = abi {
-                    x86::Flavor::Fastcall
+                let flavor = if let spec::abi::Abi::Fastcall { .. }
+                | spec::abi::Abi::Vectorcall { .. } = abi
+                {
+                    x86::Flavor::FastcallOrVectorcall
                 } else {
                     x86::Flavor::General
                 };
diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs
index d169087dfbd..c7d59baf919 100644
--- a/compiler/rustc_target/src/abi/call/x86.rs
+++ b/compiler/rustc_target/src/abi/call/x86.rs
@@ -5,7 +5,7 @@ use crate::spec::HasTargetSpec;
 #[derive(PartialEq)]
 pub enum Flavor {
     General,
-    Fastcall,
+    FastcallOrVectorcall,
 }
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, flavor: Flavor)
@@ -60,9 +60,9 @@ where
         }
     }
 
-    if flavor == Flavor::Fastcall {
+    if flavor == Flavor::FastcallOrVectorcall {
         // Mark arguments as InReg like clang does it,
-        // so our fastcall is compatible with C/C++ fastcall.
+        // so our fastcall/vectorcall is compatible with C/C++ fastcall/vectorcall.
 
         // Clang reference: lib/CodeGen/TargetInfo.cpp
         // See X86_32ABIInfo::shouldPrimitiveUseInReg(), X86_32ABIInfo::updateFreeRegs()
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index b35502d9ee4..d4d5674e246 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -1279,13 +1279,14 @@ impl<'a> fmt::Debug for LayoutS<'a> {
         // This is how `Layout` used to print before it become
         // `Interned<LayoutS>`. We print it like this to avoid having to update
         // expected output in a lot of tests.
+        let LayoutS { size, align, abi, fields, largest_niche, variants } = self;
         f.debug_struct("Layout")
-            .field("fields", &self.fields)
-            .field("variants", &self.variants)
-            .field("abi", &self.abi)
-            .field("largest_niche", &self.largest_niche)
-            .field("align", &self.align)
-            .field("size", &self.size)
+            .field("size", size)
+            .field("align", align)
+            .field("abi", abi)
+            .field("fields", fields)
+            .field("largest_niche", largest_niche)
+            .field("variants", variants)
             .finish()
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs
index 5fcaa52d417..4b575ea660a 100644
--- a/compiler/rustc_trait_selection/src/traits/codegen.rs
+++ b/compiler/rustc_trait_selection/src/traits/codegen.rs
@@ -23,8 +23,6 @@ pub fn codegen_fulfill_obligation<'tcx>(
     tcx: TyCtxt<'tcx>,
     (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
 ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
-    // Remove any references to regions; this helps improve caching.
-    let trait_ref = tcx.erase_regions(trait_ref);
     // We expect the input to be fully normalized.
     debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref));
 
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 7ee3fe844b5..e442c5c9189 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -2129,7 +2129,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                             }
                         ] = path.segments
                         && data.trait_ref.def_id == *trait_id
-                        && self.tcx.trait_of_item(item_id) == Some(*trait_id)
+                        && self.tcx.trait_of_item(*item_id) == Some(*trait_id)
                         && !self.is_tainted_by_errors()
                     {
                         let (verb, noun) = match self.tcx.associated_item(item_id).kind {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 7e8872d9018..e6907637c57 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -223,8 +223,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 if let Some(def) = aty.ty_adt_def() {
                     // We also want to be able to select the slice's type's original
                     // signature with no type arguments resolved
-                    let type_string = self.tcx.type_of(def.did()).to_string();
-                    flags.push((sym::_Self, Some(format!("[{type_string}]"))));
+                    flags.push((sym::_Self, Some(format!("[{}]", self.tcx.type_of(def.did())))));
                 }
                 if aty.is_integral() {
                     flags.push((sym::_Self, Some("[{integral}]".to_string())));
@@ -242,10 +241,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 if let Some(def) = aty.ty_adt_def() {
                     // We also want to be able to select the array's type's original
                     // signature with no type arguments resolved
-                    let type_string = self.tcx.type_of(def.did()).to_string();
-                    flags.push((sym::_Self, Some(format!("[{type_string}; _]"))));
+                    let def_ty = self.tcx.type_of(def.did());
+                    flags.push((sym::_Self, Some(format!("[{def_ty}; _]"))));
                     if let Some(n) = len {
-                        flags.push((sym::_Self, Some(format!("[{type_string}; {n}]"))));
+                        flags.push((sym::_Self, Some(format!("[{def_ty}; {n}]"))));
                     }
                 }
                 if aty.is_integral() {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index b2eb8fdf8a5..219413121d8 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1946,7 +1946,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             ));
 
             let original_span = err.span.primary_span().unwrap();
-            let original_span = self.tcx.sess.source_map().guess_head_span(original_span);
             let mut span = MultiSpan::from_span(original_span);
 
             let message = outer_generator
@@ -2715,7 +2714,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 if let Some(ident) = self
                     .tcx
                     .opt_associated_item(trait_item_def_id)
-                    .and_then(|i| self.tcx.opt_item_ident(i.container.id()))
+                    .and_then(|i| self.tcx.opt_item_ident(i.container_id(self.tcx)))
                 {
                     assoc_span.push_span_label(ident.span, "in this trait");
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 2921ce0ffef..612f5130908 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -690,7 +690,7 @@ fn receiver_is_dispatchable<'tcx>(
         // U: Trait<Arg1, ..., ArgN>
         let trait_predicate = {
             let substs =
-                InternalSubsts::for_item(tcx, method.container.assert_trait(), |param, _| {
+                InternalSubsts::for_item(tcx, method.trait_container(tcx).unwrap(), |param, _| {
                     if param.index == 0 {
                         unsized_self_ty.into()
                     } else {
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 9de4d3a646c..d22465db85b 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1988,7 +1988,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
         return Progress { term: tcx.ty_error().into(), obligations: nested };
     };
 
-    if !assoc_ty.item.defaultness.has_value() {
+    if !assoc_ty.item.defaultness(tcx).has_value() {
         // This means that the impl is missing a definition for the
         // associated type. This error will be reported by the type
         // checker method `check_impl_items_against_trait`, so here we
@@ -2089,7 +2089,11 @@ fn assoc_def(
         return Ok(specialization_graph::LeafDef {
             item: *item,
             defining_node: impl_node,
-            finalizing_node: if item.defaultness.is_default() { None } else { Some(impl_node) },
+            finalizing_node: if item.defaultness(tcx).is_default() {
+                None
+            } else {
+                Some(impl_node)
+            },
         });
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 3170b29ee69..b9259196c48 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -358,7 +358,8 @@ pub fn generator_trait_ref_and_outputs<'tcx>(
 }
 
 pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
-    assoc_item.defaultness.is_final() && tcx.impl_defaultness(assoc_item.container.id()).is_final()
+    assoc_item.defaultness(tcx).is_final()
+        && tcx.impl_defaultness(assoc_item.container_id(tcx)).is_final()
 }
 
 pub enum TupleArgumentsFlag {
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index 497819ce5c5..14a60ace441 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -8,9 +8,7 @@
 
 use rustc_middle::traits::ChalkRustInterner as RustInterner;
 use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
-use rustc_middle::ty::{
-    self, AssocItemContainer, AssocKind, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
-};
+use rustc_middle::ty::{self, AssocKind, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
 
 use rustc_ast::ast;
 use rustc_attr as attr;
@@ -74,7 +72,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
     ) -> Arc<chalk_solve::rust_ir::AssociatedTyDatum<RustInterner<'tcx>>> {
         let def_id = assoc_type_id.0;
         let assoc_item = self.interner.tcx.associated_item(def_id);
-        let AssocItemContainer::TraitContainer(trait_def_id) = assoc_item.container else {
+        let Some(trait_def_id) = assoc_item.trait_container(self.interner.tcx) else {
             unimplemented!("Not possible??");
         };
         match assoc_item.kind {
@@ -455,7 +453,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
     ) -> Arc<chalk_solve::rust_ir::AssociatedTyValue<RustInterner<'tcx>>> {
         let def_id = associated_ty_id.0;
         let assoc_item = self.interner.tcx.associated_item(def_id);
-        let impl_id = assoc_item.container.id();
+        let impl_id = assoc_item.container_id(self.interner.tcx);
         match assoc_item.kind {
             AssocKind::Type => {}
             _ => unimplemented!("Not possible??"),
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 4142c999ca7..515a73ead77 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -1,6 +1,6 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::DefId;
 use rustc_middle::ty::{self, TyCtxt};
 
 pub fn provide(providers: &mut ty::query::Providers) {
@@ -9,7 +9,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
         associated_item_def_ids,
         associated_items,
         impl_item_implementor_ids,
-        trait_of_item,
         ..*providers
     };
 }
@@ -40,16 +39,6 @@ fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap<DefId
         .collect()
 }
 
-/// If the given `DefId` describes an item belonging to a trait,
-/// returns the `DefId` of the trait that the trait item belongs to;
-/// otherwise, returns `None`.
-fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
-    tcx.opt_associated_item(def_id).and_then(|associated_item| match associated_item.container {
-        ty::TraitContainer(def_id) => Some(def_id),
-        ty::ImplContainer(_) => None,
-    })
-}
-
 fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
     let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     let parent_def_id = tcx.hir().get_parent_item(id);
@@ -59,8 +48,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
             if let Some(impl_item_ref) =
                 impl_.items.iter().find(|i| i.id.def_id.to_def_id() == def_id)
             {
-                let assoc_item =
-                    associated_item_from_impl_item_ref(tcx, parent_def_id, impl_item_ref);
+                let assoc_item = associated_item_from_impl_item_ref(impl_item_ref);
                 debug_assert_eq!(assoc_item.def_id, def_id);
                 return assoc_item;
             }
@@ -70,8 +58,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
             if let Some(trait_item_ref) =
                 trait_item_refs.iter().find(|i| i.id.def_id.to_def_id() == def_id)
             {
-                let assoc_item =
-                    associated_item_from_trait_item_ref(tcx, parent_def_id, trait_item_ref);
+                let assoc_item = associated_item_from_trait_item_ref(trait_item_ref);
                 debug_assert_eq!(assoc_item.def_id, def_id);
                 return assoc_item;
             }
@@ -87,11 +74,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
     )
 }
 
-fn associated_item_from_trait_item_ref(
-    tcx: TyCtxt<'_>,
-    parent_def_id: LocalDefId,
-    trait_item_ref: &hir::TraitItemRef,
-) -> ty::AssocItem {
+fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty::AssocItem {
     let def_id = trait_item_ref.id.def_id;
     let (kind, has_self) = match trait_item_ref.kind {
         hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
@@ -102,20 +85,14 @@ fn associated_item_from_trait_item_ref(
     ty::AssocItem {
         name: trait_item_ref.ident.name,
         kind,
-        vis: tcx.visibility(def_id),
-        defaultness: trait_item_ref.defaultness,
         def_id: def_id.to_def_id(),
         trait_item_def_id: Some(def_id.to_def_id()),
-        container: ty::TraitContainer(parent_def_id.to_def_id()),
+        container: ty::TraitContainer,
         fn_has_self_parameter: has_self,
     }
 }
 
-fn associated_item_from_impl_item_ref(
-    tcx: TyCtxt<'_>,
-    parent_def_id: LocalDefId,
-    impl_item_ref: &hir::ImplItemRef,
-) -> ty::AssocItem {
+fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::AssocItem {
     let def_id = impl_item_ref.id.def_id;
     let (kind, has_self) = match impl_item_ref.kind {
         hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
@@ -126,11 +103,9 @@ fn associated_item_from_impl_item_ref(
     ty::AssocItem {
         name: impl_item_ref.ident.name,
         kind,
-        vis: tcx.visibility(def_id),
-        defaultness: impl_item_ref.defaultness,
         def_id: def_id.to_def_id(),
         trait_item_def_id: impl_item_ref.trait_item_def_id,
-        container: ty::ImplContainer(parent_def_id.to_def_id()),
+        container: ty::ImplContainer,
         fn_has_self_parameter: has_self,
     }
 }
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 979e997f244..bd1d568cd9a 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -281,7 +281,7 @@ fn resolve_associated_item<'tcx>(
             }
 
             // If the item does not have a value, then we cannot return an instance.
-            if !leaf_def.item.defaultness.has_value() {
+            if !leaf_def.item.defaultness(tcx).has_value() {
                 return Ok(None);
             }
 
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index b1af3051719..7007e76b86e 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -70,11 +70,13 @@ fn sized_constraint_for_ty<'tcx>(
 }
 
 fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
-    let item = tcx.hir().expect_item(def_id.expect_local());
-    if let hir::ItemKind::Impl(impl_) = &item.kind {
-        impl_.defaultness
-    } else {
-        bug!("`impl_defaultness` called on {:?}", item);
+    match tcx.hir().get_by_def_id(def_id.expect_local()) {
+        hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.defaultness,
+        hir::Node::ImplItem(hir::ImplItem { defaultness, .. })
+        | hir::Node::TraitItem(hir::TraitItem { defaultness, .. }) => *defaultness,
+        node => {
+            bug!("`impl_defaultness` called on {:?}", node);
+        }
     }
 }
 
diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs
index 99a8101dc96..ff39bf36129 100644
--- a/compiler/rustc_typeck/src/astconv/errors.rs
+++ b/compiler/rustc_typeck/src/astconv/errors.rs
@@ -255,7 +255,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 trait_bound_spans.push(*span);
             }
             for assoc_item in items {
-                let trait_def_id = assoc_item.container.id();
+                let trait_def_id = assoc_item.container_id(tcx);
                 names.push(format!(
                     "`{}` (from trait `{}`)",
                     assoc_item.name,
@@ -321,7 +321,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             let mut dupes = false;
             for item in assoc_items {
                 let prefix = if names[&item.name] > 1 {
-                    let trait_def_id = item.container.id();
+                    let trait_def_id = item.container_id(tcx);
                     dupes = true;
                     format!("{}::", tcx.def_path_str(trait_def_id))
                 } else {
@@ -376,7 +376,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let mut label = vec![];
                 for item in assoc_items {
                     let postfix = if names[&item.name] > 1 {
-                        let trait_def_id = item.container.id();
+                        let trait_def_id = item.container_id(tcx);
                         format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id))
                     } else {
                         String::new()
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 444f0fdd45a..8a5c7fee697 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -1141,7 +1141,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             .or_else(|| find_item_of_kind(ty::AssocKind::Const))
             .expect("missing associated type");
 
-        if !assoc_item.vis.is_accessible_from(def_scope, tcx) {
+        if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) {
             tcx.sess
                 .struct_span_err(
                     binding.span,
@@ -1160,7 +1160,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         span: binding.span,
                         prev_span: *prev_span,
                         item_name: binding.item_name,
-                        def_path: tcx.def_path_str(assoc_item.container.id()),
+                        def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
                     });
                 })
                 .or_insert(binding.span);
@@ -1997,7 +1997,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let ty = self.normalize_ty(span, ty);
 
         let kind = DefKind::AssocTy;
-        if !item.vis.is_accessible_from(def_scope, tcx) {
+        if !item.visibility(tcx).is_accessible_from(def_scope, tcx) {
             let kind = kind.descr(item.def_id);
             let msg = format!("{} `{}` is private", kind, assoc_ident);
             tcx.sess
diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs
index df315b8a3bc..1b13c98e4c3 100644
--- a/compiler/rustc_typeck/src/check/_match.rs
+++ b/compiler/rustc_typeck/src/check/_match.rs
@@ -293,6 +293,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(crate) fn if_cause(
         &self,
         span: Span,
+        cond_span: Span,
         then_expr: &'tcx hir::Expr<'tcx>,
         else_expr: &'tcx hir::Expr<'tcx>,
         then_ty: Ty<'tcx>,
@@ -357,8 +358,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // ```
             if block.expr.is_none() && block.stmts.is_empty()
                 && let Some(outer_span) = &mut outer_span
+                && let Some(cond_span) = cond_span.find_ancestor_inside(*outer_span)
             {
-                *outer_span = self.tcx.sess.source_map().guess_head_span(*outer_span);
+                *outer_span = outer_span.with_hi(cond_span.hi())
             }
 
             (self.find_block_span(block), block.hir_id)
diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs
index 0836f15a122..75f5aced855 100644
--- a/compiler/rustc_typeck/src/check/callee.rs
+++ b/compiler/rustc_typeck/src/check/callee.rs
@@ -5,7 +5,7 @@ use crate::type_error_struct;
 use rustc_errors::{struct_span_err, Applicability, Diagnostic};
 use rustc_hir as hir;
 use rustc_hir::def::{self, Namespace, Res};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::def_id::DefId;
 use rustc_infer::{
     infer,
     traits::{self, Obligation},
@@ -19,11 +19,13 @@ use rustc_middle::ty::adjustment::{
 };
 use rustc_middle::ty::subst::{Subst, SubstsRef};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
+use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use rustc_target::spec::abi;
 use rustc_trait_selection::autoderef::Autoderef;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+
 use std::iter;
 
 /// Checks that it is legal to call methods of the trait corresponding
@@ -59,7 +61,7 @@ pub fn check_legal_trait_for_method_call(
 
 enum CallStep<'tcx> {
     Builtin(Ty<'tcx>),
-    DeferredClosure(DefId, ty::FnSig<'tcx>),
+    DeferredClosure(LocalDefId, ty::FnSig<'tcx>),
     /// E.g., enum variant constructors.
     Overloaded(MethodCallee<'tcx>),
 }
@@ -145,7 +147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
 
             ty::Closure(def_id, substs) => {
-                assert_eq!(def_id.krate, LOCAL_CRATE);
+                let def_id = def_id.expect_local();
 
                 // Check whether this is a call to a closure where we
                 // haven't yet decided on whether the closure is fn vs
@@ -558,7 +560,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         call_expr: &'tcx hir::Expr<'tcx>,
         arg_exprs: &'tcx [hir::Expr<'tcx>],
         expected: Expectation<'tcx>,
-        closure_def_id: DefId,
+        closure_def_id: LocalDefId,
         fn_sig: ty::FnSig<'tcx>,
     ) -> Ty<'tcx> {
         // `fn_sig` is the *signature* of the closure being called. We
@@ -581,7 +583,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             arg_exprs,
             fn_sig.c_variadic,
             TupleArgumentsFlag::TupleArguments,
-            Some(closure_def_id),
+            Some(closure_def_id.to_def_id()),
         );
 
         fn_sig.output()
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 9497d5c4528..9c1fd9b30b4 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -1098,7 +1098,7 @@ fn check_impl_items_against_trait<'tcx>(
         for &trait_item_id in tcx.associated_item_def_ids(impl_trait_ref.def_id) {
             let is_implemented = ancestors
                 .leaf_def(tcx, trait_item_id)
-                .map_or(false, |node_item| node_item.item.defaultness.has_value());
+                .map_or(false, |node_item| node_item.item.defaultness(tcx).has_value());
 
             if !is_implemented && tcx.impl_defaultness(impl_id).is_final() {
                 missing_items.push(tcx.associated_item(trait_item_id));
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index e3ac23686b6..666498403c4 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -165,7 +165,7 @@ fn compare_predicate_entailment<'tcx>(
 
     // Create mapping from trait to placeholder.
     let trait_to_placeholder_substs =
-        impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container.id(), trait_to_impl_substs);
+        impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs);
     debug!("compare_impl_method: trait_to_placeholder_substs={:?}", trait_to_placeholder_substs);
 
     let impl_m_generics = tcx.generics_of(impl_m.def_id);
@@ -511,8 +511,8 @@ fn compare_self_type<'tcx>(
 
     let self_string = |method: &ty::AssocItem| {
         let untransformed_self_ty = match method.container {
-            ty::ImplContainer(_) => impl_trait_ref.self_ty(),
-            ty::TraitContainer(_) => tcx.types.self_param,
+            ty::ImplContainer => impl_trait_ref.self_ty(),
+            ty::TraitContainer => tcx.types.self_param,
         };
         let self_arg_ty = tcx.fn_sig(method.def_id).input(0);
         let param_env = ty::ParamEnv::reveal_all();
@@ -1194,7 +1194,7 @@ fn compare_type_predicate_entailment<'tcx>(
 ) -> Result<(), ErrorGuaranteed> {
     let impl_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
     let trait_to_impl_substs =
-        impl_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
+        impl_substs.rebase_onto(tcx, impl_ty.container_id(tcx), impl_trait_ref.substs);
 
     let impl_ty_generics = tcx.generics_of(impl_ty.def_id);
     let trait_ty_generics = tcx.generics_of(trait_ty.def_id);
@@ -1390,9 +1390,9 @@ pub fn check_type_bounds<'tcx>(
     });
     let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
     let impl_ty_substs = tcx.intern_substs(&substs);
+    let container_id = impl_ty.container_id(tcx);
 
-    let rebased_substs =
-        impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
+    let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
     let impl_ty_value = tcx.type_of(impl_ty.def_id);
 
     let param_env = tcx.param_env(impl_ty.def_id);
@@ -1441,8 +1441,7 @@ pub fn check_type_bounds<'tcx>(
     debug!(?normalize_param_env);
 
     let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
-    let rebased_substs =
-        impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
+    let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
 
     tcx.infer_ctxt().enter(move |infcx| {
         let ocx = ObligationCtxt::new(&infcx);
@@ -1505,10 +1504,13 @@ pub fn check_type_bounds<'tcx>(
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
         let implied_bounds = match impl_ty.container {
-            ty::TraitContainer(_) => FxHashSet::default(),
-            ty::ImplContainer(def_id) => {
-                wfcheck::impl_implied_bounds(tcx, param_env, def_id.expect_local(), impl_ty_span)
-            }
+            ty::TraitContainer => FxHashSet::default(),
+            ty::ImplContainer => wfcheck::impl_implied_bounds(
+                tcx,
+                param_env,
+                container_id.expect_local(),
+                impl_ty_span,
+            ),
         };
         let mut outlives_environment = OutlivesEnvironment::new(param_env);
         outlives_environment.add_implied_bounds(&infcx, implied_bounds, impl_ty_hir_id);
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 58b0399c5c9..4de48dc5ba1 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -1,5 +1,6 @@
 use crate::check::FnCtxt;
 use rustc_infer::infer::InferOk;
+use rustc_middle::middle::stability::EvalResult;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::ObligationCause;
 
@@ -363,18 +364,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
 
-            let compatible_variants: Vec<(String, Option<String>)> = expected_adt
+            let compatible_variants: Vec<(String, _, _, Option<String>)> = expected_adt
                 .variants()
                 .iter()
                 .filter(|variant| {
-                    variant.fields.len() == 1 && variant.ctor_kind == hir::def::CtorKind::Fn
+                    variant.fields.len() == 1
                 })
                 .filter_map(|variant| {
                     let sole_field = &variant.fields[0];
 
                     let field_is_local = sole_field.did.is_local();
                     let field_is_accessible =
-                        sole_field.vis.is_accessible_from(expr.hir_id.owner.to_def_id(), self.tcx);
+                        sole_field.vis.is_accessible_from(expr.hir_id.owner.to_def_id(), self.tcx)
+                        // Skip suggestions for unstable public fields (for example `Pin::pointer`)
+                        && matches!(self.tcx.eval_stability(sole_field.did, None, expr.span, None), EvalResult::Allow | EvalResult::Unmarked);
 
                     if !field_is_local && !field_is_accessible {
                         return None;
@@ -391,33 +394,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         if let Some(path) = variant_path.strip_prefix("std::prelude::")
                             && let Some((_, path)) = path.split_once("::")
                         {
-                            return Some((path.to_string(), note_about_variant_field_privacy));
+                            return Some((path.to_string(), variant.ctor_kind, sole_field.name, note_about_variant_field_privacy));
                         }
-                        Some((variant_path, note_about_variant_field_privacy))
+                        Some((variant_path, variant.ctor_kind, sole_field.name, note_about_variant_field_privacy))
                     } else {
                         None
                     }
                 })
                 .collect();
 
-            let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
-                Some(ident) => format!("{ident}: "),
-                None => String::new(),
+            let suggestions_for = |variant: &_, ctor, field_name| {
+                let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
+                    Some(ident) => format!("{ident}: "),
+                    None => String::new(),
+                };
+
+                let (open, close) = match ctor {
+                    hir::def::CtorKind::Fn => ("(".to_owned(), ")"),
+                    hir::def::CtorKind::Fictive => (format!(" {{ {field_name}: "), " }"),
+
+                    // unit variants don't have fields
+                    hir::def::CtorKind::Const => unreachable!(),
+                };
+
+                vec![
+                    (expr.span.shrink_to_lo(), format!("{prefix}{variant}{open}")),
+                    (expr.span.shrink_to_hi(), close.to_owned()),
+                ]
             };
 
             match &compatible_variants[..] {
                 [] => { /* No variants to format */ }
-                [(variant, note)] => {
+                [(variant, ctor_kind, field_name, note)] => {
                     // Just a single matching variant.
                     err.multipart_suggestion_verbose(
                         &format!(
                             "try wrapping the expression in `{variant}`{note}",
                             note = note.as_deref().unwrap_or("")
                         ),
-                        vec![
-                            (expr.span.shrink_to_lo(), format!("{prefix}{variant}(")),
-                            (expr.span.shrink_to_hi(), ")".to_string()),
-                        ],
+                        suggestions_for(&**variant, *ctor_kind, *field_name),
                         Applicability::MaybeIncorrect,
                     );
                 }
@@ -428,12 +443,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             "try wrapping the expression in a variant of `{}`",
                             self.tcx.def_path_str(expected_adt.did())
                         ),
-                        compatible_variants.into_iter().map(|(variant, _)| {
-                            vec![
-                                (expr.span.shrink_to_lo(), format!("{prefix}{variant}(")),
-                                (expr.span.shrink_to_hi(), ")".to_string()),
-                            ]
-                        }),
+                        compatible_variants.into_iter().map(
+                            |(variant, ctor_kind, field_name, _)| {
+                                suggestions_for(&variant, ctor_kind, field_name)
+                            },
+                        ),
                         Applicability::MaybeIncorrect,
                     );
                 }
@@ -761,7 +775,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map(
                                 |did| {
                                     let ai = self.tcx.associated_item(did);
-                                    ai.container == ty::TraitContainer(clone_trait)
+                                    ai.trait_container(self.tcx) == Some(clone_trait)
                                 },
                             ),
                             segment.ident.name,
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index e20c6a2d99a..6e97b0bf2ab 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -1003,8 +1003,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let else_diverges = self.diverges.get();
 
             let opt_suggest_box_span = self.opt_suggest_box_span(else_ty, orig_expected);
-            let if_cause =
-                self.if_cause(sp, then_expr, else_expr, then_ty, else_ty, opt_suggest_box_span);
+            let if_cause = self.if_cause(
+                sp,
+                cond_expr.span,
+                then_expr,
+                else_expr,
+                then_ty,
+                else_ty,
+                opt_suggest_box_span,
+            );
 
             coerce.coerce(self, &if_cause, else_expr, else_ty);
 
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index d1c10a3b63c..3a809334511 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -29,6 +29,7 @@ use rustc_middle::ty::{
     ToPredicate, Ty, UserType,
 };
 use rustc_session::lint;
+use rustc_span::def_id::LocalDefId;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{Span, DUMMY_SP};
@@ -114,7 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub(in super::super) fn record_deferred_call_resolution(
         &self,
-        closure_def_id: DefId,
+        closure_def_id: LocalDefId,
         r: DeferredCallResolution<'tcx>,
     ) {
         let mut deferred_call_resolutions = self.deferred_call_resolutions.borrow_mut();
@@ -123,7 +124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub(in super::super) fn remove_deferred_call_resolutions(
         &self,
-        closure_def_id: DefId,
+        closure_def_id: LocalDefId,
     ) -> Vec<DeferredCallResolution<'tcx>> {
         let mut deferred_call_resolutions = self.deferred_call_resolutions.borrow_mut();
         deferred_call_resolutions.remove(&closure_def_id).unwrap_or_default()
@@ -1089,13 +1090,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 is_alias_variant_ctor = true;
             }
             Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => {
-                let container = tcx.associated_item(def_id).container;
-                debug!(?def_id, ?container);
+                let assoc_item = tcx.associated_item(def_id);
+                let container = assoc_item.container;
+                let container_id = assoc_item.container_id(tcx);
+                debug!(?def_id, ?container, ?container_id);
                 match container {
-                    ty::TraitContainer(trait_did) => {
-                        callee::check_legal_trait_for_method_call(tcx, span, None, span, trait_did)
+                    ty::TraitContainer => {
+                        callee::check_legal_trait_for_method_call(tcx, span, None, span, container_id)
                     }
-                    ty::ImplContainer(impl_def_id) => {
+                    ty::ImplContainer => {
                         if segments.len() == 1 {
                             // `<T>::assoc` will end up here, and so
                             // can `T::assoc`. It this came from an
@@ -1103,7 +1106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             // `T` for posterity (see `UserSelfTy` for
                             // details).
                             let self_ty = self_ty.expect("UFCS sugared assoc missing Self");
-                            user_self_ty = Some(UserSelfTy { impl_def_id, self_ty });
+                            user_self_ty = Some(UserSelfTy { impl_def_id: container_id, self_ty });
                         }
                     }
                 }
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index 097fff6418e..57771e0969b 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -839,8 +839,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             && results.type_dependent_def_id(expr.hir_id).map_or(
                 false,
                 |did| {
-                    self.tcx.associated_item(did).container
-                        == ty::AssocItemContainer::TraitContainer(clone_trait_did)
+                    let assoc_item = self.tcx.associated_item(did);
+                    assoc_item.container == ty::AssocItemContainer::TraitContainer
+                        && assoc_item.container_id(self.tcx) == clone_trait_did
                 },
             )
             // If that clone call hasn't already dereferenced the self type (i.e. don't give this
diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs
index 99895dc1224..cd152eb97f1 100644
--- a/compiler/rustc_typeck/src/check/inherited.rs
+++ b/compiler/rustc_typeck/src/check/inherited.rs
@@ -2,13 +2,14 @@ use super::callee::DeferredCallResolution;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefIdMap, LocalDefId};
+use rustc_hir::def_id::LocalDefId;
 use rustc_hir::HirIdMap;
 use rustc_infer::infer;
 use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::def_id::LocalDefIdMap;
 use rustc_span::{self, Span};
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt};
@@ -46,7 +47,7 @@ pub struct Inherited<'a, 'tcx> {
     // decision. We keep these deferred resolutions grouped by the
     // def-id of the closure, so that once we decide, we can easily go
     // back and process them.
-    pub(super) deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolution<'tcx>>>>,
+    pub(super) deferred_call_resolutions: RefCell<LocalDefIdMap<Vec<DeferredCallResolution<'tcx>>>>,
 
     pub(super) deferred_cast_checks: RefCell<Vec<super::cast::CastCheck<'tcx>>>,
 
diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs
index b14f3d6de4e..2c89b63ae84 100644
--- a/compiler/rustc_typeck/src/check/method/confirm.rs
+++ b/compiler/rustc_typeck/src/check/method/confirm.rs
@@ -238,7 +238,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
     ) -> SubstsRef<'tcx> {
         match pick.kind {
             probe::InherentImplPick => {
-                let impl_def_id = pick.item.container.id();
+                let impl_def_id = pick.item.container_id(self.tcx);
                 assert!(
                     self.tcx.impl_trait_ref(impl_def_id).is_none(),
                     "impl {:?} is not an inherent impl",
@@ -248,7 +248,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             }
 
             probe::ObjectPick => {
-                let trait_def_id = pick.item.container.id();
+                let trait_def_id = pick.item.container_id(self.tcx);
                 self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| {
                     // The object data has no entry for the Self
                     // Type. For the purposes of this method call, we
@@ -273,7 +273,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             }
 
             probe::TraitPick => {
-                let trait_def_id = pick.item.container.id();
+                let trait_def_id = pick.item.container_id(self.tcx);
 
                 // Make a trait reference `$0 : Trait<$1...$n>`
                 // consisting entirely of type variables. Later on in
@@ -540,15 +540,14 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
 
     fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) {
         // Disallow calls to the method `drop` defined in the `Drop` trait.
-        match pick.item.container {
-            ty::TraitContainer(trait_def_id) => callee::check_legal_trait_for_method_call(
+        if let Some(trait_def_id) = pick.item.trait_container(self.tcx) {
+            callee::check_legal_trait_for_method_call(
                 self.tcx,
                 self.span,
                 Some(self.self_expr.span),
                 self.call_expr.span,
                 trait_def_id,
-            ),
-            ty::ImplContainer(..) => {}
+            )
         }
     }
 
diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs
index c09f63f1e8f..0e678c41f8b 100644
--- a/compiler/rustc_typeck/src/check/method/mod.rs
+++ b/compiler/rustc_typeck/src/check/method/mod.rs
@@ -231,7 +231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ProbeScope::AllTraits,
             ) {
                 // If we find a different result the caller probably forgot to import a trait.
-                Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container.id()],
+                Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container_id(self.tcx)],
                 Err(Ambiguity(ref sources)) => sources
                     .iter()
                     .filter_map(|source| {
diff --git a/compiler/rustc_typeck/src/check/method/prelude2021.rs b/compiler/rustc_typeck/src/check/method/prelude2021.rs
index a2f1f5692c7..7c68d930405 100644
--- a/compiler/rustc_typeck/src/check/method/prelude2021.rs
+++ b/compiler/rustc_typeck/src/check/method/prelude2021.rs
@@ -148,7 +148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let trait_name = self.trait_path_or_bare_name(
                         span,
                         call_expr.hir_id,
-                        pick.item.container.id(),
+                        pick.item.container_id(self.tcx),
                     );
 
                     let mut lint = lint.build(&format!(
@@ -261,8 +261,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.tcx.struct_span_lint_hir(RUST_2021_PRELUDE_COLLISIONS, expr_id, span, |lint| {
             // "type" refers to either a type or, more likely, a trait from which
             // the associated function or method is from.
-            let trait_path = self.trait_path_or_bare_name(span, expr_id, pick.item.container.id());
-            let trait_generics = self.tcx.generics_of(pick.item.container.id());
+            let container_id = pick.item.container_id(self.tcx);
+            let trait_path = self.trait_path_or_bare_name(span, expr_id, container_id);
+            let trait_generics = self.tcx.generics_of(container_id);
 
             let trait_name =
                 if trait_generics.params.len() <= trait_generics.has_self as usize {
diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs
index 8f5f3657fc9..efe15fec7cb 100644
--- a/compiler/rustc_typeck/src/check/method/probe.rs
+++ b/compiler/rustc_typeck/src/check/method/probe.rs
@@ -592,9 +592,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     fn push_candidate(&mut self, candidate: Candidate<'tcx>, is_inherent: bool) {
         let is_accessible = if let Some(name) = self.method_name {
             let item = candidate.item;
-            let def_scope =
-                self.tcx.adjust_ident_and_get_scope(name, item.container.id(), self.body_id).1;
-            item.vis.is_accessible_from(def_scope, self.tcx)
+            let def_scope = self
+                .tcx
+                .adjust_ident_and_get_scope(name, item.container_id(self.tcx), self.body_id)
+                .1;
+            item.visibility(self.tcx).is_accessible_from(def_scope, self.tcx)
         } else {
             true
         };
@@ -1025,7 +1027,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         self.assemble_extension_candidates_for_all_traits();
 
         let out_of_scope_traits = match self.pick_core() {
-            Some(Ok(p)) => vec![p.item.container.id()],
+            Some(Ok(p)) => vec![p.item.container_id(self.tcx)],
             //Some(Ok(p)) => p.iter().map(|p| p.item.container().id()).collect(),
             Some(Err(MethodError::Ambiguity(v))) => v
                 .into_iter()
@@ -1387,7 +1389,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                             self.tcx.def_path_str(stable_pick.item.def_id),
                         ));
                     }
-                    (ty::AssocKind::Const, ty::AssocItemContainer::TraitContainer(def_id)) => {
+                    (ty::AssocKind::Const, ty::AssocItemContainer::TraitContainer) => {
+                        let def_id = stable_pick.item.container_id(self.tcx);
                         diag.span_suggestion(
                             self.span,
                             "use the fully qualified path to the associated const",
@@ -1429,9 +1432,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
     fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> CandidateSource {
         match candidate.kind {
-            InherentImplCandidate(..) => CandidateSource::Impl(candidate.item.container.id()),
+            InherentImplCandidate(..) => {
+                CandidateSource::Impl(candidate.item.container_id(self.tcx))
+            }
             ObjectCandidate | WhereClauseCandidate(_) => {
-                CandidateSource::Trait(candidate.item.container.id())
+                CandidateSource::Trait(candidate.item.container_id(self.tcx))
             }
             TraitCandidate(trait_ref) => self.probe(|_| {
                 let _ = self
@@ -1444,7 +1449,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                         // to that impl.
                         CandidateSource::Impl(impl_data.impl_def_id)
                     }
-                    _ => CandidateSource::Trait(candidate.item.container.id()),
+                    _ => CandidateSource::Trait(candidate.item.container_id(self.tcx)),
                 }
             }),
         }
@@ -1502,7 +1507,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty);
 
                     // Check whether the impl imposes obligations we have to worry about.
-                    let impl_def_id = probe.item.container.id();
+                    let impl_def_id = probe.item.container_id(self.tcx);
                     let impl_bounds = self.tcx.predicates_of(impl_def_id);
                     let impl_bounds = impl_bounds.instantiate(self.tcx, substs);
                     let traits::Normalized { value: impl_bounds, obligations: norm_obligations } =
@@ -1653,12 +1658,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         probes: &[(&Candidate<'tcx>, ProbeResult)],
     ) -> Option<Pick<'tcx>> {
         // Do all probes correspond to the same trait?
-        let container = probes[0].0.item.container;
-        if let ty::ImplContainer(_) = container {
-            return None;
-        }
-        if probes[1..].iter().any(|&(p, _)| p.item.container != container) {
-            return None;
+        let container = probes[0].0.item.trait_container(self.tcx)?;
+        for (p, _) in &probes[1..] {
+            let p_container = p.item.trait_container(self.tcx)?;
+            if p_container != container {
+                return None;
+            }
         }
 
         // FIXME: check the return type here somehow.
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 56fcd9e0a89..c92b93cbc22 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -1789,7 +1789,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // We point at the method, but we just skip the rest of the check for arbitrary
                         // self types and rely on the suggestion to `use` the trait from
                         // `suggest_valid_traits`.
-                        let did = Some(pick.item.container.id());
+                        let did = Some(pick.item.container_id(self.tcx));
                         let skip = skippable.contains(&did);
                         if pick.autoderefs == 0 && !skip {
                             err.span_label(
@@ -1825,7 +1825,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         )
                     {
                         debug!("try_alt_rcvr: pick candidate {:?}", pick);
-                        let did = Some(pick.item.container.id());
+                        let did = Some(pick.item.container_id(self.tcx));
                         // We don't want to suggest a container type when the missing
                         // method is `.clone()` or `.deref()` otherwise we'd suggest
                         // `Arc::new(foo).clone()`, which is far from what the user wants.
@@ -1937,7 +1937,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 }
                             }
                             // We only want to suggest public or local traits (#45781).
-                            item.vis.is_public() || info.def_id.is_local()
+                            item.visibility(self.tcx).is_public() || info.def_id.is_local()
                         })
                         .is_some()
             })
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs
index d72e215934a..dd8f943b985 100644
--- a/compiler/rustc_typeck/src/check/upvar.rs
+++ b/compiler/rustc_typeck/src/check/upvar.rs
@@ -35,7 +35,6 @@ use super::FnCtxt;
 use crate::expr_use_visitor as euv;
 use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_infer::infer::UpvarRegion;
@@ -186,6 +185,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
             }
         };
+        let closure_def_id = closure_def_id.expect_local();
 
         let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs {
             self.closure_kind(closure_substs).is_none().then_some(closure_substs)
@@ -193,20 +193,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             None
         };
 
-        let local_def_id = closure_def_id.expect_local();
-
-        let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id());
-        assert_eq!(body_owner_def_id.to_def_id(), closure_def_id);
+        assert_eq!(self.tcx.hir().body_owner_def_id(body.id()), closure_def_id);
         let mut delegate = InferBorrowKind {
             fcx: self,
-            closure_def_id: local_def_id,
+            closure_def_id,
             capture_information: Default::default(),
             fake_reads: Default::default(),
         };
         euv::ExprUseVisitor::new(
             &mut delegate,
             &self.infcx,
-            body_owner_def_id,
+            closure_def_id,
             self.param_env,
             &self.typeck_results.borrow(),
         )
@@ -224,7 +221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         self.compute_min_captures(closure_def_id, capture_information, span);
 
-        let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id);
+        let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id);
 
         if should_do_rust_2021_incompatible_closure_captures_analysis(self.tcx, closure_hir_id) {
             self.perform_2229_migration_anaysis(closure_def_id, body_id, capture_clause, span);
@@ -239,7 +236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
                 for var_hir_id in upvars.keys() {
-                    let place = self.place_for_root_variable(local_def_id, *var_hir_id);
+                    let place = self.place_for_root_variable(closure_def_id, *var_hir_id);
 
                     debug!("seed place {:?}", place);
 
@@ -333,7 +330,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     // Returns a list of `Ty`s for each upvar.
-    fn final_upvar_tys(&self, closure_id: DefId) -> Vec<Ty<'tcx>> {
+    fn final_upvar_tys(&self, closure_id: LocalDefId) -> Vec<Ty<'tcx>> {
         self.typeck_results
             .borrow()
             .closure_min_captures_flattened(closure_id)
@@ -511,7 +508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// ```
     fn compute_min_captures(
         &self,
-        closure_def_id: DefId,
+        closure_def_id: LocalDefId,
         capture_information: InferredCaptureInformation<'tcx>,
         closure_span: Span,
     ) {
@@ -730,7 +727,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// `disjoint_capture_drop_reorder` if needed.
     fn perform_2229_migration_anaysis(
         &self,
-        closure_def_id: DefId,
+        closure_def_id: LocalDefId,
         body_id: hir::BodyId,
         capture_clause: hir::CaptureBy,
         span: Span,
@@ -746,8 +743,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let (migration_string, migrated_variables_concat) =
                 migration_suggestion_for_2229(self.tcx, &need_migrations);
 
-            let closure_hir_id =
-                self.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
+            let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id);
             let closure_head_span = self.tcx.def_span(closure_def_id);
             self.tcx.struct_span_lint_hir(
                 lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
@@ -1058,7 +1054,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn compute_2229_migrations_for_drop(
         &self,
-        closure_def_id: DefId,
+        closure_def_id: LocalDefId,
         closure_span: Span,
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
         closure_clause: hir::CaptureBy,
@@ -1066,7 +1062,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Option<FxHashSet<UpvarMigrationInfo>> {
         let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id));
 
-        if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) {
+        if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id)) {
             debug!("does not have significant drop");
             return None;
         }
@@ -1160,7 +1156,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn compute_2229_migrations(
         &self,
-        closure_def_id: DefId,
+        closure_def_id: LocalDefId,
         closure_span: Span,
         closure_clause: hir::CaptureBy,
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
@@ -1343,14 +1339,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// implements Drop which will be affected since `y` isn't completely captured.
     fn has_significant_drop_outside_of_captures(
         &self,
-        closure_def_id: DefId,
+        closure_def_id: LocalDefId,
         closure_span: Span,
         base_path_ty: Ty<'tcx>,
         captured_by_move_projs: Vec<&[Projection<'tcx>]>,
     ) -> bool {
-        let needs_drop = |ty: Ty<'tcx>| {
-            ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local()))
-        };
+        let needs_drop =
+            |ty: Ty<'tcx>| ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id));
 
         let is_drop_defined_for_ty = |ty: Ty<'tcx>| {
             let drop_trait = self.tcx.require_lang_item(hir::LangItem::Drop, Some(closure_span));
@@ -1360,7 +1355,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     drop_trait,
                     ty,
                     ty_params,
-                    self.tcx.param_env(closure_def_id.expect_local()),
+                    self.tcx.param_env(closure_def_id),
                 )
                 .must_apply_modulo_regions()
         };
@@ -1518,13 +1513,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    fn should_log_capture_analysis(&self, closure_def_id: DefId) -> bool {
-        self.tcx.has_attr(closure_def_id, sym::rustc_capture_analysis)
+    fn should_log_capture_analysis(&self, closure_def_id: LocalDefId) -> bool {
+        self.tcx.has_attr(closure_def_id.to_def_id(), sym::rustc_capture_analysis)
     }
 
     fn log_capture_analysis_first_pass(
         &self,
-        closure_def_id: rustc_hir::def_id::DefId,
+        closure_def_id: LocalDefId,
         capture_information: &InferredCaptureInformation<'tcx>,
         closure_span: Span,
     ) {
@@ -1543,7 +1538,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    fn log_closure_min_capture_info(&self, closure_def_id: DefId, closure_span: Span) {
+    fn log_closure_min_capture_info(&self, closure_def_id: LocalDefId, closure_span: Span) {
         if self.should_log_capture_analysis(closure_def_id) {
             if let Some(min_captures) =
                 self.typeck_results.borrow().closure_min_captures.get(&closure_def_id)
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index faab862cc3c..95f32711225 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -977,11 +977,14 @@ fn check_associated_item(
         let item = tcx.associated_item(item_id);
 
         let (mut implied_bounds, self_ty) = match item.container {
-            ty::TraitContainer(_) => (FxHashSet::default(), tcx.types.self_param),
-            ty::ImplContainer(def_id) => (
-                impl_implied_bounds(tcx, wfcx.param_env, def_id.expect_local(), span),
-                tcx.type_of(def_id),
-            ),
+            ty::TraitContainer => (FxHashSet::default(), tcx.types.self_param),
+            ty::ImplContainer => {
+                let def_id = item.container_id(tcx);
+                (
+                    impl_implied_bounds(tcx, wfcx.param_env, def_id.expect_local(), span),
+                    tcx.type_of(def_id),
+                )
+            }
         };
 
         match item.kind {
@@ -1004,10 +1007,10 @@ fn check_associated_item(
                 check_method_receiver(wfcx, hir_sig, item, self_ty);
             }
             ty::AssocKind::Type => {
-                if let ty::AssocItemContainer::TraitContainer(_) = item.container {
+                if let ty::AssocItemContainer::TraitContainer = item.container {
                     check_associated_type_bounds(wfcx, item, span)
                 }
-                if item.defaultness.has_value() {
+                if item.defaultness(tcx).has_value() {
                     let ty = tcx.type_of(item.def_id);
                     let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
                     wfcx.register_wf_obligation(span, loc, ty.into());
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index fa6053ac395..f549807c39c 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -8,7 +8,6 @@ use hir::def_id::LocalDefId;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc_infer::infer::InferCtxt;
@@ -348,14 +347,13 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
 
 impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     fn eval_closure_size(&mut self) {
-        let mut res: FxHashMap<DefId, ClosureSizeProfileData<'tcx>> = Default::default();
-        for (closure_def_id, data) in self.fcx.typeck_results.borrow().closure_size_eval.iter() {
-            let closure_hir_id =
-                self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local());
+        let mut res: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>> = Default::default();
+        for (&closure_def_id, data) in self.fcx.typeck_results.borrow().closure_size_eval.iter() {
+            let closure_hir_id = self.tcx().hir().local_def_id_to_hir_id(closure_def_id);
 
             let data = self.resolve(*data, &closure_hir_id);
 
-            res.insert(*closure_def_id, data);
+            res.insert(closure_def_id, data);
         }
 
         self.typeck_results.closure_size_eval = res;
@@ -365,7 +363,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             self.fcx.typeck_results.borrow().closure_min_captures.len(),
             Default::default(),
         );
-        for (closure_def_id, root_min_captures) in
+        for (&closure_def_id, root_min_captures) in
             self.fcx.typeck_results.borrow().closure_min_captures.iter()
         {
             let mut root_var_map_wb = ty::RootVariableMinCaptureList::with_capacity_and_hasher(
@@ -377,7 +375,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                     .iter()
                     .map(|captured_place| {
                         let locatable = captured_place.info.path_expr_id.unwrap_or_else(|| {
-                            self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local())
+                            self.tcx().hir().local_def_id_to_hir_id(closure_def_id)
                         });
 
                         self.resolve(captured_place.clone(), &locatable)
@@ -385,7 +383,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                     .collect();
                 root_var_map_wb.insert(*var_hir_id, min_list_wb);
             }
-            min_captures_wb.insert(*closure_def_id, root_var_map_wb);
+            min_captures_wb.insert(closure_def_id, root_var_map_wb);
         }
 
         self.typeck_results.closure_min_captures = min_captures_wb;
@@ -393,21 +391,20 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
     fn visit_fake_reads_map(&mut self) {
         let mut resolved_closure_fake_reads: FxHashMap<
-            DefId,
+            LocalDefId,
             Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>,
         > = Default::default();
-        for (closure_def_id, fake_reads) in
+        for (&closure_def_id, fake_reads) in
             self.fcx.typeck_results.borrow().closure_fake_reads.iter()
         {
             let mut resolved_fake_reads = Vec::<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>::new();
             for (place, cause, hir_id) in fake_reads.iter() {
-                let locatable =
-                    self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local());
+                let locatable = self.tcx().hir().local_def_id_to_hir_id(closure_def_id);
 
                 let resolved_fake_read = self.resolve(place.clone(), &locatable);
                 resolved_fake_reads.push((resolved_fake_read, *cause, *hir_id));
             }
-            resolved_closure_fake_reads.insert(*closure_def_id, resolved_fake_reads);
+            resolved_closure_fake_reads.insert(closure_def_id, resolved_fake_reads);
         }
         self.typeck_results.closure_fake_reads = resolved_closure_fake_reads;
     }
diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs
index 1e404fda035..c23cbd71723 100644
--- a/compiler/rustc_typeck/src/coherence/builtin.rs
+++ b/compiler/rustc_typeck/src/coherence/builtin.rs
@@ -94,14 +94,6 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
 
             // We'll try to suggest constraining type parameters to fulfill the requirements of
             // their `Copy` implementation.
-            let mut generics = None;
-            if let ty::Adt(def, _substs) = self_type.kind() {
-                let self_def_id = def.did();
-                if let Some(local) = self_def_id.as_local() {
-                    let self_item = tcx.hir().expect_item(local);
-                    generics = self_item.kind.generics();
-                }
-            }
             let mut errors: BTreeMap<_, Vec<_>> = Default::default();
             let mut bounds = vec![];
 
@@ -163,16 +155,14 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
                     &format!("the `Copy` impl for `{}` requires that `{}`", ty, error_predicate),
                 );
             }
-            if let Some(generics) = generics {
-                suggest_constraining_type_params(
-                    tcx,
-                    generics,
-                    &mut err,
-                    bounds.iter().map(|(param, constraint, def_id)| {
-                        (param.as_str(), constraint.as_str(), *def_id)
-                    }),
-                );
-            }
+            suggest_constraining_type_params(
+                tcx,
+                tcx.hir().get_generics(impl_did).expect("impls always have generics"),
+                &mut err,
+                bounds.iter().map(|(param, constraint, def_id)| {
+                    (param.as_str(), constraint.as_str(), *def_id)
+                }),
+            );
             err.emit();
         }
         Err(CopyImplementationError::NotAnAdt) => {
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 36111637a56..99996e80c9c 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1234,7 +1234,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
 
                 match item {
                     Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => {
-                        if !item.defaultness.has_value() {
+                        if !tcx.impl_defaultness(item.id.def_id).has_value() {
                             tcx.sess
                                 .struct_span_err(
                                     item.span,
@@ -2433,7 +2433,7 @@ fn explicit_predicates_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::Generic
             //   supertrait).
             if let ty::Projection(projection) = ty.kind() {
                 projection.substs == trait_identity_substs
-                    && tcx.associated_item(projection.item_def_id).container.id() == def_id
+                    && tcx.associated_item(projection.item_def_id).container_id(tcx) == def_id
             } else {
                 false
             }
@@ -3264,7 +3264,7 @@ fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<S
 /// applied to the method prototype.
 fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     if let Some(impl_item) = tcx.opt_associated_item(def_id)
-        && let ty::AssocItemContainer::ImplContainer(_) = impl_item.container
+        && let ty::AssocItemContainer::ImplContainer = impl_item.container
         && let Some(trait_item) = impl_item.trait_item_def_id
     {
         return tcx
diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs
index 8801d0260bf..0d2b75d3328 100644
--- a/compiler/rustc_typeck/src/collect/item_bounds.rs
+++ b/compiler/rustc_typeck/src/collect/item_bounds.rs
@@ -3,7 +3,7 @@ use crate::astconv::AstConv;
 use rustc_hir as hir;
 use rustc_infer::traits::util;
 use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, DefIdTree, TyCtxt};
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
 
@@ -30,7 +30,7 @@ fn associated_type_bounds<'tcx>(
     // Associated types are implicitly sized unless a `?Sized` bound is found
     <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span);
 
-    let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id();
+    let trait_def_id = tcx.parent(assoc_item_def_id);
     let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
 
     let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| {
diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs
index 9d7420acd26..74a5b6e42c3 100644
--- a/compiler/rustc_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_typeck/src/expr_use_visitor.rs
@@ -468,7 +468,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
             self.borrow_expr(discr, ty::ImmBorrow);
         } else {
             let closure_def_id = match discr_place.place.base {
-                PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()),
+                PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id),
                 _ => None,
             };
 
@@ -642,7 +642,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
 
     fn walk_arm(&mut self, discr_place: &PlaceWithHirId<'tcx>, arm: &hir::Arm<'_>) {
         let closure_def_id = match discr_place.place.base {
-            PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()),
+            PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id),
             _ => None,
         };
 
@@ -666,7 +666,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
     /// let binding, and *not* a match arm or nested pat.)
     fn walk_irrefutable_pat(&mut self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>) {
         let closure_def_id = match discr_place.place.base {
-            PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()),
+            PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id),
             _ => None,
         };
 
@@ -763,7 +763,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
         debug!("walk_captures({:?})", closure_expr);
 
         let tcx = self.tcx();
-        let closure_def_id = tcx.hir().local_def_id(closure_expr.hir_id).to_def_id();
+        let closure_def_id = tcx.hir().local_def_id(closure_expr.hir_id);
         let upvars = tcx.upvars_mentioned(self.body_owner);
 
         // For purposes of this function, generator and closures are equivalent.
diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs
index 8c26c96816d..9fee1eaaec9 100644
--- a/compiler/rustc_typeck/src/impl_wf_check.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check.rs
@@ -106,7 +106,7 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
             let item = tcx.associated_item(def_id);
             match item.kind {
                 ty::AssocKind::Type => {
-                    if item.defaultness.has_value() {
+                    if item.defaultness(tcx).has_value() {
                         cgp::parameters_for(&tcx.type_of(def_id), true)
                     } else {
                         Vec::new()
diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs
index 257a9520eeb..3b779280eda 100644
--- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs
@@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
 use rustc_span::Span;
 
 use super::explicit::ExplicitPredicatesMap;
@@ -202,7 +202,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                 debug!("Projection");
                 check_explicit_predicates(
                     tcx,
-                    tcx.associated_item(obj.item_def_id).container.id(),
+                    tcx.parent(obj.item_def_id),
                     obj.substs,
                     required_predicates,
                     explicit_map,
diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs
index 057e47bfdd1..a596592311a 100644
--- a/library/panic_unwind/src/gcc.rs
+++ b/library/panic_unwind/src/gcc.rs
@@ -306,7 +306,9 @@ unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> Result<EHAction,
     let eh_context = EHContext {
         // The return address points 1 byte past the call instruction,
         // which could be in the next IP range in LSDA range table.
-        ip: if ip_before_instr != 0 { ip } else { ip - 1 },
+        //
+        // `ip = -1` has special meaning, so use wrapping sub to allow for that
+        ip: if ip_before_instr != 0 { ip } else { ip.wrapping_sub(1) },
         func_start: uw::_Unwind_GetRegionStart(context),
         get_text_start: &|| uw::_Unwind_GetTextRelBase(context),
         get_data_start: &|| uw::_Unwind_GetDataRelBase(context),
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index ff7b70c328d..722df119d22 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -260,20 +260,6 @@ pub trait Error: Debug + Display {
         TypeId::of::<Self>()
     }
 
-    /// Returns a stack backtrace, if available, of where this error occurred.
-    ///
-    /// This function allows inspecting the location, in code, of where an error
-    /// happened. The returned `Backtrace` contains information about the stack
-    /// trace of the OS thread of execution of where the error originated from.
-    ///
-    /// Note that not all errors contain a `Backtrace`. Also note that a
-    /// `Backtrace` may actually be empty. For more information consult the
-    /// `Backtrace` type itself.
-    #[unstable(feature = "backtrace", issue = "53487")]
-    fn backtrace(&self) -> Option<&Backtrace> {
-        None
-    }
-
     /// ```
     /// if let Err(e) = "xc".parse::<u32>() {
     ///     // Print `e` itself, no need for description().
@@ -370,7 +356,7 @@ pub trait Error: Debug + Display {
 }
 
 #[unstable(feature = "error_generic_member_access", issue = "99301")]
-impl Provider for dyn Error + 'static {
+impl<'b> Provider for dyn Error + 'b {
     fn provide<'a>(&'a self, req: &mut Demand<'a>) {
         self.provide(req)
     }
@@ -757,8 +743,8 @@ impl<'a, T: Error + ?Sized> Error for &'a T {
         Error::source(&**self)
     }
 
-    fn backtrace(&self) -> Option<&Backtrace> {
-        Error::backtrace(&**self)
+    fn provide<'b>(&'b self, req: &mut Demand<'b>) {
+        Error::provide(&**self, req);
     }
 }
 
@@ -778,8 +764,8 @@ impl<T: Error + ?Sized> Error for Arc<T> {
         Error::source(&**self)
     }
 
-    fn backtrace(&self) -> Option<&Backtrace> {
-        Error::backtrace(&**self)
+    fn provide<'a>(&'a self, req: &mut Demand<'a>) {
+        Error::provide(&**self, req);
     }
 }
 
@@ -871,6 +857,20 @@ impl Error for alloc::ffi::IntoStringError {
     }
 }
 
+impl<'a> dyn Error + 'a {
+    /// Request a reference of type `T` as context about this error.
+    #[unstable(feature = "error_generic_member_access", issue = "99301")]
+    pub fn request_ref<T: ?Sized + 'static>(&'a self) -> Option<&'a T> {
+        core::any::request_ref(self)
+    }
+
+    /// Request a value of type `T` as context about this error.
+    #[unstable(feature = "error_generic_member_access", issue = "99301")]
+    pub fn request_value<T: 'static>(&'a self) -> Option<T> {
+        core::any::request_value(self)
+    }
+}
+
 // Copied from `any.rs`.
 impl dyn Error + 'static {
     /// Returns `true` if the inner type is the same as `T`.
@@ -910,18 +910,6 @@ impl dyn Error + 'static {
             None
         }
     }
-
-    /// Request a reference of type `T` as context about this error.
-    #[unstable(feature = "error_generic_member_access", issue = "99301")]
-    pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
-        core::any::request_ref(self)
-    }
-
-    /// Request a value of type `T` as context about this error.
-    #[unstable(feature = "error_generic_member_access", issue = "99301")]
-    pub fn request_value<T: 'static>(&self) -> Option<T> {
-        core::any::request_value(self)
-    }
 }
 
 impl dyn Error + 'static + Send {
@@ -949,13 +937,13 @@ impl dyn Error + 'static + Send {
     /// Request a reference of type `T` as context about this error.
     #[unstable(feature = "error_generic_member_access", issue = "99301")]
     pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
-        <dyn Error + 'static>::request_ref(self)
+        <dyn Error>::request_ref(self)
     }
 
     /// Request a value of type `T` as context about this error.
     #[unstable(feature = "error_generic_member_access", issue = "99301")]
     pub fn request_value<T: 'static>(&self) -> Option<T> {
-        <dyn Error + 'static>::request_value(self)
+        <dyn Error>::request_value(self)
     }
 }
 
@@ -984,13 +972,13 @@ impl dyn Error + 'static + Send + Sync {
     /// Request a reference of type `T` as context about this error.
     #[unstable(feature = "error_generic_member_access", issue = "99301")]
     pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
-        <dyn Error + 'static>::request_ref(self)
+        <dyn Error>::request_ref(self)
     }
 
     /// Request a value of type `T` as context about this error.
     #[unstable(feature = "error_generic_member_access", issue = "99301")]
     pub fn request_value<T: 'static>(&self) -> Option<T> {
-        <dyn Error + 'static>::request_value(self)
+        <dyn Error>::request_value(self)
     }
 }
 
@@ -1467,8 +1455,11 @@ impl<E> Report<E> {
     /// ```rust
     /// #![feature(error_reporter)]
     /// #![feature(backtrace)]
+    /// #![feature(provide_any)]
+    /// #![feature(error_generic_member_access)]
     /// # use std::error::Error;
     /// # use std::fmt;
+    /// use std::any::Demand;
     /// use std::error::Report;
     /// use std::backtrace::Backtrace;
     ///
@@ -1498,8 +1489,9 @@ impl<E> Report<E> {
     /// }
     ///
     /// impl Error for SuperErrorSideKick {
-    ///     fn backtrace(&self) -> Option<&Backtrace> {
-    ///         Some(&self.backtrace)
+    ///     fn provide<'a>(&'a self, req: &mut Demand<'a>) {
+    ///         req
+    ///             .provide_ref::<Backtrace>(&self.backtrace);
     ///     }
     /// }
     ///
@@ -1552,11 +1544,11 @@ where
     fn backtrace(&self) -> Option<&Backtrace> {
         // have to grab the backtrace on the first error directly since that error may not be
         // 'static
-        let backtrace = self.error.backtrace();
+        let backtrace = (&self.error as &dyn Error).request_ref();
         let backtrace = backtrace.or_else(|| {
             self.error
                 .source()
-                .map(|source| source.chain().find_map(|source| source.backtrace()))
+                .map(|source| source.chain().find_map(|source| source.request_ref()))
                 .flatten()
         });
         backtrace
@@ -1618,11 +1610,11 @@ impl Report<Box<dyn Error>> {
     fn backtrace(&self) -> Option<&Backtrace> {
         // have to grab the backtrace on the first error directly since that error may not be
         // 'static
-        let backtrace = self.error.backtrace();
+        let backtrace = self.error.request_ref();
         let backtrace = backtrace.or_else(|| {
             self.error
                 .source()
-                .map(|source| source.chain().find_map(|source| source.backtrace()))
+                .map(|source| source.chain().find_map(|source| source.request_ref()))
                 .flatten()
         });
         backtrace
diff --git a/library/std/src/error/tests.rs b/library/std/src/error/tests.rs
index a2a35d96ec9..ee999bd65c3 100644
--- a/library/std/src/error/tests.rs
+++ b/library/std/src/error/tests.rs
@@ -1,5 +1,6 @@
 use super::Error;
 use crate::fmt;
+use core::any::Demand;
 
 #[derive(Debug, PartialEq)]
 struct A;
@@ -198,8 +199,8 @@ where
         self.source.as_deref()
     }
 
-    fn backtrace(&self) -> Option<&Backtrace> {
-        self.backtrace.as_ref()
+    fn provide<'a>(&'a self, req: &mut Demand<'a>) {
+        self.backtrace.as_ref().map(|bt| req.provide_ref::<Backtrace>(bt));
     }
 }
 
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index d799776548a..c8e131b6ee1 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -184,6 +184,11 @@ pub struct DirEntry(fs_imp::DirEntry);
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct OpenOptions(fs_imp::OpenOptions);
 
+/// Representation of the various timestamps on a file.
+#[derive(Copy, Clone, Debug, Default)]
+#[unstable(feature = "file_set_times", issue = "98245")]
+pub struct FileTimes(fs_imp::FileTimes);
+
 /// Representation of the various permissions on a file.
 ///
 /// This module only currently provides one bit of information,
@@ -596,6 +601,58 @@ impl File {
     pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
         self.inner.set_permissions(perm.0)
     }
+
+    /// Changes the timestamps of the underlying file.
+    ///
+    /// # Platform-specific behavior
+    ///
+    /// This function currently corresponds to the `futimens` function on Unix (falling back to
+    /// `futimes` on macOS before 10.13) and the `SetFileTime` function on Windows. Note that this
+    /// [may change in the future][changes].
+    ///
+    /// [changes]: io#platform-specific-behavior
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if the user lacks permission to change timestamps on the
+    /// underlying file. It may also return an error in other os-specific unspecified cases.
+    ///
+    /// This function may return an error if the operating system lacks support to change one or
+    /// more of the timestamps set in the `FileTimes` structure.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(file_set_times)]
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     use std::fs::{self, File, FileTimes};
+    ///
+    ///     let src = fs::metadata("src")?;
+    ///     let dest = File::options().write(true).open("dest")?;
+    ///     let times = FileTimes::new()
+    ///         .set_accessed(src.accessed()?)
+    ///         .set_modified(src.modified()?);
+    ///     dest.set_times(times)?;
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    #[doc(alias = "futimens")]
+    #[doc(alias = "futimes")]
+    #[doc(alias = "SetFileTime")]
+    pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
+        self.inner.set_times(times.0)
+    }
+
+    /// Changes the modification time of the underlying file.
+    ///
+    /// This is an alias for `set_times(FileTimes::new().set_modified(time))`.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    #[inline]
+    pub fn set_modified(&self, time: SystemTime) -> io::Result<()> {
+        self.set_times(FileTimes::new().set_modified(time))
+    }
 }
 
 // In addition to the `impl`s here, `File` also has `impl`s for
@@ -1252,6 +1309,30 @@ impl FromInner<fs_imp::FileAttr> for Metadata {
     }
 }
 
+impl FileTimes {
+    /// Create a new `FileTimes` with no times set.
+    ///
+    /// Using the resulting `FileTimes` in [`File::set_times`] will not modify any timestamps.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    pub fn new() -> Self {
+        Self::default()
+    }
+
+    /// Set the last access time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    pub fn set_accessed(mut self, t: SystemTime) -> Self {
+        self.0.set_accessed(t.into_inner());
+        self
+    }
+
+    /// Set the last modified time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    pub fn set_modified(mut self, t: SystemTime) -> Self {
+        self.0.set_modified(t.into_inner());
+        self
+    }
+}
+
 impl Permissions {
     /// Returns `true` if these permissions describe a readonly (unwritable) file.
     ///
diff --git a/library/std/src/net/addr.rs b/library/std/src/net/addr.rs
index 81dd042425c..53fee952a7a 100644
--- a/library/std/src/net/addr.rs
+++ b/library/std/src/net/addr.rs
@@ -7,12 +7,12 @@ use crate::hash;
 use crate::io::{self, Write};
 use crate::iter;
 use crate::mem;
-use crate::net::{htons, ntohs, IpAddr, Ipv4Addr, Ipv6Addr};
+use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr};
 use crate::option;
 use crate::slice;
 use crate::sys::net::netc as c;
 use crate::sys_common::net::LookupHost;
-use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::sys_common::{FromInner, IntoInner};
 use crate::vec;
 
 /// An internet socket address, either IPv4 or IPv6.
@@ -73,12 +73,11 @@ pub enum SocketAddr {
 /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
 /// assert_eq!(socket.port(), 8080);
 /// ```
-#[derive(Copy)]
+#[derive(Copy, Clone, Eq, PartialEq)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SocketAddrV4 {
-    // Do not assume that this struct is implemented as the underlying system representation.
-    // The memory layout is not part of the stable interface that std exposes.
-    inner: c::sockaddr_in,
+    ip: Ipv4Addr,
+    port: u16,
 }
 
 /// An IPv6 socket address.
@@ -107,12 +106,13 @@ pub struct SocketAddrV4 {
 /// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
 /// assert_eq!(socket.port(), 8080);
 /// ```
-#[derive(Copy)]
+#[derive(Copy, Clone, Eq, PartialEq)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SocketAddrV6 {
-    // Do not assume that this struct is implemented as the underlying system representation.
-    // The memory layout is not part of the stable interface that std exposes.
-    inner: c::sockaddr_in6,
+    ip: Ipv6Addr,
+    port: u16,
+    flowinfo: u32,
+    scope_id: u32,
 }
 
 impl SocketAddr {
@@ -131,7 +131,8 @@ impl SocketAddr {
     /// ```
     #[stable(feature = "ip_addr", since = "1.7.0")]
     #[must_use]
-    pub fn new(ip: IpAddr, port: u16) -> SocketAddr {
+    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    pub const fn new(ip: IpAddr, port: u16) -> SocketAddr {
         match ip {
             IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)),
             IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)),
@@ -277,15 +278,9 @@ impl SocketAddrV4 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
-    pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
-        SocketAddrV4 {
-            inner: c::sockaddr_in {
-                sin_family: c::AF_INET as c::sa_family_t,
-                sin_port: htons(port),
-                sin_addr: ip.into_inner(),
-                ..unsafe { mem::zeroed() }
-            },
-        }
+    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    pub const fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
+        SocketAddrV4 { ip, port }
     }
 
     /// Returns the IP address associated with this socket address.
@@ -302,9 +297,7 @@ impl SocketAddrV4 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
     pub const fn ip(&self) -> &Ipv4Addr {
-        // SAFETY: `Ipv4Addr` is `#[repr(C)] struct { _: in_addr; }`.
-        // It is safe to cast from `&in_addr` to `&Ipv4Addr`.
-        unsafe { &*(&self.inner.sin_addr as *const c::in_addr as *const Ipv4Addr) }
+        &self.ip
     }
 
     /// Changes the IP address associated with this socket address.
@@ -320,7 +313,7 @@ impl SocketAddrV4 {
     /// ```
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
     pub fn set_ip(&mut self, new_ip: Ipv4Addr) {
-        self.inner.sin_addr = new_ip.into_inner()
+        self.ip = new_ip;
     }
 
     /// Returns the port number associated with this socket address.
@@ -337,7 +330,7 @@ impl SocketAddrV4 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
     pub const fn port(&self) -> u16 {
-        ntohs(self.inner.sin_port)
+        self.port
     }
 
     /// Changes the port number associated with this socket address.
@@ -353,7 +346,7 @@ impl SocketAddrV4 {
     /// ```
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
     pub fn set_port(&mut self, new_port: u16) {
-        self.inner.sin_port = htons(new_port);
+        self.port = new_port;
     }
 }
 
@@ -376,17 +369,9 @@ impl SocketAddrV6 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
-    pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 {
-        SocketAddrV6 {
-            inner: c::sockaddr_in6 {
-                sin6_family: c::AF_INET6 as c::sa_family_t,
-                sin6_port: htons(port),
-                sin6_addr: *ip.as_inner(),
-                sin6_flowinfo: flowinfo,
-                sin6_scope_id: scope_id,
-                ..unsafe { mem::zeroed() }
-            },
-        }
+    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 {
+        SocketAddrV6 { ip, port, flowinfo, scope_id }
     }
 
     /// Returns the IP address associated with this socket address.
@@ -403,7 +388,7 @@ impl SocketAddrV6 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
     pub const fn ip(&self) -> &Ipv6Addr {
-        unsafe { &*(&self.inner.sin6_addr as *const c::in6_addr as *const Ipv6Addr) }
+        &self.ip
     }
 
     /// Changes the IP address associated with this socket address.
@@ -419,7 +404,7 @@ impl SocketAddrV6 {
     /// ```
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
     pub fn set_ip(&mut self, new_ip: Ipv6Addr) {
-        self.inner.sin6_addr = *new_ip.as_inner()
+        self.ip = new_ip;
     }
 
     /// Returns the port number associated with this socket address.
@@ -436,7 +421,7 @@ impl SocketAddrV6 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
     pub const fn port(&self) -> u16 {
-        ntohs(self.inner.sin6_port)
+        self.port
     }
 
     /// Changes the port number associated with this socket address.
@@ -452,7 +437,7 @@ impl SocketAddrV6 {
     /// ```
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
     pub fn set_port(&mut self, new_port: u16) {
-        self.inner.sin6_port = htons(new_port);
+        self.port = new_port;
     }
 
     /// Returns the flow information associated with this address.
@@ -479,7 +464,7 @@ impl SocketAddrV6 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
     pub const fn flowinfo(&self) -> u32 {
-        self.inner.sin6_flowinfo
+        self.flowinfo
     }
 
     /// Changes the flow information associated with this socket address.
@@ -497,7 +482,7 @@ impl SocketAddrV6 {
     /// ```
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
     pub fn set_flowinfo(&mut self, new_flowinfo: u32) {
-        self.inner.sin6_flowinfo = new_flowinfo;
+        self.flowinfo = new_flowinfo;
     }
 
     /// Returns the scope ID associated with this address.
@@ -519,7 +504,7 @@ impl SocketAddrV6 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
     pub const fn scope_id(&self) -> u32 {
-        self.inner.sin6_scope_id
+        self.scope_id
     }
 
     /// Changes the scope ID associated with this socket address.
@@ -537,19 +522,48 @@ impl SocketAddrV6 {
     /// ```
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
     pub fn set_scope_id(&mut self, new_scope_id: u32) {
-        self.inner.sin6_scope_id = new_scope_id;
+        self.scope_id = new_scope_id;
     }
 }
 
 impl FromInner<c::sockaddr_in> for SocketAddrV4 {
     fn from_inner(addr: c::sockaddr_in) -> SocketAddrV4 {
-        SocketAddrV4 { inner: addr }
+        SocketAddrV4 { ip: Ipv4Addr::from_inner(addr.sin_addr), port: u16::from_be(addr.sin_port) }
     }
 }
 
 impl FromInner<c::sockaddr_in6> for SocketAddrV6 {
     fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 {
-        SocketAddrV6 { inner: addr }
+        SocketAddrV6 {
+            ip: Ipv6Addr::from_inner(addr.sin6_addr),
+            port: u16::from_be(addr.sin6_port),
+            flowinfo: addr.sin6_flowinfo,
+            scope_id: addr.sin6_scope_id,
+        }
+    }
+}
+
+impl IntoInner<c::sockaddr_in> for SocketAddrV4 {
+    fn into_inner(self) -> c::sockaddr_in {
+        c::sockaddr_in {
+            sin_family: c::AF_INET as c::sa_family_t,
+            sin_port: self.port.to_be(),
+            sin_addr: self.ip.into_inner(),
+            ..unsafe { mem::zeroed() }
+        }
+    }
+}
+
+impl IntoInner<c::sockaddr_in6> for SocketAddrV6 {
+    fn into_inner(self) -> c::sockaddr_in6 {
+        c::sockaddr_in6 {
+            sin6_family: c::AF_INET6 as c::sa_family_t,
+            sin6_port: self.port.to_be(),
+            sin6_addr: self.ip.into_inner(),
+            sin6_flowinfo: self.flowinfo,
+            sin6_scope_id: self.scope_id,
+            ..unsafe { mem::zeroed() }
+        }
     }
 }
 
@@ -582,19 +596,6 @@ impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
     }
 }
 
-impl<'a> IntoInner<(*const c::sockaddr, c::socklen_t)> for &'a SocketAddr {
-    fn into_inner(self) -> (*const c::sockaddr, c::socklen_t) {
-        match *self {
-            SocketAddr::V4(ref a) => {
-                (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t)
-            }
-            SocketAddr::V6(ref a) => {
-                (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t)
-            }
-        }
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for SocketAddr {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -688,40 +689,6 @@ impl fmt::Debug for SocketAddrV6 {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Clone for SocketAddrV4 {
-    fn clone(&self) -> SocketAddrV4 {
-        *self
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Clone for SocketAddrV6 {
-    fn clone(&self) -> SocketAddrV6 {
-        *self
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl PartialEq for SocketAddrV4 {
-    fn eq(&self, other: &SocketAddrV4) -> bool {
-        self.inner.sin_port == other.inner.sin_port
-            && self.inner.sin_addr.s_addr == other.inner.sin_addr.s_addr
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl PartialEq for SocketAddrV6 {
-    fn eq(&self, other: &SocketAddrV6) -> bool {
-        self.inner.sin6_port == other.inner.sin6_port
-            && self.inner.sin6_addr.s6_addr == other.inner.sin6_addr.s6_addr
-            && self.inner.sin6_flowinfo == other.inner.sin6_flowinfo
-            && self.inner.sin6_scope_id == other.inner.sin6_scope_id
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Eq for SocketAddrV4 {}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Eq for SocketAddrV6 {}
-
 #[stable(feature = "socketaddr_ordering", since = "1.45.0")]
 impl PartialOrd for SocketAddrV4 {
     fn partial_cmp(&self, other: &SocketAddrV4) -> Option<Ordering> {
@@ -753,19 +720,13 @@ impl Ord for SocketAddrV6 {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl hash::Hash for SocketAddrV4 {
     fn hash<H: hash::Hasher>(&self, s: &mut H) {
-        (self.inner.sin_port, self.inner.sin_addr.s_addr).hash(s)
+        (self.port, self.ip).hash(s)
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl hash::Hash for SocketAddrV6 {
     fn hash<H: hash::Hasher>(&self, s: &mut H) {
-        (
-            self.inner.sin6_port,
-            &self.inner.sin6_addr.s6_addr,
-            self.inner.sin6_flowinfo,
-            self.inner.sin6_scope_id,
-        )
-            .hash(s)
+        (self.port, &self.ip, self.flowinfo, self.scope_id).hash(s)
     }
 }
 
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index 438bae01b60..41ca9ba8425 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -4,20 +4,16 @@ mod tests;
 
 use crate::cmp::Ordering;
 use crate::fmt::{self, Write as FmtWrite};
-use crate::hash;
 use crate::io::Write as IoWrite;
 use crate::mem::transmute;
 use crate::sys::net::netc as c;
-use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::sys_common::{FromInner, IntoInner};
 
 /// An IP address, either IPv4 or IPv6.
 ///
 /// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
 /// respective documentation for more details.
 ///
-/// The size of an `IpAddr` instance may vary depending on the target operating
-/// system.
-///
 /// # Examples
 ///
 /// ```
@@ -50,9 +46,6 @@ pub enum IpAddr {
 ///
 /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
 ///
-/// The size of an `Ipv4Addr` struct may vary depending on the target operating
-/// system.
-///
 /// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
 ///
 /// # Textual representation
@@ -77,10 +70,10 @@ pub enum IpAddr {
 /// assert!("0000000.0.0.0".parse::<Ipv4Addr>().is_err()); // first octet is a zero in octal
 /// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex
 /// ```
-#[derive(Copy)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Ipv4Addr {
-    inner: c::in_addr,
+    octets: [u8; 4],
 }
 
 /// An IPv6 address.
@@ -88,9 +81,6 @@ pub struct Ipv4Addr {
 /// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
 /// They are usually represented as eight 16-bit segments.
 ///
-/// The size of an `Ipv6Addr` struct may vary depending on the target operating
-/// system.
-///
 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
 ///
 /// # Embedding IPv4 Addresses
@@ -162,10 +152,10 @@ pub struct Ipv4Addr {
 /// assert_eq!("::1".parse(), Ok(localhost));
 /// assert_eq!(localhost.is_loopback(), true);
 /// ```
-#[derive(Copy)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Ipv6Addr {
-    inner: c::in6_addr,
+    octets: [u8; 16],
 }
 
 /// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2].
@@ -461,9 +451,7 @@ impl Ipv4Addr {
     #[must_use]
     #[inline]
     pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
-        // `s_addr` is stored as BE on all machine and the array is in BE order.
-        // So the native endian conversion method is used so that it's never swapped.
-        Ipv4Addr { inner: c::in_addr { s_addr: u32::from_ne_bytes([a, b, c, d]) } }
+        Ipv4Addr { octets: [a, b, c, d] }
     }
 
     /// An IPv4 address with the address pointing to localhost: `127.0.0.1`
@@ -523,8 +511,7 @@ impl Ipv4Addr {
     #[must_use]
     #[inline]
     pub const fn octets(&self) -> [u8; 4] {
-        // This returns the order we want because s_addr is stored in big-endian.
-        self.inner.s_addr.to_ne_bytes()
+        self.octets
     }
 
     /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`).
@@ -547,7 +534,7 @@ impl Ipv4Addr {
     #[must_use]
     #[inline]
     pub const fn is_unspecified(&self) -> bool {
-        self.inner.s_addr == 0
+        u32::from_be_bytes(self.octets) == 0
     }
 
     /// Returns [`true`] if this is a loopback address (`127.0.0.0/8`).
@@ -910,9 +897,7 @@ impl Ipv4Addr {
     #[inline]
     pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
         let [a, b, c, d] = self.octets();
-        Ipv6Addr {
-            inner: c::in6_addr { s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] },
-        }
+        Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] }
     }
 
     /// Converts this address to an [IPv4-mapped] [`IPv6` address].
@@ -937,9 +922,7 @@ impl Ipv4Addr {
     #[inline]
     pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
         let [a, b, c, d] = self.octets();
-        Ipv6Addr {
-            inner: c::in6_addr { s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] },
-        }
+        Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] }
     }
 }
 
@@ -1034,22 +1017,6 @@ impl fmt::Debug for Ipv4Addr {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Clone for Ipv4Addr {
-    #[inline]
-    fn clone(&self) -> Ipv4Addr {
-        *self
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl PartialEq for Ipv4Addr {
-    #[inline]
-    fn eq(&self, other: &Ipv4Addr) -> bool {
-        self.inner.s_addr == other.inner.s_addr
-    }
-}
-
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialEq<Ipv4Addr> for IpAddr {
     #[inline]
@@ -1073,21 +1040,6 @@ impl PartialEq<IpAddr> for Ipv4Addr {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl Eq for Ipv4Addr {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl hash::Hash for Ipv4Addr {
-    #[inline]
-    fn hash<H: hash::Hasher>(&self, s: &mut H) {
-        // NOTE:
-        // * hash in big endian order
-        // * in netbsd, `in_addr` has `repr(packed)`, we need to
-        //   copy `s_addr` to avoid unsafe borrowing
-        { self.inner.s_addr }.hash(s)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
 impl PartialOrd for Ipv4Addr {
     #[inline]
     fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
@@ -1121,15 +1073,21 @@ impl PartialOrd<IpAddr> for Ipv4Addr {
 impl Ord for Ipv4Addr {
     #[inline]
     fn cmp(&self, other: &Ipv4Addr) -> Ordering {
-        // Compare as native endian
-        u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
+        self.octets.cmp(&other.octets)
     }
 }
 
 impl IntoInner<c::in_addr> for Ipv4Addr {
     #[inline]
     fn into_inner(self) -> c::in_addr {
-        self.inner
+        // `s_addr` is stored as BE on all machines and the array is in BE order.
+        // So the native endian conversion method is used so that it's never swapped.
+        c::in_addr { s_addr: u32::from_ne_bytes(self.octets) }
+    }
+}
+impl FromInner<c::in_addr> for Ipv4Addr {
+    fn from_inner(addr: c::in_addr) -> Ipv4Addr {
+        Ipv4Addr { octets: addr.s_addr.to_ne_bytes() }
     }
 }
 
@@ -1147,8 +1105,7 @@ impl From<Ipv4Addr> for u32 {
     /// ```
     #[inline]
     fn from(ip: Ipv4Addr) -> u32 {
-        let ip = ip.octets();
-        u32::from_be_bytes(ip)
+        u32::from_be_bytes(ip.octets)
     }
 }
 
@@ -1166,7 +1123,7 @@ impl From<u32> for Ipv4Addr {
     /// ```
     #[inline]
     fn from(ip: u32) -> Ipv4Addr {
-        Ipv4Addr::from(ip.to_be_bytes())
+        Ipv4Addr { octets: ip.to_be_bytes() }
     }
 }
 
@@ -1184,7 +1141,7 @@ impl From<[u8; 4]> for Ipv4Addr {
     /// ```
     #[inline]
     fn from(octets: [u8; 4]) -> Ipv4Addr {
-        Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
+        Ipv4Addr { octets }
     }
 }
 
@@ -1234,13 +1191,9 @@ impl Ipv6Addr {
             h.to_be(),
         ];
         Ipv6Addr {
-            inner: c::in6_addr {
-                // All elements in `addr16` are big endian.
-                // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
-                // rustc_allow_const_fn_unstable: the transmute could be written as stable const
-                // code, but that leads to worse code generation (#75085)
-                s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
-            },
+            // All elements in `addr16` are big endian.
+            // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
+            octets: unsafe { transmute::<_, [u8; 16]>(addr16) },
         }
     }
 
@@ -1285,11 +1238,9 @@ impl Ipv6Addr {
     #[must_use]
     #[inline]
     pub const fn segments(&self) -> [u16; 8] {
-        // All elements in `s6_addr` must be big endian.
+        // All elements in `self.octets` must be big endian.
         // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
-        // rustc_allow_const_fn_unstable: the transmute could be written as stable const code, but
-        // that leads to worse code generation (#75085)
-        let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
+        let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.octets) };
         // We want native endian u16
         [
             u16::from_be(a),
@@ -1748,7 +1699,7 @@ impl Ipv6Addr {
     #[must_use]
     #[inline]
     pub const fn octets(&self) -> [u8; 16] {
-        self.inner.s6_addr
+        self.octets
     }
 }
 
@@ -1856,22 +1807,6 @@ impl fmt::Debug for Ipv6Addr {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Clone for Ipv6Addr {
-    #[inline]
-    fn clone(&self) -> Ipv6Addr {
-        *self
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl PartialEq for Ipv6Addr {
-    #[inline]
-    fn eq(&self, other: &Ipv6Addr) -> bool {
-        self.inner.s6_addr == other.inner.s6_addr
-    }
-}
-
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialEq<IpAddr> for Ipv6Addr {
     #[inline]
@@ -1895,17 +1830,6 @@ impl PartialEq<Ipv6Addr> for IpAddr {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl Eq for Ipv6Addr {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl hash::Hash for Ipv6Addr {
-    #[inline]
-    fn hash<H: hash::Hasher>(&self, s: &mut H) {
-        self.inner.s6_addr.hash(s)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
 impl PartialOrd for Ipv6Addr {
     #[inline]
     fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
@@ -1943,16 +1867,15 @@ impl Ord for Ipv6Addr {
     }
 }
 
-impl AsInner<c::in6_addr> for Ipv6Addr {
-    #[inline]
-    fn as_inner(&self) -> &c::in6_addr {
-        &self.inner
+impl IntoInner<c::in6_addr> for Ipv6Addr {
+    fn into_inner(self) -> c::in6_addr {
+        c::in6_addr { s6_addr: self.octets }
     }
 }
 impl FromInner<c::in6_addr> for Ipv6Addr {
     #[inline]
     fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
-        Ipv6Addr { inner: addr }
+        Ipv6Addr { octets: addr.s6_addr }
     }
 }
 
@@ -1973,8 +1896,7 @@ impl From<Ipv6Addr> for u128 {
     /// ```
     #[inline]
     fn from(ip: Ipv6Addr) -> u128 {
-        let ip = ip.octets();
-        u128::from_be_bytes(ip)
+        u128::from_be_bytes(ip.octets)
     }
 }
 #[stable(feature = "i128", since = "1.26.0")]
@@ -2025,8 +1947,7 @@ impl From<[u8; 16]> for Ipv6Addr {
     /// ```
     #[inline]
     fn from(octets: [u8; 16]) -> Ipv6Addr {
-        let inner = c::in6_addr { s6_addr: octets };
-        Ipv6Addr::from_inner(inner)
+        Ipv6Addr { octets }
     }
 }
 
diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs
index 7956c6a25e4..c29509331d7 100644
--- a/library/std/src/net/ip/tests.rs
+++ b/library/std/src/net/ip/tests.rs
@@ -944,3 +944,26 @@ fn ip_const() {
     const IS_IP_V6: bool = IP_ADDRESS.is_ipv6();
     assert!(!IS_IP_V6);
 }
+
+#[test]
+fn structural_match() {
+    // test that all IP types can be structurally matched upon
+
+    const IPV4: Ipv4Addr = Ipv4Addr::LOCALHOST;
+    match IPV4 {
+        Ipv4Addr::LOCALHOST => {}
+        _ => unreachable!(),
+    }
+
+    const IPV6: Ipv6Addr = Ipv6Addr::LOCALHOST;
+    match IPV6 {
+        Ipv6Addr::LOCALHOST => {}
+        _ => unreachable!(),
+    }
+
+    const IP: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST);
+    match IP {
+        IpAddr::V4(Ipv4Addr::LOCALHOST) => {}
+        _ => unreachable!(),
+    }
+}
diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs
index 9ed4a98f943..e7a40bdaf8e 100644
--- a/library/std/src/net/mod.rs
+++ b/library/std/src/net/mod.rs
@@ -69,15 +69,6 @@ pub enum Shutdown {
     Both,
 }
 
-#[inline]
-const fn htons(i: u16) -> u16 {
-    i.to_be()
-}
-#[inline]
-const fn ntohs(i: u16) -> u16 {
-    u16::from_be(i)
-}
-
 fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
 where
     F: FnMut(io::Result<&SocketAddr>) -> io::Result<T>,
diff --git a/library/std/src/sys/sgx/net.rs b/library/std/src/sys/sgx/net.rs
index 1d899525081..4c4cd7d1d1d 100644
--- a/library/std/src/sys/sgx/net.rs
+++ b/library/std/src/sys/sgx/net.rs
@@ -538,6 +538,4 @@ pub mod netc {
 
     #[derive(Copy, Clone)]
     pub struct sockaddr {}
-
-    pub type socklen_t = usize;
 }
diff --git a/library/std/src/sys/solid/net.rs b/library/std/src/sys/solid/net.rs
index faeda5a854d..1b98ef993b0 100644
--- a/library/std/src/sys/solid/net.rs
+++ b/library/std/src/sys/solid/net.rs
@@ -230,8 +230,8 @@ impl Socket {
     pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
         self.set_nonblocking(true)?;
         let r = unsafe {
-            let (addrp, len) = addr.into_inner();
-            cvt(netc::connect(self.0.raw(), addrp, len))
+            let (addr, len) = addr.into_inner();
+            cvt(netc::connect(self.0.raw(), addr.as_ptr(), len))
         };
         self.set_nonblocking(false)?;
 
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 71522865b7d..41405cbf657 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -20,7 +20,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
     target_os = "watchos",
 ))]
 use crate::sys::weak::syscall;
-#[cfg(target_os = "macos")]
+#[cfg(any(target_os = "android", target_os = "macos"))]
 use crate::sys::weak::weak;
 
 use libc::{c_int, mode_t};
@@ -313,6 +313,9 @@ pub struct FilePermissions {
     mode: mode_t,
 }
 
+#[derive(Copy, Clone)]
+pub struct FileTimes([libc::timespec; 2]);
+
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct FileType {
     mode: mode_t,
@@ -507,6 +510,48 @@ impl FilePermissions {
     }
 }
 
+impl FileTimes {
+    pub fn set_accessed(&mut self, t: SystemTime) {
+        self.0[0] = t.t.to_timespec().expect("Invalid system time");
+    }
+
+    pub fn set_modified(&mut self, t: SystemTime) {
+        self.0[1] = t.t.to_timespec().expect("Invalid system time");
+    }
+}
+
+struct TimespecDebugAdapter<'a>(&'a libc::timespec);
+
+impl fmt::Debug for TimespecDebugAdapter<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("timespec")
+            .field("tv_sec", &self.0.tv_sec)
+            .field("tv_nsec", &self.0.tv_nsec)
+            .finish()
+    }
+}
+
+impl fmt::Debug for FileTimes {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("FileTimes")
+            .field("accessed", &TimespecDebugAdapter(&self.0[0]))
+            .field("modified", &TimespecDebugAdapter(&self.0[1]))
+            .finish()
+    }
+}
+
+impl Default for FileTimes {
+    fn default() -> Self {
+        // Redox doesn't appear to support `UTIME_OMIT`, so we stub it out here, and always return
+        // an error in `set_times`.
+        #[cfg(target_os = "redox")]
+        let omit = libc::timespec { tv_sec: 0, tv_nsec: 0 };
+        #[cfg(not(target_os = "redox"))]
+        let omit = libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ };
+        Self([omit; 2])
+    }
+}
+
 impl FileType {
     pub fn is_dir(&self) -> bool {
         self.is(libc::S_IFDIR)
@@ -1029,6 +1074,48 @@ impl File {
         cvt_r(|| unsafe { libc::fchmod(self.as_raw_fd(), perm.mode) })?;
         Ok(())
     }
+
+    pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
+        cfg_if::cfg_if! {
+            if #[cfg(target_os = "redox")] {
+                // Redox doesn't appear to support `UTIME_OMIT`.
+                drop(times);
+                Err(io::const_io_error!(
+                    io::ErrorKind::Unsupported,
+                    "setting file times not supported",
+                ))
+            } else if #[cfg(any(target_os = "android", target_os = "macos"))] {
+                // futimens requires macOS 10.13, and Android API level 19
+                cvt(unsafe {
+                    weak!(fn futimens(c_int, *const libc::timespec) -> c_int);
+                    match futimens.get() {
+                        Some(futimens) => futimens(self.as_raw_fd(), times.0.as_ptr()),
+                        #[cfg(target_os = "macos")]
+                        None => {
+                            fn ts_to_tv(ts: &libc::timespec) -> libc::timeval {
+                                libc::timeval {
+                                    tv_sec: ts.tv_sec,
+                                    tv_usec: (ts.tv_nsec / 1000) as _
+                                }
+                            }
+                            let timevals = [ts_to_tv(&times.0[0]), ts_to_tv(&times.0[1])];
+                            libc::futimes(self.as_raw_fd(), timevals.as_ptr())
+                        }
+                        // futimes requires even newer Android.
+                        #[cfg(target_os = "android")]
+                        None => return Err(io::const_io_error!(
+                            io::ErrorKind::Unsupported,
+                            "setting file times requires Android API level >= 19",
+                        )),
+                    }
+                })?;
+                Ok(())
+            } else {
+                cvt(unsafe { libc::futimens(self.as_raw_fd(), times.0.as_ptr()) })?;
+                Ok(())
+            }
+        }
+    }
 }
 
 impl DirBuilder {
diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs
index a1bbc2d87b6..462a45b01ab 100644
--- a/library/std/src/sys/unix/net.rs
+++ b/library/std/src/sys/unix/net.rs
@@ -139,8 +139,8 @@ impl Socket {
     pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
         self.set_nonblocking(true)?;
         let r = unsafe {
-            let (addrp, len) = addr.into_inner();
-            cvt(libc::connect(self.as_raw_fd(), addrp, len))
+            let (addr, len) = addr.into_inner();
+            cvt(libc::connect(self.as_raw_fd(), addr.as_ptr(), len))
         };
         self.set_nonblocking(false)?;
 
diff --git a/library/std/src/sys/unsupported/fs.rs b/library/std/src/sys/unsupported/fs.rs
index d1d2847cd33..0e1a6257ed7 100644
--- a/library/std/src/sys/unsupported/fs.rs
+++ b/library/std/src/sys/unsupported/fs.rs
@@ -17,6 +17,9 @@ pub struct DirEntry(!);
 #[derive(Clone, Debug)]
 pub struct OpenOptions {}
 
+#[derive(Copy, Clone, Debug, Default)]
+pub struct FileTimes {}
+
 pub struct FilePermissions(!);
 
 pub struct FileType(!);
@@ -86,6 +89,11 @@ impl fmt::Debug for FilePermissions {
     }
 }
 
+impl FileTimes {
+    pub fn set_accessed(&mut self, _t: SystemTime) {}
+    pub fn set_modified(&mut self, _t: SystemTime) {}
+}
+
 impl FileType {
     pub fn is_dir(&self) -> bool {
         self.0
@@ -237,6 +245,10 @@ impl File {
     pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
         self.0
     }
+
+    pub fn set_times(&self, _times: FileTimes) -> io::Result<()> {
+        self.0
+    }
 }
 
 impl DirBuilder {
diff --git a/library/std/src/sys/unsupported/net.rs b/library/std/src/sys/unsupported/net.rs
index 360115d5033..a5204a08453 100644
--- a/library/std/src/sys/unsupported/net.rs
+++ b/library/std/src/sys/unsupported/net.rs
@@ -363,6 +363,4 @@ pub mod netc {
 
     #[derive(Copy, Clone)]
     pub struct sockaddr {}
-
-    pub type socklen_t = usize;
 }
diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs
index cd6815bfc21..6614ae397b5 100644
--- a/library/std/src/sys/wasi/fs.rs
+++ b/library/std/src/sys/wasi/fs.rs
@@ -63,6 +63,12 @@ pub struct FilePermissions {
     readonly: bool,
 }
 
+#[derive(Copy, Clone, Debug, Default)]
+pub struct FileTimes {
+    accessed: Option<wasi::Timestamp>,
+    modified: Option<wasi::Timestamp>,
+}
+
 #[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
 pub struct FileType {
     bits: wasi::Filetype,
@@ -112,6 +118,16 @@ impl FilePermissions {
     }
 }
 
+impl FileTimes {
+    pub fn set_accessed(&mut self, t: SystemTime) {
+        self.accessed = Some(t.to_wasi_timestamp_or_panic());
+    }
+
+    pub fn set_modified(&mut self, t: SystemTime) {
+        self.modified = Some(t.to_wasi_timestamp_or_panic());
+    }
+}
+
 impl FileType {
     pub fn is_dir(&self) -> bool {
         self.bits == wasi::FILETYPE_DIRECTORY
@@ -459,6 +475,15 @@ impl File {
         unsupported()
     }
 
+    pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
+        self.fd.filestat_set_times(
+            times.accessed.unwrap_or(0),
+            times.modified.unwrap_or(0),
+            times.accessed.map_or(0, |_| wasi::FSTFLAGS_ATIM)
+                | times.modified.map_or(0, |_| wasi::FSTFLAGS_MTIM),
+        )
+    }
+
     pub fn read_link(&self, file: &Path) -> io::Result<PathBuf> {
         read_link(&self.fd, file)
     }
diff --git a/library/std/src/sys/wasi/net.rs b/library/std/src/sys/wasi/net.rs
index 937b1b850e7..590d268c380 100644
--- a/library/std/src/sys/wasi/net.rs
+++ b/library/std/src/sys/wasi/net.rs
@@ -524,6 +524,4 @@ pub mod netc {
 
     #[derive(Copy, Clone)]
     pub struct sockaddr {}
-
-    pub type socklen_t = usize;
 }
diff --git a/library/std/src/sys/wasi/time.rs b/library/std/src/sys/wasi/time.rs
index 088585654b9..3d326e49106 100644
--- a/library/std/src/sys/wasi/time.rs
+++ b/library/std/src/sys/wasi/time.rs
@@ -47,6 +47,10 @@ impl SystemTime {
         SystemTime(Duration::from_nanos(ts))
     }
 
+    pub fn to_wasi_timestamp_or_panic(&self) -> wasi::Timestamp {
+        self.0.as_nanos().try_into().expect("time does not fit in WASI timestamp")
+    }
+
     pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
         self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
     }
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index c7a42ef9a93..478068c73ba 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -4,6 +4,7 @@
 #![cfg_attr(test, allow(dead_code))]
 #![unstable(issue = "none", feature = "windows_c")]
 
+use crate::ffi::CStr;
 use crate::mem;
 use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort};
 use crate::os::windows::io::{BorrowedHandle, HandleOrInvalid, HandleOrNull};
@@ -619,7 +620,7 @@ pub struct SOCKADDR {
 }
 
 #[repr(C)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug, Default)]
 pub struct FILETIME {
     pub dwLowDateTime: DWORD,
     pub dwHighDateTime: DWORD,
@@ -887,6 +888,12 @@ extern "system" {
     pub fn GetSystemDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT;
     pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
     pub fn SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL;
+    pub fn SetFileTime(
+        hFile: BorrowedHandle<'_>,
+        lpCreationTime: Option<&FILETIME>,
+        lpLastAccessTime: Option<&FILETIME>,
+        lpLastWriteTime: Option<&FILETIME>,
+    ) -> BOOL;
     pub fn SetLastError(dwErrCode: DWORD);
     pub fn GetCommandLineW() -> LPWSTR;
     pub fn GetTempPathW(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD;
@@ -1219,8 +1226,8 @@ extern "system" {
 
 // Functions that aren't available on every version of Windows that we support,
 // but we still use them and just provide some form of a fallback implementation.
-compat_fn! {
-    "kernel32":
+compat_fn_with_fallback! {
+    pub static KERNEL32: &CStr = ansi_str!("kernel32");
 
     // >= Win10 1607
     // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription
@@ -1243,8 +1250,8 @@ compat_fn! {
     }
 }
 
-compat_fn! {
-    "api-ms-win-core-synch-l1-2-0":
+compat_fn_optional! {
+    pub static SYNCH_API: &CStr = ansi_str!("api-ms-win-core-synch-l1-2-0");
 
     // >= Windows 8 / Server 2012
     // https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitonaddress
@@ -1253,17 +1260,13 @@ compat_fn! {
         CompareAddress: LPVOID,
         AddressSize: SIZE_T,
         dwMilliseconds: DWORD
-    ) -> BOOL {
-        panic!("WaitOnAddress not available")
-    }
-    pub fn WakeByAddressSingle(Address: LPVOID) -> () {
-        // If this api is unavailable, there cannot be anything waiting, because
-        // WaitOnAddress would've panicked. So it's fine to do nothing here.
-    }
+    ) -> BOOL;
+    pub fn WakeByAddressSingle(Address: LPVOID) -> ();
 }
 
-compat_fn! {
-    "ntdll":
+compat_fn_with_fallback! {
+    pub static NTDLL: &CStr = ansi_str!("ntdll");
+
     pub fn NtCreateFile(
         FileHandle: *mut HANDLE,
         DesiredAccess: ACCESS_MASK,
diff --git a/library/std/src/sys/windows/compat.rs b/library/std/src/sys/windows/compat.rs
index ded97bb7eaa..ccc90177a20 100644
--- a/library/std/src/sys/windows/compat.rs
+++ b/library/std/src/sys/windows/compat.rs
@@ -49,81 +49,225 @@
 //! * call any Rust function or CRT function that touches any static
 //!   (global) state.
 
-macro_rules! compat_fn {
-    ($module:literal: $(
+use crate::ffi::{c_void, CStr};
+use crate::ptr::NonNull;
+use crate::sys::c;
+
+/// Helper macro for creating CStrs from literals and symbol names.
+macro_rules! ansi_str {
+    (sym $ident:ident) => {{
+        #[allow(unused_unsafe)]
+        crate::sys::compat::const_cstr_from_bytes(concat!(stringify!($ident), "\0").as_bytes())
+    }};
+    ($lit:literal) => {{ crate::sys::compat::const_cstr_from_bytes(concat!($lit, "\0").as_bytes()) }};
+}
+
+/// Creates a C string wrapper from a byte slice, in a constant context.
+///
+/// This is a utility function used by the [`ansi_str`] macro.
+///
+/// # Panics
+///
+/// Panics if the slice is not null terminated or contains nulls, except as the last item
+pub(crate) const fn const_cstr_from_bytes(bytes: &'static [u8]) -> &'static CStr {
+    if !matches!(bytes.last(), Some(&0)) {
+        panic!("A CStr must be null terminated");
+    }
+    let mut i = 0;
+    // At this point `len()` is at least 1.
+    while i < bytes.len() - 1 {
+        if bytes[i] == 0 {
+            panic!("A CStr must not have interior nulls")
+        }
+        i += 1;
+    }
+    // SAFETY: The safety is ensured by the above checks.
+    unsafe { crate::ffi::CStr::from_bytes_with_nul_unchecked(bytes) }
+}
+
+#[used]
+#[link_section = ".CRT$XCU"]
+static INIT_TABLE_ENTRY: unsafe extern "C" fn() = init;
+
+/// This is where the magic preloading of symbols happens.
+///
+/// Note that any functions included here will be unconditionally included in
+/// the final binary, regardless of whether or not they're actually used.
+///
+/// Therefore, this is limited to `compat_fn_optional` functions which must be
+/// preloaded and any functions which may be more time sensitive, even for the first call.
+unsafe extern "C" fn init() {
+    // There is no locking here. This code is executed before main() is entered, and
+    // is guaranteed to be single-threaded.
+    //
+    // DO NOT do anything interesting or complicated in this function! DO NOT call
+    // any Rust functions or CRT functions if those functions touch any global state,
+    // because this function runs during global initialization. For example, DO NOT
+    // do any dynamic allocation, don't call LoadLibrary, etc.
+
+    if let Some(synch) = Module::new(c::SYNCH_API) {
+        // These are optional and so we must manually attempt to load them
+        // before they can be used.
+        c::WaitOnAddress::preload(synch);
+        c::WakeByAddressSingle::preload(synch);
+    }
+
+    if let Some(kernel32) = Module::new(c::KERNEL32) {
+        // Preloading this means getting a precise time will be as fast as possible.
+        c::GetSystemTimePreciseAsFileTime::preload(kernel32);
+    }
+}
+
+/// Represents a loaded module.
+///
+/// Note that the modules std depends on must not be unloaded.
+/// Therefore a `Module` is always valid for the lifetime of std.
+#[derive(Copy, Clone)]
+pub(in crate::sys) struct Module(NonNull<c_void>);
+impl Module {
+    /// Try to get a handle to a loaded module.
+    ///
+    /// # SAFETY
+    ///
+    /// This should only be use for modules that exist for the lifetime of std
+    /// (e.g. kernel32 and ntdll).
+    pub unsafe fn new(name: &CStr) -> Option<Self> {
+        // SAFETY: A CStr is always null terminated.
+        let module = c::GetModuleHandleA(name.as_ptr());
+        NonNull::new(module).map(Self)
+    }
+
+    // Try to get the address of a function.
+    pub fn proc_address(self, name: &CStr) -> Option<NonNull<c_void>> {
+        // SAFETY:
+        // `self.0` will always be a valid module.
+        // A CStr is always null terminated.
+        let proc = unsafe { c::GetProcAddress(self.0.as_ptr(), name.as_ptr()) };
+        NonNull::new(proc)
+    }
+}
+
+/// Load a function or use a fallback implementation if that fails.
+macro_rules! compat_fn_with_fallback {
+    (pub static $module:ident: &CStr = $name:expr; $(
         $(#[$meta:meta])*
         pub fn $symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty $fallback_body:block
-    )*) => ($(
+    )*) => (
+        pub static $module: &CStr = $name;
+    $(
         $(#[$meta])*
         pub mod $symbol {
             #[allow(unused_imports)]
             use super::*;
             use crate::mem;
+            use crate::ffi::CStr;
+            use crate::sync::atomic::{AtomicPtr, Ordering};
+            use crate::sys::compat::Module;
 
             type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
 
-            /// Points to the DLL import, or the fallback function.
-            ///
-            /// This static can be an ordinary, unsynchronized, mutable static because
-            /// we guarantee that all of the writes finish during CRT initialization,
-            /// and all of the reads occur after CRT initialization.
-            static mut PTR: Option<F> = None;
-
-            /// This symbol is what allows the CRT to find the `init` function and call it.
-            /// It is marked `#[used]` because otherwise Rust would assume that it was not
-            /// used, and would remove it.
-            #[used]
-            #[link_section = ".CRT$XCU"]
-            static INIT_TABLE_ENTRY: unsafe extern "C" fn() = init;
-
-            unsafe extern "C" fn init() {
-                PTR = get_f();
+            /// `PTR` contains a function pointer to one of three functions.
+            /// It starts with the `load` function.
+            /// When that is called it attempts to load the requested symbol.
+            /// If it succeeds, `PTR` is set to the address of that symbol.
+            /// If it fails, then `PTR` is set to `fallback`.
+            static PTR: AtomicPtr<c_void> = AtomicPtr::new(load as *mut _);
+
+            unsafe extern "system" fn load($($argname: $argtype),*) -> $rettype {
+                let func = load_from_module(Module::new($module));
+                func($($argname),*)
             }
 
-            unsafe extern "C" fn get_f() -> Option<F> {
-                // There is no locking here. This code is executed before main() is entered, and
-                // is guaranteed to be single-threaded.
-                //
-                // DO NOT do anything interesting or complicated in this function! DO NOT call
-                // any Rust functions or CRT functions, if those functions touch any global state,
-                // because this function runs during global initialization. For example, DO NOT
-                // do any dynamic allocation, don't call LoadLibrary, etc.
-                let module_name: *const u8 = concat!($module, "\0").as_ptr();
-                let symbol_name: *const u8 = concat!(stringify!($symbol), "\0").as_ptr();
-                let module_handle = $crate::sys::c::GetModuleHandleA(module_name as *const i8);
-                if !module_handle.is_null() {
-                    let ptr = $crate::sys::c::GetProcAddress(module_handle, symbol_name as *const i8);
-                    if !ptr.is_null() {
-                        // Transmute to the right function pointer type.
-                        return Some(mem::transmute(ptr));
+            fn load_from_module(module: Option<Module>) -> F {
+                unsafe {
+                    static SYMBOL_NAME: &CStr = ansi_str!(sym $symbol);
+                    if let Some(f) = module.and_then(|m| m.proc_address(SYMBOL_NAME)) {
+                        PTR.store(f.as_ptr(), Ordering::Relaxed);
+                        mem::transmute(f)
+                    } else {
+                        PTR.store(fallback as *mut _, Ordering::Relaxed);
+                        fallback
                     }
                 }
-                return None;
             }
 
-            #[allow(dead_code)]
+            #[allow(unused_variables)]
+            unsafe extern "system" fn fallback($($argname: $argtype),*) -> $rettype {
+                $fallback_body
+            }
+
+            #[allow(unused)]
+            pub(in crate::sys) fn preload(module: Module) {
+                load_from_module(Some(module));
+            }
+
+            #[inline(always)]
+            pub unsafe fn call($($argname: $argtype),*) -> $rettype {
+                let func: F = mem::transmute(PTR.load(Ordering::Relaxed));
+                func($($argname),*)
+            }
+        }
+        $(#[$meta])*
+        pub use $symbol::call as $symbol;
+    )*)
+}
+
+/// A function that either exists or doesn't.
+///
+/// NOTE: Optional functions must be preloaded in the `init` function above, or they will always be None.
+macro_rules! compat_fn_optional {
+    (pub static $module:ident: &CStr = $name:expr; $(
+        $(#[$meta:meta])*
+        pub fn $symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty;
+    )*) => (
+        pub static $module: &CStr = $name;
+    $(
+        $(#[$meta])*
+        pub mod $symbol {
+            #[allow(unused_imports)]
+            use super::*;
+            use crate::mem;
+            use crate::sync::atomic::{AtomicPtr, Ordering};
+            use crate::sys::compat::Module;
+            use crate::ptr::{self, NonNull};
+
+            type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
+
+            /// `PTR` will either be `null()` or set to the loaded function.
+            static PTR: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
+
+            /// Only allow access to the function if it has loaded successfully.
             #[inline(always)]
+            #[cfg(not(miri))]
             pub fn option() -> Option<F> {
                 unsafe {
-                    if cfg!(miri) {
-                        // Miri does not run `init`, so we just call `get_f` each time.
-                        get_f()
-                    } else {
-                        PTR
-                    }
+                    NonNull::new(PTR.load(Ordering::Relaxed)).map(|f| mem::transmute(f))
                 }
             }
 
-            #[allow(dead_code)]
-            pub unsafe fn call($($argname: $argtype),*) -> $rettype {
-                if let Some(ptr) = option() {
-                    return ptr($($argname),*);
+            // Miri does not understand the way we do preloading
+            // therefore load the function here instead.
+            #[cfg(miri)]
+            pub fn option() -> Option<F> {
+                let mut func = NonNull::new(PTR.load(Ordering::Relaxed));
+                if func.is_none() {
+                    unsafe { Module::new($module).map(preload) };
+                    func = NonNull::new(PTR.load(Ordering::Relaxed));
+                }
+                unsafe {
+                    func.map(|f| mem::transmute(f))
                 }
-                $fallback_body
             }
-        }
 
-        $(#[$meta])*
-        pub use $symbol::call as $symbol;
+            #[allow(unused)]
+            pub(in crate::sys) fn preload(module: Module) {
+                unsafe {
+                    static SYMBOL_NAME: &CStr = ansi_str!(sym $symbol);
+                    if let Some(f) = module.proc_address(SYMBOL_NAME) {
+                        PTR.store(f.as_ptr(), Ordering::Relaxed);
+                    }
+                }
+            }
+        }
     )*)
 }
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index c96bcf41d51..aed082b3e0a 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -83,6 +83,12 @@ pub struct FilePermissions {
     attrs: c::DWORD,
 }
 
+#[derive(Copy, Clone, Debug, Default)]
+pub struct FileTimes {
+    accessed: Option<c::FILETIME>,
+    modified: Option<c::FILETIME>,
+}
+
 #[derive(Debug)]
 pub struct DirBuilder;
 
@@ -536,6 +542,21 @@ impl File {
         })?;
         Ok(())
     }
+
+    pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
+        let is_zero = |t: c::FILETIME| t.dwLowDateTime == 0 && t.dwHighDateTime == 0;
+        if times.accessed.map_or(false, is_zero) || times.modified.map_or(false, is_zero) {
+            return Err(io::const_io_error!(
+                io::ErrorKind::InvalidInput,
+                "Cannot set file timestamp to 0",
+            ));
+        }
+        cvt(unsafe {
+            c::SetFileTime(self.as_handle(), None, times.accessed.as_ref(), times.modified.as_ref())
+        })?;
+        Ok(())
+    }
+
     /// Get only basic file information such as attributes and file times.
     fn basic_info(&self) -> io::Result<c::FILE_BASIC_INFO> {
         unsafe {
@@ -903,6 +924,16 @@ impl FilePermissions {
     }
 }
 
+impl FileTimes {
+    pub fn set_accessed(&mut self, t: SystemTime) {
+        self.accessed = Some(t.into_inner());
+    }
+
+    pub fn set_modified(&mut self, t: SystemTime) {
+        self.modified = Some(t.into_inner());
+    }
+}
+
 impl FileType {
     fn new(attrs: c::DWORD, reparse_tag: c::DWORD) -> FileType {
         FileType { attributes: attrs, reparse_tag }
diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs
index d1e72cd5443..e0701a498fa 100644
--- a/library/std/src/sys/windows/net.rs
+++ b/library/std/src/sys/windows/net.rs
@@ -143,8 +143,8 @@ impl Socket {
     pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
         self.set_nonblocking(true)?;
         let result = {
-            let (addrp, len) = addr.into_inner();
-            let result = unsafe { c::connect(self.as_raw_socket(), addrp, len) };
+            let (addr, len) = addr.into_inner();
+            let result = unsafe { c::connect(self.as_raw_socket(), addr.as_ptr(), len) };
             cvt(result).map(drop)
         };
         self.set_nonblocking(false)?;
diff --git a/library/std/src/sys/windows/time.rs b/library/std/src/sys/windows/time.rs
index 8f46781c753..b8209a85445 100644
--- a/library/std/src/sys/windows/time.rs
+++ b/library/std/src/sys/windows/time.rs
@@ -2,6 +2,7 @@ use crate::cmp::Ordering;
 use crate::fmt;
 use crate::mem;
 use crate::sys::c;
+use crate::sys_common::IntoInner;
 use crate::time::Duration;
 
 use core::hash::{Hash, Hasher};
@@ -136,6 +137,12 @@ impl From<c::FILETIME> for SystemTime {
     }
 }
 
+impl IntoInner<c::FILETIME> for SystemTime {
+    fn into_inner(self) -> c::FILETIME {
+        self.t
+    }
+}
+
 impl Hash for SystemTime {
     fn hash<H: Hasher>(&self, state: &mut H) {
         self.intervals().hash(state)
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index c13bda32823..33d336c4317 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -10,7 +10,7 @@ use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
 use crate::ptr;
 use crate::sys::net::netc as c;
 use crate::sys::net::{cvt, cvt_gai, cvt_r, init, wrlen_t, Socket};
-use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::sys_common::{FromInner, IntoInner};
 use crate::time::Duration;
 
 use libc::{c_int, c_void};
@@ -224,8 +224,8 @@ impl TcpStream {
 
         let sock = Socket::new(addr, c::SOCK_STREAM)?;
 
-        let (addrp, len) = addr.into_inner();
-        cvt_r(|| unsafe { c::connect(sock.as_raw(), addrp, len) })?;
+        let (addr, len) = addr.into_inner();
+        cvt_r(|| unsafe { c::connect(sock.as_raw(), addr.as_ptr(), len) })?;
         Ok(TcpStream { inner: sock })
     }
 
@@ -395,8 +395,8 @@ impl TcpListener {
         setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
 
         // Bind our new socket
-        let (addrp, len) = addr.into_inner();
-        cvt(unsafe { c::bind(sock.as_raw(), addrp, len as _) })?;
+        let (addr, len) = addr.into_inner();
+        cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
 
         cfg_if::cfg_if! {
             if #[cfg(target_os = "horizon")] {
@@ -500,8 +500,8 @@ impl UdpSocket {
         init();
 
         let sock = Socket::new(addr, c::SOCK_DGRAM)?;
-        let (addrp, len) = addr.into_inner();
-        cvt(unsafe { c::bind(sock.as_raw(), addrp, len as _) })?;
+        let (addr, len) = addr.into_inner();
+        cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
         Ok(UdpSocket { inner: sock })
     }
 
@@ -531,14 +531,14 @@ impl UdpSocket {
 
     pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
         let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
-        let (dstp, dstlen) = dst.into_inner();
+        let (dst, dstlen) = dst.into_inner();
         let ret = cvt(unsafe {
             c::sendto(
                 self.inner.as_raw(),
                 buf.as_ptr() as *const c_void,
                 len,
                 MSG_NOSIGNAL,
-                dstp,
+                dst.as_ptr(),
                 dstlen,
             )
         })?;
@@ -621,7 +621,7 @@ impl UdpSocket {
 
     pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
         let mreq = c::ipv6_mreq {
-            ipv6mr_multiaddr: *multiaddr.as_inner(),
+            ipv6mr_multiaddr: multiaddr.into_inner(),
             ipv6mr_interface: to_ipv6mr_interface(interface),
         };
         setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
@@ -637,7 +637,7 @@ impl UdpSocket {
 
     pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
         let mreq = c::ipv6_mreq {
-            ipv6mr_multiaddr: *multiaddr.as_inner(),
+            ipv6mr_multiaddr: multiaddr.into_inner(),
             ipv6mr_interface: to_ipv6mr_interface(interface),
         };
         setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq)
@@ -677,8 +677,8 @@ impl UdpSocket {
     }
 
     pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> {
-        let (addrp, len) = addr?.into_inner();
-        cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addrp, len) }).map(drop)
+        let (addr, len) = addr?.into_inner();
+        cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
     }
 }
 
@@ -700,3 +700,38 @@ impl fmt::Debug for UdpSocket {
         res.field(name, &self.inner.as_raw()).finish()
     }
 }
+
+////////////////////////////////////////////////////////////////////////////////
+// Converting SocketAddr to libc representation
+////////////////////////////////////////////////////////////////////////////////
+
+/// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level
+/// SocketAddr* types into their system representation. The benefit of this specific
+/// type over using `c::sockaddr_storage` is that this type is exactly as large as it
+/// needs to be and not a lot larger. And it can be initialized more cleanly from Rust.
+#[repr(C)]
+pub(crate) union SocketAddrCRepr {
+    v4: c::sockaddr_in,
+    v6: c::sockaddr_in6,
+}
+
+impl SocketAddrCRepr {
+    pub fn as_ptr(&self) -> *const c::sockaddr {
+        self as *const _ as *const c::sockaddr
+    }
+}
+
+impl<'a> IntoInner<(SocketAddrCRepr, c::socklen_t)> for &'a SocketAddr {
+    fn into_inner(self) -> (SocketAddrCRepr, c::socklen_t) {
+        match *self {
+            SocketAddr::V4(ref a) => {
+                let sockaddr = SocketAddrCRepr { v4: a.into_inner() };
+                (sockaddr, mem::size_of::<c::sockaddr_in>() as c::socklen_t)
+            }
+            SocketAddr::V6(ref a) => {
+                let sockaddr = SocketAddrCRepr { v6: a.into_inner() };
+                (sockaddr, mem::size_of::<c::sockaddr_in6>() as c::socklen_t)
+            }
+        }
+    }
+}
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index b2014f462bd..759a59e1f98 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -38,7 +38,7 @@ use crate::error::Error;
 use crate::fmt;
 use crate::ops::{Add, AddAssign, Sub, SubAssign};
 use crate::sys::time;
-use crate::sys_common::FromInner;
+use crate::sys_common::{FromInner, IntoInner};
 
 #[stable(feature = "time", since = "1.3.0")]
 pub use core::time::Duration;
@@ -686,3 +686,9 @@ impl FromInner<time::SystemTime> for SystemTime {
         SystemTime(time)
     }
 }
+
+impl IntoInner<time::SystemTime> for SystemTime {
+    fn into_inner(self) -> time::SystemTime {
+        self.0
+    }
+}
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 394bd8b4e28..4e1e8ef9dea 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -140,7 +140,13 @@ impl Step for Std {
             cargo_subcommand(builder.kind),
         );
 
-        cargo.arg("--all-targets");
+        // If we're not in stage 0, tests and examples will fail to compile
+        // from `core` definitions being loaded from two different `libcore`
+        // .rmeta and .rlib files.
+        if compiler.stage == 0 {
+            cargo.arg("--all-targets");
+        }
+
         std_cargo(builder, target, compiler.stage, &mut cargo);
 
         // Explicitly pass -p for all dependencies krates -- this will force cargo
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 839a6d27199..06fa5039fdf 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -158,34 +158,38 @@ impl Step for ToolBuild {
                       a transitive dependency has different features activated \
                       than in a previous build:\n"
             );
-            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 {
-                eprintln!("  {}", id);
-                // same features
-                eprintln!("    `{}` ({:?})\n    `{}` ({:?})", cur.0, cur.1, prev.0, prev.1);
-            }
-            eprintln!("the following dependencies have different features:");
-            for (id, cur, prev) in different {
-                eprintln!("  {}", id);
-                let cur_features: HashSet<_> = cur.2.into_iter().collect();
-                let prev_features: HashSet<_> = prev.2.into_iter().collect();
-                eprintln!(
-                    "    `{}` additionally enabled features {:?} at {:?}",
-                    cur.0,
-                    &cur_features - &prev_features,
-                    cur.1
-                );
+            if !same.is_empty() {
                 eprintln!(
-                    "    `{}` additionally enabled features {:?} at {:?}",
-                    prev.0,
-                    &prev_features - &cur_features,
-                    prev.1
+                    "the following dependencies are duplicated although they \
+                      have the same features enabled:"
                 );
+                for (id, cur, prev) in same {
+                    eprintln!("  {}", id);
+                    // same features
+                    eprintln!("    `{}` ({:?})\n    `{}` ({:?})", cur.0, cur.1, prev.0, prev.1);
+                }
+            }
+            if !different.is_empty() {
+                eprintln!("the following dependencies have different features:");
+                for (id, cur, prev) in different {
+                    eprintln!("  {}", id);
+                    let cur_features: HashSet<_> = cur.2.into_iter().collect();
+                    let prev_features: HashSet<_> = prev.2.into_iter().collect();
+                    eprintln!(
+                        "    `{}` additionally enabled features {:?} at {:?}",
+                        cur.0,
+                        &cur_features - &prev_features,
+                        cur.1
+                    );
+                    eprintln!(
+                        "    `{}` additionally enabled features {:?} at {:?}",
+                        prev.0,
+                        &prev_features - &cur_features,
+                        prev.1
+                    );
+                }
             }
             eprintln!();
             eprintln!(
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12-stage1/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12-stage1/Dockerfile
new file mode 100644
index 00000000000..c2f3a16d273
--- /dev/null
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12-stage1/Dockerfile
@@ -0,0 +1,44 @@
+FROM ubuntu:20.04
+
+ARG DEBIAN_FRONTEND=noninteractive
+RUN apt-get update && apt-get install -y --no-install-recommends \
+    g++ \
+    gcc-multilib \
+    make \
+    ninja-build \
+    file \
+    curl \
+    ca-certificates \
+    python2.7 \
+    git \
+    cmake \
+    sudo \
+    gdb \
+    llvm-12-tools \
+    llvm-12-dev \
+    libedit-dev \
+    libssl-dev \
+    pkg-config \
+    zlib1g-dev \
+    xz-utils \
+    nodejs
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# using llvm-link-shared due to libffi issues -- see #34486
+ENV RUST_CONFIGURE_ARGS \
+    --build=x86_64-unknown-linux-gnu \
+    --llvm-root=/usr/lib/llvm-12 \
+    --enable-llvm-link-shared \
+    --set rust.thin-lto-import-instr-limit=10
+
+ENV SCRIPT python2.7 ../x.py --stage 1 test --exclude src/tools/tidy && \
+    # Run the `mir-opt` tests again but this time for a 32-bit target.
+    # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
+    # both 32-bit and 64-bit outputs updated by the PR author, before
+    # the PR is approved and tested for merging.
+    # It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`,
+    # despite having different output on 32-bit vs 64-bit targets.
+    python2.7 ../x.py --stage 1 test src/test/mir-opt \
+    --host='' --target=i686-unknown-linux-gnu
\ No newline at end of file
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index f92e46b0a97..3ad4e3f97a3 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -134,7 +134,7 @@ x--expand-yaml-anchors--remove:
         uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
         with:
           github_token: "${{ secrets.github_token }}"
-        if: success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'
+        if: success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && github.ref != 'refs/heads/try-perf'
         <<: *step
 
       - name: collect CPU statistics
@@ -286,7 +286,7 @@ jobs:
 
           - name: x86_64-gnu-llvm-12
             <<: *job-linux-xl
-
+            
           - name: x86_64-gnu-tools
             env:
               CI_ONLY_WHEN_SUBMODULES_CHANGED: 1
@@ -436,6 +436,11 @@ jobs:
               RUST_BACKTRACE: 1
             <<: *job-linux-xl
 
+          - name: x86_64-gnu-llvm-12-stage1
+            env:
+              RUST_BACKTRACE: 1
+            <<: *job-linux-xl
+
           - name: x86_64-gnu-nopt
             <<: *job-linux-xl
 
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 16d8bdb8153..6545475d996 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -43,7 +43,7 @@ else
     PYTHON="python2"
 fi
 
-if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try; then
+if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf; then
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics"
 fi
diff --git a/src/ci/scripts/verify-channel.sh b/src/ci/scripts/verify-channel.sh
index d02dc362c63..cd28748a44b 100755
--- a/src/ci/scripts/verify-channel.sh
+++ b/src/ci/scripts/verify-channel.sh
@@ -8,7 +8,7 @@ IFS=$'\n\t'
 
 source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
 
-if isCiBranch auto || isCiBranch try; then
+if isCiBranch auto || isCiBranch try || isCiBranch try-perf; then
     echo "channel verification is only executed on PR builds"
     exit
 fi
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject 766979590da8100998f0d662499d4a901d8d164
+Subproject befe6840874311635c417cf731377f07234ee37
diff --git a/src/doc/man/rustc.1 b/src/doc/man/rustc.1
index ff41324ef26..534af3f85bb 100644
--- a/src/doc/man/rustc.1
+++ b/src/doc/man/rustc.1
@@ -44,18 +44,18 @@ The optional \fIKIND\fR can be one of \fIstatic\fR, \fIdylib\fR, or
 \fIframework\fR.
 If omitted, \fIdylib\fR is assumed.
 .TP
-\fB\-\-crate\-type\fR [bin|lib|rlib|dylib|cdylib|staticlib]
+\fB\-\-crate\-type\fR [bin|lib|rlib|dylib|cdylib|staticlib|proc\-macro]
 Comma separated list of types of crates for the compiler to emit.
 .TP
 \fB\-\-crate\-name\fR \fINAME\fR
 Specify the name of the crate being built.
 .TP
-\fB\-\-emit\fR [asm|llvm\-bc|llvm\-ir|obj|link|dep\-info|mir][=\fIPATH\fR]
+\fB\-\-emit\fR [asm|llvm\-bc|llvm\-ir|obj|metadata|link|dep\-info|mir][=\fIPATH\fR]
 Configure the output that \fBrustc\fR will produce. Each emission may also have
 an optional explicit output \fIPATH\fR specified for that particular emission
 kind. This path takes precedence over the \fB-o\fR option.
 .TP
-\fB\-\-print\fR [crate\-name|\:file\-names|\:sysroot|\:cfg|\:target\-list|\:target\-cpus|\:target\-features|\:relocation\-models|\:code\-models|\:tls\-models|\:target\-spec\-json|\:native\-static\-libs]
+\fB\-\-print\fR [crate\-name|\:file\-names|\:sysroot|\:target\-libdir|\:cfg|\:target\-list|\:target\-cpus|\:target\-features|\:relocation\-models|\:code\-models|\:tls\-models|\:target\-spec\-json|\:native\-static\-libs|\:stack\-protector\-strategies|\:link\-args]
 Comma separated list of compiler information to print on stdout.
 .TP
 \fB\-g\fR
diff --git a/src/doc/reference b/src/doc/reference
-Subproject a92be0fef439b3d8e0468d82cb24812d303520a
+Subproject f3d3953bf3b158d596c96d55ce5366f9f3f972e
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 3155db49b0d57cd82c65456ac210b69ecec5ccb
+Subproject ee342dc91e1ba1bb1e1f1318f84bbe3bfac0479
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject d5201cddace979b299ec1bf9fd8997338151aa9
+Subproject 04f3cf0bb2f5a6ee2bfc4b1a6a6cd8c11d1c553
diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md
index 486b3d4414f..bfa92e7d32a 100644
--- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md
+++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md
@@ -18,6 +18,9 @@ check cfg specification is parsed using the Rust metadata syntax, just as the `-
 These two options are independent. `names` checks only the namespace of condition names
 while `values` checks only the namespace of the values of list-valued conditions.
 
+NOTE: No implicit expectation is added when using `--cfg` for both forms. Users are expected to
+pass all expected names and values using `names(...)` and `values(...)`.
+
 ## The `names(...)` form
 
 The `names(...)` form enables checking the names. This form uses a named list:
@@ -53,27 +56,6 @@ The first form enables checking condition names, while specifying that there are
 condition names (outside of the set of well-known names defined by `rustc`). Omitting the
 `--check-cfg 'names(...)'` option does not enable checking condition names.
 
-Conditions that are enabled are implicitly valid; it is unnecessary (but legal) to specify a
-condition name as both enabled and valid. For example, the following invocations are equivalent:
-
-```bash
-# condition names will be checked, and 'has_time_travel' is valid
-rustc --cfg 'has_time_travel' --check-cfg 'names()'
-
-# condition names will be checked, and 'has_time_travel' is valid
-rustc --cfg 'has_time_travel' --check-cfg 'names(has_time_travel)'
-```
-
-In contrast, the following two invocations are _not_ equivalent:
-
-```bash
-# condition names will not be checked (because there is no --check-cfg names(...))
-rustc --cfg 'has_time_travel'
-
-# condition names will be checked, and 'has_time_travel' is both valid and enabled.
-rustc --cfg 'has_time_travel' --check-cfg 'names(has_time_travel)'
-```
-
 ## The `values(...)` form
 
 The `values(...)` form enables checking the values within list-valued conditions. It has this
@@ -149,7 +131,7 @@ fn tame_lion() {}
 ```bash
 # This turns on checking for condition names, but not values, such as 'feature' values.
 rustc --check-cfg 'names(is_embedded, has_feathers)' \
-      --cfg has_feathers --cfg 'feature = "zapping"' -Z unstable-options
+      --cfg has_feathers -Z unstable-options
 ```
 
 ```rust
@@ -159,13 +141,14 @@ fn do_embedded() {}
 #[cfg(has_feathers)]        // This is expected as "has_feathers" was provided in names()
 fn do_features() {}
 
+#[cfg(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in names()
+                                 // and because no value checking was enable for "has_feathers"
+                                 // no warning is emited for the value "zapping"
+fn do_zapping() {}
+
 #[cfg(has_mumble_frotz)]    // This is UNEXPECTED because names checking is enable and
                             // "has_mumble_frotz" was not provided in names()
 fn do_mumble_frotz() {}
-
-#[cfg(feature = "lasers")]  // This doesn't raise a warning, because values checking for "feature"
-                            // was never used
-fn shoot_lasers() {}
 ```
 
 ### Example: Checking feature values, but not condition names
diff --git a/src/doc/unstable-book/src/compiler-flags/location-detail.md b/src/doc/unstable-book/src/compiler-flags/location-detail.md
index 08d937cc282..db070619969 100644
--- a/src/doc/unstable-book/src/compiler-flags/location-detail.md
+++ b/src/doc/unstable-book/src/compiler-flags/location-detail.md
@@ -17,8 +17,9 @@ within this list are:
 - `line` - the source line of the panic will be included in the panic output
 - `column` - the source column of the panic will be included in the panic output
 
-Any combination of these three options are supported. If this option is not specified,
-all three are included by default.
+Any combination of these three options are supported. Alternatively, you can pass
+`none` to this option, which results in no location details being tracked.
+If this option is not specified, all three are included by default.
 
 An example of a panic output when using `-Z location-detail=line`:
 ```text
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 838283e32da..6577315a2b7 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -439,7 +439,7 @@ pub(crate) fn build_impl(
                             .unwrap(); // corresponding associated item has to exist
                         !tcx.is_doc_hidden(trait_item.def_id)
                     } else {
-                        item.vis.is_public()
+                        item.visibility(tcx).is_public()
                     }
                 })
                 .map(|item| item.clean(cx))
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 4067cf8441b..b6791bfab4a 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1019,7 +1019,7 @@ impl<'tcx> Clean<'tcx, bool> for hir::IsAuto {
 
 impl<'tcx> Clean<'tcx, Path> for hir::TraitRef<'tcx> {
     fn clean(&self, cx: &mut DocContext<'tcx>) -> Path {
-        let path = self.path.clean(cx);
+        let path = clean_path(self.path, cx);
         register_res(cx, path.res);
         path
     }
@@ -1101,7 +1101,7 @@ impl<'tcx> Clean<'tcx, Item> for hir::ImplItem<'tcx> {
                 }
                 hir::ImplItemKind::Fn(ref sig, body) => {
                     let m = clean_function(cx, sig, self.generics, body);
-                    let defaultness = cx.tcx.associated_item(self.def_id).defaultness;
+                    let defaultness = cx.tcx.impl_defaultness(self.def_id);
                     MethodItem(m, Some(defaultness))
                 }
                 hir::ImplItemKind::TyAlias(hir_ty) => {
@@ -1139,8 +1139,8 @@ impl<'tcx> Clean<'tcx, Item> for ty::AssocItem {
                 let ty = clean_middle_ty(tcx.type_of(self.def_id), cx, Some(self.def_id));
 
                 let provided = match self.container {
-                    ty::ImplContainer(_) => true,
-                    ty::TraitContainer(_) => self.defaultness.has_value(),
+                    ty::ImplContainer => true,
+                    ty::TraitContainer => tcx.impl_defaultness(self.def_id).has_value(),
                 };
                 if provided {
                     AssocConstItem(ty, ConstantKind::Extern { def_id: self.def_id })
@@ -1159,8 +1159,8 @@ impl<'tcx> Clean<'tcx, Item> for ty::AssocItem {
 
                 if self.fn_has_self_parameter {
                     let self_ty = match self.container {
-                        ty::ImplContainer(def_id) => tcx.type_of(def_id),
-                        ty::TraitContainer(_) => tcx.types.self_param,
+                        ty::ImplContainer => tcx.type_of(self.container_id(tcx)),
+                        ty::TraitContainer => tcx.types.self_param,
                     };
                     let self_arg_ty = sig.input(0).skip_binder();
                     if self_arg_ty == self_ty {
@@ -1178,13 +1178,13 @@ impl<'tcx> Clean<'tcx, Item> for ty::AssocItem {
                 }
 
                 let provided = match self.container {
-                    ty::ImplContainer(_) => true,
-                    ty::TraitContainer(_) => self.defaultness.has_value(),
+                    ty::ImplContainer => true,
+                    ty::TraitContainer => self.defaultness(tcx).has_value(),
                 };
                 if provided {
                     let defaultness = match self.container {
-                        ty::ImplContainer(_) => Some(self.defaultness),
-                        ty::TraitContainer(_) => None,
+                        ty::ImplContainer => Some(self.defaultness(tcx)),
+                        ty::TraitContainer => None,
                     };
                     MethodItem(Box::new(Function { generics, decl }), defaultness)
                 } else {
@@ -1215,7 +1215,7 @@ impl<'tcx> Clean<'tcx, Item> for ty::AssocItem {
                     }
                 }
 
-                if let ty::TraitContainer(_) = self.container {
+                if let ty::TraitContainer = self.container {
                     let bounds = tcx.explicit_item_bounds(self.def_id);
                     let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
                     let mut generics =
@@ -1232,7 +1232,7 @@ impl<'tcx> Clean<'tcx, Item> for ty::AssocItem {
                                 if assoc.name != my_name {
                                     return false;
                                 }
-                                if trait_.def_id() != self.container.id() {
+                                if trait_.def_id() != self.container_id(tcx) {
                                     return false;
                                 }
                                 match **self_type {
@@ -1280,7 +1280,7 @@ impl<'tcx> Clean<'tcx, Item> for ty::AssocItem {
                         None => bounds.push(GenericBound::maybe_sized(cx)),
                     }
 
-                    if self.defaultness.has_value() {
+                    if tcx.impl_defaultness(self.def_id).has_value() {
                         AssocTypeItem(
                             Box::new(Typedef {
                                 type_: clean_middle_ty(
@@ -1344,7 +1344,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
             if let Some(expanded) = maybe_expand_private_type_alias(cx, path) {
                 expanded
             } else {
-                let path = path.clean(cx);
+                let path = clean_path(path, cx);
                 resolve_type(cx, path)
             }
         }
@@ -1356,7 +1356,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
             }
 
             let trait_segments = &p.segments[..p.segments.len() - 1];
-            let trait_def = cx.tcx.associated_item(p.res.def_id()).container.id();
+            let trait_def = cx.tcx.associated_item(p.res.def_id()).container_id(cx.tcx);
             let trait_ = self::Path {
                 res: Res::Def(DefKind::Trait, trait_def),
                 segments: trait_segments.iter().map(|x| x.clean(cx)).collect(),
@@ -1380,7 +1380,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
                 ty::Error(_) => return Type::Infer,
                 _ => bug!("clean: expected associated type, found `{:?}`", ty),
             };
-            let trait_ = hir::Path { span, res, segments: &[] }.clean(cx);
+            let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx);
             register_res(cx, trait_.res);
             let self_def_id = res.opt_def_id();
             let self_type = clean_ty(qself, cx);
@@ -1857,10 +1857,8 @@ fn clean_variant_data<'tcx>(
     }
 }
 
-impl<'tcx> Clean<'tcx, Path> for hir::Path<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'tcx>) -> Path {
-        Path { res: self.res, segments: self.segments.iter().map(|x| x.clean(cx)).collect() }
-    }
+fn clean_path<'tcx>(path: &hir::Path<'tcx>, cx: &mut DocContext<'tcx>) -> Path {
+    Path { res: path.res, segments: path.segments.iter().map(|x| x.clean(cx)).collect() }
 }
 
 impl<'tcx> Clean<'tcx, GenericArgs> for hir::GenericArgs<'tcx> {
@@ -1886,7 +1884,8 @@ impl<'tcx> Clean<'tcx, GenericArgs> for hir::GenericArgs<'tcx> {
                 })
                 .collect::<Vec<_>>()
                 .into();
-            let bindings = self.bindings.iter().map(|x| x.clean(cx)).collect::<Vec<_>>().into();
+            let bindings =
+                self.bindings.iter().map(|x| clean_type_binding(x, cx)).collect::<Vec<_>>().into();
             GenericArgs::AngleBracketed { args, bindings }
         }
     }
@@ -2172,7 +2171,7 @@ fn clean_use_statement<'tcx>(
 
     // Also check whether imports were asked to be inlined, in case we're trying to re-export a
     // crate in Rust 2018+
-    let path = path.clean(cx);
+    let path = clean_path(path, cx);
     let inner = if kind == hir::UseKind::Glob {
         if !denied {
             let mut visited = FxHashSet::default();
@@ -2252,24 +2251,19 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
     })
 }
 
-impl<'tcx> Clean<'tcx, TypeBinding> for hir::TypeBinding<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'tcx>) -> TypeBinding {
-        TypeBinding {
-            assoc: PathSegment { name: self.ident.name, args: self.gen_args.clean(cx) },
-            kind: self.kind.clean(cx),
-        }
-    }
-}
-
-impl<'tcx> Clean<'tcx, TypeBindingKind> for hir::TypeBindingKind<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'tcx>) -> TypeBindingKind {
-        match *self {
+fn clean_type_binding<'tcx>(
+    type_binding: &hir::TypeBinding<'tcx>,
+    cx: &mut DocContext<'tcx>,
+) -> TypeBinding {
+    TypeBinding {
+        assoc: PathSegment { name: type_binding.ident.name, args: type_binding.gen_args.clean(cx) },
+        kind: match type_binding.kind {
             hir::TypeBindingKind::Equality { ref term } => {
                 TypeBindingKind::Equality { term: clean_hir_term(term, cx) }
             }
             hir::TypeBindingKind::Constraint { bounds } => TypeBindingKind::Constraint {
                 bounds: bounds.iter().filter_map(|b| b.clean(cx)).collect(),
             },
-        }
+        },
     }
 }
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index d022ce9696a..1a46d077f1b 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -122,10 +122,6 @@ pub(crate) struct Crate {
     pub(crate) external_traits: Rc<RefCell<FxHashMap<DefId, TraitWithExtraInfo>>>,
 }
 
-// `Crate` is frequently moved by-value. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Crate, 72);
-
 impl Crate {
     pub(crate) fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
         ExternalCrate::LOCAL.name(tcx)
@@ -389,10 +385,6 @@ impl fmt::Debug for Item {
     }
 }
 
-// `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Item, 56);
-
 pub(crate) fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
     Span::new(def_id.as_local().map_or_else(
         || tcx.def_span(def_id),
@@ -771,10 +763,6 @@ pub(crate) enum ItemKind {
     KeywordItem,
 }
 
-// `ItemKind` is an enum and large variants can bloat up memory usage even for smaller ones
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(ItemKind, 112);
-
 impl ItemKind {
     /// Some items contain others such as structs (for their fields) and Enums
     /// (for their variants). This method returns those contained items.
@@ -994,10 +982,6 @@ pub(crate) struct DocFragment {
     pub(crate) indent: usize,
 }
 
-// `DocFragment` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(DocFragment, 32);
-
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub(crate) enum DocFragmentKind {
     /// A doc fragment created from a `///` or `//!` doc comment.
@@ -1382,10 +1366,6 @@ pub(crate) struct GenericParamDef {
     pub(crate) kind: GenericParamDefKind,
 }
 
-// `GenericParamDef` is used in many places. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(GenericParamDef, 56);
-
 impl GenericParamDef {
     pub(crate) fn is_synthetic_type_param(&self) -> bool {
         match self.kind {
@@ -1590,10 +1570,6 @@ pub(crate) enum Type {
     ImplTrait(Vec<GenericBound>),
 }
 
-// `Type` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Type, 72);
-
 impl Type {
     /// When comparing types for equality, it can help to ignore `&` wrapping.
     pub(crate) fn without_borrowed_ref(&self) -> &Type {
@@ -2230,33 +2206,18 @@ pub(crate) enum GenericArg {
     Infer,
 }
 
-// `GenericArg` can occur many times in a single `Path`, so make sure it
-// doesn't increase in size unexpectedly.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(GenericArg, 80);
-
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub(crate) enum GenericArgs {
     AngleBracketed { args: Box<[GenericArg]>, bindings: ThinVec<TypeBinding> },
     Parenthesized { inputs: Box<[Type]>, output: Option<Box<Type>> },
 }
 
-// `GenericArgs` is in every `PathSegment`, so its size can significantly
-// affect rustdoc's memory usage.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(GenericArgs, 32);
-
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub(crate) struct PathSegment {
     pub(crate) name: Symbol,
     pub(crate) args: GenericArgs,
 }
 
-// `PathSegment` usually occurs multiple times in every `Path`, so its size can
-// significantly affect rustdoc's memory usage.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(PathSegment, 40);
-
 #[derive(Clone, Debug)]
 pub(crate) struct Typedef {
     pub(crate) type_: Type,
@@ -2527,3 +2488,19 @@ impl SubstParam {
         if let Self::Lifetime(lt) = self { Some(lt) } else { None }
     }
 }
+
+// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+    use super::*;
+    // These are in alphabetical order, which is easy to maintain.
+    rustc_data_structures::static_assert_size!(Crate, 72); // frequently moved by-value
+    rustc_data_structures::static_assert_size!(DocFragment, 32);
+    rustc_data_structures::static_assert_size!(GenericArg, 80);
+    rustc_data_structures::static_assert_size!(GenericArgs, 32);
+    rustc_data_structures::static_assert_size!(GenericParamDef, 56);
+    rustc_data_structures::static_assert_size!(Item, 56);
+    rustc_data_structures::static_assert_size!(ItemKind, 112);
+    rustc_data_structures::static_assert_size!(PathSegment, 40);
+    rustc_data_structures::static_assert_size!(Type, 72);
+}
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index d2ef89078bf..05547ea1515 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -213,7 +213,7 @@ impl<'a> Iterator for TokenIter<'a> {
             return None;
         }
         let token = rustc_lexer::first_token(self.src);
-        let (text, rest) = self.src.split_at(token.len);
+        let (text, rest) = self.src.split_at(token.len as usize);
         self.src = rest;
         Some((token.kind, text))
     }
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index aecc9aa879a..83fe14550cc 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1111,7 +1111,14 @@ table,
 }
 
 .item-info .stab {
-	display: inline-block;
+	width: fit-content;
+	/* This min-height is needed to unify the height of the stab elements because some of them
+	   have emojis.
+	*/
+	min-height: 36px;
+	display: flex;
+	align-items: center;
+	white-space: pre-wrap;
 }
 .stab {
 	padding: 3px;
@@ -1121,6 +1128,7 @@ table,
 }
 .stab p {
 	display: inline;
+	margin: 0;
 }
 
 .stab .emoji {
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 1751249fa62..7d7a63c5384 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -234,7 +234,7 @@ impl UrlFragment {
             &UrlFragment::Item(def_id) => {
                 let kind = match tcx.def_kind(def_id) {
                     DefKind::AssocFn => {
-                        if tcx.associated_item(def_id).defaultness.has_value() {
+                        if tcx.impl_defaultness(def_id).has_value() {
                             "method."
                         } else {
                             "tymethod."
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index fd0b19034a2..0d968402503 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -304,6 +304,12 @@ pub(crate) fn run(
         let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates };
         tcx.hir().visit_all_item_likes_in_crate(&mut finder);
 
+        // The visitor might have found a type error, which we need to
+        // promote to a fatal error
+        if tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() {
+            return Err(String::from("Compilation failed, aborting rustdoc"));
+        }
+
         // Sort call locations within a given file in document order
         for fn_calls in calls.values_mut() {
             for file_calls in fn_calls.values_mut() {
diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs
index 69883058335..1abbff32c6f 100644
--- a/src/test/incremental/hashes/inherent_impls.rs
+++ b/src/test/incremental/hashes/inherent_impls.rs
@@ -116,9 +116,9 @@ impl Foo {
 // Change Method Privacy -------------------------------------------------------
 #[cfg(any(cfail1,cfail4))]
 impl Foo {
-    //----------------------------------------------------
     //--------------------------
-    //------------------------------------------------------------------------------
+    //--------------------------
+    //--------------------------------------------------------------
     //--------------------------
     pub fn method_privacy() { }
 }
@@ -129,9 +129,9 @@ impl Foo {
 #[rustc_clean(cfg="cfail5")]
 #[rustc_clean(cfg="cfail6")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="associated_item")]
+    #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
-    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,associated_item")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
     #[rustc_clean(cfg="cfail6")]
     fn     method_privacy() { }
 }
diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs
index 9b79fd8a0a1..1988f3f3541 100644
--- a/src/test/incremental/hashes/trait_defs.rs
+++ b/src/test/incremental/hashes/trait_defs.rs
@@ -277,22 +277,22 @@ trait TraitChangeMethodParametersOrder {
 // Add default implementation to method
 #[cfg(any(cfail1,cfail4))]
 trait TraitAddMethodAutoImplementation {
-    // -----------------------------------------------------------------------------
+    // -------------------------------------------------------------
     // -------------------------
-    // -----------------------------------------------------------------------------
+    // -------------------------------------------------------------
     // -------------------------
     fn method()  ;
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
 #[rustc_clean(cfg="cfail6")]
 trait TraitAddMethodAutoImplementation {
-    #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail2")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
-    #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail5")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
     #[rustc_clean(cfg="cfail6")]
     fn method() {}
 }
@@ -795,20 +795,24 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> {
 // Add default to associated type
 #[cfg(any(cfail1,cfail4))]
 trait TraitAddDefaultToAssociatedType {
-    type Associated;
+    //--------------------------------------------------------------
+    //--------------------------
+    //--------------------------------------------------------------
+    //--------------------------
+    type Associated                 ;
 
     fn method();
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
 #[rustc_clean(cfg="cfail6")]
 trait TraitAddDefaultToAssociatedType {
-    #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail2")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
-    #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail5")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
     #[rustc_clean(cfg="cfail6")]
     type Associated = ReferenceType0;
 
@@ -839,20 +843,28 @@ trait TraitAddAssociatedConstant {
 // Add initializer to associated constant
 #[cfg(any(cfail1,cfail4))]
 trait TraitAddInitializerToAssociatedConstant {
-    const Value: u32;
+    //--------------------------------------------------------------
+    //--------------------------
+    //--------------------------------------------------------------
+    //--------------------------
+    const Value: u32    ;
 
+    //--------------------------
+    //--------------------------
+    //--------------------------
+    //--------------------------
     fn method();
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
 #[rustc_clean(cfg="cfail6")]
 trait TraitAddInitializerToAssociatedConstant {
-    #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail2")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
-    #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail5")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
     #[rustc_clean(cfg="cfail6")]
     const Value: u32 = 1;
 
diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs
index cc63aa4f556..f555f555f92 100644
--- a/src/test/incremental/hashes/trait_impls.rs
+++ b/src/test/incremental/hashes/trait_impls.rs
@@ -320,7 +320,11 @@ impl AddItemTrait for Foo {
 
 #[cfg(any(cfail1,cfail4))]
 pub trait ChangeHasValueTrait {
-    fn method_name();
+    //--------------------------------------------------------------
+    //--------------------------
+    //--------------------------------------------------------------
+    //--------------------------
+    fn method_name()   ;
 }
 
 #[cfg(any(cfail1,cfail4))]
@@ -329,14 +333,14 @@ impl ChangeHasValueTrait for Foo {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
 #[rustc_clean(cfg="cfail6")]
 pub trait ChangeHasValueTrait {
-    #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail2")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
-    #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail5")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
     #[rustc_clean(cfg="cfail6")]
     fn method_name() { }
 }
@@ -358,22 +362,22 @@ pub trait AddDefaultTrait {
 
 #[cfg(any(cfail1,cfail4))]
 impl AddDefaultTrait for Foo {
-    // ----------------------------------------------------
+    // -------------------------------------------------------------
     // -------------------------
-    // ----------------------------------------------------
+    // -------------------------------------------------------------
     // -------------------------
     fn         method_name() { }
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail5")]
 #[rustc_clean(cfg="cfail6")]
 impl AddDefaultTrait for Foo {
-    #[rustc_clean(except="associated_item", cfg="cfail2")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
-    #[rustc_clean(except="associated_item", cfg="cfail5")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
     #[rustc_clean(cfg="cfail6")]
     default fn method_name() { }
 }
diff --git a/src/test/run-make-fulldeps/symbol-visibility/Makefile b/src/test/run-make-fulldeps/symbol-visibility/Makefile
index 4bb35f33ad3..17052ef4e63 100644
--- a/src/test/run-make-fulldeps/symbol-visibility/Makefile
+++ b/src/test/run-make-fulldeps/symbol-visibility/Makefile
@@ -5,6 +5,7 @@ include ../tools.mk
 NM=nm -D
 CDYLIB_NAME=liba_cdylib.so
 RDYLIB_NAME=liba_rust_dylib.so
+PROC_MACRO_NAME=liba_proc_macro.so
 EXE_NAME=an_executable
 COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.so
 
@@ -12,6 +13,7 @@ ifeq ($(UNAME),Darwin)
 NM=nm -gU
 CDYLIB_NAME=liba_cdylib.dylib
 RDYLIB_NAME=liba_rust_dylib.dylib
+PROC_MACRO_NAME=liba_proc_macro.dylib
 EXE_NAME=an_executable
 COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dylib
 endif
@@ -20,6 +22,7 @@ ifdef IS_WINDOWS
 NM=nm -g
 CDYLIB_NAME=liba_cdylib.dll.a
 RDYLIB_NAME=liba_rust_dylib.dll.a
+PROC_MACRO_NAME=liba_proc_macro.dll
 EXE_NAME=an_executable.exe
 COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dll.a
 endif
@@ -31,6 +34,7 @@ all:
 	$(RUSTC) -Zshare-generics=no an_rlib.rs
 	$(RUSTC) -Zshare-generics=no a_cdylib.rs
 	$(RUSTC) -Zshare-generics=no a_rust_dylib.rs
+	$(RUSTC) -Zshare-generics=no a_proc_macro.rs
 	$(RUSTC) -Zshare-generics=no an_executable.rs
 	$(RUSTC) -Zshare-generics=no a_cdylib.rs --crate-name combined_rlib_dylib --crate-type=rlib,cdylib
 
@@ -54,6 +58,14 @@ all:
 	# Check that a Rust dylib does not export generics if -Zshare-generics=no
 	[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rlib)" -eq "0" ]
 
+	# Check that a proc macro exports its public #[no_mangle] functions
+	# FIXME(#99978) avoid exporting #[no_mangle] symbols for proc macros
+	[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ]
+	# Check that a proc macro exports the public #[no_mangle] functions of dependencies
+	[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
+	# Check that a proc macro DOES NOT export any public Rust functions
+	[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ]
+
 # FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032
 ifndef IS_WINDOWS
 	# Check that an executable does not export any dynamic symbols
@@ -75,6 +87,7 @@ endif
 	$(RUSTC) -Zshare-generics=yes an_rlib.rs
 	$(RUSTC) -Zshare-generics=yes a_cdylib.rs
 	$(RUSTC) -Zshare-generics=yes a_rust_dylib.rs
+	$(RUSTC) -Zshare-generics=yes a_proc_macro.rs
 	$(RUSTC) -Zshare-generics=yes an_executable.rs
 
 	# Check that a cdylib exports its public #[no_mangle] functions
@@ -94,6 +107,14 @@ endif
 	[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rlib)" -eq "1" ]
 	[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rlib)" -eq "1" ]
 
+	# Check that a proc macro exports its public #[no_mangle] functions
+	# FIXME(#99978) avoid exporting #[no_mangle] symbols for proc macros
+	[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ]
+	# Check that a proc macro exports the public #[no_mangle] functions of dependencies
+	[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
+	# Check that a proc macro DOES NOT export any public Rust functions
+	[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ]
+
 ifndef IS_WINDOWS
 	# Check that an executable does not export any dynamic symbols
 	[ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "0" ]
diff --git a/src/test/run-make-fulldeps/symbol-visibility/a_proc_macro.rs b/src/test/run-make-fulldeps/symbol-visibility/a_proc_macro.rs
new file mode 100644
index 00000000000..9fd1a8a6717
--- /dev/null
+++ b/src/test/run-make-fulldeps/symbol-visibility/a_proc_macro.rs
@@ -0,0 +1,9 @@
+#![crate_type = "proc-macro"]
+
+extern crate an_rlib;
+
+// This should not be exported
+#[no_mangle]
+extern "C" fn public_c_function_from_cdylib() {
+    an_rlib::public_c_function_from_rlib();
+}
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/Makefile b/src/test/run-make/raw-dylib-alt-calling-convention/Makefile
index 1badde54112..a254285ab76 100644
--- a/src/test/run-make/raw-dylib-alt-calling-convention/Makefile
+++ b/src/test/run-make/raw-dylib-alt-calling-convention/Makefile
@@ -14,10 +14,19 @@ ifdef IS_MSVC
 else
 	$(CC) "$(TMPDIR)"/extern.obj -shared -o "$(TMPDIR)"/extern.dll
 endif
-	"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
 
+	"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
 ifdef RUSTC_BLESS_TEST
 	cp "$(TMPDIR)"/output.txt output.txt
 else
 	$(DIFF) output.txt "$(TMPDIR)"/output.txt
 endif
+
+ifdef IS_MSVC
+	"$(TMPDIR)"/driver true > "$(TMPDIR)"/output.msvc.txt
+ifdef RUSTC_BLESS_TEST
+	cp "$(TMPDIR)"/output.msvc.txt output.msvc.txt
+else
+	$(DIFF) output.msvc.txt "$(TMPDIR)"/output.msvc.txt
+endif
+endif
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs b/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs
index 3710507f5e4..b7f372c6b2b 100644
--- a/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs
+++ b/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs
@@ -1,5 +1,8 @@
 extern crate raw_dylib_alt_calling_convention_test;
 
 fn main() {
-    raw_dylib_alt_calling_convention_test::library_function();
+    raw_dylib_alt_calling_convention_test::library_function(
+        std::env::args().skip(1).next().map_or(
+            false,
+            |s| std::str::FromStr::from_str(&s).unwrap()));
 }
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/extern.c b/src/test/run-make/raw-dylib-alt-calling-convention/extern.c
index 8f64abf2fb5..0c4d12af9b2 100644
--- a/src/test/run-make/raw-dylib-alt-calling-convention/extern.c
+++ b/src/test/run-make/raw-dylib-alt-calling-convention/extern.c
@@ -121,3 +121,58 @@ __declspec(dllexport) void __fastcall fastcall_fn_9(uint8_t x, double y) {
     printf("fastcall_fn_9(%d, %.1f)\n", x, y);
     fflush(stdout);
 }
+
+// GCC doesn't support vectorcall: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485
+#ifdef _MSC_VER
+__declspec(dllexport) void __vectorcall vectorcall_fn_1(int i) {
+    printf("vectorcall_fn_1(%d)\n", i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_2(uint8_t i, float f) {
+    printf("vectorcall_fn_2(%d, %.1f)\n", i, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_3(double d) {
+    printf("vectorcall_fn_3(%.1f)\n", d);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_4(uint8_t i, uint8_t j, float f) {
+    printf("vectorcall_fn_4(%d, %d, %.1f)\n", i, j, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_5(struct S s, int i) {
+    printf("vectorcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_6(struct S* s) {
+    if (s) {
+        printf("vectorcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y);
+    } else {
+        printf("vectorcall_fn_6(null)\n");
+    }
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_7(struct S2 s, int i) {
+    printf("vectorcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_8(struct S3 s, struct S3 t) {
+    printf("vectorcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n",
+           s.x[0], s.x[1], s.x[2], s.x[3], s.x[4],
+           t.x[0], t.x[1], t.x[2], t.x[3], t.x[4]
+        );
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_9(uint8_t x, double y) {
+    printf("vectorcall_fn_9(%d, %.1f)\n", x, y);
+    fflush(stdout);
+}
+#endif
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs b/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs
index 165792b0490..b5e9415b2be 100644
--- a/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs
+++ b/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs
@@ -1,4 +1,5 @@
 #![feature(raw_dylib)]
+#![feature(abi_vectorcall)]
 
 #[repr(C)]
 #[derive(Clone)]
@@ -46,29 +47,60 @@ extern "fastcall" {
     fn fastcall_fn_9(x: u8, y: f64);
 }
 
-pub fn library_function() {
+#[cfg(target_env = "msvc")]
+#[link(name = "extern", kind = "raw-dylib")]
+extern "vectorcall" {
+    fn vectorcall_fn_1(i: i32);
+    fn vectorcall_fn_2(c: u8, f: f32);
+    fn vectorcall_fn_3(d: f64);
+    fn vectorcall_fn_4(i: u8, j: u8, f: f32);
+    fn vectorcall_fn_5(a: S, b: i32);
+    fn vectorcall_fn_6(a: Option<&S>);
+    fn vectorcall_fn_7(a: S2, b: i32);
+    fn vectorcall_fn_8(a: S3, b: S3);
+    fn vectorcall_fn_9(x: u8, y: f64);
+}
+
+pub fn library_function(run_msvc_only: bool) {
     unsafe {
-        stdcall_fn_1(14);
-        stdcall_fn_2(16, 3.5);
-        stdcall_fn_3(3.5);
-        stdcall_fn_4(1, 2, 3.0);
-        stdcall_fn_5(S { x: 1, y: 2 }, 16);
-        stdcall_fn_6(Some(&S { x: 10, y: 12 }));
-        stdcall_fn_7(S2 { x: 15, y: 16 }, 3);
-        stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
-        stdcall_fn_9(1, 3.0);
+        if !run_msvc_only {
+            stdcall_fn_1(14);
+            stdcall_fn_2(16, 3.5);
+            stdcall_fn_3(3.5);
+            stdcall_fn_4(1, 2, 3.0);
+            stdcall_fn_5(S { x: 1, y: 2 }, 16);
+            stdcall_fn_6(Some(&S { x: 10, y: 12 }));
+            stdcall_fn_7(S2 { x: 15, y: 16 }, 3);
+            stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+            stdcall_fn_9(1, 3.0);
+
+            fastcall_fn_1(14);
+            fastcall_fn_2(16, 3.5);
+            fastcall_fn_3(3.5);
+            fastcall_fn_4(1, 2, 3.0);
+            fastcall_fn_6(Some(&S { x: 10, y: 12 }));
+            fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+            fastcall_fn_9(1, 3.0);
+        } else {
+            // FIXME: 91167
+            // rustc generates incorrect code for the calls to fastcall_fn_5 and fastcall_fn_7
+            // on i686-pc-windows-gnu; disabling these until the indicated issue is fixed.
+            fastcall_fn_5(S { x: 1, y: 2 }, 16);
+            fastcall_fn_7(S2 { x: 15, y: 16 }, 3);
 
-        fastcall_fn_1(14);
-        fastcall_fn_2(16, 3.5);
-        fastcall_fn_3(3.5);
-        fastcall_fn_4(1, 2, 3.0);
-        // FIXME: 91167
-        // rustc generates incorrect code for the calls to fastcall_fn_5 and fastcall_fn_7
-        // on i686-pc-windows-gnu; commenting these out until the indicated issue is fixed.
-        //fastcall_fn_5(S { x: 1, y: 2 }, 16);
-        fastcall_fn_6(Some(&S { x: 10, y: 12 }));
-        //fastcall_fn_7(S2 { x: 15, y: 16 }, 3);
-        fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
-        fastcall_fn_9(1, 3.0);
+            // GCC doesn't support vectorcall: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485
+            #[cfg(target_env = "msvc")]
+            {
+                vectorcall_fn_1(14);
+                vectorcall_fn_2(16, 3.5);
+                vectorcall_fn_3(3.5);
+                vectorcall_fn_4(1, 2, 3.0);
+                vectorcall_fn_5(S { x: 1, y: 2 }, 16);
+                vectorcall_fn_6(Some(&S { x: 10, y: 12 }));
+                vectorcall_fn_7(S2 { x: 15, y: 16 }, 3);
+                vectorcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+                vectorcall_fn_9(1, 3.0);
+            }
+        }
     }
 }
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/output.msvc.txt b/src/test/run-make/raw-dylib-alt-calling-convention/output.msvc.txt
new file mode 100644
index 00000000000..9ddd1b11016
--- /dev/null
+++ b/src/test/run-make/raw-dylib-alt-calling-convention/output.msvc.txt
@@ -0,0 +1,11 @@
+fastcall_fn_5(S { x: 1, y: 2 }, 16)
+fastcall_fn_7(S2 { x: 15, y: 16 }, 3)
+vectorcall_fn_1(14)
+vectorcall_fn_2(16, 3.5)
+vectorcall_fn_3(3.5)
+vectorcall_fn_4(1, 2, 3.0)
+vectorcall_fn_5(S { x: 1, y: 2 }, 16)
+vectorcall_fn_6(S { x: 10, y: 12 })
+vectorcall_fn_7(S2 { x: 15, y: 16 }, 3)
+vectorcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] })
+vectorcall_fn_9(1, 3.0)
diff --git a/src/test/rustdoc-gui/item-info-width.goml b/src/test/rustdoc-gui/item-info-width.goml
deleted file mode 100644
index 8b6d355a8f1..00000000000
--- a/src/test/rustdoc-gui/item-info-width.goml
+++ /dev/null
@@ -1,8 +0,0 @@
-// This test ensures that the item information don't take 100% of the width if unnecessary.
-goto: file://|DOC_PATH|/lib2/struct.Foo.html
-// We set a fixed size so there is no chance of "random" resize.
-size: (1100, 800)
-// We check that ".item-info" is bigger than its content.
-assert-css: (".item-info", {"width": "790px"})
-assert-css: (".item-info .stab", {"width": "289px"})
-assert-position: (".item-info .stab", {"x": 295})
diff --git a/src/test/rustdoc-gui/item-info.goml b/src/test/rustdoc-gui/item-info.goml
new file mode 100644
index 00000000000..50c45b76bd6
--- /dev/null
+++ b/src/test/rustdoc-gui/item-info.goml
@@ -0,0 +1,32 @@
+// This test ensures a few things for item info elements.
+goto: file://|DOC_PATH|/lib2/struct.Foo.html
+// Ensuring that the item information don't take 100% of the width if unnecessary.
+// We set a fixed size so there is no chance of "random" resize.
+size: (1100, 800)
+// We check that ".item-info" is bigger than its content.
+assert-css: (".item-info", {"width": "790px"})
+assert-css: (".item-info .stab", {"width": "289px"})
+assert-position: (".item-info .stab", {"x": 295})
+
+// Now we ensure that they're not rendered on the same line.
+goto: file://|DOC_PATH|/lib2/trait.Trait.html
+// We first ensure that there are two item info on the trait.
+assert-count: ("#main-content > .item-info .stab", 2)
+// They should not have the same `y` position!
+compare-elements-position-false: (
+    "#main-content > .item-info .stab:nth-of-type(1)",
+    "#main-content > .item-info .stab:nth-of-type(2)",
+    ("y"),
+)
+// But they should have the same `x` position.
+compare-elements-position: (
+    "#main-content > .item-info .stab:nth-of-type(1)",
+    "#main-content > .item-info .stab:nth-of-type(2)",
+    ("x"),
+)
+// They are supposed to have the same height too.
+compare-elements-css: (
+    "#main-content > .item-info .stab:nth-of-type(1)",
+    "#main-content > .item-info .stab:nth-of-type(2)",
+    ["height"],
+)
diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs
index 4546449e102..87f91be3ac8 100644
--- a/src/test/rustdoc-gui/src/lib2/lib.rs
+++ b/src/test/rustdoc-gui/src/lib2/lib.rs
@@ -30,10 +30,13 @@ impl Foo {
     pub fn a_method(&self) {}
 }
 
+#[doc(cfg(feature = "foo-method"))]
+#[deprecated = "Whatever [`Foo::a_method`](#method.a_method)"]
 pub trait Trait {
     type X;
     const Y: u32;
 
+    #[deprecated = "Whatever [`Foo`](#tadam)"]
     fn foo() {}
 }
 
diff --git a/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.rs b/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.rs
new file mode 100644
index 00000000000..8f4fde96d7e
--- /dev/null
+++ b/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.rs
@@ -0,0 +1,7 @@
+// check-fail
+// compile-flags: -Z unstable-options --scrape-examples-output-path {{build-base}}/t.calls --scrape-examples-target-crate foobar
+
+pub fn foo() {
+  INVALID_FUNC();
+  //~^ ERROR could not resolve path
+}
diff --git a/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.stderr b/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.stderr
new file mode 100644
index 00000000000..750aa320719
--- /dev/null
+++ b/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.stderr
@@ -0,0 +1,14 @@
+error[E0433]: failed to resolve: could not resolve path `INVALID_FUNC`
+  --> $DIR/scrape-examples-fail-if-type-error.rs:5:3
+   |
+LL |   INVALID_FUNC();
+   |   ^^^^^^^^^^^^ could not resolve path `INVALID_FUNC`
+   |
+   = note: this error was originally ignored because you are running `rustdoc`
+   = note: try running again with `rustc` or `cargo check` and you may get a more detailed error
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout
index c8e5cac0594..6dc41231559 100644
--- a/src/test/rustdoc-ui/z-help.stdout
+++ b/src/test/rustdoc-ui/z-help.stdout
@@ -69,7 +69,7 @@
     -Z                               link-only=val -- link the `.rlink` file generated by `-Z no-link` (default: no)
     -Z                            llvm-plugins=val -- a list LLVM plugins to enable (space separated)
     -Z                         llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no)
-    -Z                         location-detail=val -- comma separated list of location details to be tracked when using caller_location valid options are `file`, `line`, and `column` (default: all)
+    -Z                         location-detail=val -- what location details should be tracked when using caller_location, either `none`, or a comma separated list of location details, for which valid options are `file`, `line`, and `column` (default: `file,line,column`)
     -Z                                      ls=val -- list the symbols defined by a library crate (default: no)
     -Z                         macro-backtrace=val -- show macro backtraces (default: no)
     -Z                         merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name
diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr
index fd76c282f96..e6f6e9e9f65 100644
--- a/src/test/ui/async-await/no-const-async.stderr
+++ b/src/test/ui/async-await/no-const-async.stderr
@@ -35,7 +35,7 @@ note: cycle used when checking item types in top-level module
   --> $DIR/no-const-async.rs:4:1
    |
 LL | pub const async fn x() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/access-mode-in-closures.stderr b/src/test/ui/borrowck/access-mode-in-closures.stderr
index c32e944afe3..13a6277da14 100644
--- a/src/test/ui/borrowck/access-mode-in-closures.stderr
+++ b/src/test/ui/borrowck/access-mode-in-closures.stderr
@@ -1,4 +1,4 @@
-error[E0507]: cannot move out of `s.0` which is behind a shared reference
+error[E0507]: cannot move out of `s` which is behind a shared reference
   --> $DIR/access-mode-in-closures.rs:8:15
    |
 LL |         match *s { S(v) => v }
diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.stderr b/src/test/ui/borrowck/borrowck-move-error-with-note.stderr
index ead02414a62..96246d9ae1a 100644
--- a/src/test/ui/borrowck/borrowck-move-error-with-note.stderr
+++ b/src/test/ui/borrowck/borrowck-move-error-with-note.stderr
@@ -1,4 +1,4 @@
-error[E0507]: cannot move out of `f.0` which is behind a shared reference
+error[E0507]: cannot move out of `f` as enum variant `Foo1` which is behind a shared reference
   --> $DIR/borrowck-move-error-with-note.rs:11:11
    |
 LL |     match *f {
diff --git a/src/test/ui/check-cfg/invalid-cfg-value.rs b/src/test/ui/check-cfg/invalid-cfg-value.rs
index a60095a5aae..9e428d367fd 100644
--- a/src/test/ui/check-cfg/invalid-cfg-value.rs
+++ b/src/test/ui/check-cfg/invalid-cfg-value.rs
@@ -12,6 +12,7 @@ pub fn f() {}
 pub fn g() {}
 
 #[cfg(feature = "rand")]
+//~^ WARNING unexpected `cfg` condition value
 pub fn h() {}
 
 pub fn main() {}
diff --git a/src/test/ui/check-cfg/invalid-cfg-value.stderr b/src/test/ui/check-cfg/invalid-cfg-value.stderr
index bc2c053fed6..6cce31d3392 100644
--- a/src/test/ui/check-cfg/invalid-cfg-value.stderr
+++ b/src/test/ui/check-cfg/invalid-cfg-value.stderr
@@ -5,7 +5,15 @@ LL | #[cfg(feature = "sedre")]
    |       ^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(unexpected_cfgs)]` on by default
-   = note: expected values for `feature` are: full, rand, serde
+   = note: expected values for `feature` are: full, serde
 
-warning: 1 warning emitted
+warning: unexpected `cfg` condition value
+  --> $DIR/invalid-cfg-value.rs:14:7
+   |
+LL | #[cfg(feature = "rand")]
+   |       ^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `feature` are: full, serde
+
+warning: 2 warnings emitted
 
diff --git a/src/test/ui/check-cfg/mix.rs b/src/test/ui/check-cfg/mix.rs
index b51d356f61f..8e3d20d5045 100644
--- a/src/test/ui/check-cfg/mix.rs
+++ b/src/test/ui/check-cfg/mix.rs
@@ -1,6 +1,6 @@
-// This test checks the combination of well known names, their activation via names(), the usage of
-// partial values() with a --cfg and test that we also correctly lint on the `cfg!` macro and
-// `cfg_attr` attribute.
+// This test checks the combination of well known names, their activation via names(),
+// the usage of values(), and that no implicit is done with --cfg while also testing that
+// we correctly lint on the `cfg!` macro and `cfg_attr` attribute.
 //
 // check-pass
 // compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --cfg feature="bar" -Z unstable-options
@@ -16,6 +16,7 @@ fn do_windows_stuff() {}
 fn use_foo() {}
 
 #[cfg(feature = "bar")]
+//~^ WARNING unexpected `cfg` condition value
 fn use_bar() {}
 
 #[cfg(feature = "zebra")]
@@ -35,6 +36,7 @@ fn test_cfg_macro() {
     //~^ WARNING unexpected `cfg` condition name
     cfg!(feature = "foo");
     cfg!(feature = "bar");
+    //~^ WARNING unexpected `cfg` condition value
     cfg!(feature = "zebra");
     //~^ WARNING unexpected `cfg` condition value
     cfg!(xxx = "foo");
diff --git a/src/test/ui/check-cfg/mix.stderr b/src/test/ui/check-cfg/mix.stderr
index 08a338da104..e51b75b3d43 100644
--- a/src/test/ui/check-cfg/mix.stderr
+++ b/src/test/ui/check-cfg/mix.stderr
@@ -7,21 +7,29 @@ LL | #[cfg(widnows)]
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value
-  --> $DIR/mix.rs:21:7
+  --> $DIR/mix.rs:18:7
+   |
+LL | #[cfg(feature = "bar")]
+   |       ^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `feature` are: foo
+
+warning: unexpected `cfg` condition value
+  --> $DIR/mix.rs:22:7
    |
 LL | #[cfg(feature = "zebra")]
    |       ^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `feature` are: bar, foo
+   = note: expected values for `feature` are: foo
 
 warning: unexpected `cfg` condition name
-  --> $DIR/mix.rs:25:12
+  --> $DIR/mix.rs:26:12
    |
 LL | #[cfg_attr(uu, test)]
    |            ^^
 
 warning: unexpected `cfg` condition name
-  --> $DIR/mix.rs:34:10
+  --> $DIR/mix.rs:35:10
    |
 LL |     cfg!(widnows);
    |          ^^^^^^^ help: did you mean: `windows`
@@ -29,132 +37,138 @@ LL |     cfg!(widnows);
 warning: unexpected `cfg` condition value
   --> $DIR/mix.rs:38:10
    |
+LL |     cfg!(feature = "bar");
+   |          ^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `feature` are: foo
+
+warning: unexpected `cfg` condition value
+  --> $DIR/mix.rs:40:10
+   |
 LL |     cfg!(feature = "zebra");
    |          ^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `feature` are: bar, foo
+   = note: expected values for `feature` are: foo
 
 warning: unexpected `cfg` condition name
-  --> $DIR/mix.rs:40:10
+  --> $DIR/mix.rs:42:10
    |
 LL |     cfg!(xxx = "foo");
    |          ^^^^^^^^^^^
 
 warning: unexpected `cfg` condition name
-  --> $DIR/mix.rs:42:10
+  --> $DIR/mix.rs:44:10
    |
 LL |     cfg!(xxx);
    |          ^^^
 
 warning: unexpected `cfg` condition name
-  --> $DIR/mix.rs:44:14
+  --> $DIR/mix.rs:46:14
    |
 LL |     cfg!(any(xxx, windows));
    |              ^^^
 
 warning: unexpected `cfg` condition value
-  --> $DIR/mix.rs:46:14
+  --> $DIR/mix.rs:48:14
    |
 LL |     cfg!(any(feature = "bad", windows));
-   |              ^^^^^^^^^^-----
-   |                        |
-   |                        help: did you mean: `"bar"`
+   |              ^^^^^^^^^^^^^^^
    |
-   = note: expected values for `feature` are: bar, foo
+   = note: expected values for `feature` are: foo
 
 warning: unexpected `cfg` condition name
-  --> $DIR/mix.rs:48:23
+  --> $DIR/mix.rs:50:23
    |
 LL |     cfg!(any(windows, xxx));
    |                       ^^^
 
 warning: unexpected `cfg` condition name
-  --> $DIR/mix.rs:50:20
+  --> $DIR/mix.rs:52:20
    |
 LL |     cfg!(all(unix, xxx));
    |                    ^^^
 
 warning: unexpected `cfg` condition name
-  --> $DIR/mix.rs:52:14
+  --> $DIR/mix.rs:54:14
    |
 LL |     cfg!(all(aa, bb));
    |              ^^
 
 warning: unexpected `cfg` condition name
-  --> $DIR/mix.rs:52:18
+  --> $DIR/mix.rs:54:18
    |
 LL |     cfg!(all(aa, bb));
    |                  ^^
 
 warning: unexpected `cfg` condition name
-  --> $DIR/mix.rs:55:14
+  --> $DIR/mix.rs:57:14
    |
 LL |     cfg!(any(aa, bb));
    |              ^^
 
 warning: unexpected `cfg` condition name
-  --> $DIR/mix.rs:55:18
+  --> $DIR/mix.rs:57:18
    |
 LL |     cfg!(any(aa, bb));
    |                  ^^
 
 warning: unexpected `cfg` condition value
-  --> $DIR/mix.rs:58:20
+  --> $DIR/mix.rs:60:20
    |
 LL |     cfg!(any(unix, feature = "zebra"));
    |                    ^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `feature` are: bar, foo
+   = note: expected values for `feature` are: foo
 
 warning: unexpected `cfg` condition name
-  --> $DIR/mix.rs:60:14
+  --> $DIR/mix.rs:62:14
    |
 LL |     cfg!(any(xxx, feature = "zebra"));
    |              ^^^
 
 warning: unexpected `cfg` condition value
-  --> $DIR/mix.rs:60:19
+  --> $DIR/mix.rs:62:19
    |
 LL |     cfg!(any(xxx, feature = "zebra"));
    |                   ^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `feature` are: bar, foo
+   = note: expected values for `feature` are: foo
 
 warning: unexpected `cfg` condition name
-  --> $DIR/mix.rs:63:14
+  --> $DIR/mix.rs:65:14
    |
 LL |     cfg!(any(xxx, unix, xxx));
    |              ^^^
 
 warning: unexpected `cfg` condition name
-  --> $DIR/mix.rs:63:25
+  --> $DIR/mix.rs:65:25
    |
 LL |     cfg!(any(xxx, unix, xxx));
    |                         ^^^
 
 warning: unexpected `cfg` condition value
-  --> $DIR/mix.rs:66:14
+  --> $DIR/mix.rs:68:14
    |
 LL |     cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
    |              ^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `feature` are: bar, foo
+   = note: expected values for `feature` are: foo
 
 warning: unexpected `cfg` condition value
-  --> $DIR/mix.rs:66:33
+  --> $DIR/mix.rs:68:33
    |
 LL |     cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
    |                                 ^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `feature` are: bar, foo
+   = note: expected values for `feature` are: foo
 
 warning: unexpected `cfg` condition value
-  --> $DIR/mix.rs:66:52
+  --> $DIR/mix.rs:68:52
    |
 LL |     cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
    |                                                    ^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `feature` are: bar, foo
+   = note: expected values for `feature` are: foo
 
-warning: 23 warnings emitted
+warning: 25 warnings emitted
 
diff --git a/src/test/ui/consts/issue-44415.stderr b/src/test/ui/consts/issue-44415.stderr
index c085beb0ea5..57f94f8c6ab 100644
--- a/src/test/ui/consts/issue-44415.stderr
+++ b/src/test/ui/consts/issue-44415.stderr
@@ -2,18 +2,18 @@ error[E0391]: cycle detected when evaluating type-level constant
   --> $DIR/issue-44415.rs:6:17
    |
 LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
-   |                 ^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
   --> $DIR/issue-44415.rs:6:17
    |
 LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
-   |                 ^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
   --> $DIR/issue-44415.rs:6:17
    |
 LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
-   |                 ^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires computing layout of `Foo`...
    = note: ...which requires computing layout of `[u8; _]`...
    = note: ...which requires normalizing `[u8; _]`...
diff --git a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr
index fc842fada5a..d4976a0f9c9 100644
--- a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr
+++ b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr
@@ -8,8 +8,13 @@ LL | trait Foo<X = Box<dyn Foo>> {
 note: cycle used when collecting item types in top-level module
   --> $DIR/cycle-trait-default-type-trait.rs:4:1
    |
-LL | trait Foo<X = Box<dyn Foo>> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Foo<X = Box<dyn Foo>> {
+LL | |
+LL | |
+LL | | }
+LL | |
+LL | | fn main() { }
+   | |_____________^
 
 error[E0391]: cycle detected when computing type of `Foo::X`
   --> $DIR/cycle-trait-default-type-trait.rs:4:23
@@ -21,8 +26,13 @@ LL | trait Foo<X = Box<dyn Foo>> {
 note: cycle used when collecting item types in top-level module
   --> $DIR/cycle-trait-default-type-trait.rs:4:1
    |
-LL | trait Foo<X = Box<dyn Foo>> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Foo<X = Box<dyn Foo>> {
+LL | |
+LL | |
+LL | | }
+LL | |
+LL | | fn main() { }
+   | |_____________^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr b/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr
index ee54b2fd151..f6ffcc4b5aa 100644
--- a/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr
+++ b/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr
@@ -13,8 +13,10 @@ LL | trait Chromosome: Chromosome {
 note: cycle used when collecting item types in top-level module
   --> $DIR/cycle-trait-supertrait-direct.rs:3:1
    |
-LL | trait Chromosome: Chromosome {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Chromosome: Chromosome {
+LL | |
+LL | | }
+   | |_^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/compatible-variants.rs b/src/test/ui/did_you_mean/compatible-variants.rs
index 5d7c611980f..b1c7dc2a7f6 100644
--- a/src/test/ui/did_you_mean/compatible-variants.rs
+++ b/src/test/ui/did_you_mean/compatible-variants.rs
@@ -66,7 +66,7 @@ fn main() {
 }
 
 enum A {
-    B { b: B},
+    B { b: B },
 }
 
 struct A2(B);
@@ -77,13 +77,12 @@ enum B {
 }
 
 fn foo() {
-    // We don't want to suggest `A::B(B::Fst)` here.
     let a: A = B::Fst;
     //~^ ERROR mismatched types
+    //~| HELP try wrapping
 }
 
 fn bar() {
-    // But we _do_ want to suggest `A2(B::Fst)` here!
     let a: A2 = B::Fst;
     //~^ ERROR mismatched types
     //~| HELP try wrapping
diff --git a/src/test/ui/did_you_mean/compatible-variants.stderr b/src/test/ui/did_you_mean/compatible-variants.stderr
index a16cdee4462..fe81da19833 100644
--- a/src/test/ui/did_you_mean/compatible-variants.stderr
+++ b/src/test/ui/did_you_mean/compatible-variants.stderr
@@ -191,15 +191,20 @@ LL |     let _ = Foo { bar: Some(bar) };
    |                   ++++++++++   +
 
 error[E0308]: mismatched types
-  --> $DIR/compatible-variants.rs:81:16
+  --> $DIR/compatible-variants.rs:80:16
    |
 LL |     let a: A = B::Fst;
    |            -   ^^^^^^ expected enum `A`, found enum `B`
    |            |
    |            expected due to this
+   |
+help: try wrapping the expression in `A::B`
+   |
+LL |     let a: A = A::B { b: B::Fst };
+   |                +++++++++        +
 
 error[E0308]: mismatched types
-  --> $DIR/compatible-variants.rs:87:17
+  --> $DIR/compatible-variants.rs:86:17
    |
 LL |     let a: A2 = B::Fst;
    |            --   ^^^^^^ expected struct `A2`, found enum `B`
diff --git a/src/test/ui/did_you_mean/issue-42764.rs b/src/test/ui/did_you_mean/issue-42764.rs
index 6da640b2b7c..eb96c248063 100644
--- a/src/test/ui/did_you_mean/issue-42764.rs
+++ b/src/test/ui/did_you_mean/issue-42764.rs
@@ -26,4 +26,5 @@ struct Context { wrapper: Wrapper }
 fn overton() {
     let _c = Context { wrapper: Payload{} };
     //~^ ERROR mismatched types
+    //~| try wrapping the expression in `Wrapper`
 }
diff --git a/src/test/ui/did_you_mean/issue-42764.stderr b/src/test/ui/did_you_mean/issue-42764.stderr
index 95b572133c5..6a7fd8fe251 100644
--- a/src/test/ui/did_you_mean/issue-42764.stderr
+++ b/src/test/ui/did_you_mean/issue-42764.stderr
@@ -25,6 +25,11 @@ error[E0308]: mismatched types
    |
 LL |     let _c = Context { wrapper: Payload{} };
    |                                 ^^^^^^^^^ expected struct `Wrapper`, found struct `Payload`
+   |
+help: try wrapping the expression in `Wrapper`
+   |
+LL |     let _c = Context { wrapper: Wrapper { payload: Payload{} } };
+   |                                 ++++++++++++++++++           +
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
index 68da46d46bd..1461e7fd2dd 100644
--- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
@@ -4,12 +4,10 @@ warning: function cannot return without recursing
 LL | / fn no_hrtb<'b, T>(mut t: T)
 LL | | where
 LL | |     T: Bar<&'b isize>,
-LL | | {
-...  |
-LL | |     no_hrtb(&mut t);
-   | |     --------------- recursive call site
-LL | | }
-   | |_^ cannot return without recursing
+   | |______________________^ cannot return without recursing
+...
+LL |       no_hrtb(&mut t);
+   |       --------------- recursive call site
    |
    = note: `#[warn(unconditional_recursion)]` on by default
    = help: a `loop` may express intention better if this is on purpose
@@ -20,12 +18,10 @@ warning: function cannot return without recursing
 LL | / fn bar_hrtb<T>(mut t: T)
 LL | | where
 LL | |     T: for<'b> Bar<&'b isize>,
-LL | | {
-...  |
-LL | |     bar_hrtb(&mut t);
-   | |     ---------------- recursive call site
-LL | | }
-   | |_^ cannot return without recursing
+   | |______________________________^ cannot return without recursing
+...
+LL |       bar_hrtb(&mut t);
+   |       ---------------- recursive call site
    |
    = help: a `loop` may express intention better if this is on purpose
 
@@ -35,14 +31,10 @@ warning: function cannot return without recursing
 LL | / fn foo_hrtb_bar_not<'b, T>(mut t: T)
 LL | | where
 LL | |     T: for<'a> Foo<&'a isize> + Bar<&'b isize>,
-LL | | {
-...  |
-LL | |     foo_hrtb_bar_not(&mut t);
-   | |     ------------------------ recursive call site
-LL | |
-LL | |
-LL | | }
-   | |_^ cannot return without recursing
+   | |_______________________________________________^ cannot return without recursing
+...
+LL |       foo_hrtb_bar_not(&mut t);
+   |       ------------------------ recursive call site
    |
    = help: a `loop` may express intention better if this is on purpose
 
@@ -70,12 +62,10 @@ warning: function cannot return without recursing
 LL | / fn foo_hrtb_bar_hrtb<T>(mut t: T)
 LL | | where
 LL | |     T: for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>,
-LL | | {
-LL | |     // OK -- now we have `T : for<'b> Bar<&'b isize>`.
-LL | |     foo_hrtb_bar_hrtb(&mut t);
-   | |     ------------------------- recursive call site
-LL | | }
-   | |_^ cannot return without recursing
+   | |_______________________________________________________^ cannot return without recursing
+...
+LL |       foo_hrtb_bar_hrtb(&mut t);
+   |       ------------------------- recursive call site
    |
    = help: a `loop` may express intention better if this is on purpose
 
diff --git a/src/test/ui/issues/issue-12511.stderr b/src/test/ui/issues/issue-12511.stderr
index 5f2b98c5237..789a1141c04 100644
--- a/src/test/ui/issues/issue-12511.stderr
+++ b/src/test/ui/issues/issue-12511.stderr
@@ -23,8 +23,10 @@ LL | trait T2 : T1 {
 note: cycle used when collecting item types in top-level module
   --> $DIR/issue-12511.rs:1:1
    |
-LL | trait T1 : T2 {
-   | ^^^^^^^^^^^^^
+LL | / trait T1 : T2 {
+LL | |
+LL | | }
+   | |_^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/layout/debug.stderr b/src/test/ui/layout/debug.stderr
index 7ba9657fcd6..c5e1c41d130 100644
--- a/src/test/ui/layout/debug.stderr
+++ b/src/test/ui/layout/debug.stderr
@@ -1,4 +1,12 @@
 error: layout_of(E) = Layout {
+           size: Size(12 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(4 bytes),
+               pref: $PREF_ALIGN,
+           },
+           abi: Aggregate {
+               sized: true,
+           },
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -7,6 +15,16 @@ error: layout_of(E) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I32,
+                       false,
+                   ),
+                   valid_range: 0..=0,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -19,24 +37,30 @@ error: layout_of(E) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(4 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(1 bytes),
+                           pref: $PREF_ALIGN,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
+                   },
+                   Layout {
+                       size: Size(12 bytes),
                        align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
+                           abi: Align(4 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       size: Size(4 bytes),
-                   },
-                   Layout {
+                       abi: Uninhabited,
                        fields: Arbitrary {
                            offsets: [
                                Size(4 bytes),
@@ -49,37 +73,13 @@ error: layout_of(E) = Layout {
                                2,
                            ],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 1,
                        },
-                       abi: Uninhabited,
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(4 bytes),
-                           pref: $PREF_ALIGN,
-                       },
-                       size: Size(12 bytes),
                    },
                ],
            },
-           abi: Aggregate {
-               sized: true,
-           },
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I32,
-                       false,
-                   ),
-                   valid_range: 0..=0,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(4 bytes),
-               pref: $PREF_ALIGN,
-           },
-           size: Size(12 bytes),
        }
   --> $DIR/debug.rs:6:1
    |
@@ -87,20 +87,10 @@ LL | enum E { Foo, Bar(!, i32, i32) }
    | ^^^^^^
 
 error: layout_of(S) = Layout {
-           fields: Arbitrary {
-               offsets: [
-                   Size(0 bytes),
-                   Size(0 bytes),
-                   Size(4 bytes),
-               ],
-               memory_index: [
-                   1,
-                   0,
-                   2,
-               ],
-           },
-           variants: Single {
-               index: 0,
+           size: Size(8 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(4 bytes),
+               pref: $PREF_ALIGN,
            },
            abi: ScalarPair(
                Initialized {
@@ -118,12 +108,22 @@ error: layout_of(S) = Layout {
                    valid_range: 0..=4294967295,
                },
            ),
+           fields: Arbitrary {
+               offsets: [
+                   Size(0 bytes),
+                   Size(0 bytes),
+                   Size(4 bytes),
+               ],
+               memory_index: [
+                   1,
+                   0,
+                   2,
+               ],
+           },
            largest_niche: None,
-           align: AbiAndPrefAlign {
-               abi: Align(4 bytes),
-               pref: $PREF_ALIGN,
+           variants: Single {
+               index: 0,
            },
-           size: Size(8 bytes),
        }
   --> $DIR/debug.rs:9:1
    |
@@ -131,21 +131,21 @@ LL | struct S { f1: i32, f2: (), f3: i32 }
    | ^^^^^^^^
 
 error: layout_of(U) = Layout {
-           fields: Union(
-               2,
-           ),
-           variants: Single {
-               index: 0,
+           size: Size(8 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(4 bytes),
+               pref: $PREF_ALIGN,
            },
            abi: Aggregate {
                sized: true,
            },
+           fields: Union(
+               2,
+           ),
            largest_niche: None,
-           align: AbiAndPrefAlign {
-               abi: Align(4 bytes),
-               pref: $PREF_ALIGN,
+           variants: Single {
+               index: 0,
            },
-           size: Size(8 bytes),
        }
   --> $DIR/debug.rs:12:1
    |
@@ -153,6 +153,27 @@ LL | union U { f1: (i32, i32), f3: i32 }
    | ^^^^^^^
 
 error: layout_of(std::result::Result<i32, i32>) = Layout {
+           size: Size(8 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(4 bytes),
+               pref: $PREF_ALIGN,
+           },
+           abi: ScalarPair(
+               Initialized {
+                   value: Int(
+                       I32,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+               Initialized {
+                   value: Int(
+                       I32,
+                       true,
+                   ),
+                   valid_range: 0..=4294967295,
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -161,6 +182,16 @@ error: layout_of(std::result::Result<i32, i32>) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I32,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -173,16 +204,10 @@ error: layout_of(std::result::Result<i32, i32>) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
-                       fields: Arbitrary {
-                           offsets: [
-                               Size(4 bytes),
-                           ],
-                           memory_index: [
-                               0,
-                           ],
-                       },
-                       variants: Single {
-                           index: 0,
+                       size: Size(8 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(4 bytes),
+                           pref: $PREF_ALIGN,
                        },
                        abi: ScalarPair(
                            Initialized {
@@ -200,14 +225,6 @@ error: layout_of(std::result::Result<i32, i32>) = Layout {
                                valid_range: 0..=4294967295,
                            },
                        ),
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(4 bytes),
-                           pref: $PREF_ALIGN,
-                       },
-                       size: Size(8 bytes),
-                   },
-                   Layout {
                        fields: Arbitrary {
                            offsets: [
                                Size(4 bytes),
@@ -216,8 +233,16 @@ error: layout_of(std::result::Result<i32, i32>) = Layout {
                                0,
                            ],
                        },
+                       largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: 0,
+                       },
+                   },
+                   Layout {
+                       size: Size(8 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(4 bytes),
+                           pref: $PREF_ALIGN,
                        },
                        abi: ScalarPair(
                            Initialized {
@@ -235,46 +260,21 @@ error: layout_of(std::result::Result<i32, i32>) = Layout {
                                valid_range: 0..=4294967295,
                            },
                        ),
+                       fields: Arbitrary {
+                           offsets: [
+                               Size(4 bytes),
+                           ],
+                           memory_index: [
+                               0,
+                           ],
+                       },
                        largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(4 bytes),
-                           pref: $PREF_ALIGN,
+                       variants: Single {
+                           index: 1,
                        },
-                       size: Size(8 bytes),
                    },
                ],
            },
-           abi: ScalarPair(
-               Initialized {
-                   value: Int(
-                       I32,
-                       false,
-                   ),
-                   valid_range: 0..=1,
-               },
-               Initialized {
-                   value: Int(
-                       I32,
-                       true,
-                   ),
-                   valid_range: 0..=4294967295,
-               },
-           ),
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I32,
-                       false,
-                   ),
-                   valid_range: 0..=1,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(4 bytes),
-               pref: $PREF_ALIGN,
-           },
-           size: Size(8 bytes),
        }
   --> $DIR/debug.rs:15:1
    |
@@ -282,9 +282,10 @@ LL | type Test = Result<i32, i32>;
    | ^^^^^^^^^
 
 error: layout_of(i32) = Layout {
-           fields: Primitive,
-           variants: Single {
-               index: 0,
+           size: Size(4 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(4 bytes),
+               pref: $PREF_ALIGN,
            },
            abi: Scalar(
                Initialized {
@@ -295,12 +296,11 @@ error: layout_of(i32) = Layout {
                    valid_range: 0..=4294967295,
                },
            ),
+           fields: Primitive,
            largest_niche: None,
-           align: AbiAndPrefAlign {
-               abi: Align(4 bytes),
-               pref: $PREF_ALIGN,
+           variants: Single {
+               index: 0,
            },
-           size: Size(4 bytes),
        }
   --> $DIR/debug.rs:18:1
    |
diff --git a/src/test/ui/layout/hexagon-enum.stderr b/src/test/ui/layout/hexagon-enum.stderr
index f3123cb0ad2..d850dd69c96 100644
--- a/src/test/ui/layout/hexagon-enum.stderr
+++ b/src/test/ui/layout/hexagon-enum.stderr
@@ -1,4 +1,18 @@
 error: layout_of(A) = Layout {
+           size: Size(1 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(1 bytes),
+               pref: Align(1 bytes),
+           },
+           abi: Scalar(
+               Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=0,
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -7,6 +21,16 @@ error: layout_of(A) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=0,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -19,34 +43,54 @@ error: layout_of(A) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(1 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(1 bytes),
+                           pref: Align(1 bytes),
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: Align(1 bytes),
-                       },
-                       size: Size(1 bytes),
                    },
                ],
            },
+       }
+  --> $DIR/hexagon-enum.rs:16:1
+   |
+LL | enum A { Apple }
+   | ^^^^^^
+
+error: layout_of(B) = Layout {
+           size: Size(1 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(1 bytes),
+               pref: Align(1 bytes),
+           },
            abi: Scalar(
                Initialized {
                    value: Int(
                        I8,
                        false,
                    ),
-                   valid_range: 0..=0,
+                   valid_range: 255..=255,
                },
            ),
+           fields: Arbitrary {
+               offsets: [
+                   Size(0 bytes),
+               ],
+               memory_index: [
+                   0,
+               ],
+           },
            largest_niche: Some(
                Niche {
                    offset: Size(0 bytes),
@@ -54,29 +98,9 @@ error: layout_of(A) = Layout {
                        I8,
                        false,
                    ),
-                   valid_range: 0..=0,
+                   valid_range: 255..=255,
                },
            ),
-           align: AbiAndPrefAlign {
-               abi: Align(1 bytes),
-               pref: Align(1 bytes),
-           },
-           size: Size(1 bytes),
-       }
-  --> $DIR/hexagon-enum.rs:16:1
-   |
-LL | enum A { Apple }
-   | ^^^^^^
-
-error: layout_of(B) = Layout {
-           fields: Arbitrary {
-               offsets: [
-                   Size(0 bytes),
-               ],
-               memory_index: [
-                   0,
-               ],
-           },
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -89,49 +113,25 @@ error: layout_of(B) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(1 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(1 bytes),
+                           pref: Align(1 bytes),
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: Align(1 bytes),
-                       },
-                       size: Size(1 bytes),
                    },
                ],
            },
-           abi: Scalar(
-               Initialized {
-                   value: Int(
-                       I8,
-                       false,
-                   ),
-                   valid_range: 255..=255,
-               },
-           ),
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I8,
-                       false,
-                   ),
-                   valid_range: 255..=255,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(1 bytes),
-               pref: Align(1 bytes),
-           },
-           size: Size(1 bytes),
        }
   --> $DIR/hexagon-enum.rs:20:1
    |
@@ -139,6 +139,20 @@ LL | enum B { Banana = 255, }
    | ^^^^^^
 
 error: layout_of(C) = Layout {
+           size: Size(2 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(2 bytes),
+               pref: Align(2 bytes),
+           },
+           abi: Scalar(
+               Initialized {
+                   value: Int(
+                       I16,
+                       false,
+                   ),
+                   valid_range: 256..=256,
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -147,6 +161,16 @@ error: layout_of(C) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I16,
+                       false,
+                   ),
+                   valid_range: 256..=256,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -159,49 +183,25 @@ error: layout_of(C) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(2 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(2 bytes),
+                           pref: Align(2 bytes),
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(2 bytes),
-                           pref: Align(2 bytes),
-                       },
-                       size: Size(2 bytes),
                    },
                ],
            },
-           abi: Scalar(
-               Initialized {
-                   value: Int(
-                       I16,
-                       false,
-                   ),
-                   valid_range: 256..=256,
-               },
-           ),
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I16,
-                       false,
-                   ),
-                   valid_range: 256..=256,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(2 bytes),
-               pref: Align(2 bytes),
-           },
-           size: Size(2 bytes),
        }
   --> $DIR/hexagon-enum.rs:24:1
    |
@@ -209,6 +209,20 @@ LL | enum C { Chaenomeles = 256, }
    | ^^^^^^
 
 error: layout_of(P) = Layout {
+           size: Size(4 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(4 bytes),
+               pref: Align(4 bytes),
+           },
+           abi: Scalar(
+               Initialized {
+                   value: Int(
+                       I32,
+                       false,
+                   ),
+                   valid_range: 268435456..=268435456,
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -217,6 +231,16 @@ error: layout_of(P) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I32,
+                       false,
+                   ),
+                   valid_range: 268435456..=268435456,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -229,49 +253,25 @@ error: layout_of(P) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(4 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(4 bytes),
+                           pref: Align(4 bytes),
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(4 bytes),
-                           pref: Align(4 bytes),
-                       },
-                       size: Size(4 bytes),
                    },
                ],
            },
-           abi: Scalar(
-               Initialized {
-                   value: Int(
-                       I32,
-                       false,
-                   ),
-                   valid_range: 268435456..=268435456,
-               },
-           ),
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I32,
-                       false,
-                   ),
-                   valid_range: 268435456..=268435456,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(4 bytes),
-               pref: Align(4 bytes),
-           },
-           size: Size(4 bytes),
        }
   --> $DIR/hexagon-enum.rs:28:1
    |
@@ -279,6 +279,20 @@ LL | enum P { Peach = 0x1000_0000isize, }
    | ^^^^^^
 
 error: layout_of(T) = Layout {
+           size: Size(4 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(4 bytes),
+               pref: Align(4 bytes),
+           },
+           abi: Scalar(
+               Initialized {
+                   value: Int(
+                       I32,
+                       true,
+                   ),
+                   valid_range: 2164260864..=2164260864,
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -287,6 +301,16 @@ error: layout_of(T) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I32,
+                       true,
+                   ),
+                   valid_range: 2164260864..=2164260864,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -299,49 +323,25 @@ error: layout_of(T) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(4 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(4 bytes),
+                           pref: Align(4 bytes),
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(4 bytes),
-                           pref: Align(4 bytes),
-                       },
-                       size: Size(4 bytes),
                    },
                ],
            },
-           abi: Scalar(
-               Initialized {
-                   value: Int(
-                       I32,
-                       true,
-                   ),
-                   valid_range: 2164260864..=2164260864,
-               },
-           ),
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I32,
-                       true,
-                   ),
-                   valid_range: 2164260864..=2164260864,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(4 bytes),
-               pref: Align(4 bytes),
-           },
-           size: Size(4 bytes),
        }
   --> $DIR/hexagon-enum.rs:34:1
    |
diff --git a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
index 84d8bc799b9..6deb1f271a7 100644
--- a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
+++ b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
@@ -1,4 +1,24 @@
 error: layout_of(MissingPayloadField) = Layout {
+           size: Size(2 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(1 bytes),
+               pref: $PREF_ALIGN,
+           },
+           abi: ScalarPair(
+               Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+               Union {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -7,6 +27,16 @@ error: layout_of(MissingPayloadField) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -19,16 +49,10 @@ error: layout_of(MissingPayloadField) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
-                       fields: Arbitrary {
-                           offsets: [
-                               Size(1 bytes),
-                           ],
-                           memory_index: [
-                               0,
-                           ],
-                       },
-                       variants: Single {
-                           index: 0,
+                       size: Size(2 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(1 bytes),
+                           pref: $PREF_ALIGN,
                        },
                        abi: ScalarPair(
                            Initialized {
@@ -45,33 +69,51 @@ error: layout_of(MissingPayloadField) = Layout {
                                ),
                            },
                        ),
+                       fields: Arbitrary {
+                           offsets: [
+                               Size(1 bytes),
+                           ],
+                           memory_index: [
+                               0,
+                           ],
+                       },
                        largest_niche: None,
+                       variants: Single {
+                           index: 0,
+                       },
+                   },
+                   Layout {
+                       size: Size(1 bytes),
                        align: AbiAndPrefAlign {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       size: Size(2 bytes),
-                   },
-                   Layout {
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 1,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: $PREF_ALIGN,
-                       },
-                       size: Size(1 bytes),
                    },
                ],
            },
+       }
+  --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:16:1
+   |
+LL | pub enum MissingPayloadField {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: layout_of(CommonPayloadField) = Layout {
+           size: Size(2 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(1 bytes),
+               pref: $PREF_ALIGN,
+           },
            abi: ScalarPair(
                Initialized {
                    value: Int(
@@ -80,13 +122,22 @@ error: layout_of(MissingPayloadField) = Layout {
                    ),
                    valid_range: 0..=1,
                },
-               Union {
+               Initialized {
                    value: Int(
                        I8,
                        false,
                    ),
+                   valid_range: 0..=255,
                },
            ),
+           fields: Arbitrary {
+               offsets: [
+                   Size(0 bytes),
+               ],
+               memory_index: [
+                   0,
+               ],
+           },
            largest_niche: Some(
                Niche {
                    offset: Size(0 bytes),
@@ -97,26 +148,6 @@ error: layout_of(MissingPayloadField) = Layout {
                    valid_range: 0..=1,
                },
            ),
-           align: AbiAndPrefAlign {
-               abi: Align(1 bytes),
-               pref: $PREF_ALIGN,
-           },
-           size: Size(2 bytes),
-       }
-  --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:16:1
-   |
-LL | pub enum MissingPayloadField {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: layout_of(CommonPayloadField) = Layout {
-           fields: Arbitrary {
-               offsets: [
-                   Size(0 bytes),
-               ],
-               memory_index: [
-                   0,
-               ],
-           },
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -129,16 +160,10 @@ error: layout_of(CommonPayloadField) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
-                       fields: Arbitrary {
-                           offsets: [
-                               Size(1 bytes),
-                           ],
-                           memory_index: [
-                               0,
-                           ],
-                       },
-                       variants: Single {
-                           index: 0,
+                       size: Size(2 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(1 bytes),
+                           pref: $PREF_ALIGN,
                        },
                        abi: ScalarPair(
                            Initialized {
@@ -156,14 +181,6 @@ error: layout_of(CommonPayloadField) = Layout {
                                valid_range: 0..=255,
                            },
                        ),
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: $PREF_ALIGN,
-                       },
-                       size: Size(2 bytes),
-                   },
-                   Layout {
                        fields: Arbitrary {
                            offsets: [
                                Size(1 bytes),
@@ -172,8 +189,16 @@ error: layout_of(CommonPayloadField) = Layout {
                                0,
                            ],
                        },
+                       largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: 0,
+                       },
+                   },
+                   Layout {
+                       size: Size(2 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(1 bytes),
+                           pref: $PREF_ALIGN,
                        },
                        abi: ScalarPair(
                            Initialized {
@@ -191,15 +216,33 @@ error: layout_of(CommonPayloadField) = Layout {
                                valid_range: 0..=255,
                            },
                        ),
+                       fields: Arbitrary {
+                           offsets: [
+                               Size(1 bytes),
+                           ],
+                           memory_index: [
+                               0,
+                           ],
+                       },
                        largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: $PREF_ALIGN,
+                       variants: Single {
+                           index: 1,
                        },
-                       size: Size(2 bytes),
                    },
                ],
            },
+       }
+  --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:25:1
+   |
+LL | pub enum CommonPayloadField {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
+           size: Size(2 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(1 bytes),
+               pref: $PREF_ALIGN,
+           },
            abi: ScalarPair(
                Initialized {
                    value: Int(
@@ -208,14 +251,21 @@ error: layout_of(CommonPayloadField) = Layout {
                    ),
                    valid_range: 0..=1,
                },
-               Initialized {
+               Union {
                    value: Int(
                        I8,
                        false,
                    ),
-                   valid_range: 0..=255,
                },
            ),
+           fields: Arbitrary {
+               offsets: [
+                   Size(0 bytes),
+               ],
+               memory_index: [
+                   0,
+               ],
+           },
            largest_niche: Some(
                Niche {
                    offset: Size(0 bytes),
@@ -226,26 +276,6 @@ error: layout_of(CommonPayloadField) = Layout {
                    valid_range: 0..=1,
                },
            ),
-           align: AbiAndPrefAlign {
-               abi: Align(1 bytes),
-               pref: $PREF_ALIGN,
-           },
-           size: Size(2 bytes),
-       }
-  --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:25:1
-   |
-LL | pub enum CommonPayloadField {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
-           fields: Arbitrary {
-               offsets: [
-                   Size(0 bytes),
-               ],
-               memory_index: [
-                   0,
-               ],
-           },
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -258,16 +288,10 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
-                       fields: Arbitrary {
-                           offsets: [
-                               Size(1 bytes),
-                           ],
-                           memory_index: [
-                               0,
-                           ],
-                       },
-                       variants: Single {
-                           index: 0,
+                       size: Size(2 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(1 bytes),
+                           pref: $PREF_ALIGN,
                        },
                        abi: ScalarPair(
                            Initialized {
@@ -284,14 +308,6 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
                                ),
                            },
                        ),
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: $PREF_ALIGN,
-                       },
-                       size: Size(2 bytes),
-                   },
-                   Layout {
                        fields: Arbitrary {
                            offsets: [
                                Size(1 bytes),
@@ -300,8 +316,16 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
                                0,
                            ],
                        },
+                       largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: 0,
+                       },
+                   },
+                   Layout {
+                       size: Size(2 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(1 bytes),
+                           pref: $PREF_ALIGN,
                        },
                        abi: ScalarPair(
                            Initialized {
@@ -318,22 +342,40 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
                                ),
                            },
                        ),
+                       fields: Arbitrary {
+                           offsets: [
+                               Size(1 bytes),
+                           ],
+                           memory_index: [
+                               0,
+                           ],
+                       },
                        largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: $PREF_ALIGN,
+                       variants: Single {
+                           index: 1,
                        },
-                       size: Size(2 bytes),
                    },
                ],
            },
+       }
+  --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:33:1
+   |
+LL | pub enum CommonPayloadFieldIsMaybeUninit {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: layout_of(NicheFirst) = Layout {
+           size: Size(2 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(1 bytes),
+               pref: $PREF_ALIGN,
+           },
            abi: ScalarPair(
                Initialized {
                    value: Int(
                        I8,
                        false,
                    ),
-                   valid_range: 0..=1,
+                   valid_range: 0..=4,
                },
                Union {
                    value: Int(
@@ -342,6 +384,14 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
                    ),
                },
            ),
+           fields: Arbitrary {
+               offsets: [
+                   Size(0 bytes),
+               ],
+               memory_index: [
+                   0,
+               ],
+           },
            largest_niche: Some(
                Niche {
                    offset: Size(0 bytes),
@@ -349,29 +399,9 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
                        I8,
                        false,
                    ),
-                   valid_range: 0..=1,
+                   valid_range: 0..=4,
                },
            ),
-           align: AbiAndPrefAlign {
-               abi: Align(1 bytes),
-               pref: $PREF_ALIGN,
-           },
-           size: Size(2 bytes),
-       }
-  --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:33:1
-   |
-LL | pub enum CommonPayloadFieldIsMaybeUninit {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: layout_of(NicheFirst) = Layout {
-           fields: Arbitrary {
-               offsets: [
-                   Size(0 bytes),
-               ],
-               memory_index: [
-                   0,
-               ],
-           },
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -388,18 +418,10 @@ error: layout_of(NicheFirst) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
-                       fields: Arbitrary {
-                           offsets: [
-                               Size(0 bytes),
-                               Size(1 bytes),
-                           ],
-                           memory_index: [
-                               0,
-                               1,
-                           ],
-                       },
-                       variants: Single {
-                           index: 0,
+                       size: Size(2 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(1 bytes),
+                           pref: $PREF_ALIGN,
                        },
                        abi: ScalarPair(
                            Initialized {
@@ -417,6 +439,16 @@ error: layout_of(NicheFirst) = Layout {
                                valid_range: 0..=255,
                            },
                        ),
+                       fields: Arbitrary {
+                           offsets: [
+                               Size(0 bytes),
+                               Size(1 bytes),
+                           ],
+                           memory_index: [
+                               0,
+                               1,
+                           ],
+                       },
                        largest_niche: Some(
                            Niche {
                                offset: Size(0 bytes),
@@ -427,68 +459,68 @@ error: layout_of(NicheFirst) = Layout {
                                valid_range: 0..=2,
                            },
                        ),
+                       variants: Single {
+                           index: 0,
+                       },
+                   },
+                   Layout {
+                       size: Size(0 bytes),
                        align: AbiAndPrefAlign {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       size: Size(2 bytes),
-                   },
-                   Layout {
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 1,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
+                   },
+                   Layout {
+                       size: Size(0 bytes),
                        align: AbiAndPrefAlign {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       size: Size(0 bytes),
-                   },
-                   Layout {
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 2,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: $PREF_ALIGN,
-                       },
-                       size: Size(0 bytes),
                    },
                ],
            },
+       }
+  --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:41:1
+   |
+LL | pub enum NicheFirst {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: layout_of(NicheSecond) = Layout {
+           size: Size(2 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(1 bytes),
+               pref: $PREF_ALIGN,
+           },
            abi: ScalarPair(
-               Initialized {
-                   value: Int(
-                       I8,
-                       false,
-                   ),
-                   valid_range: 0..=4,
-               },
                Union {
                    value: Int(
                        I8,
                        false,
                    ),
                },
-           ),
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
+               Initialized {
                    value: Int(
                        I8,
                        false,
@@ -496,18 +528,6 @@ error: layout_of(NicheFirst) = Layout {
                    valid_range: 0..=4,
                },
            ),
-           align: AbiAndPrefAlign {
-               abi: Align(1 bytes),
-               pref: $PREF_ALIGN,
-           },
-           size: Size(2 bytes),
-       }
-  --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:41:1
-   |
-LL | pub enum NicheFirst {
-   | ^^^^^^^^^^^^^^^^^^^
-
-error: layout_of(NicheSecond) = Layout {
            fields: Arbitrary {
                offsets: [
                    Size(1 bytes),
@@ -516,6 +536,16 @@ error: layout_of(NicheSecond) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(1 bytes),
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=4,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -532,18 +562,10 @@ error: layout_of(NicheSecond) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
-                       fields: Arbitrary {
-                           offsets: [
-                               Size(0 bytes),
-                               Size(1 bytes),
-                           ],
-                           memory_index: [
-                               0,
-                               1,
-                           ],
-                       },
-                       variants: Single {
-                           index: 0,
+                       size: Size(2 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(1 bytes),
+                           pref: $PREF_ALIGN,
                        },
                        abi: ScalarPair(
                            Initialized {
@@ -561,6 +583,16 @@ error: layout_of(NicheSecond) = Layout {
                                valid_range: 0..=2,
                            },
                        ),
+                       fields: Arbitrary {
+                           offsets: [
+                               Size(0 bytes),
+                               Size(1 bytes),
+                           ],
+                           memory_index: [
+                               0,
+                               1,
+                           ],
+                       },
                        largest_niche: Some(
                            Niche {
                                offset: Size(1 bytes),
@@ -571,80 +603,48 @@ error: layout_of(NicheSecond) = Layout {
                                valid_range: 0..=2,
                            },
                        ),
+                       variants: Single {
+                           index: 0,
+                       },
+                   },
+                   Layout {
+                       size: Size(0 bytes),
                        align: AbiAndPrefAlign {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       size: Size(2 bytes),
-                   },
-                   Layout {
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 1,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
+                   },
+                   Layout {
+                       size: Size(0 bytes),
                        align: AbiAndPrefAlign {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       size: Size(0 bytes),
-                   },
-                   Layout {
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 2,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: $PREF_ALIGN,
-                       },
-                       size: Size(0 bytes),
                    },
                ],
            },
-           abi: ScalarPair(
-               Union {
-                   value: Int(
-                       I8,
-                       false,
-                   ),
-               },
-               Initialized {
-                   value: Int(
-                       I8,
-                       false,
-                   ),
-                   valid_range: 0..=4,
-               },
-           ),
-           largest_niche: Some(
-               Niche {
-                   offset: Size(1 bytes),
-                   value: Int(
-                       I8,
-                       false,
-                   ),
-                   valid_range: 0..=4,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(1 bytes),
-               pref: $PREF_ALIGN,
-           },
-           size: Size(2 bytes),
        }
   --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:50:1
    |
diff --git a/src/test/ui/layout/issue-96185-overaligned-enum.stderr b/src/test/ui/layout/issue-96185-overaligned-enum.stderr
index 8dc364fa7c9..de6177c8dfc 100644
--- a/src/test/ui/layout/issue-96185-overaligned-enum.stderr
+++ b/src/test/ui/layout/issue-96185-overaligned-enum.stderr
@@ -1,4 +1,12 @@
 error: layout_of(Aligned1) = Layout {
+           size: Size(8 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(8 bytes),
+               pref: $PREF_ALIGN,
+           },
+           abi: Aggregate {
+               sized: true,
+           },
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -7,6 +15,16 @@ error: layout_of(Aligned1) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -19,49 +37,57 @@ error: layout_of(Aligned1) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(8 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(8 bytes),
+                           pref: $PREF_ALIGN,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
+                   },
+                   Layout {
+                       size: Size(8 bytes),
                        align: AbiAndPrefAlign {
                            abi: Align(8 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       size: Size(8 bytes),
-                   },
-                   Layout {
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 1,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(8 bytes),
-                           pref: $PREF_ALIGN,
-                       },
-                       size: Size(8 bytes),
                    },
                ],
            },
-           abi: Aggregate {
-               sized: true,
+       }
+  --> $DIR/issue-96185-overaligned-enum.rs:8:1
+   |
+LL | pub enum Aligned1 {
+   | ^^^^^^^^^^^^^^^^^
+
+error: layout_of(Aligned2) = Layout {
+           size: Size(1 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(1 bytes),
+               pref: $PREF_ALIGN,
            },
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
+           abi: Scalar(
+               Initialized {
                    value: Int(
                        I8,
                        false,
@@ -69,18 +95,6 @@ error: layout_of(Aligned1) = Layout {
                    valid_range: 0..=1,
                },
            ),
-           align: AbiAndPrefAlign {
-               abi: Align(8 bytes),
-               pref: $PREF_ALIGN,
-           },
-           size: Size(8 bytes),
-       }
-  --> $DIR/issue-96185-overaligned-enum.rs:8:1
-   |
-LL | pub enum Aligned1 {
-   | ^^^^^^^^^^^^^^^^^
-
-error: layout_of(Aligned2) = Layout {
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -89,6 +103,16 @@ error: layout_of(Aligned2) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -101,67 +125,43 @@ error: layout_of(Aligned2) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(1 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(1 bytes),
+                           pref: $PREF_ALIGN,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
+                   },
+                   Layout {
+                       size: Size(1 bytes),
                        align: AbiAndPrefAlign {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       size: Size(1 bytes),
-                   },
-                   Layout {
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 1,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: $PREF_ALIGN,
-                       },
-                       size: Size(1 bytes),
                    },
                ],
            },
-           abi: Scalar(
-               Initialized {
-                   value: Int(
-                       I8,
-                       false,
-                   ),
-                   valid_range: 0..=1,
-               },
-           ),
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I8,
-                       false,
-                   ),
-                   valid_range: 0..=1,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(1 bytes),
-               pref: $PREF_ALIGN,
-           },
-           size: Size(1 bytes),
        }
   --> $DIR/issue-96185-overaligned-enum.rs:16:1
    |
diff --git a/src/test/ui/layout/thumb-enum.stderr b/src/test/ui/layout/thumb-enum.stderr
index e6ed626d5f1..227bd950b66 100644
--- a/src/test/ui/layout/thumb-enum.stderr
+++ b/src/test/ui/layout/thumb-enum.stderr
@@ -1,4 +1,18 @@
 error: layout_of(A) = Layout {
+           size: Size(1 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(1 bytes),
+               pref: Align(4 bytes),
+           },
+           abi: Scalar(
+               Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=0,
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -7,6 +21,16 @@ error: layout_of(A) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=0,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -19,34 +43,54 @@ error: layout_of(A) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(1 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(1 bytes),
+                           pref: Align(4 bytes),
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: Align(4 bytes),
-                       },
-                       size: Size(1 bytes),
                    },
                ],
            },
+       }
+  --> $DIR/thumb-enum.rs:16:1
+   |
+LL | enum A { Apple }
+   | ^^^^^^
+
+error: layout_of(B) = Layout {
+           size: Size(1 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(1 bytes),
+               pref: Align(4 bytes),
+           },
            abi: Scalar(
                Initialized {
                    value: Int(
                        I8,
                        false,
                    ),
-                   valid_range: 0..=0,
+                   valid_range: 255..=255,
                },
            ),
+           fields: Arbitrary {
+               offsets: [
+                   Size(0 bytes),
+               ],
+               memory_index: [
+                   0,
+               ],
+           },
            largest_niche: Some(
                Niche {
                    offset: Size(0 bytes),
@@ -54,29 +98,9 @@ error: layout_of(A) = Layout {
                        I8,
                        false,
                    ),
-                   valid_range: 0..=0,
+                   valid_range: 255..=255,
                },
            ),
-           align: AbiAndPrefAlign {
-               abi: Align(1 bytes),
-               pref: Align(4 bytes),
-           },
-           size: Size(1 bytes),
-       }
-  --> $DIR/thumb-enum.rs:16:1
-   |
-LL | enum A { Apple }
-   | ^^^^^^
-
-error: layout_of(B) = Layout {
-           fields: Arbitrary {
-               offsets: [
-                   Size(0 bytes),
-               ],
-               memory_index: [
-                   0,
-               ],
-           },
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -89,49 +113,25 @@ error: layout_of(B) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(1 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(1 bytes),
+                           pref: Align(4 bytes),
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: Align(4 bytes),
-                       },
-                       size: Size(1 bytes),
                    },
                ],
            },
-           abi: Scalar(
-               Initialized {
-                   value: Int(
-                       I8,
-                       false,
-                   ),
-                   valid_range: 255..=255,
-               },
-           ),
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I8,
-                       false,
-                   ),
-                   valid_range: 255..=255,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(1 bytes),
-               pref: Align(4 bytes),
-           },
-           size: Size(1 bytes),
        }
   --> $DIR/thumb-enum.rs:20:1
    |
@@ -139,6 +139,20 @@ LL | enum B { Banana = 255, }
    | ^^^^^^
 
 error: layout_of(C) = Layout {
+           size: Size(2 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(2 bytes),
+               pref: Align(4 bytes),
+           },
+           abi: Scalar(
+               Initialized {
+                   value: Int(
+                       I16,
+                       false,
+                   ),
+                   valid_range: 256..=256,
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -147,6 +161,16 @@ error: layout_of(C) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I16,
+                       false,
+                   ),
+                   valid_range: 256..=256,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -159,49 +183,25 @@ error: layout_of(C) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(2 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(2 bytes),
+                           pref: Align(4 bytes),
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(2 bytes),
-                           pref: Align(4 bytes),
-                       },
-                       size: Size(2 bytes),
                    },
                ],
            },
-           abi: Scalar(
-               Initialized {
-                   value: Int(
-                       I16,
-                       false,
-                   ),
-                   valid_range: 256..=256,
-               },
-           ),
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I16,
-                       false,
-                   ),
-                   valid_range: 256..=256,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(2 bytes),
-               pref: Align(4 bytes),
-           },
-           size: Size(2 bytes),
        }
   --> $DIR/thumb-enum.rs:24:1
    |
@@ -209,6 +209,20 @@ LL | enum C { Chaenomeles = 256, }
    | ^^^^^^
 
 error: layout_of(P) = Layout {
+           size: Size(4 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(4 bytes),
+               pref: Align(4 bytes),
+           },
+           abi: Scalar(
+               Initialized {
+                   value: Int(
+                       I32,
+                       false,
+                   ),
+                   valid_range: 268435456..=268435456,
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -217,6 +231,16 @@ error: layout_of(P) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I32,
+                       false,
+                   ),
+                   valid_range: 268435456..=268435456,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -229,49 +253,25 @@ error: layout_of(P) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(4 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(4 bytes),
+                           pref: Align(4 bytes),
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(4 bytes),
-                           pref: Align(4 bytes),
-                       },
-                       size: Size(4 bytes),
                    },
                ],
            },
-           abi: Scalar(
-               Initialized {
-                   value: Int(
-                       I32,
-                       false,
-                   ),
-                   valid_range: 268435456..=268435456,
-               },
-           ),
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I32,
-                       false,
-                   ),
-                   valid_range: 268435456..=268435456,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(4 bytes),
-               pref: Align(4 bytes),
-           },
-           size: Size(4 bytes),
        }
   --> $DIR/thumb-enum.rs:28:1
    |
@@ -279,6 +279,20 @@ LL | enum P { Peach = 0x1000_0000isize, }
    | ^^^^^^
 
 error: layout_of(T) = Layout {
+           size: Size(4 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(4 bytes),
+               pref: Align(4 bytes),
+           },
+           abi: Scalar(
+               Initialized {
+                   value: Int(
+                       I32,
+                       true,
+                   ),
+                   valid_range: 2164260864..=2164260864,
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -287,6 +301,16 @@ error: layout_of(T) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I32,
+                       true,
+                   ),
+                   valid_range: 2164260864..=2164260864,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -299,49 +323,25 @@ error: layout_of(T) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(4 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(4 bytes),
+                           pref: Align(4 bytes),
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [],
                            memory_index: [],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
-                       align: AbiAndPrefAlign {
-                           abi: Align(4 bytes),
-                           pref: Align(4 bytes),
-                       },
-                       size: Size(4 bytes),
                    },
                ],
            },
-           abi: Scalar(
-               Initialized {
-                   value: Int(
-                       I32,
-                       true,
-                   ),
-                   valid_range: 2164260864..=2164260864,
-               },
-           ),
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I32,
-                       true,
-                   ),
-                   valid_range: 2164260864..=2164260864,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(4 bytes),
-               pref: Align(4 bytes),
-           },
-           size: Size(4 bytes),
        }
   --> $DIR/thumb-enum.rs:34:1
    |
diff --git a/src/test/ui/layout/zero-sized-array-enum-niche.stderr b/src/test/ui/layout/zero-sized-array-enum-niche.stderr
index 0dbecbe412b..56d3a52bb7f 100644
--- a/src/test/ui/layout/zero-sized-array-enum-niche.stderr
+++ b/src/test/ui/layout/zero-sized-array-enum-niche.stderr
@@ -1,4 +1,12 @@
 error: layout_of(std::result::Result<[u32; 0], bool>) = Layout {
+           size: Size(4 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(4 bytes),
+               pref: $PREF_ALIGN,
+           },
+           abi: Aggregate {
+               sized: true,
+           },
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -7,6 +15,16 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -19,6 +37,14 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(4 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(4 bytes),
+                           pref: $PREF_ALIGN,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(4 bytes),
@@ -27,20 +53,20 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout {
                                0,
                            ],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
+                   },
+                   Layout {
+                       size: Size(2 bytes),
                        align: AbiAndPrefAlign {
-                           abi: Align(4 bytes),
+                           abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       size: Size(4 bytes),
-                   },
-                   Layout {
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(1 bytes),
@@ -49,12 +75,6 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout {
                                0,
                            ],
                        },
-                       variants: Single {
-                           index: 1,
-                       },
-                       abi: Aggregate {
-                           sized: true,
-                       },
                        largest_niche: Some(
                            Niche {
                                offset: Size(1 bytes),
@@ -65,32 +85,12 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout {
                                valid_range: 0..=1,
                            },
                        ),
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: $PREF_ALIGN,
+                       variants: Single {
+                           index: 1,
                        },
-                       size: Size(2 bytes),
                    },
                ],
            },
-           abi: Aggregate {
-               sized: true,
-           },
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I8,
-                       false,
-                   ),
-                   valid_range: 0..=1,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(4 bytes),
-               pref: $PREF_ALIGN,
-           },
-           size: Size(4 bytes),
        }
   --> $DIR/zero-sized-array-enum-niche.rs:13:1
    |
@@ -98,6 +98,14 @@ LL | type AlignedResult = Result<[u32; 0], bool>;
    | ^^^^^^^^^^^^^^^^^^
 
 error: layout_of(MultipleAlignments) = Layout {
+           size: Size(4 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(4 bytes),
+               pref: $PREF_ALIGN,
+           },
+           abi: Aggregate {
+               sized: true,
+           },
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -106,6 +114,16 @@ error: layout_of(MultipleAlignments) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=2,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -118,6 +136,14 @@ error: layout_of(MultipleAlignments) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(2 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(2 bytes),
+                           pref: $PREF_ALIGN,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(2 bytes),
@@ -126,20 +152,20 @@ error: layout_of(MultipleAlignments) = Layout {
                                0,
                            ],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
+                   },
+                   Layout {
+                       size: Size(4 bytes),
                        align: AbiAndPrefAlign {
-                           abi: Align(2 bytes),
+                           abi: Align(4 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       size: Size(2 bytes),
-                   },
-                   Layout {
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(4 bytes),
@@ -148,20 +174,20 @@ error: layout_of(MultipleAlignments) = Layout {
                                0,
                            ],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 1,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
+                   },
+                   Layout {
+                       size: Size(2 bytes),
                        align: AbiAndPrefAlign {
-                           abi: Align(4 bytes),
+                           abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       size: Size(4 bytes),
-                   },
-                   Layout {
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(1 bytes),
@@ -170,12 +196,6 @@ error: layout_of(MultipleAlignments) = Layout {
                                0,
                            ],
                        },
-                       variants: Single {
-                           index: 2,
-                       },
-                       abi: Aggregate {
-                           sized: true,
-                       },
                        largest_niche: Some(
                            Niche {
                                offset: Size(1 bytes),
@@ -186,32 +206,12 @@ error: layout_of(MultipleAlignments) = Layout {
                                valid_range: 0..=1,
                            },
                        ),
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: $PREF_ALIGN,
+                       variants: Single {
+                           index: 2,
                        },
-                       size: Size(2 bytes),
                    },
                ],
            },
-           abi: Aggregate {
-               sized: true,
-           },
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I8,
-                       false,
-                   ),
-                   valid_range: 0..=2,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(4 bytes),
-               pref: $PREF_ALIGN,
-           },
-           size: Size(4 bytes),
        }
   --> $DIR/zero-sized-array-enum-niche.rs:21:1
    |
@@ -219,6 +219,14 @@ LL | enum MultipleAlignments {
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: layout_of(std::result::Result<[u32; 0], Packed<std::num::NonZeroU16>>) = Layout {
+           size: Size(4 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(4 bytes),
+               pref: $PREF_ALIGN,
+           },
+           abi: Aggregate {
+               sized: true,
+           },
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -227,6 +235,16 @@ error: layout_of(std::result::Result<[u32; 0], Packed<std::num::NonZeroU16>>) =
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -239,6 +257,14 @@ error: layout_of(std::result::Result<[u32; 0], Packed<std::num::NonZeroU16>>) =
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(4 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(4 bytes),
+                           pref: $PREF_ALIGN,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(4 bytes),
@@ -247,20 +273,20 @@ error: layout_of(std::result::Result<[u32; 0], Packed<std::num::NonZeroU16>>) =
                                0,
                            ],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
+                   },
+                   Layout {
+                       size: Size(3 bytes),
                        align: AbiAndPrefAlign {
-                           abi: Align(4 bytes),
+                           abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       size: Size(4 bytes),
-                   },
-                   Layout {
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(1 bytes),
@@ -269,12 +295,6 @@ error: layout_of(std::result::Result<[u32; 0], Packed<std::num::NonZeroU16>>) =
                                0,
                            ],
                        },
-                       variants: Single {
-                           index: 1,
-                       },
-                       abi: Aggregate {
-                           sized: true,
-                       },
                        largest_niche: Some(
                            Niche {
                                offset: Size(1 bytes),
@@ -285,32 +305,12 @@ error: layout_of(std::result::Result<[u32; 0], Packed<std::num::NonZeroU16>>) =
                                valid_range: 1..=65535,
                            },
                        ),
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: $PREF_ALIGN,
+                       variants: Single {
+                           index: 1,
                        },
-                       size: Size(3 bytes),
                    },
                ],
            },
-           abi: Aggregate {
-               sized: true,
-           },
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I8,
-                       false,
-                   ),
-                   valid_range: 0..=1,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(4 bytes),
-               pref: $PREF_ALIGN,
-           },
-           size: Size(4 bytes),
        }
   --> $DIR/zero-sized-array-enum-niche.rs:37:1
    |
@@ -318,6 +318,14 @@ LL | type NicheLosesToTagged = Result<[u32; 0], Packed<std::num::NonZeroU16>>;
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: layout_of(std::result::Result<[u32; 0], Packed<U16IsZero>>) = Layout {
+           size: Size(4 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(4 bytes),
+               pref: $PREF_ALIGN,
+           },
+           abi: Aggregate {
+               sized: true,
+           },
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -326,6 +334,16 @@ error: layout_of(std::result::Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                    0,
                ],
            },
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I16,
+                       false,
+                   ),
+                   valid_range: 0..=1,
+               },
+           ),
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -342,6 +360,14 @@ error: layout_of(std::result::Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
+                       size: Size(0 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: Align(4 bytes),
+                           pref: $PREF_ALIGN,
+                       },
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(0 bytes),
@@ -350,20 +376,20 @@ error: layout_of(std::result::Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                                0,
                            ],
                        },
+                       largest_niche: None,
                        variants: Single {
                            index: 0,
                        },
-                       abi: Aggregate {
-                           sized: true,
-                       },
-                       largest_niche: None,
+                   },
+                   Layout {
+                       size: Size(2 bytes),
                        align: AbiAndPrefAlign {
-                           abi: Align(4 bytes),
+                           abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       size: Size(0 bytes),
-                   },
-                   Layout {
+                       abi: Aggregate {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(0 bytes),
@@ -372,12 +398,6 @@ error: layout_of(std::result::Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                                0,
                            ],
                        },
-                       variants: Single {
-                           index: 1,
-                       },
-                       abi: Aggregate {
-                           sized: true,
-                       },
                        largest_niche: Some(
                            Niche {
                                offset: Size(0 bytes),
@@ -388,32 +408,12 @@ error: layout_of(std::result::Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                                valid_range: 0..=0,
                            },
                        ),
-                       align: AbiAndPrefAlign {
-                           abi: Align(1 bytes),
-                           pref: $PREF_ALIGN,
+                       variants: Single {
+                           index: 1,
                        },
-                       size: Size(2 bytes),
                    },
                ],
            },
-           abi: Aggregate {
-               sized: true,
-           },
-           largest_niche: Some(
-               Niche {
-                   offset: Size(0 bytes),
-                   value: Int(
-                       I16,
-                       false,
-                   ),
-                   valid_range: 0..=1,
-               },
-           ),
-           align: AbiAndPrefAlign {
-               abi: Align(4 bytes),
-               pref: $PREF_ALIGN,
-           },
-           size: Size(4 bytes),
        }
   --> $DIR/zero-sized-array-enum-niche.rs:44:1
    |
diff --git a/src/test/ui/lint/unreachable_pub.stderr b/src/test/ui/lint/unreachable_pub.stderr
index ce22eca1b8c..e021f500c66 100644
--- a/src/test/ui/lint/unreachable_pub.stderr
+++ b/src/test/ui/lint/unreachable_pub.stderr
@@ -1,8 +1,8 @@
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:8:5
+  --> $DIR/unreachable_pub.rs:8:13
    |
 LL |     pub use std::fmt;
-   |     ---^^^^^^^^^^^^^^
+   |     ---     ^^^^^^^^
    |     |
    |     help: consider restricting its visibility: `pub(crate)`
    |
@@ -93,7 +93,7 @@ warning: unreachable `pub` item
   --> $DIR/unreachable_pub.rs:33:5
    |
 LL |     pub const CARBON: usize = 1;
-   |     ---^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ---^^^^^^^^^^^^^^^^^^^^
    |     |
    |     help: consider restricting its visibility: `pub(crate)`
    |
@@ -103,7 +103,7 @@ warning: unreachable `pub` item
   --> $DIR/unreachable_pub.rs:34:5
    |
 LL |     pub static NITROGEN: usize = 2;
-   |     ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ---^^^^^^^^^^^^^^^^^^^^^^^
    |     |
    |     help: consider restricting its visibility: `pub(crate)`
    |
@@ -113,7 +113,7 @@ warning: unreachable `pub` item
   --> $DIR/unreachable_pub.rs:35:5
    |
 LL |     pub type Oxygen = bool;
-   |     ---^^^^^^^^^^^^^^^^^^^^
+   |     ---^^^^^^^^^^^^
    |     |
    |     help: consider restricting its visibility: `pub(crate)`
    |
@@ -123,7 +123,7 @@ warning: unreachable `pub` item
   --> $DIR/unreachable_pub.rs:38:47
    |
 LL |         ($visibility: vis, $name: ident) => { $visibility struct $name {} }
-   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ...
 LL |     define_empty_struct_with_visibility!(pub, Fluorine);
    |     ---------------------------------------------------
@@ -138,7 +138,7 @@ warning: unreachable `pub` item
   --> $DIR/unreachable_pub.rs:44:9
    |
 LL |         pub fn catalyze() -> bool;
-   |         ---^^^^^^^^^^^^^^^^^^^^^^^
+   |         ---^^^^^^^^^^^^^^^^^^^^^^
    |         |
    |         help: consider restricting its visibility: `pub(crate)`
    |
diff --git a/src/test/ui/moves/issue-99470-move-out-of-some.rs b/src/test/ui/moves/issue-99470-move-out-of-some.rs
new file mode 100644
index 00000000000..f404cd3cd71
--- /dev/null
+++ b/src/test/ui/moves/issue-99470-move-out-of-some.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let x: &Option<Box<i32>> = &Some(Box::new(0));
+
+    match x {
+    //~^ ERROR cannot move out of `x` as enum variant `Some` which is behind a shared reference
+        &Some(_y) => (),
+        &None => (),
+    }
+}
diff --git a/src/test/ui/moves/issue-99470-move-out-of-some.stderr b/src/test/ui/moves/issue-99470-move-out-of-some.stderr
new file mode 100644
index 00000000000..6e4a4e5ba22
--- /dev/null
+++ b/src/test/ui/moves/issue-99470-move-out-of-some.stderr
@@ -0,0 +1,16 @@
+error[E0507]: cannot move out of `x` as enum variant `Some` which is behind a shared reference
+  --> $DIR/issue-99470-move-out-of-some.rs:4:11
+   |
+LL |     match x {
+   |           ^
+LL |
+LL |         &Some(_y) => (),
+   |         ---------
+   |         |     |
+   |         |     data moved here
+   |         |     move occurs because `_y` has type `Box<i32>`, which does not implement the `Copy` trait
+   |         help: consider removing the `&`: `Some(_y)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/moves/moves-based-on-type-block-bad.stderr b/src/test/ui/moves/moves-based-on-type-block-bad.stderr
index a9ac9d63a95..5ed91a0d559 100644
--- a/src/test/ui/moves/moves-based-on-type-block-bad.stderr
+++ b/src/test/ui/moves/moves-based-on-type-block-bad.stderr
@@ -1,4 +1,4 @@
-error[E0507]: cannot move out of `hellothere.x.0` which is behind a shared reference
+error[E0507]: cannot move out of `hellothere.x` as enum variant `Bar` which is behind a shared reference
   --> $DIR/moves-based-on-type-block-bad.rs:22:19
    |
 LL |             match hellothere.x {
diff --git a/src/test/ui/nll/move-errors.stderr b/src/test/ui/nll/move-errors.stderr
index 0df326425ad..b03fcf70bab 100644
--- a/src/test/ui/nll/move-errors.stderr
+++ b/src/test/ui/nll/move-errors.stderr
@@ -45,7 +45,7 @@ LL |     let a = [A("".to_string())][0];
    |             move occurs because value has type `A`, which does not implement the `Copy` trait
    |             help: consider borrowing here: `&[A("".to_string())][0]`
 
-error[E0507]: cannot move out of `a.0` which is behind a shared reference
+error[E0507]: cannot move out of `a` which is behind a shared reference
   --> $DIR/move-errors.rs:38:16
    |
 LL |     let A(s) = *a;
@@ -134,7 +134,7 @@ LL |         F(s, mut t) => (),
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
 
-error[E0507]: cannot move out of `x.0` which is behind a shared reference
+error[E0507]: cannot move out of `x` as enum variant `Err` which is behind a shared reference
   --> $DIR/move-errors.rs:110:11
    |
 LL |     match *x {
diff --git a/src/test/ui/panics/location-detail-panic-no-location-info.rs b/src/test/ui/panics/location-detail-panic-no-location-info.rs
new file mode 100644
index 00000000000..7b609145bad
--- /dev/null
+++ b/src/test/ui/panics/location-detail-panic-no-location-info.rs
@@ -0,0 +1,8 @@
+// run-fail
+// check-run-results
+// compile-flags: -Zlocation-detail=none
+// exec-env:RUST_BACKTRACE=0
+
+fn main() {
+    panic!("no location info");
+}
diff --git a/src/test/ui/panics/location-detail-panic-no-location-info.run.stderr b/src/test/ui/panics/location-detail-panic-no-location-info.run.stderr
new file mode 100644
index 00000000000..d1c3108643c
--- /dev/null
+++ b/src/test/ui/panics/location-detail-panic-no-location-info.run.stderr
@@ -0,0 +1,2 @@
+thread 'main' panicked at 'no location info', <redacted>:0:0
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/test/ui-fulldeps/auxiliary/proc-macro-panic.rs b/src/test/ui/proc-macro/auxiliary/proc-macro-panic.rs
index fc15bb9c59d..fc15bb9c59d 100644
--- a/src/test/ui-fulldeps/auxiliary/proc-macro-panic.rs
+++ b/src/test/ui/proc-macro/auxiliary/proc-macro-panic.rs
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.rs b/src/test/ui/proc-macro/invalid-punct-ident-1.rs
index fdf3ca2e261..814cd77cfe9 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-1.rs
+++ b/src/test/ui/proc-macro/invalid-punct-ident-1.rs
@@ -1,9 +1,4 @@
 // aux-build:invalid-punct-ident.rs
-// ignore-stage1
-// only-linux
-//
-// FIXME: This should be a normal (stage1, all platforms) test in
-// src/test/ui/proc-macro once issue #59998 is fixed.
 
 #[macro_use]
 extern crate invalid_punct_ident;
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr
index bb0a48cb16b..7babe685bed 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr
+++ b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr
@@ -1,5 +1,5 @@
 error: proc macro panicked
-  --> $DIR/invalid-punct-ident-1.rs:11:1
+  --> $DIR/invalid-punct-ident-1.rs:6:1
    |
 LL | invalid_punct!();
    | ^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.rs b/src/test/ui/proc-macro/invalid-punct-ident-2.rs
index 151f6203439..a04dec707fe 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-2.rs
+++ b/src/test/ui/proc-macro/invalid-punct-ident-2.rs
@@ -1,9 +1,4 @@
 // aux-build:invalid-punct-ident.rs
-// ignore-stage1
-// only-linux
-//
-// FIXME: This should be a normal (stage1, all platforms) test in
-// src/test/ui/proc-macro once issue #59998 is fixed.
 
 #[macro_use]
 extern crate invalid_punct_ident;
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr
index 0bd07bd649e..01b80768c57 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr
+++ b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr
@@ -1,5 +1,5 @@
 error: proc macro panicked
-  --> $DIR/invalid-punct-ident-2.rs:11:1
+  --> $DIR/invalid-punct-ident-2.rs:6:1
    |
 LL | invalid_ident!();
    | ^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.rs b/src/test/ui/proc-macro/invalid-punct-ident-3.rs
index 7c22a56b6fb..f0e953608cb 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-3.rs
+++ b/src/test/ui/proc-macro/invalid-punct-ident-3.rs
@@ -1,9 +1,4 @@
 // aux-build:invalid-punct-ident.rs
-// ignore-stage1
-// only-linux
-//
-// FIXME: This should be a normal (stage1, all platforms) test in
-// src/test/ui/proc-macro once issue #59998 is fixed.
 
 #[macro_use]
 extern crate invalid_punct_ident;
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
index a0cc5ef6e2d..899c38158c2 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
+++ b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
@@ -1,5 +1,5 @@
 error: proc macro panicked
-  --> $DIR/invalid-punct-ident-3.rs:11:1
+  --> $DIR/invalid-punct-ident-3.rs:6:1
    |
 LL | invalid_raw_ident!();
    | ^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui-fulldeps/issue-76270-panic-in-libproc-macro.rs b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs
index 981abb4e2c4..98fa06b6e45 100644
--- a/src/test/ui-fulldeps/issue-76270-panic-in-libproc-macro.rs
+++ b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs
@@ -1,10 +1,5 @@
 // aux-build:proc-macro-panic.rs
 // edition:2018
-// ignore-stage1
-// only-linux
-//
-// FIXME: This should be a normal (stage1, all platforms) test in
-// src/test/ui/proc-macro once issue #59998 is fixed.
 
 // Regression test for issue #76270
 // Tests that we don't print an ICE message when a panic
diff --git a/src/test/ui-fulldeps/issue-76270-panic-in-libproc-macro.stderr b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr
index 5cc292dbb40..1dc0f16bf6c 100644
--- a/src/test/ui-fulldeps/issue-76270-panic-in-libproc-macro.stderr
+++ b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr
@@ -1,5 +1,5 @@
 error: proc macro panicked
-  --> $DIR/issue-76270-panic-in-libproc-macro.rs:15:1
+  --> $DIR/issue-76270-panic-in-libproc-macro.rs:10:1
    |
 LL | proc_macro_panic::panic_in_libproc_macro!();
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/proc-macro/load-panic-backtrace.rs b/src/test/ui/proc-macro/load-panic-backtrace.rs
index 4a3ba9aee74..cd6f70a5575 100644
--- a/src/test/ui/proc-macro/load-panic-backtrace.rs
+++ b/src/test/ui/proc-macro/load-panic-backtrace.rs
@@ -1,18 +1,8 @@
 // aux-build:test-macros.rs
 // compile-flags: -Z proc-macro-backtrace
 // rustc-env:RUST_BACKTRACE=0
-
-// FIXME https://github.com/rust-lang/rust/issues/59998
 // normalize-stderr-test "thread '.*' panicked " -> ""
 // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
-// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
-// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> ""
-// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
-// normalize-stderr-test "note: compiler flags.*\n\n" -> ""
-// normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
-// normalize-stderr-test "query stack during panic:\n" -> ""
-// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> ""
-// normalize-stderr-test "end of query stack\n" -> ""
 
 #[macro_use]
 extern crate test_macros;
diff --git a/src/test/ui/proc-macro/load-panic-backtrace.stderr b/src/test/ui/proc-macro/load-panic-backtrace.stderr
index f825047e331..cef5786d1b8 100644
--- a/src/test/ui/proc-macro/load-panic-backtrace.stderr
+++ b/src/test/ui/proc-macro/load-panic-backtrace.stderr
@@ -1,6 +1,6 @@
 at 'panic-derive', $DIR/auxiliary/test-macros.rs:43:5
 error: proc-macro derive panicked
-  --> $DIR/load-panic-backtrace.rs:20:10
+  --> $DIR/load-panic-backtrace.rs:10:10
    |
 LL | #[derive(Panic)]
    |          ^^^^^
diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr
index f839bd42432..20aeb7b995a 100644
--- a/src/test/ui/resolve/issue-23305.stderr
+++ b/src/test/ui/resolve/issue-23305.stderr
@@ -8,8 +8,14 @@ LL | impl dyn ToNbt<Self> {}
 note: cycle used when collecting item types in top-level module
   --> $DIR/issue-23305.rs:1:1
    |
-LL | pub trait ToNbt<T> {
-   | ^^^^^^^^^^^^^^^^^^
+LL | / pub trait ToNbt<T> {
+LL | |     fn new(val: T) -> Self;
+LL | | }
+LL | |
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs b/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs
index 689fdcebbfb..0fe50932b4b 100644
--- a/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs
+++ b/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs
@@ -32,6 +32,8 @@ fn _if_let_guard() {
         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
         //~^ ERROR `if let` guards are experimental
         //~| ERROR expected expression, found `let` statement
+        //~| ERROR expected expression, found `let` statement
+        //~| ERROR expected expression, found `let` statement
 
         () if let Range { start: _, end: _ } = (true..true) && false => {}
         //~^ ERROR `if let` guards are experimental
diff --git a/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr b/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr
index b61041050a8..35db84a6cb7 100644
--- a/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr
+++ b/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr
@@ -41,19 +41,31 @@ LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
    |                                          ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/feature-gate.rs:52:16
+  --> $DIR/feature-gate.rs:32:55
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                                                       ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/feature-gate.rs:32:68
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                                                                    ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/feature-gate.rs:54:16
    |
 LL |     use_expr!((let 0 = 1 && 0 == 0));
    |                ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/feature-gate.rs:54:16
+  --> $DIR/feature-gate.rs:56:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^
 
 error: no rules expected the token `let`
-  --> $DIR/feature-gate.rs:62:15
+  --> $DIR/feature-gate.rs:64:15
    |
 LL |     macro_rules! use_expr {
    |     --------------------- when calling this macro
@@ -102,7 +114,7 @@ LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
    = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
 
 error[E0658]: `if let` guards are experimental
-  --> $DIR/feature-gate.rs:36:12
+  --> $DIR/feature-gate.rs:38:12
    |
 LL |         () if let Range { start: _, end: _ } = (true..true) && false => {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -112,7 +124,7 @@ LL |         () if let Range { start: _, end: _ } = (true..true) && false => {}
    = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
 
 error[E0658]: `if let` guards are experimental
-  --> $DIR/feature-gate.rs:58:12
+  --> $DIR/feature-gate.rs:60:12
    |
 LL |         () if let 0 = 1 => {}
    |            ^^^^^^^^^^^^
@@ -121,6 +133,6 @@ LL |         () if let 0 = 1 => {}
    = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
    = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
 
-error: aborting due to 16 previous errors
+error: aborting due to 18 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs
index a89c58785e3..e8f1ff9c3fd 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs
@@ -51,6 +51,8 @@ fn _if() {
     //~| ERROR `let` expressions are not supported here
     //~| ERROR `let` expressions are not supported here
     //~| ERROR expected expression, found `let` statement
+    //~| ERROR expected expression, found `let` statement
+    //~| ERROR expected expression, found `let` statement
 }
 
 fn _while() {
@@ -81,6 +83,8 @@ fn _while() {
     //~| ERROR `let` expressions are not supported here
     //~| ERROR `let` expressions are not supported here
     //~| ERROR expected expression, found `let` statement
+    //~| ERROR expected expression, found `let` statement
+    //~| ERROR expected expression, found `let` statement
 }
 
 fn _macros() {
@@ -146,6 +150,7 @@ fn nested_within_if_expr() {
     //~| ERROR expected expression, found `let` statement
     if true || (true && let 0 = 0) {}
     //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
 
     let mut x = true;
     if x = let 0 = 0 {}
@@ -237,6 +242,7 @@ fn nested_within_while_expr() {
     //~| ERROR expected expression, found `let` statement
     while true || (true && let 0 = 0) {}
     //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
 
     let mut x = true;
     while x = let 0 = 0 {}
@@ -388,16 +394,19 @@ fn inside_const_generic_arguments() {
     if let A::<{
         true && let 1 = 1
         //~^ ERROR `let` expressions are not supported here
+        //~| ERROR expected expression, found `let` statement
     }>::O = 5 {}
 
     while let A::<{
         true && let 1 = 1
         //~^ ERROR `let` expressions are not supported here
+        //~| ERROR expected expression, found `let` statement
     }>::O = 5 {}
 
     if A::<{
         true && let 1 = 1
         //~^ ERROR `let` expressions are not supported here
+        //~| ERROR expected expression, found `let` statement
     }>::O == 5 {}
 
     // In the cases above we have `ExprKind::Block` to help us out.
@@ -409,7 +418,8 @@ fn inside_const_generic_arguments() {
     if A::<
         true && let 1 = 1
         //~^ ERROR `let` expressions are not supported here
-        //~| ERROR  expressions must be enclosed in braces
+        //~| ERROR expressions must be enclosed in braces
+        //~| ERROR expected expression, found `let` statement
     >::O == 5 {}
 }
 
diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
index 5e5289f1693..d5d82166a4a 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
@@ -41,313 +41,373 @@ LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
    |                                   ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:57:12
+  --> $DIR/disallowed-positions.rs:49:48
+   |
+LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                                ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:49:61
+   |
+LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                                             ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:59:12
    |
 LL |     while (let 0 = 1) {}
    |            ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:61:14
+  --> $DIR/disallowed-positions.rs:63:14
    |
 LL |     while (((let 0 = 1))) {}
    |              ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:65:12
+  --> $DIR/disallowed-positions.rs:67:12
    |
 LL |     while (let 0 = 1) && true {}
    |            ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:69:20
+  --> $DIR/disallowed-positions.rs:71:20
    |
 LL |     while true && (let 0 = 1) {}
    |                    ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:73:12
+  --> $DIR/disallowed-positions.rs:75:12
    |
 LL |     while (let 0 = 1) && (let 0 = 1) {}
    |            ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:73:27
+  --> $DIR/disallowed-positions.rs:75:27
    |
 LL |     while (let 0 = 1) && (let 0 = 1) {}
    |                           ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:79:38
+  --> $DIR/disallowed-positions.rs:81:38
    |
 LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
    |                                      ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:110:9
+  --> $DIR/disallowed-positions.rs:81:51
+   |
+LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                                   ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:81:64
+   |
+LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                                                ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:114:9
    |
 LL |     if &let 0 = 0 {}
    |         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:115:9
+  --> $DIR/disallowed-positions.rs:119:9
    |
 LL |     if !let 0 = 0 {}
    |         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:118:9
+  --> $DIR/disallowed-positions.rs:122:9
    |
 LL |     if *let 0 = 0 {}
    |         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:122:9
+  --> $DIR/disallowed-positions.rs:126:9
    |
 LL |     if -let 0 = 0 {}
    |         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:132:9
+  --> $DIR/disallowed-positions.rs:136:9
    |
 LL |     if (let 0 = 0)? {}
    |         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:138:16
+  --> $DIR/disallowed-positions.rs:142:16
    |
 LL |     if true || let 0 = 0 {}
    |                ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:141:17
+  --> $DIR/disallowed-positions.rs:145:17
    |
 LL |     if (true || let 0 = 0) {}
    |                 ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:144:25
+  --> $DIR/disallowed-positions.rs:148:25
    |
 LL |     if true && (true || let 0 = 0) {}
    |                         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:151:12
+  --> $DIR/disallowed-positions.rs:151:25
+   |
+LL |     if true || (true && let 0 = 0) {}
+   |                         ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:156:12
    |
 LL |     if x = let 0 = 0 {}
    |            ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:156:15
+  --> $DIR/disallowed-positions.rs:161:15
    |
 LL |     if true..(let 0 = 0) {}
    |               ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:160:11
+  --> $DIR/disallowed-positions.rs:165:11
    |
 LL |     if ..(let 0 = 0) {}
    |           ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:164:9
+  --> $DIR/disallowed-positions.rs:169:9
    |
 LL |     if (let 0 = 0).. {}
    |         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:195:19
+  --> $DIR/disallowed-positions.rs:200:19
    |
 LL |     if let true = let true = true {}
    |                   ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:201:12
+  --> $DIR/disallowed-positions.rs:206:12
    |
 LL |     while &let 0 = 0 {}
    |            ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:206:12
+  --> $DIR/disallowed-positions.rs:211:12
    |
 LL |     while !let 0 = 0 {}
    |            ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:209:12
+  --> $DIR/disallowed-positions.rs:214:12
    |
 LL |     while *let 0 = 0 {}
    |            ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:213:12
+  --> $DIR/disallowed-positions.rs:218:12
    |
 LL |     while -let 0 = 0 {}
    |            ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:223:12
+  --> $DIR/disallowed-positions.rs:228:12
    |
 LL |     while (let 0 = 0)? {}
    |            ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:229:19
+  --> $DIR/disallowed-positions.rs:234:19
    |
 LL |     while true || let 0 = 0 {}
    |                   ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:232:20
+  --> $DIR/disallowed-positions.rs:237:20
    |
 LL |     while (true || let 0 = 0) {}
    |                    ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:235:28
+  --> $DIR/disallowed-positions.rs:240:28
    |
 LL |     while true && (true || let 0 = 0) {}
    |                            ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:242:15
+  --> $DIR/disallowed-positions.rs:243:28
+   |
+LL |     while true || (true && let 0 = 0) {}
+   |                            ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:248:15
    |
 LL |     while x = let 0 = 0 {}
    |               ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:247:18
+  --> $DIR/disallowed-positions.rs:253:18
    |
 LL |     while true..(let 0 = 0) {}
    |                  ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:251:14
+  --> $DIR/disallowed-positions.rs:257:14
    |
 LL |     while ..(let 0 = 0) {}
    |              ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:255:12
+  --> $DIR/disallowed-positions.rs:261:12
    |
 LL |     while (let 0 = 0).. {}
    |            ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:286:22
+  --> $DIR/disallowed-positions.rs:292:22
    |
 LL |     while let true = let true = true {}
    |                      ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:302:6
+  --> $DIR/disallowed-positions.rs:308:6
    |
 LL |     &let 0 = 0;
    |      ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:306:6
+  --> $DIR/disallowed-positions.rs:312:6
    |
 LL |     !let 0 = 0;
    |      ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:309:6
+  --> $DIR/disallowed-positions.rs:315:6
    |
 LL |     *let 0 = 0;
    |      ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:313:6
+  --> $DIR/disallowed-positions.rs:319:6
    |
 LL |     -let 0 = 0;
    |      ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:323:6
+  --> $DIR/disallowed-positions.rs:329:6
    |
 LL |     (let 0 = 0)?;
    |      ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:329:13
+  --> $DIR/disallowed-positions.rs:335:13
    |
 LL |     true || let 0 = 0;
    |             ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:332:14
+  --> $DIR/disallowed-positions.rs:338:14
    |
 LL |     (true || let 0 = 0);
    |              ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:335:22
+  --> $DIR/disallowed-positions.rs:341:22
    |
 LL |     true && (true || let 0 = 0);
    |                      ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:340:9
+  --> $DIR/disallowed-positions.rs:346:9
    |
 LL |     x = let 0 = 0;
    |         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:344:12
+  --> $DIR/disallowed-positions.rs:350:12
    |
 LL |     true..(let 0 = 0);
    |            ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:347:8
+  --> $DIR/disallowed-positions.rs:353:8
    |
 LL |     ..(let 0 = 0);
    |        ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:350:6
+  --> $DIR/disallowed-positions.rs:356:6
    |
 LL |     (let 0 = 0)..;
    |      ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:354:6
+  --> $DIR/disallowed-positions.rs:360:6
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |      ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:359:6
+  --> $DIR/disallowed-positions.rs:365:6
    |
 LL |     (let true = let true = true);
    |      ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:359:17
+  --> $DIR/disallowed-positions.rs:365:17
    |
 LL |     (let true = let true = true);
    |                 ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:366:25
+  --> $DIR/disallowed-positions.rs:372:25
    |
 LL |         let x = true && let y = 1;
    |                         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:372:19
+  --> $DIR/disallowed-positions.rs:378:19
    |
 LL |         [1, 2, 3][let _ = ()]
    |                   ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:377:6
+  --> $DIR/disallowed-positions.rs:383:6
    |
 LL |     &let 0 = 0
    |      ^^^
 
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:395:17
+   |
+LL |         true && let 1 = 1
+   |                 ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:401:17
+   |
+LL |         true && let 1 = 1
+   |                 ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:407:17
+   |
+LL |         true && let 1 = 1
+   |                 ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:419:17
+   |
+LL |         true && let 1 = 1
+   |                 ^^^
+
 error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/disallowed-positions.rs:410:9
+  --> $DIR/disallowed-positions.rs:419:9
    |
 LL |         true && let 1 = 1
    |         ^^^^^^^^^^^^^^^^^
@@ -358,97 +418,97 @@ LL |         { true && let 1 = 1 }
    |         +                   +
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:419:9
+  --> $DIR/disallowed-positions.rs:429:9
    |
 LL |     if (let Some(a) = opt && true) {
    |         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:424:9
+  --> $DIR/disallowed-positions.rs:434:9
    |
 LL |     if (let Some(a) = opt) && true {
    |         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:428:9
+  --> $DIR/disallowed-positions.rs:438:9
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:428:32
+  --> $DIR/disallowed-positions.rs:438:32
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |                                ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:437:9
+  --> $DIR/disallowed-positions.rs:447:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:437:31
+  --> $DIR/disallowed-positions.rs:447:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |                               ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:443:9
+  --> $DIR/disallowed-positions.rs:453:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:443:31
+  --> $DIR/disallowed-positions.rs:453:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |                               ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:449:9
+  --> $DIR/disallowed-positions.rs:459:9
    |
 LL |     if (let Some(a) = opt && (true)) && true {
    |         ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:466:22
+  --> $DIR/disallowed-positions.rs:476:22
    |
 LL |     let x = (true && let y = 1);
    |                      ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:471:20
+  --> $DIR/disallowed-positions.rs:481:20
    |
 LL |         ([1, 2, 3][let _ = ()])
    |                    ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:475:20
+  --> $DIR/disallowed-positions.rs:485:20
    |
 LL |     #[cfg(FALSE)] (let 0 = 1);
    |                    ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:93:16
+  --> $DIR/disallowed-positions.rs:97:16
    |
 LL |     use_expr!((let 0 = 1 && 0 == 0));
    |                ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:97:16
+  --> $DIR/disallowed-positions.rs:101:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:101:23
+  --> $DIR/disallowed-positions.rs:105:23
    |
 LL |     use_expr!(true && let 0 = 1);
    |                       ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:105:17
+  --> $DIR/disallowed-positions.rs:109:17
    |
 LL |     noop_expr!((let 0 = 1));
    |                 ^^^
@@ -571,176 +631,176 @@ LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:57:12
+  --> $DIR/disallowed-positions.rs:59:12
    |
 LL |     while (let 0 = 1) {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:57:12
+  --> $DIR/disallowed-positions.rs:59:12
    |
 LL |     while (let 0 = 1) {}
    |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:61:14
+  --> $DIR/disallowed-positions.rs:63:14
    |
 LL |     while (((let 0 = 1))) {}
    |              ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:61:14
+  --> $DIR/disallowed-positions.rs:63:14
    |
 LL |     while (((let 0 = 1))) {}
    |              ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:65:12
+  --> $DIR/disallowed-positions.rs:67:12
    |
 LL |     while (let 0 = 1) && true {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:65:12
+  --> $DIR/disallowed-positions.rs:67:12
    |
 LL |     while (let 0 = 1) && true {}
    |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:69:20
+  --> $DIR/disallowed-positions.rs:71:20
    |
 LL |     while true && (let 0 = 1) {}
    |                    ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:69:20
+  --> $DIR/disallowed-positions.rs:71:20
    |
 LL |     while true && (let 0 = 1) {}
    |                    ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:73:12
+  --> $DIR/disallowed-positions.rs:75:12
    |
 LL |     while (let 0 = 1) && (let 0 = 1) {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:73:12
+  --> $DIR/disallowed-positions.rs:75:12
    |
 LL |     while (let 0 = 1) && (let 0 = 1) {}
    |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:73:27
+  --> $DIR/disallowed-positions.rs:75:27
    |
 LL |     while (let 0 = 1) && (let 0 = 1) {}
    |                           ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:73:27
+  --> $DIR/disallowed-positions.rs:75:27
    |
 LL |     while (let 0 = 1) && (let 0 = 1) {}
    |                           ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:79:38
+  --> $DIR/disallowed-positions.rs:81:38
    |
 LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
    |                                      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:79:38
+  --> $DIR/disallowed-positions.rs:81:38
    |
 LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:79:51
+  --> $DIR/disallowed-positions.rs:81:51
    |
 LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
    |                                                   ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:79:38
+  --> $DIR/disallowed-positions.rs:81:38
    |
 LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:79:64
+  --> $DIR/disallowed-positions.rs:81:64
    |
 LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
    |                                                                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:79:38
+  --> $DIR/disallowed-positions.rs:81:38
    |
 LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:93:16
+  --> $DIR/disallowed-positions.rs:97:16
    |
 LL |     use_expr!((let 0 = 1 && 0 == 0));
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:93:16
+  --> $DIR/disallowed-positions.rs:97:16
    |
 LL |     use_expr!((let 0 = 1 && 0 == 0));
    |                ^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:93:16
+  --> $DIR/disallowed-positions.rs:97:16
    |
 LL |     use_expr!((let 0 = 1 && 0 == 0));
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:93:16
+  --> $DIR/disallowed-positions.rs:97:16
    |
 LL |     use_expr!((let 0 = 1 && 0 == 0));
    |                ^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:97:16
+  --> $DIR/disallowed-positions.rs:101:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:97:16
+  --> $DIR/disallowed-positions.rs:101:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:97:16
+  --> $DIR/disallowed-positions.rs:101:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:97:16
+  --> $DIR/disallowed-positions.rs:101:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:110:9
+  --> $DIR/disallowed-positions.rs:114:9
    |
 LL |     if &let 0 = 0 {}
    |         ^^^^^^^^^
@@ -748,7 +808,7 @@ LL |     if &let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:115:9
+  --> $DIR/disallowed-positions.rs:119:9
    |
 LL |     if !let 0 = 0 {}
    |         ^^^^^^^^^
@@ -756,7 +816,7 @@ LL |     if !let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:118:9
+  --> $DIR/disallowed-positions.rs:122:9
    |
 LL |     if *let 0 = 0 {}
    |         ^^^^^^^^^
@@ -764,7 +824,7 @@ LL |     if *let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:122:9
+  --> $DIR/disallowed-positions.rs:126:9
    |
 LL |     if -let 0 = 0 {}
    |         ^^^^^^^^^
@@ -772,72 +832,72 @@ LL |     if -let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:132:9
+  --> $DIR/disallowed-positions.rs:136:9
    |
 LL |     if (let 0 = 0)? {}
    |         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:132:9
+  --> $DIR/disallowed-positions.rs:136:9
    |
 LL |     if (let 0 = 0)? {}
    |         ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:138:16
+  --> $DIR/disallowed-positions.rs:142:16
    |
 LL |     if true || let 0 = 0 {}
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:138:13
+  --> $DIR/disallowed-positions.rs:142:13
    |
 LL |     if true || let 0 = 0 {}
    |             ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:141:17
+  --> $DIR/disallowed-positions.rs:145:17
    |
 LL |     if (true || let 0 = 0) {}
    |                 ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:141:14
+  --> $DIR/disallowed-positions.rs:145:14
    |
 LL |     if (true || let 0 = 0) {}
    |              ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:144:25
+  --> $DIR/disallowed-positions.rs:148:25
    |
 LL |     if true && (true || let 0 = 0) {}
    |                         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:144:22
+  --> $DIR/disallowed-positions.rs:148:22
    |
 LL |     if true && (true || let 0 = 0) {}
    |                      ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:147:25
+  --> $DIR/disallowed-positions.rs:151:25
    |
 LL |     if true || (true && let 0 = 0) {}
    |                         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:147:17
+  --> $DIR/disallowed-positions.rs:151:17
    |
 LL |     if true || (true && let 0 = 0) {}
    |                 ^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:151:12
+  --> $DIR/disallowed-positions.rs:156:12
    |
 LL |     if x = let 0 = 0 {}
    |            ^^^^^^^^^
@@ -845,46 +905,46 @@ LL |     if x = let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:156:15
+  --> $DIR/disallowed-positions.rs:161:15
    |
 LL |     if true..(let 0 = 0) {}
    |               ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:156:15
+  --> $DIR/disallowed-positions.rs:161:15
    |
 LL |     if true..(let 0 = 0) {}
    |               ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:160:11
+  --> $DIR/disallowed-positions.rs:165:11
    |
 LL |     if ..(let 0 = 0) {}
    |           ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:160:11
+  --> $DIR/disallowed-positions.rs:165:11
    |
 LL |     if ..(let 0 = 0) {}
    |           ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:164:9
+  --> $DIR/disallowed-positions.rs:169:9
    |
 LL |     if (let 0 = 0).. {}
    |         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:164:9
+  --> $DIR/disallowed-positions.rs:169:9
    |
 LL |     if (let 0 = 0).. {}
    |         ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:170:8
+  --> $DIR/disallowed-positions.rs:175:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -892,7 +952,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:174:8
+  --> $DIR/disallowed-positions.rs:179:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -900,7 +960,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:181:8
+  --> $DIR/disallowed-positions.rs:186:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -908,7 +968,7 @@ LL |     if let Range { start: F, end } = F..|| true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:189:8
+  --> $DIR/disallowed-positions.rs:194:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -916,7 +976,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:195:19
+  --> $DIR/disallowed-positions.rs:200:19
    |
 LL |     if let true = let true = true {}
    |                   ^^^^^^^^^^^^^^^
@@ -924,7 +984,7 @@ LL |     if let true = let true = true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:201:12
+  --> $DIR/disallowed-positions.rs:206:12
    |
 LL |     while &let 0 = 0 {}
    |            ^^^^^^^^^
@@ -932,7 +992,7 @@ LL |     while &let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:206:12
+  --> $DIR/disallowed-positions.rs:211:12
    |
 LL |     while !let 0 = 0 {}
    |            ^^^^^^^^^
@@ -940,7 +1000,7 @@ LL |     while !let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:209:12
+  --> $DIR/disallowed-positions.rs:214:12
    |
 LL |     while *let 0 = 0 {}
    |            ^^^^^^^^^
@@ -948,7 +1008,7 @@ LL |     while *let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:213:12
+  --> $DIR/disallowed-positions.rs:218:12
    |
 LL |     while -let 0 = 0 {}
    |            ^^^^^^^^^
@@ -956,72 +1016,72 @@ LL |     while -let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:223:12
+  --> $DIR/disallowed-positions.rs:228:12
    |
 LL |     while (let 0 = 0)? {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:223:12
+  --> $DIR/disallowed-positions.rs:228:12
    |
 LL |     while (let 0 = 0)? {}
    |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:229:19
+  --> $DIR/disallowed-positions.rs:234:19
    |
 LL |     while true || let 0 = 0 {}
    |                   ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:229:16
+  --> $DIR/disallowed-positions.rs:234:16
    |
 LL |     while true || let 0 = 0 {}
    |                ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:232:20
+  --> $DIR/disallowed-positions.rs:237:20
    |
 LL |     while (true || let 0 = 0) {}
    |                    ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:232:17
+  --> $DIR/disallowed-positions.rs:237:17
    |
 LL |     while (true || let 0 = 0) {}
    |                 ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:235:28
+  --> $DIR/disallowed-positions.rs:240:28
    |
 LL |     while true && (true || let 0 = 0) {}
    |                            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:235:25
+  --> $DIR/disallowed-positions.rs:240:25
    |
 LL |     while true && (true || let 0 = 0) {}
    |                         ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:238:28
+  --> $DIR/disallowed-positions.rs:243:28
    |
 LL |     while true || (true && let 0 = 0) {}
    |                            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:238:20
+  --> $DIR/disallowed-positions.rs:243:20
    |
 LL |     while true || (true && let 0 = 0) {}
    |                    ^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:242:15
+  --> $DIR/disallowed-positions.rs:248:15
    |
 LL |     while x = let 0 = 0 {}
    |               ^^^^^^^^^
@@ -1029,46 +1089,46 @@ LL |     while x = let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:247:18
+  --> $DIR/disallowed-positions.rs:253:18
    |
 LL |     while true..(let 0 = 0) {}
    |                  ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:247:18
+  --> $DIR/disallowed-positions.rs:253:18
    |
 LL |     while true..(let 0 = 0) {}
    |                  ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:251:14
+  --> $DIR/disallowed-positions.rs:257:14
    |
 LL |     while ..(let 0 = 0) {}
    |              ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:251:14
+  --> $DIR/disallowed-positions.rs:257:14
    |
 LL |     while ..(let 0 = 0) {}
    |              ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:255:12
+  --> $DIR/disallowed-positions.rs:261:12
    |
 LL |     while (let 0 = 0).. {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:255:12
+  --> $DIR/disallowed-positions.rs:261:12
    |
 LL |     while (let 0 = 0).. {}
    |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:261:11
+  --> $DIR/disallowed-positions.rs:267:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1076,7 +1136,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:265:11
+  --> $DIR/disallowed-positions.rs:271:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1084,7 +1144,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:272:11
+  --> $DIR/disallowed-positions.rs:278:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1092,7 +1152,7 @@ LL |     while let Range { start: F, end } = F..|| true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:280:11
+  --> $DIR/disallowed-positions.rs:286:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1100,7 +1160,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:286:22
+  --> $DIR/disallowed-positions.rs:292:22
    |
 LL |     while let true = let true = true {}
    |                      ^^^^^^^^^^^^^^^
@@ -1108,7 +1168,7 @@ LL |     while let true = let true = true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:302:6
+  --> $DIR/disallowed-positions.rs:308:6
    |
 LL |     &let 0 = 0;
    |      ^^^^^^^^^
@@ -1116,7 +1176,7 @@ LL |     &let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:306:6
+  --> $DIR/disallowed-positions.rs:312:6
    |
 LL |     !let 0 = 0;
    |      ^^^^^^^^^
@@ -1124,7 +1184,7 @@ LL |     !let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:309:6
+  --> $DIR/disallowed-positions.rs:315:6
    |
 LL |     *let 0 = 0;
    |      ^^^^^^^^^
@@ -1132,7 +1192,7 @@ LL |     *let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:313:6
+  --> $DIR/disallowed-positions.rs:319:6
    |
 LL |     -let 0 = 0;
    |      ^^^^^^^^^
@@ -1140,59 +1200,59 @@ LL |     -let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:323:6
+  --> $DIR/disallowed-positions.rs:329:6
    |
 LL |     (let 0 = 0)?;
    |      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:323:6
+  --> $DIR/disallowed-positions.rs:329:6
    |
 LL |     (let 0 = 0)?;
    |      ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:329:13
+  --> $DIR/disallowed-positions.rs:335:13
    |
 LL |     true || let 0 = 0;
    |             ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:329:10
+  --> $DIR/disallowed-positions.rs:335:10
    |
 LL |     true || let 0 = 0;
    |          ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:332:14
+  --> $DIR/disallowed-positions.rs:338:14
    |
 LL |     (true || let 0 = 0);
    |              ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:332:11
+  --> $DIR/disallowed-positions.rs:338:11
    |
 LL |     (true || let 0 = 0);
    |           ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:335:22
+  --> $DIR/disallowed-positions.rs:341:22
    |
 LL |     true && (true || let 0 = 0);
    |                      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:335:19
+  --> $DIR/disallowed-positions.rs:341:19
    |
 LL |     true && (true || let 0 = 0);
    |                   ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:340:9
+  --> $DIR/disallowed-positions.rs:346:9
    |
 LL |     x = let 0 = 0;
    |         ^^^^^^^^^
@@ -1200,46 +1260,46 @@ LL |     x = let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:344:12
+  --> $DIR/disallowed-positions.rs:350:12
    |
 LL |     true..(let 0 = 0);
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:344:12
+  --> $DIR/disallowed-positions.rs:350:12
    |
 LL |     true..(let 0 = 0);
    |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:347:8
+  --> $DIR/disallowed-positions.rs:353:8
    |
 LL |     ..(let 0 = 0);
    |        ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:347:8
+  --> $DIR/disallowed-positions.rs:353:8
    |
 LL |     ..(let 0 = 0);
    |        ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:350:6
+  --> $DIR/disallowed-positions.rs:356:6
    |
 LL |     (let 0 = 0)..;
    |      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:350:6
+  --> $DIR/disallowed-positions.rs:356:6
    |
 LL |     (let 0 = 0)..;
    |      ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:354:6
+  --> $DIR/disallowed-positions.rs:360:6
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1247,20 +1307,20 @@ LL |     (let Range { start: _, end: _ } = true..true || false);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:359:6
+  --> $DIR/disallowed-positions.rs:365:6
    |
 LL |     (let true = let true = true);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:359:6
+  --> $DIR/disallowed-positions.rs:365:6
    |
 LL |     (let true = let true = true);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:377:6
+  --> $DIR/disallowed-positions.rs:383:6
    |
 LL |     &let 0 = 0
    |      ^^^^^^^^^
@@ -1268,7 +1328,7 @@ LL |     &let 0 = 0
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:389:17
+  --> $DIR/disallowed-positions.rs:395:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -1276,7 +1336,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:394:17
+  --> $DIR/disallowed-positions.rs:401:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -1284,7 +1344,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:399:17
+  --> $DIR/disallowed-positions.rs:407:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -1292,7 +1352,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:410:17
+  --> $DIR/disallowed-positions.rs:419:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -1300,124 +1360,124 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:419:9
+  --> $DIR/disallowed-positions.rs:429:9
    |
 LL |     if (let Some(a) = opt && true) {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:419:9
+  --> $DIR/disallowed-positions.rs:429:9
    |
 LL |     if (let Some(a) = opt && true) {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:424:9
+  --> $DIR/disallowed-positions.rs:434:9
    |
 LL |     if (let Some(a) = opt) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:424:9
+  --> $DIR/disallowed-positions.rs:434:9
    |
 LL |     if (let Some(a) = opt) && true {
    |         ^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:428:9
+  --> $DIR/disallowed-positions.rs:438:9
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:428:9
+  --> $DIR/disallowed-positions.rs:438:9
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |         ^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:428:32
+  --> $DIR/disallowed-positions.rs:438:32
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |                                ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:428:32
+  --> $DIR/disallowed-positions.rs:438:32
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |                                ^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:437:9
+  --> $DIR/disallowed-positions.rs:447:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:437:9
+  --> $DIR/disallowed-positions.rs:447:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:437:31
+  --> $DIR/disallowed-positions.rs:447:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |                               ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:437:31
+  --> $DIR/disallowed-positions.rs:447:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |                               ^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:443:9
+  --> $DIR/disallowed-positions.rs:453:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:443:9
+  --> $DIR/disallowed-positions.rs:453:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:443:31
+  --> $DIR/disallowed-positions.rs:453:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |                               ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:443:31
+  --> $DIR/disallowed-positions.rs:453:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |                               ^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:449:9
+  --> $DIR/disallowed-positions.rs:459:9
    |
 LL |     if (let Some(a) = opt && (true)) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:449:9
+  --> $DIR/disallowed-positions.rs:459:9
    |
 LL |     if (let Some(a) = opt && (true)) && true {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:110:8
+  --> $DIR/disallowed-positions.rs:114:8
    |
 LL |     if &let 0 = 0 {}
    |        ^^^^^^^^^^ expected `bool`, found `&bool`
@@ -1429,19 +1489,19 @@ LL +     if let 0 = 0 {}
    |
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:118:8
+  --> $DIR/disallowed-positions.rs:122:8
    |
 LL |     if *let 0 = 0 {}
    |        ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:122:8
+  --> $DIR/disallowed-positions.rs:126:8
    |
 LL |     if -let 0 = 0 {}
    |        ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:132:8
+  --> $DIR/disallowed-positions.rs:136:8
    |
 LL |     if (let 0 = 0)? {}
    |        ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -1449,7 +1509,7 @@ LL |     if (let 0 = 0)? {}
    = help: the trait `Try` is not implemented for `bool`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:132:19
+  --> $DIR/disallowed-positions.rs:136:19
    |
 LL | / fn nested_within_if_expr() {
 LL | |     if &let 0 = 0 {}
@@ -1466,7 +1526,7 @@ LL | | }
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:151:8
+  --> $DIR/disallowed-positions.rs:156:8
    |
 LL |     if x = let 0 = 0 {}
    |        ^^^^^^^^^^^^^ expected `bool`, found `()`
@@ -1477,7 +1537,7 @@ LL |     if x == let 0 = 0 {}
    |          ~~
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:156:8
+  --> $DIR/disallowed-positions.rs:161:8
    |
 LL |     if true..(let 0 = 0) {}
    |        ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1486,7 +1546,7 @@ LL |     if true..(let 0 = 0) {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:160:8
+  --> $DIR/disallowed-positions.rs:165:8
    |
 LL |     if ..(let 0 = 0) {}
    |        ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo`
@@ -1495,7 +1555,7 @@ LL |     if ..(let 0 = 0) {}
             found struct `RangeTo<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:164:8
+  --> $DIR/disallowed-positions.rs:169:8
    |
 LL |     if (let 0 = 0).. {}
    |        ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom`
@@ -1504,7 +1564,7 @@ LL |     if (let 0 = 0).. {}
             found struct `RangeFrom<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:170:12
+  --> $DIR/disallowed-positions.rs:175:12
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1515,7 +1575,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:170:8
+  --> $DIR/disallowed-positions.rs:175:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1524,7 +1584,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:174:12
+  --> $DIR/disallowed-positions.rs:179:12
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1535,7 +1595,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:174:8
+  --> $DIR/disallowed-positions.rs:179:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1544,7 +1604,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:181:12
+  --> $DIR/disallowed-positions.rs:186:12
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
@@ -1555,20 +1615,20 @@ LL |     if let Range { start: F, end } = F..|| true {}
                   found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:181:41
+  --> $DIR/disallowed-positions.rs:186:41
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |                                         ^^^^^^^ expected `bool`, found closure
    |
    = note: expected type `bool`
-           found closure `[closure@$DIR/disallowed-positions.rs:181:41: 181:43]`
+           found closure `[closure@$DIR/disallowed-positions.rs:186:41: 186:43]`
 help: use parentheses to call this closure
    |
 LL |     if let Range { start: F, end } = F..(|| true)() {}
    |                                         +       +++
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:181:8
+  --> $DIR/disallowed-positions.rs:186:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1577,7 +1637,7 @@ LL |     if let Range { start: F, end } = F..|| true {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:189:12
+  --> $DIR/disallowed-positions.rs:194:12
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
@@ -1588,7 +1648,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:189:44
+  --> $DIR/disallowed-positions.rs:194:44
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |                                            ^^^^^^^ expected `bool`, found `&&bool`
@@ -1600,7 +1660,7 @@ LL +     if let Range { start: true, end } = t..false {}
    |
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:189:8
+  --> $DIR/disallowed-positions.rs:194:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1609,7 +1669,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<bool>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:128:20
+  --> $DIR/disallowed-positions.rs:132:20
    |
 LL |         if let 0 = 0? {}
    |                    ^^ the `?` operator cannot be applied to type `{integer}`
@@ -1617,7 +1677,7 @@ LL |         if let 0 = 0? {}
    = help: the trait `Try` is not implemented for `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:201:11
+  --> $DIR/disallowed-positions.rs:206:11
    |
 LL |     while &let 0 = 0 {}
    |           ^^^^^^^^^^ expected `bool`, found `&bool`
@@ -1629,19 +1689,19 @@ LL +     while let 0 = 0 {}
    |
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:209:11
+  --> $DIR/disallowed-positions.rs:214:11
    |
 LL |     while *let 0 = 0 {}
    |           ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:213:11
+  --> $DIR/disallowed-positions.rs:218:11
    |
 LL |     while -let 0 = 0 {}
    |           ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:223:11
+  --> $DIR/disallowed-positions.rs:228:11
    |
 LL |     while (let 0 = 0)? {}
    |           ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -1649,7 +1709,7 @@ LL |     while (let 0 = 0)? {}
    = help: the trait `Try` is not implemented for `bool`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:223:22
+  --> $DIR/disallowed-positions.rs:228:22
    |
 LL | / fn nested_within_while_expr() {
 LL | |     while &let 0 = 0 {}
@@ -1666,7 +1726,7 @@ LL | | }
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:242:11
+  --> $DIR/disallowed-positions.rs:248:11
    |
 LL |     while x = let 0 = 0 {}
    |           ^^^^^^^^^^^^^ expected `bool`, found `()`
@@ -1677,7 +1737,7 @@ LL |     while x == let 0 = 0 {}
    |             ~~
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:247:11
+  --> $DIR/disallowed-positions.rs:253:11
    |
 LL |     while true..(let 0 = 0) {}
    |           ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1686,7 +1746,7 @@ LL |     while true..(let 0 = 0) {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:251:11
+  --> $DIR/disallowed-positions.rs:257:11
    |
 LL |     while ..(let 0 = 0) {}
    |           ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo`
@@ -1695,7 +1755,7 @@ LL |     while ..(let 0 = 0) {}
             found struct `RangeTo<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:255:11
+  --> $DIR/disallowed-positions.rs:261:11
    |
 LL |     while (let 0 = 0).. {}
    |           ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom`
@@ -1704,7 +1764,7 @@ LL |     while (let 0 = 0).. {}
             found struct `RangeFrom<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:261:15
+  --> $DIR/disallowed-positions.rs:267:15
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1715,7 +1775,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:261:11
+  --> $DIR/disallowed-positions.rs:267:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1724,7 +1784,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:265:15
+  --> $DIR/disallowed-positions.rs:271:15
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1735,7 +1795,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:265:11
+  --> $DIR/disallowed-positions.rs:271:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1744,7 +1804,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:272:15
+  --> $DIR/disallowed-positions.rs:278:15
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
@@ -1755,20 +1815,20 @@ LL |     while let Range { start: F, end } = F..|| true {}
                   found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:272:44
+  --> $DIR/disallowed-positions.rs:278:44
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |                                            ^^^^^^^ expected `bool`, found closure
    |
    = note: expected type `bool`
-           found closure `[closure@$DIR/disallowed-positions.rs:272:44: 272:46]`
+           found closure `[closure@$DIR/disallowed-positions.rs:278:44: 278:46]`
 help: use parentheses to call this closure
    |
 LL |     while let Range { start: F, end } = F..(|| true)() {}
    |                                            +       +++
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:272:11
+  --> $DIR/disallowed-positions.rs:278:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1777,7 +1837,7 @@ LL |     while let Range { start: F, end } = F..|| true {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:280:15
+  --> $DIR/disallowed-positions.rs:286:15
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
@@ -1788,7 +1848,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:280:47
+  --> $DIR/disallowed-positions.rs:286:47
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |                                               ^^^^^^^ expected `bool`, found `&&bool`
@@ -1800,7 +1860,7 @@ LL +     while let Range { start: true, end } = t..false {}
    |
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:280:11
+  --> $DIR/disallowed-positions.rs:286:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1809,7 +1869,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<bool>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:219:23
+  --> $DIR/disallowed-positions.rs:224:23
    |
 LL |         while let 0 = 0? {}
    |                       ^^ the `?` operator cannot be applied to type `{integer}`
@@ -1817,19 +1877,19 @@ LL |         while let 0 = 0? {}
    = help: the trait `Try` is not implemented for `{integer}`
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:309:5
+  --> $DIR/disallowed-positions.rs:315:5
    |
 LL |     *let 0 = 0;
    |     ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:313:5
+  --> $DIR/disallowed-positions.rs:319:5
    |
 LL |     -let 0 = 0;
    |     ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:323:5
+  --> $DIR/disallowed-positions.rs:329:5
    |
 LL |     (let 0 = 0)?;
    |     ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -1837,7 +1897,7 @@ LL |     (let 0 = 0)?;
    = help: the trait `Try` is not implemented for `bool`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:323:16
+  --> $DIR/disallowed-positions.rs:329:16
    |
 LL | / fn outside_if_and_while_expr() {
 LL | |     &let 0 = 0;
@@ -1854,7 +1914,7 @@ LL | | }
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:354:10
+  --> $DIR/disallowed-positions.rs:360:10
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1865,7 +1925,7 @@ LL |     (let Range { start: _, end: _ } = true..true || false);
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:377:5
+  --> $DIR/disallowed-positions.rs:383:5
    |
 LL | fn outside_if_and_while_expr() {
    |                                - help: try adding a return type: `-> &bool`
@@ -1874,14 +1934,14 @@ LL |     &let 0 = 0
    |     ^^^^^^^^^^ expected `()`, found `&bool`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:319:17
+  --> $DIR/disallowed-positions.rs:325:17
    |
 LL |         let 0 = 0?;
    |                 ^^ the `?` operator cannot be applied to type `{integer}`
    |
    = help: the trait `Try` is not implemented for `{integer}`
 
-error: aborting due to 208 previous errors
+error: aborting due to 218 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0600, E0614.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.stderr b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr
index ca09c3d5ff1..e5443290f9e 100644
--- a/src/test/ui/suggestions/dont-suggest-ref/simple.stderr
+++ b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr
@@ -1,4 +1,4 @@
-error[E0507]: cannot move out of `s.0` which is behind a shared reference
+error[E0507]: cannot move out of `s` which is behind a shared reference
   --> $DIR/simple.rs:38:17
    |
 LL |     let X(_t) = *s;
@@ -7,7 +7,7 @@ LL |     let X(_t) = *s;
    |           data moved here
    |           move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
 
-error[E0507]: cannot move out of `r.0` which is behind a shared reference
+error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
   --> $DIR/simple.rs:42:30
    |
 LL |     if let Either::One(_t) = *r { }
@@ -16,7 +16,7 @@ LL |     if let Either::One(_t) = *r { }
    |                        data moved here
    |                        move occurs because `_t` has type `X`, which does not implement the `Copy` trait
 
-error[E0507]: cannot move out of `r.0` which is behind a shared reference
+error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
   --> $DIR/simple.rs:46:33
    |
 LL |     while let Either::One(_t) = *r { }
@@ -25,7 +25,7 @@ LL |     while let Either::One(_t) = *r { }
    |                           data moved here
    |                           move occurs because `_t` has type `X`, which does not implement the `Copy` trait
 
-error[E0507]: cannot move out of `r.0` which is behind a shared reference
+error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference
   --> $DIR/simple.rs:50:11
    |
 LL |     match *r {
@@ -37,7 +37,7 @@ LL |         Either::One(_t)
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
 
-error[E0507]: cannot move out of `r.0` which is behind a shared reference
+error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
   --> $DIR/simple.rs:57:11
    |
 LL |     match *r {
@@ -49,7 +49,7 @@ LL |         Either::One(_t) => (),
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
 
-error[E0507]: cannot move out of `sm.0` which is behind a mutable reference
+error[E0507]: cannot move out of `sm` which is behind a mutable reference
   --> $DIR/simple.rs:66:17
    |
 LL |     let X(_t) = *sm;
@@ -58,7 +58,7 @@ LL |     let X(_t) = *sm;
    |           data moved here
    |           move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
 
-error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
   --> $DIR/simple.rs:70:30
    |
 LL |     if let Either::One(_t) = *rm { }
@@ -67,7 +67,7 @@ LL |     if let Either::One(_t) = *rm { }
    |                        data moved here
    |                        move occurs because `_t` has type `X`, which does not implement the `Copy` trait
 
-error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
   --> $DIR/simple.rs:74:33
    |
 LL |     while let Either::One(_t) = *rm { }
@@ -76,7 +76,7 @@ LL |     while let Either::One(_t) = *rm { }
    |                           data moved here
    |                           move occurs because `_t` has type `X`, which does not implement the `Copy` trait
 
-error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
+error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference
   --> $DIR/simple.rs:78:11
    |
 LL |     match *rm {
@@ -88,7 +88,7 @@ LL |         Either::One(_t)
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
 
-error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
   --> $DIR/simple.rs:85:11
    |
 LL |     match *rm {
@@ -100,7 +100,7 @@ LL |         Either::One(_t) => (),
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
 
-error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
   --> $DIR/simple.rs:93:11
    |
 LL |     match *rm {
@@ -226,7 +226,7 @@ LL |         Either::One(_t) => (),
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
 
-error[E0507]: cannot move out of `s.0` which is behind a shared reference
+error[E0507]: cannot move out of `s` which is behind a shared reference
   --> $DIR/simple.rs:168:18
    |
 LL |     let &X(_t) = s;
@@ -236,7 +236,7 @@ LL |     let &X(_t) = s;
    |         |  move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
    |         help: consider removing the `&`: `X(_t)`
 
-error[E0507]: cannot move out of `r.0` which is behind a shared reference
+error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
   --> $DIR/simple.rs:172:31
    |
 LL |     if let &Either::One(_t) = r { }
@@ -246,7 +246,7 @@ LL |     if let &Either::One(_t) = r { }
    |            |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |            help: consider removing the `&`: `Either::One(_t)`
 
-error[E0507]: cannot move out of `r.0` which is behind a shared reference
+error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
   --> $DIR/simple.rs:176:34
    |
 LL |     while let &Either::One(_t) = r { }
@@ -256,7 +256,7 @@ LL |     while let &Either::One(_t) = r { }
    |               |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |               help: consider removing the `&`: `Either::One(_t)`
 
-error[E0507]: cannot move out of `r.0` which is behind a shared reference
+error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference
   --> $DIR/simple.rs:180:11
    |
 LL |     match r {
@@ -276,7 +276,7 @@ LL +
 LL ~         | &Either::Two(_t) => (),
    |
 
-error[E0507]: cannot move out of `r.0` which is behind a shared reference
+error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
   --> $DIR/simple.rs:188:11
    |
 LL |     match r {
@@ -289,7 +289,7 @@ LL |         &Either::One(_t) => (),
    |         |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |         help: consider removing the `&`: `Either::One(_t)`
 
-error[E0507]: cannot move out of `r.0` which is behind a shared reference
+error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
   --> $DIR/simple.rs:195:11
    |
 LL |     match r {
@@ -302,7 +302,7 @@ LL |         &Either::One(_t) => (),
    |         |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |         help: consider removing the `&`: `Either::One(_t)`
 
-error[E0507]: cannot move out of `sm.0` which is behind a mutable reference
+error[E0507]: cannot move out of `sm` which is behind a mutable reference
   --> $DIR/simple.rs:207:22
    |
 LL |     let &mut X(_t) = sm;
@@ -312,7 +312,7 @@ LL |     let &mut X(_t) = sm;
    |         |      move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
    |         help: consider removing the `&mut`: `X(_t)`
 
-error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
   --> $DIR/simple.rs:211:35
    |
 LL |     if let &mut Either::One(_t) = rm { }
@@ -322,7 +322,7 @@ LL |     if let &mut Either::One(_t) = rm { }
    |            |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |            help: consider removing the `&mut`: `Either::One(_t)`
 
-error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
   --> $DIR/simple.rs:215:38
    |
 LL |     while let &mut Either::One(_t) = rm { }
@@ -332,7 +332,7 @@ LL |     while let &mut Either::One(_t) = rm { }
    |               |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |               help: consider removing the `&mut`: `Either::One(_t)`
 
-error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
+error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference
   --> $DIR/simple.rs:219:11
    |
 LL |     match rm {
@@ -354,7 +354,7 @@ help: consider removing the `&mut`
 LL |         Either::Two(_t) => (),
    |         ~~~~~~~~~~~~~~~
 
-error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
   --> $DIR/simple.rs:228:11
    |
 LL |     match rm {
@@ -367,7 +367,7 @@ LL |         &mut Either::One(_t) => (),
    |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |         help: consider removing the `&mut`: `Either::One(_t)`
 
-error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
   --> $DIR/simple.rs:235:11
    |
 LL |     match rm {
@@ -380,7 +380,7 @@ LL |         &mut Either::One(_t) => (),
    |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |         help: consider removing the `&mut`: `Either::One(_t)`
 
-error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
   --> $DIR/simple.rs:242:11
    |
 LL |     match rm {
diff --git a/src/test/ui/suggestions/if-then-neeing-semi.rs b/src/test/ui/suggestions/if-then-neeing-semi.rs
new file mode 100644
index 00000000000..b487f013d27
--- /dev/null
+++ b/src/test/ui/suggestions/if-then-neeing-semi.rs
@@ -0,0 +1,70 @@
+// edition:2018
+
+fn dummy() -> i32 {
+    42
+}
+
+fn extra_semicolon() {
+    let _ = if true {
+        //~^ NOTE `if` and `else` have incompatible types
+        dummy(); //~ NOTE expected because of this
+        //~^ HELP consider removing this semicolon
+    } else {
+        dummy() //~ ERROR `if` and `else` have incompatible types
+        //~^ NOTE expected `()`, found `i32`
+    };
+}
+
+async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
+//~| NOTE while checking the return type of the `async fn`
+//~| NOTE in this expansion of desugaring of `async` block or function
+//~| NOTE checked the `Output` of this `async fn`, expected opaque type
+//~| NOTE while checking the return type of the `async fn`
+//~| NOTE in this expansion of desugaring of `async` block or function
+async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
+//~| NOTE checked the `Output` of this `async fn`, found opaque type
+//~| NOTE while checking the return type of the `async fn`
+//~| NOTE in this expansion of desugaring of `async` block or function
+//~| NOTE while checking the return type of the `async fn`
+//~| NOTE in this expansion of desugaring of `async` block or function
+
+async fn async_extra_semicolon_same() {
+    let _ = if true {
+        //~^ NOTE `if` and `else` have incompatible types
+        async_dummy(); //~ NOTE expected because of this
+        //~^ HELP consider removing this semicolon
+    } else {
+        async_dummy() //~ ERROR `if` and `else` have incompatible types
+        //~^ NOTE expected `()`, found opaque type
+        //~| NOTE expected unit type `()`
+        //~| HELP consider `await`ing on the `Future`
+    };
+}
+
+async fn async_extra_semicolon_different() {
+    let _ = if true {
+        //~^ NOTE `if` and `else` have incompatible types
+        async_dummy(); //~ NOTE expected because of this
+        //~^ HELP consider removing this semicolon
+    } else {
+        async_dummy2() //~ ERROR `if` and `else` have incompatible types
+        //~^ NOTE expected `()`, found opaque type
+        //~| NOTE expected unit type `()`
+        //~| HELP consider `await`ing on the `Future`
+    };
+}
+
+async fn async_different_futures() {
+    let _ = if true {
+        //~^ NOTE `if` and `else` have incompatible types
+        async_dummy() //~ NOTE expected because of this
+        //~| HELP consider `await`ing on both `Future`s
+    } else {
+        async_dummy2() //~ ERROR `if` and `else` have incompatible types
+        //~^ NOTE expected opaque type, found a different opaque type
+        //~| NOTE expected opaque type `impl Future<Output = ()>`
+        //~| NOTE distinct uses of `impl Trait` result in different opaque types
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/if-then-neeing-semi.stderr b/src/test/ui/suggestions/if-then-neeing-semi.stderr
new file mode 100644
index 00000000000..d7c5818abbd
--- /dev/null
+++ b/src/test/ui/suggestions/if-then-neeing-semi.stderr
@@ -0,0 +1,130 @@
+error[E0308]: `if` and `else` have incompatible types
+  --> $DIR/if-then-neeing-semi.rs:37:9
+   |
+LL |       let _ = if true {
+   |  _____________-
+LL | |
+LL | |         async_dummy();
+   | |         -------------- expected because of this
+LL | |
+LL | |     } else {
+LL | |         async_dummy()
+   | |         ^^^^^^^^^^^^^ expected `()`, found opaque type
+...  |
+LL | |
+LL | |     };
+   | |_____- `if` and `else` have incompatible types
+   |
+note: while checking the return type of the `async fn`
+  --> $DIR/if-then-neeing-semi.rs:18:24
+   |
+LL | async fn async_dummy() {}
+   |                        ^ checked the `Output` of this `async fn`, found opaque type
+   = note: expected unit type `()`
+            found opaque type `impl Future<Output = ()>`
+help: consider `await`ing on the `Future`
+   |
+LL |         async_dummy().await
+   |                      ++++++
+help: consider removing this semicolon
+   |
+LL -         async_dummy();
+LL +         async_dummy()
+   |
+
+error[E0308]: `if` and `else` have incompatible types
+  --> $DIR/if-then-neeing-semi.rs:50:9
+   |
+LL |       let _ = if true {
+   |  _____________-
+LL | |
+LL | |         async_dummy();
+   | |         -------------- expected because of this
+LL | |
+LL | |     } else {
+LL | |         async_dummy2()
+   | |         ^^^^^^^^^^^^^^ expected `()`, found opaque type
+...  |
+LL | |
+LL | |     };
+   | |_____- `if` and `else` have incompatible types
+   |
+note: while checking the return type of the `async fn`
+  --> $DIR/if-then-neeing-semi.rs:24:25
+   |
+LL | async fn async_dummy2() {}
+   |                         ^ checked the `Output` of this `async fn`, found opaque type
+   = note: expected unit type `()`
+            found opaque type `impl Future<Output = ()>`
+help: consider `await`ing on the `Future`
+   |
+LL |         async_dummy2().await
+   |                       ++++++
+help: consider removing this semicolon and boxing the expressions
+   |
+LL ~         Box::new(async_dummy())
+LL |
+LL |     } else {
+LL ~         Box::new(async_dummy2())
+   |
+
+error[E0308]: `if` and `else` have incompatible types
+  --> $DIR/if-then-neeing-semi.rs:63:9
+   |
+LL |       let _ = if true {
+   |  _____________-
+LL | |
+LL | |         async_dummy()
+   | |         ------------- expected because of this
+LL | |
+LL | |     } else {
+LL | |         async_dummy2()
+   | |         ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
+...  |
+LL | |
+LL | |     };
+   | |_____- `if` and `else` have incompatible types
+   |
+note: while checking the return type of the `async fn`
+  --> $DIR/if-then-neeing-semi.rs:18:24
+   |
+LL | async fn async_dummy() {}
+   |                        ^ checked the `Output` of this `async fn`, expected opaque type
+note: while checking the return type of the `async fn`
+  --> $DIR/if-then-neeing-semi.rs:24:25
+   |
+LL | async fn async_dummy2() {}
+   |                         ^ checked the `Output` of this `async fn`, found opaque type
+   = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:18:24>)
+              found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:24:25>)
+   = note: distinct uses of `impl Trait` result in different opaque types
+help: consider `await`ing on both `Future`s
+   |
+LL ~         async_dummy().await
+LL |
+LL |     } else {
+LL ~         async_dummy2().await
+   |
+
+error[E0308]: `if` and `else` have incompatible types
+  --> $DIR/if-then-neeing-semi.rs:13:9
+   |
+LL |       let _ = if true {
+   |  _____________-
+LL | |
+LL | |         dummy();
+   | |         --------
+   | |         |      |
+   | |         |      help: consider removing this semicolon
+   | |         expected because of this
+LL | |
+LL | |     } else {
+LL | |         dummy()
+   | |         ^^^^^^^ expected `()`, found `i32`
+LL | |
+LL | |     };
+   | |_____- `if` and `else` have incompatible types
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed
new file mode 100644
index 00000000000..691e7553a09
--- /dev/null
+++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed
@@ -0,0 +1,19 @@
+// run-rustfix
+
+#[derive(Clone)]
+struct Wrapper<T>(T);
+
+struct OnlyCopyIfDisplay<T>(std::marker::PhantomData<T>);
+
+impl<T: std::fmt::Display> Clone for OnlyCopyIfDisplay<T> {
+    fn clone(&self) -> Self {
+        OnlyCopyIfDisplay(std::marker::PhantomData)
+    }
+}
+
+impl<T: std::fmt::Display> Copy for OnlyCopyIfDisplay<T> {}
+
+impl<S: std::fmt::Display> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
+//~^ ERROR the trait `Copy` may not be implemented for this type
+
+fn main() {}
diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs
new file mode 100644
index 00000000000..e3185e7eff8
--- /dev/null
+++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs
@@ -0,0 +1,19 @@
+// run-rustfix
+
+#[derive(Clone)]
+struct Wrapper<T>(T);
+
+struct OnlyCopyIfDisplay<T>(std::marker::PhantomData<T>);
+
+impl<T: std::fmt::Display> Clone for OnlyCopyIfDisplay<T> {
+    fn clone(&self) -> Self {
+        OnlyCopyIfDisplay(std::marker::PhantomData)
+    }
+}
+
+impl<T: std::fmt::Display> Copy for OnlyCopyIfDisplay<T> {}
+
+impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
+//~^ ERROR the trait `Copy` may not be implemented for this type
+
+fn main() {}
diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr
new file mode 100644
index 00000000000..e0f405eedfa
--- /dev/null
+++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr
@@ -0,0 +1,22 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:9
+   |
+LL | struct Wrapper<T>(T);
+   |                   - this field does not implement `Copy`
+...
+LL | impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
+   |         ^^^^
+   |
+note: the `Copy` impl for `OnlyCopyIfDisplay<S>` requires that `S: std::fmt::Display`
+  --> $DIR/missing-bound-in-manual-copy-impl-2.rs:4:19
+   |
+LL | struct Wrapper<T>(T);
+   |                   ^
+help: consider restricting type parameter `S`
+   |
+LL | impl<S: std::fmt::Display> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
+   |       +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.fixed b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.fixed
new file mode 100644
index 00000000000..32a7215c5bd
--- /dev/null
+++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.fixed
@@ -0,0 +1,9 @@
+// run-rustfix
+
+#[derive(Clone)]
+struct Wrapper<T>(T);
+
+impl<S: Copy> Copy for Wrapper<S> {}
+//~^ ERROR the trait `Copy` may not be implemented for this type
+
+fn main() {}
diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.rs b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.rs
new file mode 100644
index 00000000000..c688f4d41ee
--- /dev/null
+++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.rs
@@ -0,0 +1,9 @@
+// run-rustfix
+
+#[derive(Clone)]
+struct Wrapper<T>(T);
+
+impl<S> Copy for Wrapper<S> {}
+//~^ ERROR the trait `Copy` may not be implemented for this type
+
+fn main() {}
diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr
new file mode 100644
index 00000000000..218988511db
--- /dev/null
+++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr
@@ -0,0 +1,17 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/missing-bound-in-manual-copy-impl.rs:6:9
+   |
+LL | struct Wrapper<T>(T);
+   |                   - this field does not implement `Copy`
+LL |
+LL | impl<S> Copy for Wrapper<S> {}
+   |         ^^^^
+   |
+help: consider restricting type parameter `S`
+   |
+LL | impl<S: Copy> Copy for Wrapper<S> {}
+   |       ++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
index 86dbd0aac03..f5d6d72afc2 100644
--- a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
+++ b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
@@ -4,11 +4,10 @@ warning: function cannot return without recursing
 LL | / fn recurse<T>(elements: T) -> Vec<char>
 LL | | where
 LL | |     T: Iterator<Item = ()>,
-LL | | {
-LL | |     recurse(IteratorOfWrapped(elements).map(|t| t.0))
-   | |     ------------------------------------------------- recursive call site
-LL | | }
-   | |_^ cannot return without recursing
+   | |___________________________^ cannot return without recursing
+LL |   {
+LL |       recurse(IteratorOfWrapped(elements).map(|t| t.0))
+   |       ------------------------------------------------- recursive call site
    |
    = note: `#[warn(unconditional_recursion)]` on by default
    = help: a `loop` may express intention better if this is on purpose
diff --git a/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr b/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
index ac005725ab4..15faab16abe 100644
--- a/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
+++ b/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
@@ -14,7 +14,7 @@ note: cycle used when collecting item types in top-level module
   --> $DIR/cyclic-trait-resolution.rs:1:1
    |
 LL | trait A: B + A {}
-   | ^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr b/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr
index 277f4e84240..4775e68820b 100644
--- a/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr
+++ b/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr
@@ -2,18 +2,18 @@ error[E0391]: cycle detected when simplifying constant for the type system `Alph
   --> $DIR/self-in-enum-definition.rs:5:10
    |
 LL |     V3 = Self::V1 {} as u8 + 2,
-   |          ^^^^^^^^
+   |          ^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires simplifying constant for the type system `Alpha::V3::{constant#0}`...
   --> $DIR/self-in-enum-definition.rs:5:10
    |
 LL |     V3 = Self::V1 {} as u8 + 2,
-   |          ^^^^^^^^
+   |          ^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`...
   --> $DIR/self-in-enum-definition.rs:5:10
    |
 LL |     V3 = Self::V1 {} as u8 + 2,
-   |          ^^^^^^^^
+   |          ^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires computing layout of `Alpha`...
    = note: ...which again requires simplifying constant for the type system `Alpha::V3::{constant#0}`, completing the cycle
 note: cycle used when collecting item types in top-level module
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 80c84014bfd..4f9ff97f1fd 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -220,9 +220,11 @@ fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure_ty: Ty<'tcx>, call_ty: Ty<'tc
 }
 
 fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: DefId) -> String {
-    match cx.tcx.associated_item(method_def_id).container {
-        ty::TraitContainer(def_id) => cx.tcx.def_path_str(def_id),
-        ty::ImplContainer(def_id) => {
+    let assoc_item = cx.tcx.associated_item(method_def_id);
+    let def_id = assoc_item.container_id(cx.tcx);
+    match assoc_item.container {
+        ty::TraitContainer => cx.tcx.def_path_str(def_id),
+        ty::ImplContainer => {
             let ty = cx.tcx.type_of(def_id);
             match ty.kind() {
                 ty::Adt(adt, _) => cx.tcx.def_path_str(adt.did()),
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index b638f271602..e9e13aece18 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -1112,7 +1112,7 @@ fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool {
     let mut pos = 0usize;
     let mut iter = tokenize(&snip).map(|t| {
         let start = pos;
-        pos += t.len;
+        pos += t.len as usize;
         (t.kind, start..pos)
     });
 
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index a20377f320b..88ba002927a 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -10,7 +10,7 @@ use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::ty::{self, DefIdTree};
+use rustc_middle::ty::DefIdTree;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::source_map::Span;
@@ -153,13 +153,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
         // If the method is an impl for a trait, don't doc.
-        match cx.tcx.associated_item(impl_item.def_id).container {
-            ty::TraitContainer(_) => return,
-            ty::ImplContainer(cid) => {
-                if cx.tcx.impl_trait_ref(cid).is_some() {
-                    return;
-                }
-            },
+        if let Some(cid) = cx.tcx.associated_item(impl_item.def_id).impl_container(cx.tcx) {
+            if cx.tcx.impl_trait_ref(cid).is_some() {
+                return;
+            }
+        } else {
+            return;
         }
 
         let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id());
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 0d953299189..07bc2ca5d3c 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
                     match tit_.kind {
                         hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => {},
                         hir::TraitItemKind::Fn(..) => {
-                            if tit.defaultness.has_value() {
+                            if cx.tcx.impl_defaultness(tit.id.def_id).has_value() {
                                 // trait method with default body needs inline in case
                                 // an impl is not provided
                                 let desc = "a default trait method";
@@ -151,9 +151,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
             hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(_) => return,
         };
 
-        let trait_def_id = match cx.tcx.associated_item(impl_item.def_id).container {
-            TraitContainer(cid) => Some(cid),
-            ImplContainer(cid) => cx.tcx.impl_trait_ref(cid).map(|t| t.def_id),
+        let assoc_item = cx.tcx.associated_item(impl_item.def_id);
+        let container_id = assoc_item.container_id(cx.tcx);
+        let trait_def_id = match assoc_item.container {
+            TraitContainer => Some(container_id),
+            ImplContainer => cx.tcx.impl_trait_ref(container_id).map(|t| t.def_id),
         };
 
         if let Some(trait_def_id) = trait_def_id {
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index 04f16fd2161..d2e675a783e 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -345,7 +345,7 @@ fn text_has_safety_comment(src: &str, line_starts: &[BytePos], offset: usize) ->
         if line.starts_with("/*") {
             let src = src[line_start..line_starts.last().unwrap().to_usize() - offset].trim_start();
             let mut tokens = tokenize(src);
-            return src[..tokens.next().unwrap().len]
+            return src[..tokens.next().unwrap().len as usize]
                 .to_ascii_uppercase()
                 .contains("SAFETY:")
                 && tokens.all(|t| t.kind == TokenKind::Whitespace);
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index eaf260ddfb8..1834e2a2de8 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -141,7 +141,7 @@ impl HirEqInterExpr<'_, '_, '_> {
                 let mut left_pos = 0;
                 let left = tokenize(&left)
                     .map(|t| {
-                        let end = left_pos + t.len;
+                        let end = left_pos + t.len as usize;
                         let s = &left[left_pos..end];
                         left_pos = end;
                         (t, s)
@@ -156,7 +156,7 @@ impl HirEqInterExpr<'_, '_, '_> {
                 let mut right_pos = 0;
                 let right = tokenize(&right)
                     .map(|t| {
-                        let end = right_pos + t.len;
+                        let end = right_pos + t.len as usize;
                         let s = &right[right_pos..end];
                         right_pos = end;
                         (t, s)
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 50bb008098d..7493a8685df 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -968,7 +968,7 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'
                     }
                 },
                 ExprKind::Closure { .. } => {
-                    let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id).to_def_id();
+                    let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id);
                     for capture in self.cx.typeck_results().closure_min_captures_flattened(closure_id) {
                         let local_id = match capture.place.base {
                             PlaceBase::Local(id) => id,
diff --git a/src/tools/x/src/main.rs b/src/tools/x/src/main.rs
index 57d548f313d..9187c3551d7 100644
--- a/src/tools/x/src/main.rs
+++ b/src/tools/x/src/main.rs
@@ -41,9 +41,9 @@ fn python() -> &'static str {
     } else if python2 {
         PYTHON2
     } else {
-        // We would have returned early if we found that python is installed ...
-        // maybe this should panic with an error instead?
-        PYTHON
+        // Python was not found on path, so exit
+        eprintln!("Unable to find python in your PATH. Please check it is installed.");
+        process::exit(1);
     }
 }
 
diff --git a/triagebot.toml b/triagebot.toml
index f2930b50e3e..ea654192bbf 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -323,6 +323,7 @@ otherwise, make sure you bump the `FORMAT_VERSION` constant.
 cc = [
     "@CraftSpider",
     "@aDotInTheVoid",
+    "@Enselic",
 ]
 
 [mentions."src/tools/cargo"]