about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/dependencies.yml7
-rw-r--r--Cargo.lock14
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs2
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs23
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs4
-rw-r--r--compiler/rustc_attr/src/builtin.rs2
-rw-r--r--compiler/rustc_attr/src/session_diagnostics.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/allocator.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs53
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs4
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs14
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs7
-rw-r--r--compiler/rustc_const_eval/src/errors.rs10
-rw-r--r--compiler/rustc_errors/Cargo.toml2
-rw-r--r--compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs69
-rw-r--r--compiler/rustc_expand/src/errors.rs2
-rw-r--r--compiler/rustc_expand/src/expand.rs2
-rw-r--r--compiler/rustc_fluent_macro/Cargo.toml2
-rw-r--r--compiler/rustc_fluent_macro/src/fluent.rs30
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/entry.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs2
-rw-r--r--compiler/rustc_incremental/src/errors.rs4
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs6
-rw-r--r--compiler/rustc_infer/src/infer/context.rs2
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs10
-rw-r--r--compiler/rustc_lint/messages.ftl3
-rw-r--r--compiler/rustc_lint/src/builtin.rs2
-rw-r--r--compiler/rustc_lint/src/errors.rs2
-rw-r--r--compiler/rustc_lint/src/expect.rs2
-rw-r--r--compiler/rustc_lint/src/internal.rs152
-rw-r--r--compiler/rustc_lint/src/levels.rs2
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/lints.rs8
-rw-r--r--compiler/rustc_lint/src/reference_casting.rs2
-rw-r--r--compiler/rustc_lint/src/tail_expr_drop_order.rs306
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs2
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp11
-rw-r--r--compiler/rustc_metadata/src/locator.rs8
-rw-r--r--compiler/rustc_middle/src/error.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs2
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs2
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs4
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs5
-rw-r--r--compiler/rustc_mir_build/messages.ftl11
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs2
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs6
-rw-r--r--compiler/rustc_mir_build/src/errors.rs24
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs7
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs28
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs4
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs2
-rw-r--r--compiler/rustc_parse/src/errors.rs12
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs10
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs4
-rw-r--r--compiler/rustc_parse/src/parser/item.rs4
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs2
-rw-r--r--compiler/rustc_parse/src/parser/path.rs12
-rw-r--r--compiler/rustc_passes/src/check_attr.rs3
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs2
-rw-r--r--compiler/rustc_passes/src/errors.rs4
-rw-r--r--compiler/rustc_query_impl/src/lib.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs2
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs20
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/errors.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs6
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_smir/alloc.rs2
-rw-r--r--compiler/rustc_span/src/hygiene.rs8
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs18
-rw-r--r--compiler/rustc_target/src/abi/call/powerpc.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/s390x.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/sparc64.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/x86_win64.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs12
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/note.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/region.rs50
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs2
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs18
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/mod.rs13
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs4
-rw-r--r--compiler/rustc_ty_utils/src/errors.rs2
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/core/src/alloc/layout.rs29
-rw-r--r--library/core/src/ascii/ascii_char.rs10
-rw-r--r--library/core/src/cell/once.rs3
-rw-r--r--library/core/src/fmt/builders.rs224
-rw-r--r--library/core/src/iter/mod.rs2
-rw-r--r--library/core/src/iter/sources.rs2
-rw-r--r--library/core/src/iter/sources/repeat_n.rs18
-rw-r--r--library/core/src/iter/traits/accum.rs4
-rw-r--r--library/core/src/result.rs2
-rw-r--r--library/core/src/str/mod.rs2
-rw-r--r--library/core/src/ub_checks.rs2
-rw-r--r--library/core/tests/fmt/builders.rs386
-rw-r--r--library/core/tests/lib.rs2
-rw-r--r--library/core/tests/num/float_iter_sum_identity.rs27
-rw-r--r--library/core/tests/num/mod.rs1
-rw-r--r--library/std/src/os/wasi/fs.rs1
-rw-r--r--library/std/src/os/wasi/mod.rs2
-rw-r--r--library/std/src/os/wasip2/mod.rs1
-rw-r--r--library/std/src/sys/pal/unix/mod.rs4
-rw-r--r--library/std/src/sys/pal/unix/thread.rs30
-rw-r--r--library/std/src/sys/pal/wasi/args.rs2
-rw-r--r--library/std/src/sys/pal/wasi/env.rs2
-rw-r--r--library/std/src/sys/pal/wasi/fd.rs2
-rw-r--r--library/std/src/sys/pal/wasi/fs.rs2
-rw-r--r--library/std/src/sys/pal/wasi/helpers.rs2
-rw-r--r--library/std/src/sys/pal/wasi/io.rs2
-rw-r--r--library/std/src/sys/pal/wasi/net.rs2
-rw-r--r--library/std/src/sys/pal/wasi/os.rs2
-rw-r--r--library/std/src/sys/pal/wasi/stdio.rs2
-rw-r--r--library/std/src/sys/pal/wasi/thread.rs18
-rw-r--r--library/std/src/sys/pal/wasi/time.rs2
m---------library/stdarch0
-rw-r--r--src/bootstrap/src/core/build_steps/clean.rs93
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs2
-rw-r--r--src/bootstrap/src/core/config/config.rs147
-rw-r--r--src/bootstrap/src/core/download.rs2
-rw-r--r--src/bootstrap/src/lib.rs117
-rw-r--r--src/librustdoc/clean/types.rs7
-rw-r--r--src/librustdoc/doctest/rust.rs2
-rw-r--r--src/librustdoc/html/markdown.rs44
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css13
-rw-r--r--src/librustdoc/passes/lint/check_code_block_syntax.rs6
-rw-r--r--src/tools/compiletest/src/runtest.rs27
-rw-r--r--src/tools/lint-docs/src/lib.rs1
-rw-r--r--src/tools/run-make-support/src/run.rs2
-rw-r--r--src/tools/tidy/src/issues.txt3
-rw-r--r--tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs10
-rw-r--r--tests/codegen/sanitizer/kcfi/add-cfi-normalize-integers-flag.rs21
-rw-r--r--tests/codegen/sanitizer/kcfi/add-kcfi-offset-flag.rs21
-rw-r--r--tests/debuginfo/dummy_span.rs45
-rw-r--r--tests/incremental/decl_macro.rs34
-rw-r--r--tests/run-make/debugger-visualizer-dep-info/foo.py1
-rw-r--r--tests/run-make/debugger-visualizer-dep-info/main.rs2
-rw-r--r--tests/run-make/debugger-visualizer-dep-info/my_gdb_script.py6
-rw-r--r--tests/run-make/debugger-visualizer-dep-info/rmake.rs2
-rwxr-xr-xtests/run-make/libtest-junit/validate_junit.py10
-rw-r--r--tests/rustdoc-gui/target.goml2
-rw-r--r--tests/ui-fulldeps/internal-lints/diagnostics.rs7
-rw-r--r--tests/ui-fulldeps/internal-lints/diagnostics.stderr42
-rw-r--r--tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr9
-rw-r--r--tests/ui/consts/packed_pattern.stderr4
-rw-r--r--tests/ui/consts/packed_pattern2.stderr4
-rw-r--r--tests/ui/consts/static-default-lifetime/elided-lifetime.stderr6
-rw-r--r--tests/ui/consts/static-default-lifetime/static-trait-impl.stderr6
-rw-r--r--tests/ui/drop/lint-tail-expr-drop-order-gated.rs35
-rw-r--r--tests/ui/drop/lint-tail-expr-drop-order.rs71
-rw-r--r--tests/ui/drop/lint-tail-expr-drop-order.stderr42
-rw-r--r--tests/ui/error-codes/E0001.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-repr-simd.stderr14
-rw-r--r--tests/ui/generic-associated-types/gat-in-trait-path.base.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-76535.base.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-79422.base.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-79422.extended.stderr2
-rw-r--r--tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr4
-rw-r--r--tests/ui/imports/auxiliary/empty.rs (renamed from tests/ui/imports/auxiliary/issue-85992-extern-2.rs)0
-rw-r--r--tests/ui/imports/auxiliary/issue-85992-extern.rs (renamed from tests/ui/imports/auxiliary/issue-85992-extern-1.rs)2
-rw-r--r--tests/ui/imports/issue-85992.rs12
-rw-r--r--tests/ui/imports/issue-85992.stderr6
-rw-r--r--tests/ui/imports/multiple-extern-by-macro-for-buitlin.rs18
-rw-r--r--tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr22
-rw-r--r--tests/ui/imports/multiple-extern-by-macro-for-custom.rs19
-rw-r--r--tests/ui/imports/multiple-extern-by-macro-for-custom.stderr22
-rw-r--r--tests/ui/imports/multiple-extern-by-macro-for-inexist.rs19
-rw-r--r--tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr29
-rw-r--r--tests/ui/imports/multiple-extern-by-macro-for-underscore.rs18
-rw-r--r--tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr8
-rw-r--r--tests/ui/issues/issue-20831-debruijn.stderr4
-rw-r--r--tests/ui/issues/issue-37884.stderr5
-rw-r--r--tests/ui/issues/issue-47094.stderr25
-rw-r--r--tests/ui/lint/issue-30302.stderr2
-rw-r--r--tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr136
-rw-r--r--tests/ui/pattern/issue-14221.stderr2
-rw-r--r--tests/ui/pattern/usefulness/consts-opaque.stderr24
-rw-r--r--tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr26
-rw-r--r--tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr26
-rw-r--r--tests/ui/pattern/usefulness/empty-match-check-notes.rs4
-rw-r--r--tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr156
-rw-r--r--tests/ui/pattern/usefulness/empty-types.never_pats.stderr156
-rw-r--r--tests/ui/pattern/usefulness/empty-types.normal.stderr156
-rw-r--r--tests/ui/pattern/usefulness/explain-unreachable-pats.rs52
-rw-r--r--tests/ui/pattern/usefulness/explain-unreachable-pats.stderr78
-rw-r--r--tests/ui/pattern/usefulness/floats.stderr56
-rw-r--r--tests/ui/pattern/usefulness/impl-trait.stderr48
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/reachability.stderr98
-rw-r--r--tests/ui/pattern/usefulness/issue-12116.stderr4
-rw-r--r--tests/ui/pattern/usefulness/issue-12369.stderr4
-rw-r--r--tests/ui/pattern/usefulness/issue-13727.stderr4
-rw-r--r--tests/ui/pattern/usefulness/issue-30240-b.stderr4
-rw-r--r--tests/ui/pattern/usefulness/issue-31221.stderr8
-rw-r--r--tests/ui/pattern/usefulness/issue-57472.stderr8
-rw-r--r--tests/ui/pattern/usefulness/match-arm-statics.stderr12
-rw-r--r--tests/ui/pattern/usefulness/match-byte-array-patterns.stderr32
-rw-r--r--tests/ui/pattern/usefulness/match-ref-ice.stderr4
-rw-r--r--tests/ui/pattern/usefulness/match-vec-fixed.stderr8
-rw-r--r--tests/ui/pattern/usefulness/match-vec-unreachable.stderr12
-rw-r--r--tests/ui/pattern/usefulness/slice-pattern-const-2.stderr16
-rw-r--r--tests/ui/pattern/usefulness/slice-pattern-const-3.stderr16
-rw-r--r--tests/ui/pattern/usefulness/slice-pattern-const.stderr36
-rw-r--r--tests/ui/pattern/usefulness/slice-patterns-reachability.stderr24
-rw-r--r--tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr2
-rw-r--r--tests/ui/pattern/usefulness/top-level-alternation.stderr44
-rw-r--r--tests/ui/reachable/unreachable-arm.stderr4
-rw-r--r--tests/ui/reachable/unreachable-loop-patterns.stderr4
-rw-r--r--tests/ui/reachable/unreachable-try-pattern.stderr8
-rw-r--r--tests/ui/regions/explicit-static-bound-on-trait.rs13
-rw-r--r--tests/ui/regions/explicit-static-bound-on-trait.stderr32
-rw-r--r--tests/ui/repr/conflicting-repr-hints.stderr22
-rw-r--r--tests/ui/resolve/local-shadows-inner-generic.rs8
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr24
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr4
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr4
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr20
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr4
-rw-r--r--tests/ui/sanitizer/cfi/transparent-has-regions.rs18
-rw-r--r--tests/ui/traits/object/pretty.rs7
-rw-r--r--tests/ui/traits/object/pretty.stderr50
-rw-r--r--tests/ui/transmutability/arrays/huge-len.stderr4
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs26
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.stderr46
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs12
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr31
-rw-r--r--tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs1
-rw-r--r--tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr19
-rw-r--r--tests/ui/uninhabited/uninhabited-patterns.stderr12
249 files changed, 3191 insertions, 1522 deletions
diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml
index 5e54ceea3d7..83b92b7fa09 100644
--- a/.github/workflows/dependencies.yml
+++ b/.github/workflows/dependencies.yml
@@ -64,6 +64,10 @@ jobs:
       - name: cargo update
         # Remove first line that always just says "Updating crates.io index"
         run: cargo update 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log
+      - name: cargo update library
+        run: |
+          echo -e "\nlibrary dependencies:" >> cargo_update.log
+          cargo update --manifest-path library/Cargo.toml 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log
       - name: cargo update rustbook
         run: |
           echo -e "\nrustbook dependencies:" >> cargo_update.log
@@ -74,6 +78,7 @@ jobs:
           name: Cargo-lock
           path: |
             Cargo.lock
+            library/Cargo.lock
             src/tools/rustbook/Cargo.lock
           retention-days: 1
       - name: upload cargo-update log artifact for use in PR
@@ -119,7 +124,7 @@ jobs:
           git config user.name github-actions
           git config user.email github-actions@github.com
           git switch --force-create cargo_update
-          git add ./Cargo.lock ./src/tools/rustbook/Cargo.lock
+          git add ./Cargo.lock ./library/Cargo.lock ./src/tools/rustbook/Cargo.lock
           git commit --no-verify --file=commit.txt
 
       - name: push
diff --git a/Cargo.lock b/Cargo.lock
index ac347d02af7..a18219b5683 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -96,16 +96,6 @@ dependencies = [
 
 [[package]]
 name = "annotate-snippets"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d9b665789884a7e8fb06c84b295e923b03ca51edbb7d08f91a6a50322ecbfe6"
-dependencies = [
- "anstyle",
- "unicode-width",
-]
-
-[[package]]
-name = "annotate-snippets"
 version = "0.11.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "24e35ed54e5ea7997c14ed4c70ba043478db1112e98263b3b035907aa197d991"
@@ -3642,7 +3632,7 @@ dependencies = [
 name = "rustc_errors"
 version = "0.0.0"
 dependencies = [
- "annotate-snippets 0.10.2",
+ "annotate-snippets 0.11.4",
  "derive_setters",
  "rustc_ast",
  "rustc_ast_pretty",
@@ -3702,7 +3692,7 @@ dependencies = [
 name = "rustc_fluent_macro"
 version = "0.0.0"
 dependencies = [
- "annotate-snippets 0.10.2",
+ "annotate-snippets 0.11.4",
  "fluent-bundle",
  "fluent-syntax",
  "proc-macro2",
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 7d9d689e6d7..51cbe808a3a 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -86,9 +86,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                 // Multiple different abi names may actually be the same ABI
                                 // If the specified ABIs are not the same name, alert the user that they resolve to the same ABI
                                 let source_map = self.tcx.sess.source_map();
-                                let equivalent = (source_map.span_to_snippet(*prev_sp)
-                                    != source_map.span_to_snippet(*abi_span))
-                                .then_some(());
+                                let equivalent = source_map.span_to_snippet(*prev_sp)
+                                    != source_map.span_to_snippet(*abi_span);
 
                                 self.dcx().emit_err(AbiSpecifiedMultipleTimes {
                                     abi_span: *abi_span,
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 7a6c9d8d0d3..8237bfd6792 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -184,7 +184,7 @@ pub struct AbiSpecifiedMultipleTimes {
     #[label]
     pub prev_span: Span,
     #[note]
-    pub equivalent: Option<()>,
+    pub equivalent: bool,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index f6065259d8d..eef87879c24 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1421,7 +1421,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         };
         hir::FnHeader {
             safety: self.lower_safety(h.safety, default_safety),
-            asyncness: asyncness,
+            asyncness,
             constness: self.lower_constness(h.constness),
             abi: self.lower_extern(h.ext),
         }
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 837cb805700..a9b65456b8c 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -562,10 +562,8 @@ impl<'a> AstValidator<'a> {
         FnHeader { safety: _, coroutine_kind, constness, ext }: FnHeader,
     ) {
         let report_err = |span| {
-            self.dcx().emit_err(errors::FnQualifierInExtern {
-                span: span,
-                block: self.current_extern_span(),
-            });
+            self.dcx()
+                .emit_err(errors::FnQualifierInExtern { span, block: self.current_extern_span() });
         };
         match coroutine_kind {
             Some(knd) => report_err(knd.span()),
@@ -963,14 +961,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 self_ty,
                 items,
             }) => {
-                let error =
-                    |annotation_span, annotation, only_trait: bool| errors::InherentImplCannot {
-                        span: self_ty.span,
-                        annotation_span,
-                        annotation,
-                        self_ty: self_ty.span,
-                        only_trait: only_trait.then_some(()),
-                    };
+                let error = |annotation_span, annotation, only_trait| errors::InherentImplCannot {
+                    span: self_ty.span,
+                    annotation_span,
+                    annotation,
+                    self_ty: self_ty.span,
+                    only_trait,
+                };
 
                 self.with_in_trait_impl(None, |this| {
                     this.visibility_not_permitted(
@@ -1195,7 +1192,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 } else if where_clauses.after.has_where_token {
                     self.dcx().emit_err(errors::WhereClauseAfterTypeAlias {
                         span: where_clauses.after.span,
-                        help: self.session.is_nightly_build().then_some(()),
+                        help: self.session.is_nightly_build(),
                     });
                 }
             }
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 9e403680837..de1b3f55e80 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -484,7 +484,7 @@ pub struct InherentImplCannot<'a> {
     #[label(ast_passes_type)]
     pub self_ty: Span,
     #[note(ast_passes_only_trait)]
-    pub only_trait: Option<()>,
+    pub only_trait: bool,
 }
 
 #[derive(Diagnostic)]
@@ -528,7 +528,7 @@ pub struct WhereClauseAfterTypeAlias {
     #[primary_span]
     pub span: Span,
     #[help]
-    pub help: Option<()>,
+    pub help: bool,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index d057dcfdf9d..e46dabc7a6e 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -846,7 +846,7 @@ pub fn find_deprecation(
                                     sess.dcx().emit_err(
                                         session_diagnostics::DeprecatedItemSuggestion {
                                             span: mi.span,
-                                            is_nightly: sess.is_nightly_build().then_some(()),
+                                            is_nightly: sess.is_nightly_build(),
                                             details: (),
                                         },
                                     );
diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs
index 92a3a385a74..9b69325a053 100644
--- a/compiler/rustc_attr/src/session_diagnostics.rs
+++ b/compiler/rustc_attr/src/session_diagnostics.rs
@@ -342,7 +342,7 @@ pub(crate) struct DeprecatedItemSuggestion {
     pub span: Span,
 
     #[help]
-    pub is_nightly: Option<()>,
+    pub is_nightly: bool,
 
     #[note]
     pub details: (),
diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs
index 8fb31082793..b4f3784a31a 100644
--- a/compiler/rustc_codegen_llvm/src/allocator.rs
+++ b/compiler/rustc_codegen_llvm/src/allocator.rs
@@ -149,7 +149,7 @@ fn create_wrapper_function(
         }
         llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
 
-        let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr().cast());
+        let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr());
 
         let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
         llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index f68155f523a..aac446f3149 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -616,7 +616,7 @@ pub(crate) fn run_pass_manager(
             llvm::LLVMRustAddModuleFlagU32(
                 module.module_llvm.llmod(),
                 llvm::LLVMModFlagBehavior::Error,
-                c"LTOPostLink".as_ptr().cast(),
+                c"LTOPostLink".as_ptr(),
                 1,
             );
         }
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index a1f2433ab6f..51b02891d02 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -1031,7 +1031,7 @@ unsafe fn embed_bitcode(
             let llglobal = llvm::LLVMAddGlobal(
                 llmod,
                 common::val_ty(llconst),
-                c"rustc.embedded.module".as_ptr().cast(),
+                c"rustc.embedded.module".as_ptr(),
             );
             llvm::LLVMSetInitializer(llglobal, llconst);
 
@@ -1044,7 +1044,7 @@ unsafe fn embed_bitcode(
             let llglobal = llvm::LLVMAddGlobal(
                 llmod,
                 common::val_ty(llconst),
-                c"rustc.embedded.cmdline".as_ptr().cast(),
+                c"rustc.embedded.cmdline".as_ptr(),
             );
             llvm::LLVMSetInitializer(llglobal, llconst);
             let section = if is_apple {
@@ -1054,7 +1054,7 @@ unsafe fn embed_bitcode(
             } else {
                 c".llvmcmd"
             };
-            llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
+            llvm::LLVMSetSection(llglobal, section.as_ptr());
             llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
         } else {
             // We need custom section flags, so emit module-level inline assembly.
@@ -1107,7 +1107,7 @@ fn create_msvc_imps(
             .collect::<Vec<_>>();
 
         for (imp_name, val) in globals {
-            let imp = llvm::LLVMAddGlobal(llmod, ptr_ty, imp_name.as_ptr().cast());
+            let imp = llvm::LLVMAddGlobal(llmod, ptr_ty, imp_name.as_ptr());
             llvm::LLVMSetInitializer(imp, val);
             llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage);
         }
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 75b298f14ca..a764b263ec7 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -525,7 +525,7 @@ impl<'ll> CodegenCx<'ll, '_> {
                     let val = llvm::LLVMMetadataAsValue(self.llcx, meta);
                     llvm::LLVMAddNamedMetadataOperand(
                         self.llmod,
-                        c"wasm.custom_sections".as_ptr().cast(),
+                        c"wasm.custom_sections".as_ptr(),
                         val,
                     );
                 }
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 1fd9f9e8116..fe71b2e669e 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -11,6 +11,7 @@ use rustc_data_structures::base_n::{ToBaseN, ALPHANUMERIC_ONLY};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_hir::def_id::DefId;
+use rustc_middle::middle::codegen_fn_attrs::PatchableFunctionEntry;
 use rustc_middle::mir::mono::CodegenUnit;
 use rustc_middle::ty::layout::{
     FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers,
@@ -207,7 +208,7 @@ pub unsafe fn create_module<'ll>(
     // If skipping the PLT is enabled, we need to add some module metadata
     // to ensure intrinsic calls don't use it.
     if !sess.needs_plt() {
-        let avoid_plt = c"RtLibUseGOT".as_ptr().cast();
+        let avoid_plt = c"RtLibUseGOT".as_ptr();
         unsafe {
             llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
         }
@@ -215,7 +216,7 @@ pub unsafe fn create_module<'ll>(
 
     // Enable canonical jump tables if CFI is enabled. (See https://reviews.llvm.org/D65629.)
     if sess.is_sanitizer_cfi_canonical_jump_tables_enabled() && sess.is_sanitizer_cfi_enabled() {
-        let canonical_jump_tables = c"CFI Canonical Jump Tables".as_ptr().cast();
+        let canonical_jump_tables = c"CFI Canonical Jump Tables".as_ptr();
         unsafe {
             llvm::LLVMRustAddModuleFlagU32(
                 llmod,
@@ -226,9 +227,23 @@ pub unsafe fn create_module<'ll>(
         }
     }
 
+    // If we're normalizing integers with CFI, ensure LLVM generated functions do the same.
+    // See https://github.com/llvm/llvm-project/pull/104826
+    if sess.is_sanitizer_cfi_normalize_integers_enabled() {
+        let cfi_normalize_integers = c"cfi-normalize-integers".as_ptr().cast();
+        unsafe {
+            llvm::LLVMRustAddModuleFlagU32(
+                llmod,
+                llvm::LLVMModFlagBehavior::Override,
+                cfi_normalize_integers,
+                1,
+            );
+        }
+    }
+
     // Enable LTO unit splitting if specified or if CFI is enabled. (See https://reviews.llvm.org/D53891.)
     if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() {
-        let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr().cast();
+        let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr();
         unsafe {
             llvm::LLVMRustAddModuleFlagU32(
                 llmod,
@@ -241,10 +256,26 @@ pub unsafe fn create_module<'ll>(
 
     // Add "kcfi" module flag if KCFI is enabled. (See https://reviews.llvm.org/D119296.)
     if sess.is_sanitizer_kcfi_enabled() {
-        let kcfi = c"kcfi".as_ptr().cast();
+        let kcfi = c"kcfi".as_ptr();
         unsafe {
             llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
         }
+
+        // Add "kcfi-offset" module flag with -Z patchable-function-entry (See
+        // https://reviews.llvm.org/D141172).
+        let pfe =
+            PatchableFunctionEntry::from_config(sess.opts.unstable_opts.patchable_function_entry);
+        if pfe.prefix() > 0 {
+            let kcfi_offset = c"kcfi-offset".as_ptr().cast();
+            unsafe {
+                llvm::LLVMRustAddModuleFlagU32(
+                    llmod,
+                    llvm::LLVMModFlagBehavior::Override,
+                    kcfi_offset,
+                    pfe.prefix().into(),
+                );
+            }
+        }
     }
 
     // Control Flow Guard is currently only supported by the MSVC linker on Windows.
@@ -280,26 +311,26 @@ pub unsafe fn create_module<'ll>(
                 llvm::LLVMRustAddModuleFlagU32(
                     llmod,
                     llvm::LLVMModFlagBehavior::Min,
-                    c"branch-target-enforcement".as_ptr().cast(),
+                    c"branch-target-enforcement".as_ptr(),
                     bti.into(),
                 );
                 llvm::LLVMRustAddModuleFlagU32(
                     llmod,
                     llvm::LLVMModFlagBehavior::Min,
-                    c"sign-return-address".as_ptr().cast(),
+                    c"sign-return-address".as_ptr(),
                     pac_ret.is_some().into(),
                 );
                 let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
                 llvm::LLVMRustAddModuleFlagU32(
                     llmod,
                     llvm::LLVMModFlagBehavior::Min,
-                    c"sign-return-address-all".as_ptr().cast(),
+                    c"sign-return-address-all".as_ptr(),
                     pac_opts.leaf.into(),
                 );
                 llvm::LLVMRustAddModuleFlagU32(
                     llmod,
                     llvm::LLVMModFlagBehavior::Min,
-                    c"sign-return-address-with-bkey".as_ptr().cast(),
+                    c"sign-return-address-with-bkey".as_ptr(),
                     u32::from(pac_opts.key == PAuthKey::B),
                 );
             }
@@ -317,7 +348,7 @@ pub unsafe fn create_module<'ll>(
             llvm::LLVMRustAddModuleFlagU32(
                 llmod,
                 llvm::LLVMModFlagBehavior::Override,
-                c"cf-protection-branch".as_ptr().cast(),
+                c"cf-protection-branch".as_ptr(),
                 1,
             );
         }
@@ -327,7 +358,7 @@ pub unsafe fn create_module<'ll>(
             llvm::LLVMRustAddModuleFlagU32(
                 llmod,
                 llvm::LLVMModFlagBehavior::Override,
-                c"cf-protection-return".as_ptr().cast(),
+                c"cf-protection-return".as_ptr(),
                 1,
             );
         }
@@ -338,7 +369,7 @@ pub unsafe fn create_module<'ll>(
             llvm::LLVMRustAddModuleFlagU32(
                 llmod,
                 llvm::LLVMModFlagBehavior::Error,
-                c"Virtual Function Elim".as_ptr().cast(),
+                c"Virtual Function Elim".as_ptr(),
                 1,
             );
         }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index 5a08f2f00e5..e91bcea16a2 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -34,8 +34,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, '
     let c_section_var_name = c"__rustc_debug_gdb_scripts_section__";
     let section_var_name = c_section_var_name.to_str().unwrap();
 
-    let section_var =
-        unsafe { llvm::LLVMGetNamedGlobal(cx.llmod, c_section_var_name.as_ptr().cast()) };
+    let section_var = unsafe { llvm::LLVMGetNamedGlobal(cx.llmod, c_section_var_name.as_ptr()) };
 
     section_var.unwrap_or_else(|| {
         let mut section_contents = Vec::new();
@@ -70,7 +69,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, '
             let section_var = cx
                 .define_global(section_var_name, llvm_type)
                 .unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name));
-            llvm::LLVMSetSection(section_var, c".debug_gdb_scripts".as_ptr().cast());
+            llvm::LLVMSetSection(section_var, c".debug_gdb_scripts".as_ptr());
             llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents));
             llvm::LLVMSetGlobalConstant(section_var, llvm::True);
             llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 87bea22d8dd..30f90bada9a 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -952,7 +952,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
             producer.as_ptr().cast(),
             producer.len(),
             tcx.sess.opts.optimize != config::OptLevel::No,
-            c"".as_ptr().cast(),
+            c"".as_ptr(),
             0,
             // NB: this doesn't actually have any perceptible effect, it seems. LLVM will instead
             // put the path supplied to `MCSplitDwarfFile` into the debug info of the final
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index b23e05182ca..eb446d2d7b2 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -109,7 +109,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
                 llvm::LLVMRustAddModuleFlagU32(
                     self.llmod,
                     llvm::LLVMModFlagBehavior::Warning,
-                    c"Dwarf Version".as_ptr().cast(),
+                    c"Dwarf Version".as_ptr(),
                     dwarf_version,
                 );
             } else {
@@ -117,7 +117,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
                 llvm::LLVMRustAddModuleFlagU32(
                     self.llmod,
                     llvm::LLVMModFlagBehavior::Warning,
-                    c"CodeView".as_ptr().cast(),
+                    c"CodeView".as_ptr(),
                     1,
                 )
             }
@@ -126,7 +126,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
             llvm::LLVMRustAddModuleFlagU32(
                 self.llmod,
                 llvm::LLVMModFlagBehavior::Warning,
-                c"Debug Info Version".as_ptr().cast(),
+                c"Debug Info Version".as_ptr(),
                 llvm::LLVMRustDebugMetadataVersion(),
             );
         }
@@ -570,7 +570,17 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         inlined_at: Option<&'ll DILocation>,
         span: Span,
     ) -> &'ll DILocation {
-        let DebugLoc { line, col, .. } = self.lookup_debug_loc(span.lo());
+        // When emitting debugging information, DWARF (i.e. everything but MSVC)
+        // treats line 0 as a magic value meaning that the code could not be
+        // attributed to any line in the source. That's also exactly what dummy
+        // spans are. Make that equivalence here, rather than passing dummy spans
+        // to lookup_debug_loc, which will return line 1 for them.
+        let (line, col) = if span.is_dummy() && !self.sess().target.is_like_msvc {
+            (0, 0)
+        } else {
+            let DebugLoc { line, col, .. } = self.lookup_debug_loc(span.lo());
+            (line, col)
+        };
 
         unsafe { llvm::LLVMRustDIBuilderCreateDebugLocation(line, col, scope, inlined_at) }
     }
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index febeb7093a3..fbab988a32b 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -1500,7 +1500,7 @@ impl<'a> Linker for L4Bender<'a> {
 
 impl<'a> L4Bender<'a> {
     pub fn new(cmd: Command, sess: &'a Session) -> L4Bender<'a> {
-        L4Bender { cmd, sess: sess, hinted_static: false }
+        L4Bender { cmd, sess, hinted_static: false }
     }
 
     fn hint_static(&mut self) {
@@ -1520,7 +1520,7 @@ pub struct AixLinker<'a> {
 
 impl<'a> AixLinker<'a> {
     pub fn new(cmd: Command, sess: &'a Session) -> AixLinker<'a> {
-        AixLinker { cmd, sess: sess, hinted_static: None }
+        AixLinker { cmd, sess, hinted_static: None }
     }
 
     fn hint_static(&mut self) {
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index c6361710ac9..259114dbdc2 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -384,7 +384,7 @@ impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
         ccx.dcx().create_err(errors::UnallowedHeapAllocations {
             span,
             kind: ccx.const_kind(),
-            teach: ccx.tcx.sess.teach(E0010).then_some(()),
+            teach: ccx.tcx.sess.teach(E0010),
         })
     }
 }
@@ -444,16 +444,16 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow {
         if let hir::ConstContext::Static(_) = ccx.const_kind() {
             ccx.dcx().create_err(errors::InteriorMutableDataRefer {
                 span,
-                opt_help: Some(()),
+                opt_help: true,
                 kind: ccx.const_kind(),
-                teach: ccx.tcx.sess.teach(E0492).then_some(()),
+                teach: ccx.tcx.sess.teach(E0492),
             })
         } else {
             ccx.dcx().create_err(errors::InteriorMutableDataRefer {
                 span,
-                opt_help: None,
+                opt_help: false,
                 kind: ccx.const_kind(),
-                teach: ccx.tcx.sess.teach(E0492).then_some(()),
+                teach: ccx.tcx.sess.teach(E0492),
             })
         }
     }
@@ -481,12 +481,12 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow {
             hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::UnallowedMutableRaw {
                 span,
                 kind: ccx.const_kind(),
-                teach: ccx.tcx.sess.teach(E0764).then_some(()),
+                teach: ccx.tcx.sess.teach(E0764),
             }),
             hir::BorrowKind::Ref => ccx.dcx().create_err(errors::UnallowedMutableRefs {
                 span,
                 kind: ccx.const_kind(),
-                teach: ccx.tcx.sess.teach(E0764).then_some(()),
+                teach: ccx.tcx.sess.teach(E0764),
             }),
         }
     }
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index a075bdc1911..c3d94ca0e59 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -40,7 +40,10 @@ const TINY_LINT_TERMINATOR_LIMIT: usize = 20;
 /// power of two of interpreted terminators.
 const PROGRESS_INDICATOR_START: usize = 4_000_000;
 
-/// Extra machine state for CTFE, and the Machine instance
+/// Extra machine state for CTFE, and the Machine instance.
+//
+// Should be public because out-of-tree rustc consumers need this
+// if they want to interact with constant values.
 pub struct CompileTimeMachine<'tcx> {
     /// The number of terminators that have been evaluated.
     ///
@@ -160,7 +163,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxIndexMap<K, V> {
     }
 }
 
-pub(crate) type CompileTimeInterpCx<'tcx> = InterpCx<'tcx, CompileTimeMachine<'tcx>>;
+pub type CompileTimeInterpCx<'tcx> = InterpCx<'tcx, CompileTimeMachine<'tcx>>;
 
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
 pub enum MemoryKind {
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 7afb92c08ec..6075f3f84cd 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -151,7 +151,7 @@ pub(crate) struct UnallowedMutableRefs {
     pub span: Span,
     pub kind: ConstContext,
     #[note(const_eval_teach_note)]
-    pub teach: Option<()>,
+    pub teach: bool,
 }
 
 #[derive(Diagnostic)]
@@ -161,7 +161,7 @@ pub(crate) struct UnallowedMutableRaw {
     pub span: Span,
     pub kind: ConstContext,
     #[note(const_eval_teach_note)]
-    pub teach: Option<()>,
+    pub teach: bool,
 }
 #[derive(Diagnostic)]
 #[diag(const_eval_non_const_fmt_macro_call, code = E0015)]
@@ -196,7 +196,7 @@ pub(crate) struct UnallowedHeapAllocations {
     pub span: Span,
     pub kind: ConstContext,
     #[note(const_eval_teach_note)]
-    pub teach: Option<()>,
+    pub teach: bool,
 }
 
 #[derive(Diagnostic)]
@@ -214,10 +214,10 @@ pub(crate) struct InteriorMutableDataRefer {
     #[label]
     pub span: Span,
     #[help]
-    pub opt_help: Option<()>,
+    pub opt_help: bool,
     pub kind: ConstContext,
     #[note(const_eval_teach_note)]
-    pub teach: Option<()>,
+    pub teach: bool,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index 2fff9f2de50..59cf4e5f210 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
-annotate-snippets = "0.10"
+annotate-snippets = "0.11"
 derive_setters = "0.1.6"
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index df4e9792f95..d71ae9d210d 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -5,7 +5,7 @@
 //!
 //! [annotate_snippets]: https://docs.rs/crate/annotate-snippets/
 
-use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
+use annotate_snippets::{Renderer, Snippet};
 use rustc_data_structures::sync::Lrc;
 use rustc_error_messages::FluentArgs;
 use rustc_span::source_map::SourceMap;
@@ -83,15 +83,17 @@ fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
     file.get_line(line.line_index - 1).map(|a| a.to_string()).unwrap_or_default()
 }
 
-/// Maps `diagnostic::Level` to `snippet::AnnotationType`
-fn annotation_type_for_level(level: Level) -> AnnotationType {
+/// Maps [`crate::Level`] to [`annotate_snippets::Level`]
+fn annotation_level_for_level(level: Level) -> annotate_snippets::Level {
     match level {
-        Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => AnnotationType::Error,
-        Level::ForceWarning(_) | Level::Warning => AnnotationType::Warning,
-        Level::Note | Level::OnceNote => AnnotationType::Note,
-        Level::Help | Level::OnceHelp => AnnotationType::Help,
+        Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => {
+            annotate_snippets::Level::Error
+        }
+        Level::ForceWarning(_) | Level::Warning => annotate_snippets::Level::Warning,
+        Level::Note | Level::OnceNote => annotate_snippets::Level::Note,
+        Level::Help | Level::OnceHelp => annotate_snippets::Level::Help,
         // FIXME(#59346): Not sure how to map this level
-        Level::FailureNote => AnnotationType::Error,
+        Level::FailureNote => annotate_snippets::Level::Error,
         Level::Allow => panic!("Should not call with Allow"),
         Level::Expect(_) => panic!("Should not call with Expect"),
     }
@@ -180,42 +182,29 @@ impl AnnotateSnippetEmitter {
                 })
                 .collect();
             let code = code.map(|code| code.to_string());
-            let snippet = Snippet {
-                title: Some(Annotation {
-                    label: Some(&message),
-                    id: code.as_deref(),
-                    annotation_type: annotation_type_for_level(*level),
-                }),
-                footer: vec![],
-                slices: annotated_files
-                    .iter()
-                    .map(|(file_name, source, line_index, annotations)| {
-                        Slice {
-                            source,
-                            line_start: *line_index,
-                            origin: Some(file_name),
-                            // FIXME(#59346): Not really sure when `fold` should be true or false
-                            fold: false,
-                            annotations: annotations
-                                .iter()
-                                .map(|annotation| SourceAnnotation {
-                                    range: (
-                                        annotation.start_col.display,
-                                        annotation.end_col.display,
-                                    ),
-                                    label: annotation.label.as_deref().unwrap_or_default(),
-                                    annotation_type: annotation_type_for_level(*level),
-                                })
-                                .collect(),
-                        }
-                    })
-                    .collect(),
-            };
+
+            let snippets =
+                annotated_files.iter().map(|(file_name, source, line_index, annotations)| {
+                    Snippet::source(source)
+                        .line_start(*line_index)
+                        .origin(file_name)
+                        // FIXME(#59346): Not really sure when `fold` should be true or false
+                        .fold(false)
+                        .annotations(annotations.iter().map(|annotation| {
+                            annotation_level_for_level(*level)
+                                .span(annotation.start_col.display..annotation.end_col.display)
+                                .label(annotation.label.as_deref().unwrap_or_default())
+                        }))
+                });
+            let mut message = annotation_level_for_level(*level).title(&message).snippets(snippets);
+            if let Some(code) = code.as_deref() {
+                message = message.id(code)
+            }
             // FIXME(#59346): Figure out if we can _always_ print to stderr or not.
             // `emitter.rs` has the `Destination` enum that lists various possible output
             // destinations.
             let renderer = Renderer::plain().anonymized_line_numbers(self.ui_testing);
-            eprintln!("{}", renderer.render(snippet))
+            eprintln!("{}", renderer.render(message))
         }
         // FIXME(#59346): Is it ok to return None if there's no source_map?
     }
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index c30a9b0c357..f6b5cd394b6 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -281,7 +281,7 @@ pub(crate) struct IncompleteParse<'a> {
     pub macro_path: &'a ast::Path,
     pub kind_name: &'a str,
     #[note(expand_macro_expands_to_match_arm)]
-    pub expands_to_match_arm: Option<()>,
+    pub expands_to_match_arm: bool,
 
     #[suggestion(
         expand_suggestion_add_semi,
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index cb6b13282a2..0d56a005f15 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1031,7 +1031,7 @@ pub(crate) fn ensure_complete_parse<'a>(
             label_span: span,
             macro_path,
             kind_name,
-            expands_to_match_arm: expands_to_match_arm.then_some(()),
+            expands_to_match_arm,
             add_semicolon,
         });
     }
diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml
index c5a53ae8313..eeceaa4691a 100644
--- a/compiler/rustc_fluent_macro/Cargo.toml
+++ b/compiler/rustc_fluent_macro/Cargo.toml
@@ -8,7 +8,7 @@ proc-macro = true
 
 [dependencies]
 # tidy-alphabetical-start
-annotate-snippets = "0.10"
+annotate-snippets = "0.11"
 fluent-bundle = "0.15.2"
 fluent-syntax = "0.11"
 proc-macro2 = "1"
diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs
index 23795a96b92..ca8bace28f3 100644
--- a/compiler/rustc_fluent_macro/src/fluent.rs
+++ b/compiler/rustc_fluent_macro/src/fluent.rs
@@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet};
 use std::fs::read_to_string;
 use std::path::{Path, PathBuf};
 
-use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
+use annotate_snippets::{Renderer, Snippet};
 use fluent_bundle::{FluentBundle, FluentError, FluentResource};
 use fluent_syntax::ast::{
     Attribute, Entry, Expression, Identifier, InlineExpression, Message, Pattern, PatternElement,
@@ -154,27 +154,15 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
                     .unwrap()
                     .0;
 
-                let snippet = Snippet {
-                    title: Some(Annotation {
-                        label: Some(&err),
-                        id: None,
-                        annotation_type: AnnotationType::Error,
-                    }),
-                    footer: vec![],
-                    slices: vec![Slice {
-                        source: this.source(),
-                        line_start,
-                        origin: Some(&relative_ftl_path),
-                        fold: true,
-                        annotations: vec![SourceAnnotation {
-                            label: "",
-                            annotation_type: AnnotationType::Error,
-                            range: (pos.start, pos.end - 1),
-                        }],
-                    }],
-                };
+                let message = annotate_snippets::Level::Error.title(&err).snippet(
+                    Snippet::source(this.source())
+                        .line_start(line_start)
+                        .origin(&relative_ftl_path)
+                        .fold(true)
+                        .annotation(annotate_snippets::Level::Error.span(pos.start..pos.end - 1)),
+                );
                 let renderer = Renderer::plain();
-                eprintln!("{}\n", renderer.render(snippet));
+                eprintln!("{}\n", renderer.render(message));
             }
 
             return failed(&crate_name);
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 0135cdf1e90..16eeb57b2b9 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1564,7 +1564,7 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD
             // * compare the param span to the pred span to detect lone user-written `Sized` bounds
             let has_explicit_bounds = bounded_params.is_empty()
                 || (*bounded_params).get(&param.index).is_some_and(|&&pred_sp| pred_sp != span);
-            let const_param_help = (!has_explicit_bounds).then_some(());
+            let const_param_help = !has_explicit_bounds;
 
             let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter {
                 span,
diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs
index 1f724580564..83d2c2c1e28 100644
--- a/compiler/rustc_hir_analysis/src/check/entry.rs
+++ b/compiler/rustc_hir_analysis/src/check/entry.rs
@@ -216,7 +216,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
                     }
                     if sig.header.asyncness.is_async() {
                         let span = tcx.def_span(it.owner_id);
-                        tcx.dcx().emit_err(errors::StartAsync { span: span });
+                        tcx.dcx().emit_err(errors::StartAsync { span });
                         error = true;
                     }
 
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index bdf2914fc50..fb9bcc113c6 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -747,7 +747,7 @@ fn region_known_to_outlive<'tcx>(
     region_b: ty::Region<'tcx>,
 ) -> bool {
     test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {
-        infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP), region_b, region_a);
+        infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP, None), region_b, region_a);
     })
 }
 
@@ -1972,8 +1972,7 @@ fn report_bivariance<'tcx>(
     }
 
     let const_param_help =
-        matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds)
-            .then_some(());
+        matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds);
 
     let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter {
         span: param.span,
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 7034735aec0..821f79505f0 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1606,7 +1606,7 @@ pub(crate) struct UnusedGenericParameter {
     #[subdiagnostic]
     pub help: UnusedGenericParameterHelp,
     #[help(hir_analysis_const_param_help)]
-    pub const_param_help: Option<()>,
+    pub const_param_help: bool,
 }
 
 #[derive(Diagnostic)]
@@ -1643,9 +1643,9 @@ pub(crate) struct UnconstrainedGenericParameter {
     pub param_name: Symbol,
     pub param_def_kind: &'static str,
     #[note(hir_analysis_const_param_note)]
-    pub const_param_note: Option<()>,
+    pub const_param_note: bool,
     #[note(hir_analysis_const_param_note2)]
-    pub const_param_note2: Option<()>,
+    pub const_param_note2: bool,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index d865357b829..2fb1bcf2dbf 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -959,11 +959,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                      \n    where\n        T: {qself_str},\n{}",
                     where_bounds.join(",\n"),
                 ));
-            }
-            let reported = err.emit();
-            if !where_bounds.is_empty() {
+                let reported = err.emit();
                 return Err(reported);
             }
+            err.emit();
         }
 
         Ok(bound)
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index ab441ed4cde..02520c472b9 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -137,8 +137,7 @@ fn enforce_impl_params_are_constrained(
             }
         };
         if err {
-            let const_param_note =
-                matches!(param.kind, ty::GenericParamDefKind::Const { .. }).then_some(());
+            let const_param_note = matches!(param.kind, ty::GenericParamDefKind::Const { .. });
             let mut diag = tcx.dcx().create_err(UnconstrainedGenericParameter {
                 span: tcx.def_span(param.def_id),
                 param_name: param.name,
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 03a76d44cc9..3a309d2ec0b 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -505,7 +505,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     span: self.span,
                     expr_ty: self.expr_ty,
                     cast_ty: fcx.ty_to_string(self.cast_ty),
-                    teach: fcx.tcx.sess.teach(E0607).then_some(()),
+                    teach: fcx.tcx.sess.teach(E0607),
                 });
             }
             CastError::IntToFatCast(known_metadata) => {
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index f802b8cf9cc..c35f7a84c4f 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -706,7 +706,7 @@ pub(crate) struct CastThinPointerToFatPointer<'tcx> {
     pub expr_ty: Ty<'tcx>,
     pub cast_ty: String,
     #[note(hir_typeck_teach_help)]
-    pub(crate) teach: Option<()>,
+    pub(crate) teach: bool,
 }
 
 #[derive(Diagnostic)]
@@ -720,7 +720,7 @@ pub(crate) struct PassToVariadicFunction<'tcx, 'a> {
     pub sugg_span: Option<Span>,
     pub replace: String,
     #[help]
-    pub help: Option<()>,
+    pub help: bool,
     #[note(hir_typeck_teach_help)]
-    pub(crate) teach: Option<()>,
+    pub(crate) teach: bool,
 }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 7720faddba3..aca29d47587 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -406,9 +406,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ) {
                     let (sugg_span, replace, help) =
                         if let Ok(snippet) = sess.source_map().span_to_snippet(span) {
-                            (Some(span), format!("{snippet} as {cast_ty}"), None)
+                            (Some(span), format!("{snippet} as {cast_ty}"), false)
                         } else {
-                            (None, "".to_string(), Some(()))
+                            (None, "".to_string(), true)
                         };
 
                     sess.dcx().emit_err(errors::PassToVariadicFunction {
@@ -418,7 +418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         help,
                         replace,
                         sugg_span,
-                        teach: sess.teach(E0617).then_some(()),
+                        teach: sess.teach(E0617),
                     });
                 }
 
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index b3cf73bac1a..3df32dd8505 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -527,7 +527,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 {
                     if self.check_and_add_sugg_binding(LetStmt {
                         ty_hir_id_opt: if let Some(ty) = ty { Some(ty.hir_id) } else { None },
-                        binding_id: binding_id,
+                        binding_id,
                         span: pat.span,
                         init_hir_id: init.hir_id,
                     }) {
diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs
index f8910030634..b68c149d398 100644
--- a/compiler/rustc_incremental/src/errors.rs
+++ b/compiler/rustc_incremental/src/errors.rs
@@ -189,10 +189,10 @@ pub struct CreateLock<'a> {
     pub lock_err: std::io::Error,
     pub session_dir: &'a Path,
     #[note(incremental_lock_unsupported)]
-    pub is_unsupported_lock: Option<()>,
+    pub is_unsupported_lock: bool,
     #[help(incremental_cargo_help_1)]
     #[help(incremental_cargo_help_2)]
-    pub is_cargo: Option<()>,
+    pub is_cargo: bool,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 5f85e622e89..0e87bc1e692 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -486,12 +486,12 @@ fn lock_directory(
         // the lock should be exclusive
         Ok(lock) => Ok((lock, lock_file_path)),
         Err(lock_err) => {
-            let is_unsupported_lock = flock::Lock::error_unsupported(&lock_err).then_some(());
+            let is_unsupported_lock = flock::Lock::error_unsupported(&lock_err);
             Err(sess.dcx().emit_err(errors::CreateLock {
                 lock_err,
                 session_dir,
                 is_unsupported_lock,
-                is_cargo: rustc_session::utils::was_invoked_from_cargo().then_some(()),
+                is_cargo: rustc_session::utils::was_invoked_from_cargo(),
             }))
         }
     }
@@ -851,7 +851,7 @@ fn delete_old(sess: &Session, path: &Path) {
     debug!("garbage_collect_session_directories() - deleting `{}`", path.display());
 
     if let Err(err) = safe_remove_dir_all(path) {
-        sess.dcx().emit_warn(errors::SessionGcFailed { path: path, err });
+        sess.dcx().emit_warn(errors::SessionGcFailed { path, err });
     } else {
         delete_session_dir_lock_file(sess, &lock_file_path(path));
     }
diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs
index f35a8162d96..95888beb6b1 100644
--- a/compiler/rustc_infer/src/infer/context.rs
+++ b/compiler/rustc_infer/src/infer/context.rs
@@ -167,7 +167,7 @@ impl<'tcx> InferCtxtLike for InferCtxt<'tcx> {
     }
 
     fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>) {
-        self.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP), sub, sup)
+        self.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), sub, sup)
     }
 
     fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>) {
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index f2fc25a2d2e..5aa7f259685 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -390,7 +390,7 @@ pub enum SubregionOrigin<'tcx> {
 
     /// The given region parameter was instantiated with a region
     /// that must outlive some other region.
-    RelateRegionParamBound(Span),
+    RelateRegionParamBound(Span, Option<Ty<'tcx>>),
 
     /// Creating a pointer `b` to contents of another reference.
     Reborrow(Span),
@@ -859,7 +859,7 @@ impl<'tcx> InferCtxt<'tcx> {
     ) {
         self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| {
             let origin = SubregionOrigin::from_obligation_cause(cause, || {
-                RelateRegionParamBound(cause.span)
+                RelateRegionParamBound(cause.span, None)
             });
             self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
         })
@@ -1685,7 +1685,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
             Subtype(ref a) => a.span(),
             RelateObjectBound(a) => a,
             RelateParamBound(a, ..) => a,
-            RelateRegionParamBound(a) => a,
+            RelateRegionParamBound(a, _) => a,
             Reborrow(a) => a,
             ReferenceOutlivesReferent(_, a) => a,
             CompareImplItemObligation { span, .. } => span,
@@ -1726,6 +1726,10 @@ impl<'tcx> SubregionOrigin<'tcx> {
                 SubregionOrigin::AscribeUserTypeProvePredicate(span)
             }
 
+            traits::ObligationCauseCode::ObjectTypeBound(ty, _reg) => {
+                SubregionOrigin::RelateRegionParamBound(cause.span, Some(ty))
+            }
+
             _ => default(),
         }
     }
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 7a394a6d6c1..28aef9055ef 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -758,6 +758,9 @@ lint_suspicious_double_ref_clone =
 lint_suspicious_double_ref_deref =
     using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type
 
+lint_tail_expr_drop_order = these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021
+    .label = these values have significant drop implementation and will observe changes in drop order under Edition 2024
+
 lint_trailing_semi_macro = trailing semicolon in macro used in expression position
     .note1 = macro invocations at the end of a block are treated as expressions
     .note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}`
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 5f6e7fb314d..85132dd4f98 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1330,7 +1330,7 @@ impl UnreachablePub {
                 BuiltinUnreachablePub {
                     what,
                     suggestion: (vis_span, applicability),
-                    help: exportable.then_some(()),
+                    help: exportable,
                 },
             );
         }
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index 23e6b73ee37..85ee18aba8f 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -77,7 +77,7 @@ pub struct UnknownToolInScopedLint {
     pub tool_name: Symbol,
     pub lint_name: String,
     #[help]
-    pub is_nightly_build: Option<()>,
+    pub is_nightly_build: bool,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs
index 35af694213d..42b33f9882d 100644
--- a/compiler/rustc_lint/src/expect.rs
+++ b/compiler/rustc_lint/src/expect.rs
@@ -24,7 +24,7 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option<Symbol>) {
                 && tool_filter.map_or(true, |filter| expectation.lint_tool == Some(filter))
             {
                 let rationale = expectation.reason.map(|rationale| ExpectationNote { rationale });
-                let note = expectation.is_unfulfilled_lint_expectations.then_some(());
+                let note = expectation.is_unfulfilled_lint_expectations;
                 tcx.emit_node_span_lint(
                     UNFULFILLED_LINT_EXPECTATIONS,
                     *hir_id,
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 044c9413f0b..65571815019 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -8,7 +8,7 @@ use rustc_hir::{
     BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat, PatKind,
     Path, PathSegment, QPath, Ty, TyKind,
 };
-use rustc_middle::ty::{self, Ty as MiddleTy};
+use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -415,14 +415,17 @@ declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE
 
 impl LateLintPass<'_> for Diagnostics {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        let collect_args_tys_and_spans = |args: &[Expr<'_>], reserve_one_extra: bool| {
+            let mut result = Vec::with_capacity(args.len() + usize::from(reserve_one_extra));
+            result.extend(args.iter().map(|arg| (cx.typeck_results().expr_ty(arg), arg.span)));
+            result
+        };
         // Only check function calls and method calls.
-        let (span, def_id, fn_gen_args, call_tys) = match expr.kind {
+        let (span, def_id, fn_gen_args, arg_tys_and_spans) = match expr.kind {
             ExprKind::Call(callee, args) => {
                 match cx.typeck_results().node_type(callee.hir_id).kind() {
                     &ty::FnDef(def_id, fn_gen_args) => {
-                        let call_tys: Vec<_> =
-                            args.iter().map(|arg| cx.typeck_results().expr_ty(arg)).collect();
-                        (callee.span, def_id, fn_gen_args, call_tys)
+                        (callee.span, def_id, fn_gen_args, collect_args_tys_and_spans(args, false))
                     }
                     _ => return, // occurs for fns passed as args
                 }
@@ -432,38 +435,40 @@ impl LateLintPass<'_> for Diagnostics {
                 else {
                     return;
                 };
-                let mut call_tys: Vec<_> =
-                    args.iter().map(|arg| cx.typeck_results().expr_ty(arg)).collect();
-                call_tys.insert(0, cx.tcx.types.self_param); // dummy inserted for `self`
-                (span, def_id, fn_gen_args, call_tys)
+                let mut args = collect_args_tys_and_spans(args, true);
+                args.insert(0, (cx.tcx.types.self_param, _recv.span)); // dummy inserted for `self`
+                (span, def_id, fn_gen_args, args)
             }
             _ => return,
         };
 
-        // Is the callee marked with `#[rustc_lint_diagnostics]`?
-        let has_attr = ty::Instance::try_resolve(cx.tcx, cx.param_env, def_id, fn_gen_args)
-            .ok()
-            .flatten()
-            .is_some_and(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics));
-
-        // Closure: is the type `{D,Subd}iagMessage`?
-        let is_diag_message = |ty: MiddleTy<'_>| {
-            if let Some(adt_def) = ty.ty_adt_def()
-                && let Some(name) = cx.tcx.get_diagnostic_name(adt_def.did())
-                && matches!(name, sym::DiagMessage | sym::SubdiagMessage)
-            {
-                true
-            } else {
-                false
-            }
-        };
+        Self::diagnostic_outside_of_impl(cx, span, expr.hir_id, def_id, fn_gen_args);
+        Self::untranslatable_diagnostic(cx, def_id, &arg_tys_and_spans);
+    }
+}
 
-        // Does the callee have one or more `impl Into<{D,Subd}iagMessage>` parameters?
-        let mut impl_into_diagnostic_message_params = vec![];
+impl Diagnostics {
+    // Is the type `{D,Subd}iagMessage`?
+    fn is_diag_message<'cx>(cx: &LateContext<'cx>, ty: MiddleTy<'cx>) -> bool {
+        if let Some(adt_def) = ty.ty_adt_def()
+            && let Some(name) = cx.tcx.get_diagnostic_name(adt_def.did())
+            && matches!(name, sym::DiagMessage | sym::SubdiagMessage)
+        {
+            true
+        } else {
+            false
+        }
+    }
+
+    fn untranslatable_diagnostic<'cx>(
+        cx: &LateContext<'cx>,
+        def_id: DefId,
+        arg_tys_and_spans: &[(MiddleTy<'cx>, Span)],
+    ) {
         let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder();
         let predicates = cx.tcx.predicates_of(def_id).instantiate_identity(cx.tcx).predicates;
         for (i, &param_ty) in fn_sig.inputs().iter().enumerate() {
-            if let ty::Param(p) = param_ty.kind() {
+            if let ty::Param(sig_param) = param_ty.kind() {
                 // It is a type parameter. Check if it is `impl Into<{D,Subd}iagMessage>`.
                 for pred in predicates.iter() {
                     if let Some(trait_pred) = pred.as_trait_clause()
@@ -471,27 +476,53 @@ impl LateLintPass<'_> for Diagnostics {
                         && trait_ref.self_ty() == param_ty // correct predicate for the param?
                         && cx.tcx.is_diagnostic_item(sym::Into, trait_ref.def_id)
                         && let ty1 = trait_ref.args.type_at(1)
-                        && is_diag_message(ty1)
+                        && Self::is_diag_message(cx, ty1)
                     {
-                        impl_into_diagnostic_message_params.push((i, p.name));
+                        // Calls to methods with an `impl Into<{D,Subd}iagMessage>` parameter must be passed an arg
+                        // with type `{D,Subd}iagMessage` or `impl Into<{D,Subd}iagMessage>`. Otherwise, emit an
+                        // `UNTRANSLATABLE_DIAGNOSTIC` lint.
+                        let (arg_ty, arg_span) = arg_tys_and_spans[i];
+
+                        // Is the arg type `{Sub,D}iagMessage`or `impl Into<{Sub,D}iagMessage>`?
+                        let is_translatable = Self::is_diag_message(cx, arg_ty)
+                            || matches!(arg_ty.kind(), ty::Param(arg_param) if arg_param.name == sig_param.name);
+                        if !is_translatable {
+                            cx.emit_span_lint(
+                                UNTRANSLATABLE_DIAGNOSTIC,
+                                arg_span,
+                                UntranslatableDiag,
+                            );
+                        }
                     }
                 }
             }
         }
+    }
 
-        // Is the callee interesting?
-        if !has_attr && impl_into_diagnostic_message_params.is_empty() {
+    fn diagnostic_outside_of_impl<'cx>(
+        cx: &LateContext<'cx>,
+        span: Span,
+        current_id: HirId,
+        def_id: DefId,
+        fn_gen_args: GenericArgsRef<'cx>,
+    ) {
+        // Is the callee marked with `#[rustc_lint_diagnostics]`?
+        let Some(inst) =
+            ty::Instance::try_resolve(cx.tcx, cx.param_env, def_id, fn_gen_args).ok().flatten()
+        else {
             return;
-        }
+        };
+        let has_attr = cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics);
+        if !has_attr {
+            return;
+        };
 
-        // Is the parent method marked with `#[rustc_lint_diagnostics]`?
-        let mut parent_has_attr = false;
-        for (hir_id, _parent) in cx.tcx.hir().parent_iter(expr.hir_id) {
+        for (hir_id, _parent) in cx.tcx.hir().parent_iter(current_id) {
             if let Some(owner_did) = hir_id.as_owner()
                 && cx.tcx.has_attr(owner_did, sym::rustc_lint_diagnostics)
             {
-                parent_has_attr = true;
-                break;
+                // The parent method is marked with `#[rustc_lint_diagnostics]`
+                return;
             }
         }
 
@@ -500,37 +531,22 @@ impl LateLintPass<'_> for Diagnostics {
         // - inside a parent function that is itself marked with `#[rustc_lint_diagnostics]`.
         //
         // Otherwise, emit a `DIAGNOSTIC_OUTSIDE_OF_IMPL` lint.
-        if has_attr && !parent_has_attr {
-            let mut is_inside_appropriate_impl = false;
-            for (_hir_id, parent) in cx.tcx.hir().parent_iter(expr.hir_id) {
-                debug!(?parent);
-                if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent
-                    && let Impl { of_trait: Some(of_trait), .. } = impl_
-                    && let Some(def_id) = of_trait.trait_def_id()
-                    && let Some(name) = cx.tcx.get_diagnostic_name(def_id)
-                    && matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic)
-                {
-                    is_inside_appropriate_impl = true;
-                    break;
-                }
-            }
-            debug!(?is_inside_appropriate_impl);
-            if !is_inside_appropriate_impl {
-                cx.emit_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, DiagOutOfImpl);
+        let mut is_inside_appropriate_impl = false;
+        for (_hir_id, parent) in cx.tcx.hir().parent_iter(current_id) {
+            debug!(?parent);
+            if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent
+                && let Impl { of_trait: Some(of_trait), .. } = impl_
+                && let Some(def_id) = of_trait.trait_def_id()
+                && let Some(name) = cx.tcx.get_diagnostic_name(def_id)
+                && matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic)
+            {
+                is_inside_appropriate_impl = true;
+                break;
             }
         }
-
-        // Calls to methods with an `impl Into<{D,Subd}iagMessage>` parameter must be passed an arg
-        // with type `{D,Subd}iagMessage` or `impl Into<{D,Subd}iagMessage>`. Otherwise, emit an
-        // `UNTRANSLATABLE_DIAGNOSTIC` lint.
-        for (param_i, param_i_p_name) in impl_into_diagnostic_message_params {
-            // Is the arg type `{Sub,D}iagMessage`or `impl Into<{Sub,D}iagMessage>`?
-            let arg_ty = call_tys[param_i];
-            let is_translatable = is_diag_message(arg_ty)
-                || matches!(arg_ty.kind(), ty::Param(p) if p.name == param_i_p_name);
-            if !is_translatable {
-                cx.emit_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, UntranslatableDiag);
-            }
+        debug!(?is_inside_appropriate_impl);
+        if !is_inside_appropriate_impl {
+            cx.emit_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, DiagOutOfImpl);
         }
     }
 }
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 44117e5d7a5..91d4f95df80 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -936,7 +936,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                             span: tool_ident.map(|ident| ident.span),
                             tool_name: tool_name.unwrap(),
                             lint_name: pprust::path_to_string(&meta_item.path),
-                            is_nightly_build: sess.is_nightly_build().then_some(()),
+                            is_nightly_build: sess.is_nightly_build(),
                         });
                         continue;
                     }
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 4f3933d461b..1828b6ea93c 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -78,6 +78,7 @@ mod ptr_nulls;
 mod redundant_semicolon;
 mod reference_casting;
 mod shadowed_into_iter;
+mod tail_expr_drop_order;
 mod traits;
 mod types;
 mod unit_bindings;
@@ -115,6 +116,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use shadowed_into_iter::ShadowedIntoIter;
 pub use shadowed_into_iter::{ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER};
+use tail_expr_drop_order::TailExprDropOrder;
 use traits::*;
 use types::*;
 use unit_bindings::*;
@@ -238,6 +240,7 @@ late_lint_methods!(
             AsyncFnInTrait: AsyncFnInTrait,
             NonLocalDefinitions: NonLocalDefinitions::default(),
             ImplTraitOvercaptures: ImplTraitOvercaptures,
+            TailExprDropOrder: TailExprDropOrder,
         ]
     ]
 );
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 03962d796f4..c12c5427997 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -257,7 +257,7 @@ pub struct BuiltinUnreachablePub<'a> {
     #[suggestion(code = "pub(crate)")]
     pub suggestion: (Span, Applicability),
     #[help]
-    pub help: Option<()>,
+    pub help: bool,
 }
 
 #[derive(LintDiagnostic)]
@@ -572,7 +572,7 @@ pub struct Expectation {
     #[subdiagnostic]
     pub rationale: Option<ExpectationNote>,
     #[note]
-    pub note: Option<()>,
+    pub note: bool,
 }
 
 #[derive(Subdiagnostic)]
@@ -756,7 +756,7 @@ pub enum InvalidReferenceCastingDiag<'tcx> {
         #[label]
         orig_cast: Option<Span>,
         #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)]
-        ty_has_interior_mutability: Option<()>,
+        ty_has_interior_mutability: bool,
     },
     #[diag(lint_invalid_reference_casting_assign_to_ref)]
     #[note(lint_invalid_reference_casting_note_book)]
@@ -764,7 +764,7 @@ pub enum InvalidReferenceCastingDiag<'tcx> {
         #[label]
         orig_cast: Option<Span>,
         #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)]
-        ty_has_interior_mutability: Option<()>,
+        ty_has_interior_mutability: bool,
     },
     #[diag(lint_invalid_reference_casting_bigger_layout)]
     #[note(lint_layout)]
diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs
index 5e8c39c0023..45d97403d60 100644
--- a/compiler/rustc_lint/src/reference_casting.rs
+++ b/compiler/rustc_lint/src/reference_casting.rs
@@ -54,8 +54,6 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
                 && let Some(ty_has_interior_mutability) =
                     is_cast_from_ref_to_mut_ptr(cx, init, &mut peel_casts)
             {
-                let ty_has_interior_mutability = ty_has_interior_mutability.then_some(());
-
                 cx.emit_span_lint(
                     INVALID_REFERENCE_CASTING,
                     expr.span,
diff --git a/compiler/rustc_lint/src/tail_expr_drop_order.rs b/compiler/rustc_lint/src/tail_expr_drop_order.rs
new file mode 100644
index 00000000000..f9ecc8c9806
--- /dev/null
+++ b/compiler/rustc_lint/src/tail_expr_drop_order.rs
@@ -0,0 +1,306 @@
+use std::mem::swap;
+
+use rustc_ast::UnOp;
+use rustc_hir::def::Res;
+use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::{self as hir, Block, Expr, ExprKind, LetStmt, Pat, PatKind, QPath, StmtKind};
+use rustc_macros::LintDiagnostic;
+use rustc_middle::ty;
+use rustc_session::lint::FutureIncompatibilityReason;
+use rustc_session::{declare_lint, declare_lint_pass};
+use rustc_span::edition::Edition;
+use rustc_span::Span;
+
+use crate::{LateContext, LateLintPass};
+
+declare_lint! {
+    /// The `tail_expr_drop_order` lint looks for those values generated at the tail expression location, that of type
+    /// with a significant `Drop` implementation, such as locks.
+    /// In case there are also local variables of type with significant `Drop` implementation as well,
+    /// this lint warns you of a potential transposition in the drop order.
+    /// Your discretion on the new drop order introduced by Edition 2024 is required.
+    ///
+    /// ### Example
+    /// ```rust,edition2024
+    /// #![feature(shorter_tail_lifetimes)]
+    /// #![warn(tail_expr_drop_order)]
+    /// struct Droppy(i32);
+    /// impl Droppy {
+    ///     fn get(&self) -> i32 {
+    ///         self.0
+    ///     }
+    /// }
+    /// impl Drop for Droppy {
+    ///     fn drop(&mut self) {
+    ///         // This is a custom destructor and it induces side-effects that is observable
+    ///         // especially when the drop order at a tail expression changes.
+    ///         println!("loud drop {}", self.0);
+    ///     }
+    /// }
+    /// fn edition_2024() -> i32 {
+    ///     let another_droppy = Droppy(0);
+    ///     Droppy(1).get()
+    /// }
+    /// fn main() {
+    ///     edition_2024();
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// In tail expression of blocks or function bodies,
+    /// values of type with significant `Drop` implementation has an ill-specified drop order
+    /// before Edition 2024 so that they are dropped only after dropping local variables.
+    /// Edition 2024 introduces a new rule with drop orders for them,
+    /// so that they are dropped first before dropping local variables.
+    ///
+    /// A significant `Drop::drop` destructor here refers to an explicit, arbitrary
+    /// implementation of the `Drop` trait on the type, with exceptions including `Vec`,
+    /// `Box`, `Rc`, `BTreeMap` and `HashMap` that are marked by the compiler otherwise
+    /// so long that the generic types have no significant destructor recursively.
+    /// In other words, a type has a significant drop destructor when it has a `Drop` implementation
+    /// or its destructor invokes a significant destructor on a type.
+    /// Since we cannot completely reason about the change by just inspecting the existence of
+    /// a significant destructor, this lint remains only a suggestion and is set to `allow` by default.
+    ///
+    /// This lint only points out the issue with `Droppy`, which will be dropped before `another_droppy`
+    /// does in Edition 2024.
+    /// No fix will be proposed by this lint.
+    /// However, the most probable fix is to hoist `Droppy` into its own local variable binding.
+    /// ```rust
+    /// struct Droppy(i32);
+    /// impl Droppy {
+    ///     fn get(&self) -> i32 {
+    ///         self.0
+    ///     }
+    /// }
+    /// fn edition_2024() -> i32 {
+    ///     let value = Droppy(0);
+    ///     let another_droppy = Droppy(1);
+    ///     value.get()
+    /// }
+    /// ```
+    pub TAIL_EXPR_DROP_ORDER,
+    Allow,
+    "Detect and warn on significant change in drop order in tail expression location",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
+        reference: "issue #123739 <https://github.com/rust-lang/rust/issues/123739>",
+    };
+}
+
+declare_lint_pass!(TailExprDropOrder => [TAIL_EXPR_DROP_ORDER]);
+
+impl TailExprDropOrder {
+    fn check_fn_or_closure<'tcx>(
+        cx: &LateContext<'tcx>,
+        fn_kind: hir::intravisit::FnKind<'tcx>,
+        body: &'tcx hir::Body<'tcx>,
+        def_id: rustc_span::def_id::LocalDefId,
+    ) {
+        let mut locals = vec![];
+        if matches!(fn_kind, hir::intravisit::FnKind::Closure) {
+            for &capture in cx.tcx.closure_captures(def_id) {
+                if matches!(capture.info.capture_kind, ty::UpvarCapture::ByValue)
+                    && capture.place.ty().has_significant_drop(cx.tcx, cx.param_env)
+                {
+                    locals.push(capture.var_ident.span);
+                }
+            }
+        }
+        for param in body.params {
+            if cx
+                .typeck_results()
+                .node_type(param.hir_id)
+                .has_significant_drop(cx.tcx, cx.param_env)
+            {
+                locals.push(param.span);
+            }
+        }
+        if let hir::ExprKind::Block(block, _) = body.value.kind {
+            LintVisitor { cx, locals }.check_block_inner(block);
+        } else {
+            LintTailExpr { cx, locals: &locals, is_root_tail_expr: true }.visit_expr(body.value);
+        }
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for TailExprDropOrder {
+    fn check_fn(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        fn_kind: hir::intravisit::FnKind<'tcx>,
+        _: &'tcx hir::FnDecl<'tcx>,
+        body: &'tcx hir::Body<'tcx>,
+        _: Span,
+        def_id: rustc_span::def_id::LocalDefId,
+    ) {
+        if cx.tcx.sess.at_least_rust_2024() && cx.tcx.features().shorter_tail_lifetimes {
+            Self::check_fn_or_closure(cx, fn_kind, body, def_id);
+        }
+    }
+}
+
+struct LintVisitor<'tcx, 'a> {
+    cx: &'a LateContext<'tcx>,
+    // We only record locals that have significant drops
+    locals: Vec<Span>,
+}
+
+struct LocalCollector<'tcx, 'a> {
+    cx: &'a LateContext<'tcx>,
+    locals: &'a mut Vec<Span>,
+}
+
+impl<'tcx, 'a> Visitor<'tcx> for LocalCollector<'tcx, 'a> {
+    type Result = ();
+    fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) {
+        if let PatKind::Binding(_binding_mode, id, ident, pat) = pat.kind {
+            let ty = self.cx.typeck_results().node_type(id);
+            if ty.has_significant_drop(self.cx.tcx, self.cx.param_env) {
+                self.locals.push(ident.span);
+            }
+            if let Some(pat) = pat {
+                self.visit_pat(pat);
+            }
+        } else {
+            intravisit::walk_pat(self, pat);
+        }
+    }
+}
+
+impl<'tcx, 'a> Visitor<'tcx> for LintVisitor<'tcx, 'a> {
+    fn visit_block(&mut self, block: &'tcx Block<'tcx>) {
+        let mut locals = <_>::default();
+        swap(&mut locals, &mut self.locals);
+        self.check_block_inner(block);
+        swap(&mut locals, &mut self.locals);
+    }
+    fn visit_local(&mut self, local: &'tcx LetStmt<'tcx>) {
+        LocalCollector { cx: self.cx, locals: &mut self.locals }.visit_local(local);
+    }
+}
+
+impl<'tcx, 'a> LintVisitor<'tcx, 'a> {
+    fn check_block_inner(&mut self, block: &Block<'tcx>) {
+        if !block.span.at_least_rust_2024() {
+            // We only lint for Edition 2024 onwards
+            return;
+        }
+        let Some(tail_expr) = block.expr else { return };
+        for stmt in block.stmts {
+            match stmt.kind {
+                StmtKind::Let(let_stmt) => self.visit_local(let_stmt),
+                StmtKind::Item(_) => {}
+                StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e),
+            }
+        }
+        if self.locals.is_empty() {
+            return;
+        }
+        LintTailExpr { cx: self.cx, locals: &self.locals, is_root_tail_expr: true }
+            .visit_expr(tail_expr);
+    }
+}
+
+struct LintTailExpr<'tcx, 'a> {
+    cx: &'a LateContext<'tcx>,
+    is_root_tail_expr: bool,
+    locals: &'a [Span],
+}
+
+impl<'tcx, 'a> LintTailExpr<'tcx, 'a> {
+    fn expr_eventually_point_into_local(mut expr: &Expr<'tcx>) -> bool {
+        loop {
+            match expr.kind {
+                ExprKind::Index(access, _, _) | ExprKind::Field(access, _) => expr = access,
+                ExprKind::AddrOf(_, _, referee) | ExprKind::Unary(UnOp::Deref, referee) => {
+                    expr = referee
+                }
+                ExprKind::Path(_)
+                    if let ExprKind::Path(QPath::Resolved(_, path)) = expr.kind
+                        && let [local, ..] = path.segments
+                        && let Res::Local(_) = local.res =>
+                {
+                    return true;
+                }
+                _ => return false,
+            }
+        }
+    }
+
+    fn expr_generates_nonlocal_droppy_value(&self, expr: &Expr<'tcx>) -> bool {
+        if Self::expr_eventually_point_into_local(expr) {
+            return false;
+        }
+        self.cx.typeck_results().expr_ty(expr).has_significant_drop(self.cx.tcx, self.cx.param_env)
+    }
+}
+
+impl<'tcx, 'a> Visitor<'tcx> for LintTailExpr<'tcx, 'a> {
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
+        if self.is_root_tail_expr {
+            self.is_root_tail_expr = false;
+        } else if self.expr_generates_nonlocal_droppy_value(expr) {
+            self.cx.tcx.emit_node_span_lint(
+                TAIL_EXPR_DROP_ORDER,
+                expr.hir_id,
+                expr.span,
+                TailExprDropOrderLint { spans: self.locals.to_vec() },
+            );
+            return;
+        }
+        match expr.kind {
+            ExprKind::Match(scrutinee, _, _) => self.visit_expr(scrutinee),
+
+            ExprKind::ConstBlock(_)
+            | ExprKind::Array(_)
+            | ExprKind::Break(_, _)
+            | ExprKind::Continue(_)
+            | ExprKind::Ret(_)
+            | ExprKind::Become(_)
+            | ExprKind::Yield(_, _)
+            | ExprKind::InlineAsm(_)
+            | ExprKind::If(_, _, _)
+            | ExprKind::Loop(_, _, _, _)
+            | ExprKind::Closure(_)
+            | ExprKind::DropTemps(_)
+            | ExprKind::OffsetOf(_, _)
+            | ExprKind::Assign(_, _, _)
+            | ExprKind::AssignOp(_, _, _)
+            | ExprKind::Lit(_)
+            | ExprKind::Err(_) => {}
+
+            ExprKind::MethodCall(_, _, _, _)
+            | ExprKind::Call(_, _)
+            | ExprKind::Type(_, _)
+            | ExprKind::Tup(_)
+            | ExprKind::Binary(_, _, _)
+            | ExprKind::Unary(_, _)
+            | ExprKind::Path(_)
+            | ExprKind::Let(_)
+            | ExprKind::Cast(_, _)
+            | ExprKind::Field(_, _)
+            | ExprKind::Index(_, _, _)
+            | ExprKind::AddrOf(_, _, _)
+            | ExprKind::Struct(_, _, _)
+            | ExprKind::Repeat(_, _) => intravisit::walk_expr(self, expr),
+
+            ExprKind::Block(_, _) => {
+                // We do not lint further because the drop order stays the same inside the block
+            }
+        }
+    }
+    fn visit_block(&mut self, block: &'tcx Block<'tcx>) {
+        LintVisitor { cx: self.cx, locals: <_>::default() }.check_block_inner(block);
+    }
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_tail_expr_drop_order)]
+struct TailExprDropOrderLint {
+    #[label]
+    pub spans: Vec<Span>,
+}
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 56d77c9d1d0..a65d30eb817 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -251,7 +251,7 @@ declare_lint! {
     Deny,
     "conflicts between `#[repr(..)]` hints that were previously accepted and used in practice",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
         reference: "issue #68585 <https://github.com/rust-lang/rust/issues/68585>",
     };
 }
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 283c4fbbb7c..9884ed15b8a 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -1607,8 +1607,13 @@ extern "C" void LLVMRustComputeLTOCacheKey(RustStringRef KeyOut,
   const auto &ExportList = Data->ExportLists.lookup(ModId);
   const auto &ResolvedODR = Data->ResolvedODR.lookup(ModId);
   const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(ModId);
+#if LLVM_VERSION_GE(20, 0)
+  DenseSet<GlobalValue::GUID> CfiFunctionDefs;
+  DenseSet<GlobalValue::GUID> CfiFunctionDecls;
+#else
   std::set<GlobalValue::GUID> CfiFunctionDefs;
   std::set<GlobalValue::GUID> CfiFunctionDecls;
+#endif
 
   // Based on the 'InProcessThinBackend' constructor in LLVM
   for (auto &Name : Data->Index.cfiFunctionDefs())
@@ -1618,9 +1623,15 @@ extern "C" void LLVMRustComputeLTOCacheKey(RustStringRef KeyOut,
     CfiFunctionDecls.insert(
         GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
 
+#if LLVM_VERSION_GE(20, 0)
+  Key = llvm::computeLTOCacheKey(conf, Data->Index, ModId, ImportList,
+                                 ExportList, ResolvedODR, DefinedGlobals,
+                                 CfiFunctionDefs, CfiFunctionDecls);
+#else
   llvm::computeLTOCacheKey(Key, conf, Data->Index, ModId, ImportList,
                            ExportList, ResolvedODR, DefinedGlobals,
                            CfiFunctionDefs, CfiFunctionDecls);
+#endif
 
   LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size());
 }
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 25ae7b2bc31..90228db378a 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -1002,11 +1002,7 @@ impl CrateError {
                 if !locator.crate_rejections.via_filename.is_empty() {
                     let mismatches = locator.crate_rejections.via_filename.iter();
                     for CrateMismatch { path, .. } in mismatches {
-                        dcx.emit_err(errors::CrateLocationUnknownType {
-                            span,
-                            path: path,
-                            crate_name,
-                        });
+                        dcx.emit_err(errors::CrateLocationUnknownType { span, path, crate_name });
                         dcx.emit_err(errors::LibFilenameForm {
                             span,
                             dll_prefix: &locator.dll_prefix,
@@ -1035,7 +1031,7 @@ impl CrateError {
                     }
                     dcx.emit_err(errors::NewerCrateVersion {
                         span,
-                        crate_name: crate_name,
+                        crate_name,
                         add_info,
                         found_crates,
                     });
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index 61348cdce23..5c2aa0005d4 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -160,7 +160,7 @@ pub struct TypeLengthLimit {
     pub span: Span,
     pub shrunk: String,
     #[note(middle_written_to_path)]
-    pub was_written: Option<()>,
+    pub was_written: bool,
     pub path: PathBuf,
     pub type_length: usize,
 }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 46c4d586f6a..5b2aac781eb 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1368,7 +1368,7 @@ rustc_index::newtype_index! {
     /// [CFG]: https://rustc-dev-guide.rust-lang.org/appendix/background.html#cfg
     /// [data-flow analyses]:
     ///     https://rustc-dev-guide.rust-lang.org/appendix/background.html#what-is-a-dataflow-analysis
-    /// [`CriticalCallEdges`]: ../../rustc_const_eval/transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges
+    /// [`CriticalCallEdges`]: ../../rustc_mir_transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges
     /// [guide-mir]: https://rustc-dev-guide.rust-lang.org/mir/
     #[derive(HashStable)]
     #[encodable]
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 51b4154ddab..748ca047754 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -395,7 +395,7 @@ pub enum StatementKind<'tcx> {
     /// `PlaceMention(PLACE)`.
     ///
     /// When executed at runtime, this computes the given place, but then discards
-    /// it without doing a load. It is UB if the place is not pointing to live memory.
+    /// it without doing a load. `let _ = *ptr;` is fine even if the pointer is dangling.
     PlaceMention(Box<Place<'tcx>>),
 
     /// Encodes a user's type ascription. These need to be preserved
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 6f19739de45..ecb3943e788 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -581,9 +581,9 @@ impl<'tcx> Instance<'tcx> {
                     let mut path = PathBuf::new();
                     let was_written = if let Some(path2) = written_to_path {
                         path = path2;
-                        Some(())
+                        true
                     } else {
-                        None
+                        false
                     };
                     tcx.dcx().emit_fatal(error::TypeLengthLimit {
                         // We don't use `def_span(def_id)` so that diagnostics point
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 319fb7ef03b..f1ff90831b0 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -3119,7 +3119,10 @@ define_print! {
 
     ty::ExistentialProjection<'tcx> {
         let name = cx.tcx().associated_item(self.def_id).name;
-        p!(write("{} = ", name), print(self.term))
+        // The args don't contain the self ty (as it has been erased) but the corresp.
+        // generics do as the trait always has a self ty param. We need to offset.
+        let args = &self.args[cx.tcx().generics_of(self.def_id).parent_count - 1..];
+        p!(path_generic_args(|cx| write!(cx, "{name}"), args), " = ", print(self.term))
     }
 
     ty::ProjectionPredicate<'tcx> {
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index 7baf0256dd8..7a10e627ccd 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -327,14 +327,17 @@ mir_build_union_pattern = cannot use unions in constant patterns
 
 mir_build_unreachable_making_this_unreachable = collectively making this unreachable
 
+mir_build_unreachable_making_this_unreachable_n_more = ...and {$covered_by_many_n_more_count} other patterns collectively make this unreachable
+
 mir_build_unreachable_matches_same_values = matches some of the same values
 
 mir_build_unreachable_pattern = unreachable pattern
-    .label = unreachable pattern
-    .unreachable_matches_no_values = this pattern matches no values because `{$ty}` is uninhabited
+    .label = no value can reach this
+    .unreachable_matches_no_values = matches no values because `{$matches_no_values_ty}` is uninhabited
+    .unreachable_uninhabited_note = to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
     .unreachable_covered_by_catchall = matches any value
-    .unreachable_covered_by_one = matches all the values already
-    .unreachable_covered_by_many = these patterns collectively make the last one unreachable
+    .unreachable_covered_by_one = matches all the relevant values
+    .unreachable_covered_by_many = multiple earlier patterns match some of the same values
 
 mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its body is safe by default
 mir_build_unsafe_not_inherited = items do not inherit unsafety from separate enclosing items
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 8546a2539d7..693037d03e0 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -748,7 +748,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.cfg.terminate(block, source_info, TerminatorKind::UnwindResume);
     }
 
-    /// Sets up the drops for explict tail calls.
+    /// Sets up the drops for explicit tail calls.
     ///
     /// Unlike other kinds of early exits, tail calls do not go through the drop tree.
     /// Instead, all scheduled drops are immediately added to the CFG.
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index e4e5844d2ef..b6cf7a40ecd 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -793,7 +793,7 @@ impl UnsafeOpKind {
                         missing.iter().map(|feature| Cow::from(feature.to_string())).collect(),
                     ),
                     missing_target_features_count: missing.len(),
-                    note: if build_enabled.is_empty() { None } else { Some(()) },
+                    note: !build_enabled.is_empty(),
                     build_target_features: DiagArgValue::StrListSepByAnd(
                         build_enabled
                             .iter()
@@ -958,7 +958,7 @@ impl UnsafeOpKind {
                         missing.iter().map(|feature| Cow::from(feature.to_string())).collect(),
                     ),
                     missing_target_features_count: missing.len(),
-                    note: if build_enabled.is_empty() { None } else { Some(()) },
+                    note: !build_enabled.is_empty(),
                     build_target_features: DiagArgValue::StrListSepByAnd(
                         build_enabled
                             .iter()
@@ -977,7 +977,7 @@ impl UnsafeOpKind {
                         missing.iter().map(|feature| Cow::from(feature.to_string())).collect(),
                     ),
                     missing_target_features_count: missing.len(),
-                    note: if build_enabled.is_empty() { None } else { Some(()) },
+                    note: !build_enabled.is_empty(),
                     build_target_features: DiagArgValue::StrListSepByAnd(
                         build_enabled
                             .iter()
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 34577f102d1..843ac2eb240 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -161,7 +161,7 @@ pub(crate) struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
     pub(crate) missing_target_features: DiagArgValue,
     pub(crate) missing_target_features_count: usize,
     #[note]
-    pub(crate) note: Option<()>,
+    pub(crate) note: bool,
     pub(crate) build_target_features: DiagArgValue,
     pub(crate) build_target_features_count: usize,
     #[subdiagnostic]
@@ -413,7 +413,7 @@ pub(crate) struct CallToFunctionWithRequiresUnsafe {
     pub(crate) missing_target_features: DiagArgValue,
     pub(crate) missing_target_features_count: usize,
     #[note]
-    pub(crate) note: Option<()>,
+    pub(crate) note: bool,
     pub(crate) build_target_features: DiagArgValue,
     pub(crate) build_target_features_count: usize,
     #[subdiagnostic]
@@ -431,7 +431,7 @@ pub(crate) struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     pub(crate) missing_target_features: DiagArgValue,
     pub(crate) missing_target_features_count: usize,
     #[note]
-    pub(crate) note: Option<()>,
+    pub(crate) note: bool,
     pub(crate) build_target_features: DiagArgValue,
     pub(crate) build_target_features_count: usize,
     #[subdiagnostic]
@@ -586,20 +586,18 @@ pub(crate) struct NonConstPath {
 pub(crate) struct UnreachablePattern<'tcx> {
     #[label]
     pub(crate) span: Option<Span>,
-    #[subdiagnostic]
-    pub(crate) matches_no_values: Option<UnreachableMatchesNoValues<'tcx>>,
+    #[label(mir_build_unreachable_matches_no_values)]
+    pub(crate) matches_no_values: Option<Span>,
+    pub(crate) matches_no_values_ty: Ty<'tcx>,
+    #[note(mir_build_unreachable_uninhabited_note)]
+    pub(crate) uninhabited_note: Option<()>,
     #[label(mir_build_unreachable_covered_by_catchall)]
     pub(crate) covered_by_catchall: Option<Span>,
     #[label(mir_build_unreachable_covered_by_one)]
     pub(crate) covered_by_one: Option<Span>,
     #[note(mir_build_unreachable_covered_by_many)]
     pub(crate) covered_by_many: Option<MultiSpan>,
-}
-
-#[derive(Subdiagnostic)]
-#[note(mir_build_unreachable_matches_no_values)]
-pub(crate) struct UnreachableMatchesNoValues<'tcx> {
-    pub(crate) ty: Ty<'tcx>,
+    pub(crate) covered_by_many_n_more_count: usize,
 }
 
 #[derive(Diagnostic)]
@@ -623,7 +621,7 @@ pub(crate) struct LowerRangeBoundMustBeLessThanOrEqualToUpper {
     #[label]
     pub(crate) span: Span,
     #[note(mir_build_teach_note)]
-    pub(crate) teach: Option<()>,
+    pub(crate) teach: bool,
 }
 
 #[derive(Diagnostic)]
@@ -865,7 +863,7 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
     #[subdiagnostic]
     pub(crate) adt_defined_here: Option<AdtDefinedHere<'tcx>>,
     #[note(mir_build_privately_uninhabited)]
-    pub(crate) witness_1_is_privately_uninhabited: Option<()>,
+    pub(crate) witness_1_is_privately_uninhabited: bool,
     #[note(mir_build_pattern_ty)]
     pub(crate) _p: (),
     pub(crate) pattern_ty: Ty<'tcx>,
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 2cbaed2cc62..89f98a40201 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -218,12 +218,7 @@ impl<'tcx> Cx<'tcx> {
                     let lhs =
                         self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind });
                     let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset };
-                    self.thir.exprs.push(Expr {
-                        temp_lifetime,
-                        ty: discr_ty,
-                        span: span,
-                        kind: bin,
-                    })
+                    self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind: bin })
                 }
                 None => offset,
             };
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index bc1acd51c69..4c066a68ef9 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -718,7 +718,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
             uncovered: Uncovered::new(pat.span, &cx, witnesses),
             inform,
             interpreted_as_const,
-            witness_1_is_privately_uninhabited: witness_1_is_privately_uninhabited.then_some(()),
+            witness_1_is_privately_uninhabited,
             _p: (),
             pattern_ty,
             let_suggestion,
@@ -917,22 +917,28 @@ fn report_unreachable_pattern<'p, 'tcx>(
     pat: &DeconstructedPat<'p, 'tcx>,
     explanation: &RedundancyExplanation<'p, 'tcx>,
 ) {
+    static CAP_COVERED_BY_MANY: usize = 4;
     let pat_span = pat.data().span;
     let mut lint = UnreachablePattern {
         span: Some(pat_span),
         matches_no_values: None,
+        matches_no_values_ty: **pat.ty(),
+        uninhabited_note: None,
         covered_by_catchall: None,
         covered_by_one: None,
         covered_by_many: None,
+        covered_by_many_n_more_count: 0,
     };
     match explanation.covered_by.as_slice() {
         [] => {
             // Empty pattern; we report the uninhabited type that caused the emptiness.
             lint.span = None; // Don't label the pattern itself
+            lint.uninhabited_note = Some(()); // Give a link about empty types
+            lint.matches_no_values = Some(pat_span);
             pat.walk(&mut |subpat| {
                 let ty = **subpat.ty();
                 if cx.is_uninhabited(ty) {
-                    lint.matches_no_values = Some(UnreachableMatchesNoValues { ty });
+                    lint.matches_no_values_ty = ty;
                     false // No need to dig further.
                 } else if matches!(subpat.ctor(), Constructor::Ref | Constructor::UnionField) {
                     false // Don't explore further since they are not by-value.
@@ -948,15 +954,27 @@ fn report_unreachable_pattern<'p, 'tcx>(
             lint.covered_by_one = Some(covering_pat.data().span);
         }
         covering_pats => {
+            let mut iter = covering_pats.iter();
             let mut multispan = MultiSpan::from_span(pat_span);
-            for p in covering_pats {
+            for p in iter.by_ref().take(CAP_COVERED_BY_MANY) {
                 multispan.push_span_label(
                     p.data().span,
                     fluent::mir_build_unreachable_matches_same_values,
                 );
             }
-            multispan
-                .push_span_label(pat_span, fluent::mir_build_unreachable_making_this_unreachable);
+            let remain = iter.count();
+            if remain == 0 {
+                multispan.push_span_label(
+                    pat_span,
+                    fluent::mir_build_unreachable_making_this_unreachable,
+                );
+            } else {
+                lint.covered_by_many_n_more_count = remain;
+                multispan.push_span_label(
+                    pat_span,
+                    fluent::mir_build_unreachable_making_this_unreachable_n_more,
+                );
+            }
             lint.covered_by_many = Some(multispan);
         }
     }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 6f8d17b772a..53393046610 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -129,7 +129,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 let err = TypeNotPartialEq { span: self.span, non_peq_ty: ty };
                 let e = self.tcx().dcx().emit_err(err);
                 let kind = PatKind::Error(e);
-                return Box::new(Pat { span: self.span, ty: ty, kind });
+                return Box::new(Pat { span: self.span, ty, kind });
             }
         }
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 615070034b9..d78e1f5da09 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -256,7 +256,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                     RangeEnd::Included => {
                         self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
                             span,
-                            teach: self.tcx.sess.teach(E0030).then_some(()),
+                            teach: self.tcx.sess.teach(E0030),
                         })
                     }
                     RangeEnd::Excluded => {
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 82528109be9..703339bf5bc 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -931,7 +931,7 @@ fn compute_storage_conflicts<'mir, 'tcx>(
     // Compute the storage conflicts for all eligible locals.
     let mut visitor = StorageConflictVisitor {
         body,
-        saved_locals: saved_locals,
+        saved_locals,
         local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len()),
         eligible_storage_live: BitSet::new_empty(body.local_decls.len()),
     };
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 0fc4d6b9f4e..f207216d6f4 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -338,7 +338,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
             tcx,
             local_decls: &body.local_decls,
             ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine),
-            param_env: param_env,
+            param_env,
         }
     }
 
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 9f449868f03..77f6a1e17ce 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -580,9 +580,9 @@ fn check_recursion_limit<'tcx>(
         let mut path = PathBuf::new();
         let was_written = if let Some(written_to_path) = written_to_path {
             path = written_to_path;
-            Some(())
+            true
         } else {
-            None
+            false
         };
         tcx.dcx().emit_fatal(RecursionLimit {
             span,
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index 88286cb73a6..c97e07ee3ba 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -16,7 +16,7 @@ pub struct RecursionLimit {
     pub def_span: Span,
     pub def_path_str: String,
     #[note(monomorphize_written_to_path)]
-    pub was_written: Option<()>,
+    pub was_written: bool,
     pub path: PathBuf,
 }
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 0d4512be480..abaff7d9c19 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -913,7 +913,7 @@ pub(crate) struct InvalidLiteralSuffixOnTupleIndex {
     #[help(parse_tuple_exception_line_1)]
     #[help(parse_tuple_exception_line_2)]
     #[help(parse_tuple_exception_line_3)]
-    pub exception: Option<()>,
+    pub exception: bool,
 }
 
 #[derive(Diagnostic)]
@@ -1299,7 +1299,7 @@ pub(crate) struct ComparisonOperatorsCannotBeChained {
     pub suggest_turbofish: Option<Span>,
     #[help(parse_sugg_turbofish_syntax)]
     #[help(parse_sugg_parentheses_for_function_args)]
-    pub help_turbofish: Option<()>,
+    pub help_turbofish: bool,
     #[subdiagnostic]
     pub chaining_sugg: Option<ComparisonOperatorsCannotBeChainedSugg>,
 }
@@ -1578,7 +1578,7 @@ pub(crate) struct PathSingleColon {
     pub suggestion: Span,
 
     #[note(parse_type_ascription_removed)]
-    pub type_ascription: Option<()>,
+    pub type_ascription: bool,
 }
 
 #[derive(Diagnostic)]
@@ -1589,7 +1589,7 @@ pub(crate) struct ColonAsSemi {
     pub span: Span,
 
     #[note(parse_type_ascription_removed)]
-    pub type_ascription: Option<()>,
+    pub type_ascription: bool,
 }
 
 #[derive(Diagnostic)]
@@ -2462,7 +2462,7 @@ pub(crate) struct TrailingVertNotAllowed {
     pub start: Option<Span>,
     pub token: Token,
     #[note(parse_note_pattern_alternatives_use_single_vert)]
-    pub note_double_vert: Option<()>,
+    pub note_double_vert: bool,
 }
 
 #[derive(Diagnostic)]
@@ -2894,7 +2894,7 @@ pub(crate) struct BadItemKind {
     pub descr: &'static str,
     pub ctx: &'static str,
     #[help]
-    pub help: Option<()>,
+    pub help: bool,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index ef1387c50fa..fcdc10c0837 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -1403,7 +1403,7 @@ impl<'a> Parser<'a> {
                 let mut err = ComparisonOperatorsCannotBeChained {
                     span: vec![op.span, self.prev_token.span],
                     suggest_turbofish: None,
-                    help_turbofish: None,
+                    help_turbofish: false,
                     chaining_sugg: None,
                 };
 
@@ -1436,7 +1436,7 @@ impl<'a> Parser<'a> {
                         {
                             err.suggest_turbofish = Some(op.span.shrink_to_lo());
                         } else {
-                            err.help_turbofish = Some(());
+                            err.help_turbofish = true;
                         }
 
                         let snapshot = self.create_snapshot_for_diagnostic();
@@ -1468,7 +1468,7 @@ impl<'a> Parser<'a> {
                         {
                             err.suggest_turbofish = Some(op.span.shrink_to_lo());
                         } else {
-                            err.help_turbofish = Some(());
+                            err.help_turbofish = true;
                         }
                         // Consume the fn call arguments.
                         match self.consume_fn_args() {
@@ -1487,7 +1487,7 @@ impl<'a> Parser<'a> {
                         {
                             // All we know is that this is `foo < bar >` and *nothing* else. Try to
                             // be helpful, but don't attempt to recover.
-                            err.help_turbofish = Some(());
+                            err.help_turbofish = true;
                         }
 
                         // If it looks like a genuine attempt to chain operators (as opposed to a
@@ -1895,7 +1895,7 @@ impl<'a> Parser<'a> {
         {
             self.dcx().emit_err(ColonAsSemi {
                 span: self.token.span,
-                type_ascription: self.psess.unstable_features.is_nightly_build().then_some(()),
+                type_ascription: self.psess.unstable_features.is_nightly_build(),
             });
             self.bump();
             return true;
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 422206ebbce..84684e808d9 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2162,13 +2162,13 @@ impl<'a> Parser<'a> {
             self.dcx().emit_warn(errors::InvalidLiteralSuffixOnTupleIndex {
                 span,
                 suffix,
-                exception: Some(()),
+                exception: true,
             });
         } else {
             self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex {
                 span,
                 suffix,
-                exception: None,
+                exception: false,
             });
         }
     }
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 47820e93c23..14da6c331f1 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1248,8 +1248,8 @@ impl<'a> Parser<'a> {
         let span = self.psess.source_map().guess_head_span(span);
         let descr = kind.descr();
         let help = match kind {
-            ItemKind::DelegationMac(deleg) if deleg.suffixes.is_none() => None,
-            _ => Some(()),
+            ItemKind::DelegationMac(deleg) if deleg.suffixes.is_none() => false,
+            _ => true,
         };
         self.dcx().emit_err(errors::BadItemKind { span, descr, ctx, help });
         None
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index eb9a957032f..cc68ae237ba 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -333,7 +333,7 @@ impl<'a> Parser<'a> {
                     span: self.token.span,
                     start: lo,
                     token: self.token.clone(),
-                    note_double_vert: matches!(self.token.kind, token::OrOr).then_some(()),
+                    note_double_vert: matches!(self.token.kind, token::OrOr),
                 });
                 self.bump();
                 true
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index b58f398efed..d8bf10e6021 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -261,11 +261,7 @@ impl<'a> Parser<'a> {
                         self.dcx().emit_err(PathSingleColon {
                             span: self.prev_token.span,
                             suggestion: self.prev_token.span.shrink_to_hi(),
-                            type_ascription: self
-                                .psess
-                                .unstable_features
-                                .is_nightly_build()
-                                .then_some(()),
+                            type_ascription: self.psess.unstable_features.is_nightly_build(),
                         });
                     }
                     continue;
@@ -334,11 +330,7 @@ impl<'a> Parser<'a> {
                             err = self.dcx().create_err(PathSingleColon {
                                 span: self.token.span,
                                 suggestion: self.prev_token.span.shrink_to_hi(),
-                                type_ascription: self
-                                    .psess
-                                    .unstable_features
-                                    .is_nightly_build()
-                                    .then_some(()),
+                                type_ascription: self.psess.unstable_features.is_nightly_build(),
                             });
                         }
                         // Attempt to find places where a missing `>` might belong.
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index e3c2999142f..c93fb5c23b1 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -2619,8 +2619,7 @@ fn check_duplicates(
                             warning: matches!(
                                 duplicates,
                                 FutureWarnFollowing | FutureWarnPreceding
-                            )
-                            .then_some(()),
+                            ),
                         },
                     );
                 }
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 659281c5e71..624ebb2f9f2 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -49,7 +49,7 @@ fn report_duplicate_item(
         orig_span,
         crate_name: tcx.crate_name(item_def_id.krate),
         orig_crate_name: tcx.crate_name(original_def_id.krate),
-        different_crates: (item_def_id.krate != original_def_id.krate).then_some(()),
+        different_crates: (item_def_id.krate != original_def_id.krate),
         name,
     });
 }
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index ee7d097e5d3..1190e60f41f 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -752,7 +752,7 @@ pub struct UnusedDuplicate {
     #[note]
     pub other: Span,
     #[warning]
-    pub warning: Option<()>,
+    pub warning: bool,
 }
 
 #[derive(Diagnostic)]
@@ -911,7 +911,7 @@ pub struct DuplicateDiagnosticItemInCrate {
     #[note(passes_diagnostic_item_first_defined)]
     pub orig_span: Option<Span>,
     #[note]
-    pub different_crates: Option<()>,
+    pub different_crates: bool,
     pub crate_name: Symbol,
     pub orig_crate_name: Symbol,
     pub name: Symbol,
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 18f97d6fb8f..f4a4c602f69 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -214,7 +214,7 @@ pub fn query_system<'tcx>(
             local_providers,
             extern_providers,
             encode_query_results: encode_all_query_results,
-            try_mark_green: try_mark_green,
+            try_mark_green,
         },
         jobs: AtomicU64::new(1),
     }
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index ff1c3431b7c..ab4a8be0fbf 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -547,7 +547,7 @@ impl<D: Deps> EncoderState<D> {
     /// Encodes a node that was promoted from the previous graph. It reads the information directly from
     /// the previous dep graph for performance reasons.
     ///
-    /// This differs from `encode_node` where you have to explictly provide the relevant `NodeInfo`.
+    /// This differs from `encode_node` where you have to explicitly provide the relevant `NodeInfo`.
     ///
     /// It expects all edges to already have a new dep node index assigned.
     #[inline]
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index d57dabdd78d..fee42ba87c9 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -896,7 +896,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
         self.r.potentially_unused_imports.push(import);
         let imported_binding = self.r.import(binding, import);
         if parent == self.r.graph_root {
-            if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
+            let ident = ident.normalize_to_macros_2_0();
+            if let Some(entry) = self.r.extern_prelude.get(&ident) {
                 if expansion != LocalExpnId::ROOT && orig_name.is_some() && !entry.is_import() {
                     self.r.dcx().emit_err(
                         errors::MacroExpandedExternCrateCannotShadowExternArguments {
@@ -913,14 +914,21 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             let entry = self
                 .r
                 .extern_prelude
-                .entry(ident.normalize_to_macros_2_0())
+                .entry(ident)
                 .or_insert(ExternPreludeEntry { binding: None, introduced_by_item: true });
-            // Binding from `extern crate` item in source code can replace
-            // a binding from `--extern` on command line here.
-            entry.binding = Some(imported_binding);
             if orig_name.is_some() {
                 entry.introduced_by_item = true;
             }
+            // Binding from `extern crate` item in source code can replace
+            // a binding from `--extern` on command line here.
+            if !entry.is_import() {
+                entry.binding = Some(imported_binding)
+            } else if ident.name != kw::Underscore {
+                self.r.dcx().span_delayed_bug(
+                    item.span,
+                    format!("it had been define the external module '{ident}' multiple times"),
+                );
+            }
         }
         self.r.define(parent, ident, TypeNS, imported_binding);
     }
@@ -1150,7 +1158,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
     fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool {
         for attr in attrs {
             if attr.has_name(sym::macro_escape) {
-                let inner_attribute = matches!(attr.style, ast::AttrStyle::Inner).then_some(());
+                let inner_attribute = matches!(attr.style, ast::AttrStyle::Inner);
                 self.r
                     .dcx()
                     .emit_warn(errors::MacroExternDeprecated { span: attr.span, inner_attribute });
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 942026ef012..bcbdf627b56 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1456,7 +1456,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             let label_span = ident.span.shrink_to_hi();
             let mut spans = MultiSpan::from_span(label_span);
             spans.push_span_label(label_span, "put a macro name here");
-            err.subdiagnostic(MaybeMissingMacroRulesName { spans: spans });
+            err.subdiagnostic(MaybeMissingMacroRulesName { spans });
             return;
         }
 
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index ad1841e3e89..662b772413b 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -850,7 +850,7 @@ pub(crate) struct MacroExternDeprecated {
     #[primary_span]
     pub(crate) span: Span,
     #[help]
-    pub inner_attribute: Option<()>,
+    pub inner_attribute: bool,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 4a70fc0f308..40fdb01a72c 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2677,14 +2677,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             // We also can't shadow bindings from associated parent items.
             for ns in [ValueNS, TypeNS] {
                 for parent_rib in self.ribs[ns].iter().rev() {
-                    seen_bindings
-                        .extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
-
                     // Break at mod level, to account for nested items which are
                     // allowed to shadow generic param names.
                     if matches!(parent_rib.kind, RibKind::Module(..)) {
                         break;
                     }
+
+                    seen_bindings
+                        .extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
                 }
             }
 
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
index e628c17aca3..2f43199796c 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
@@ -146,7 +146,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TransformTy<'tcx> {
                         !is_zst
                     });
                     if let Some(field) = field {
-                        let ty0 = self.tcx.type_of(field.did).instantiate(self.tcx, args);
+                        let ty0 = self.tcx.erase_regions(field.ty(self.tcx, args));
                         // Generalize any repr(transparent) user-defined type that is either a
                         // pointer or reference, and either references itself or any other type that
                         // contains or references itself, to avoid a reference cycle.
@@ -316,7 +316,7 @@ pub fn transform_instance<'tcx>(
             .drop_trait()
             .unwrap_or_else(|| bug!("typeid_for_instance: couldn't get drop_trait lang item"));
         let predicate = ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef {
-            def_id: def_id,
+            def_id,
             args: List::empty(),
         });
         let predicates = tcx.mk_poly_existential_predicates(&[ty::Binder::dummy(predicate)]);
diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs
index 0519722e4be..677b4c7a9c0 100644
--- a/compiler/rustc_smir/src/rustc_smir/alloc.rs
+++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs
@@ -132,7 +132,7 @@ pub(super) fn allocation_filter<'tcx>(
         ));
     }
     Allocation {
-        bytes: bytes,
+        bytes,
         provenance: ProvenanceMap { ptrs },
         align: alloc.align.bytes(),
         mutability: alloc.mutability.stable(tables),
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 434df35a515..5e1b1b44bc2 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1415,6 +1415,14 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
 
     // Overwrite the dummy data with our decoded SyntaxContextData
     HygieneData::with(|hygiene_data| {
+        if let Some(old) = hygiene_data.syntax_context_data.get(raw_id as usize)
+            && old.outer_expn == ctxt_data.outer_expn
+            && old.outer_transparency == ctxt_data.outer_transparency
+            && old.parent == ctxt_data.parent
+        {
+            ctxt_data = old.clone();
+        }
+
         let dummy = std::mem::replace(
             &mut hygiene_data.syntax_context_data[ctxt.as_u32() as usize],
             ctxt_data,
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 25e4d70945b..c1ddfcb2f90 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -642,7 +642,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
     pub fn make_indirect(&mut self) {
         match self.mode {
             PassMode::Direct(_) | PassMode::Pair(_, _) => {
-                self.make_indirect_force();
+                self.mode = Self::indirect_pass_mode(&self.layout);
             }
             PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => {
                 // already indirect
@@ -652,9 +652,19 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
         }
     }
 
-    /// Same as make_indirect, but doesn't check the current `PassMode`.
-    pub fn make_indirect_force(&mut self) {
-        self.mode = Self::indirect_pass_mode(&self.layout);
+    /// Same as `make_indirect`, but for arguments that are ignored. Only needed for ABIs that pass
+    /// ZSTs indirectly.
+    pub fn make_indirect_from_ignore(&mut self) {
+        match self.mode {
+            PassMode::Ignore => {
+                self.mode = Self::indirect_pass_mode(&self.layout);
+            }
+            PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => {
+                // already indirect
+                return;
+            }
+            _ => panic!("Tried to make {:?} indirect (expected `PassMode::Ignore`)", self.mode),
+        }
     }
 
     /// Pass this argument indirectly, by placing it at a fixed stack offset.
diff --git a/compiler/rustc_target/src/abi/call/powerpc.rs b/compiler/rustc_target/src/abi/call/powerpc.rs
index cb80d64c943..8f67f57cd2b 100644
--- a/compiler/rustc_target/src/abi/call/powerpc.rs
+++ b/compiler/rustc_target/src/abi/call/powerpc.rs
@@ -16,7 +16,7 @@ fn classify_arg<Ty>(cx: &impl HasTargetSpec, arg: &mut ArgAbi<'_, Ty>) {
             && matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc")
             && arg.layout.is_zst()
         {
-            arg.make_indirect_force();
+            arg.make_indirect_from_ignore();
         }
         return;
     }
diff --git a/compiler/rustc_target/src/abi/call/s390x.rs b/compiler/rustc_target/src/abi/call/s390x.rs
index 7dcbb3e4a9e..901ce139c7b 100644
--- a/compiler/rustc_target/src/abi/call/s390x.rs
+++ b/compiler/rustc_target/src/abi/call/s390x.rs
@@ -28,7 +28,7 @@ where
             && matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc")
             && arg.layout.is_zst()
         {
-            arg.make_indirect_force();
+            arg.make_indirect_from_ignore();
         }
         return;
     }
diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs
index 3b2bf9b3187..311691d8efb 100644
--- a/compiler/rustc_target/src/abi/call/sparc64.rs
+++ b/compiler/rustc_target/src/abi/call/sparc64.rs
@@ -225,7 +225,7 @@ where
                 && matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc")
                 && arg.layout.is_zst()
             {
-                arg.make_indirect_force();
+                arg.make_indirect_from_ignore();
             }
             return;
         }
diff --git a/compiler/rustc_target/src/abi/call/x86_win64.rs b/compiler/rustc_target/src/abi/call/x86_win64.rs
index 6ca01cf84ea..720707ef53f 100644
--- a/compiler/rustc_target/src/abi/call/x86_win64.rs
+++ b/compiler/rustc_target/src/abi/call/x86_win64.rs
@@ -43,7 +43,7 @@ pub fn compute_abi_info<Ty>(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>)
                 && cx.target_spec().env == "gnu"
                 && arg.layout.is_zst()
             {
-                arg.make_indirect_force();
+                arg.make_indirect_from_ignore();
             }
             continue;
         }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index f6dd7898fb2..173671059ca 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -382,7 +382,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
-                was_written: None,
+                was_written: false,
                 path: Default::default(),
             }),
             TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
@@ -393,7 +393,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
-                was_written: None,
+                was_written: false,
                 path: Default::default(),
             }),
             TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
@@ -404,7 +404,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
-                was_written: None,
+                was_written: false,
                 path: Default::default(),
             }),
         }
@@ -586,7 +586,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
-                was_written: path.as_ref().map(|_| ()),
+                was_written: path.is_some(),
                 path: path.unwrap_or_default(),
             }),
             TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
@@ -597,7 +597,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
-                was_written: path.as_ref().map(|_| ()),
+                was_written: path.is_some(),
                 path: path.unwrap_or_default(),
             }),
             TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
@@ -608,7 +608,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
-                was_written: path.as_ref().map(|_| ()),
+                was_written: path.is_some(),
                 path: path.unwrap_or_default(),
             }),
         }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs
index 9c772f42cca..f2a7da707b8 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs
@@ -11,7 +11,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
     pub(super) fn try_report_placeholder_relation(&self) -> Option<Diag<'tcx>> {
         match &self.error {
             Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::RelateRegionParamBound(span),
+                SubregionOrigin::RelateRegionParamBound(span, _),
                 Region(Interned(
                     RePlaceholder(ty::Placeholder {
                         bound: ty::BoundRegion { kind: sub_name, .. },
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs
index 04e1be22a4d..600da730845 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs
@@ -52,7 +52,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         .add_to_diag(err);
                 }
             }
-            infer::RelateRegionParamBound(span) => {
+            infer::RelateRegionParamBound(span, _) => {
                 RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
                     .add_to_diag(err);
             }
@@ -199,7 +199,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     note,
                 })
             }
-            infer::RelateRegionParamBound(span) => {
+            infer::RelateRegionParamBound(span, _) => {
                 let param_instantiated = note_and_explain::RegionExplanation::new(
                     self.tcx,
                     generic_param_scope,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
index 877a8a23d7f..ada44b632d4 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -257,7 +257,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     .add_to_diag(err);
                 }
             }
-            infer::RelateRegionParamBound(span) => {
+            infer::RelateRegionParamBound(span, _) => {
                 RegionOriginNote::Plain {
                     span,
                     msg: fluent::trait_selection_relate_region_param_bound,
@@ -410,7 +410,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     note,
                 })
             }
-            infer::RelateRegionParamBound(span) => {
+            infer::RelateRegionParamBound(span, ty) => {
                 let param_instantiated = note_and_explain::RegionExplanation::new(
                     self.tcx,
                     generic_param_scope,
@@ -419,11 +419,31 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     note_and_explain::PrefixKind::LfParamInstantiatedWith,
                     note_and_explain::SuffixKind::Empty,
                 );
+                let mut alt_span = None;
+                if let Some(ty) = ty
+                    && sub.is_static()
+                    && let ty::Dynamic(preds, _, ty::DynKind::Dyn) = ty.kind()
+                    && let Some(def_id) = preds.principal_def_id()
+                {
+                    for (clause, span) in
+                        self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
+                    {
+                        if let ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) =
+                            clause.kind().skip_binder()
+                            && let ty::Param(param) = a.kind()
+                            && param.name == kw::SelfUpper
+                            && b.is_static()
+                        {
+                            // Point at explicit `'static` bound on the trait (`trait T: 'static`).
+                            alt_span = Some(span);
+                        }
+                    }
+                }
                 let param_must_outlive = note_and_explain::RegionExplanation::new(
                     self.tcx,
                     generic_param_scope,
                     sub,
-                    None,
+                    alt_span,
                     note_and_explain::PrefixKind::LfParamMustOutlive,
                     note_and_explain::SuffixKind::Empty,
                 );
@@ -1079,16 +1099,8 @@ fn msg_span_from_named_region<'tcx>(
 ) -> (String, Option<Span>) {
     match *region {
         ty::ReEarlyParam(br) => {
-            let scope = tcx
-                .parent(tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id)
-                .expect_local();
-            let span = if let Some(param) =
-                tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
-            {
-                param.span
-            } else {
-                tcx.def_span(scope)
-            };
+            let param_def_id = tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id;
+            let span = tcx.def_span(param_def_id);
             let text = if br.has_name() {
                 format!("the lifetime `{}` as defined here", br.name)
             } else {
@@ -1104,16 +1116,8 @@ fn msg_span_from_named_region<'tcx>(
                 ("the anonymous lifetime defined here".to_string(), Some(ty.span))
             } else {
                 match fr.bound_region {
-                    ty::BoundRegionKind::BrNamed(_, name) => {
-                        let span = if let Some(param) = tcx
-                            .hir()
-                            .get_generics(generic_param_scope)
-                            .and_then(|generics| generics.get_named(name))
-                        {
-                            param.span
-                        } else {
-                            tcx.def_span(generic_param_scope)
-                        };
+                    ty::BoundRegionKind::BrNamed(param_def_id, name) => {
+                        let span = tcx.def_span(param_def_id);
                         let text = if name == kw::UnderscoreLifetime {
                             "the anonymous lifetime as defined here".to_string()
                         } else {
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 78f1f7d9b9b..5384084f6d7 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -203,7 +203,7 @@ pub struct AnnotationRequired<'a> {
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
     #[note(trait_selection_full_type_written)]
-    pub was_written: Option<()>,
+    pub was_written: bool,
     pub path: PathBuf,
 }
 
@@ -224,7 +224,7 @@ pub struct AmbiguousImpl<'a> {
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
     #[note(trait_selection_full_type_written)]
-    pub was_written: Option<()>,
+    pub was_written: bool,
     pub path: PathBuf,
 }
 
@@ -245,7 +245,7 @@ pub struct AmbiguousReturn<'a> {
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
     #[note(trait_selection_full_type_written)]
-    pub was_written: Option<()>,
+    pub was_written: bool,
     pub path: PathBuf,
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 29f78f9d5f0..38d338598a1 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -770,7 +770,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                                     let reported =
                                         tcx.dcx().emit_err(UnableToConstructConstantValue {
                                             span: tcx.def_span(unevaluated.def),
-                                            unevaluated: unevaluated,
+                                            unevaluated,
                                         });
                                     Err(ErrorHandled::Reported(reported.into(), tcx.def_span(unevaluated.def)))
                                 }
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 7c73f74e629..2c67e7d4847 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -179,7 +179,7 @@ pub(crate) mod rustc {
     };
 
     use super::Tree;
-    use crate::layout::rustc::{Def, Ref};
+    use crate::layout::rustc::{layout_of, Def, Ref};
 
     #[derive(Debug, Copy, Clone)]
     pub(crate) enum Err {
@@ -206,7 +206,7 @@ pub(crate) mod rustc {
     impl<'tcx> Tree<Def<'tcx>, Ref<'tcx>> {
         pub fn from_ty(ty: Ty<'tcx>, cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result<Self, Err> {
             use rustc_target::abi::HasDataLayout;
-            let layout = ty_layout(cx, ty);
+            let layout = layout_of(cx, ty)?;
 
             if let Err(e) = ty.error_reported() {
                 return Err(Err::TypeError(e));
@@ -239,7 +239,7 @@ pub(crate) mod rustc {
                     let FieldsShape::Array { stride, count } = &layout.fields else {
                         return Err(Err::NotYetSupported);
                     };
-                    let inner_layout = ty_layout(cx, *inner_ty);
+                    let inner_layout = layout_of(cx, *inner_ty)?;
                     assert_eq!(*stride, inner_layout.size);
                     let elt = Tree::from_ty(*inner_ty, cx)?;
                     Ok(std::iter::repeat(elt)
@@ -254,7 +254,7 @@ pub(crate) mod rustc {
                 },
 
                 ty::Ref(lifetime, ty, mutability) => {
-                    let layout = ty_layout(cx, *ty);
+                    let layout = layout_of(cx, *ty)?;
                     let align = layout.align.abi.bytes_usize();
                     let size = layout.size.bytes_usize();
                     Ok(Tree::Ref(Ref {
@@ -280,7 +280,7 @@ pub(crate) mod rustc {
                 FieldsShape::Primitive => {
                     assert_eq!(members.len(), 1);
                     let inner_ty = members[0];
-                    let inner_layout = ty_layout(cx, inner_ty);
+                    let inner_layout = layout_of(cx, inner_ty)?;
                     Self::from_ty(inner_ty, cx)
                 }
                 FieldsShape::Arbitrary { offsets, .. } => {
@@ -413,7 +413,7 @@ pub(crate) mod rustc {
                 let padding = Self::padding(padding_needed.bytes_usize());
 
                 let field_ty = ty_field(cx, (ty, layout), field_idx);
-                let field_layout = ty_layout(cx, field_ty);
+                let field_layout = layout_of(cx, field_ty)?;
                 let field_tree = Self::from_ty(field_ty, cx)?;
 
                 struct_tree = struct_tree.then(padding).then(field_tree);
@@ -471,7 +471,7 @@ pub(crate) mod rustc {
                 |fields, (idx, field_def)| {
                     let field_def = Def::Field(field_def);
                     let field_ty = ty_field(cx, (ty, layout), idx);
-                    let field_layout = ty_layout(cx, field_ty);
+                    let field_layout = layout_of(cx, field_ty)?;
                     let field = Self::from_ty(field_ty, cx)?;
                     let trailing_padding_needed = layout.size - field_layout.size;
                     let trailing_padding = Self::padding(trailing_padding_needed.bytes_usize());
@@ -484,10 +484,6 @@ pub(crate) mod rustc {
         }
     }
 
-    pub(crate) fn ty_layout<'tcx>(cx: LayoutCx<'tcx, TyCtxt<'tcx>>, ty: Ty<'tcx>) -> Layout<'tcx> {
-        crate::layout::rustc::layout_of(cx, ty).unwrap()
-    }
-
     fn ty_field<'tcx>(
         cx: LayoutCx<'tcx, TyCtxt<'tcx>>,
         (ty, layout): (Ty<'tcx>, Layout<'tcx>),
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
index 1f3c4e3c817..2762b4e6384 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
@@ -44,18 +44,11 @@ mod rustc {
             let Self { src, dst, assume, context } = self;
 
             let layout_cx = LayoutCx { tcx: context, param_env: ParamEnv::reveal_all() };
-            let layout_of = |ty| {
-                crate::layout::rustc::layout_of(layout_cx, ty)
-                    .map_err(|_| Err::NotYetSupported)
-                    .and_then(|_| Tree::from_ty(ty, layout_cx))
-            };
 
             // Convert `src` and `dst` from their rustc representations, to `Tree`-based
-            // representations. If these conversions fail, conclude that the transmutation is
-            // unacceptable; the layouts of both the source and destination types must be
-            // well-defined.
-            let src = layout_of(src);
-            let dst = layout_of(dst);
+            // representations.
+            let src = Tree::from_ty(src, layout_cx);
+            let dst = Tree::from_ty(dst, layout_cx);
 
             match (src, dst) {
                 (Err(Err::TypeError(_)), _) | (_, Err(Err::TypeError(_))) => {
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 4ded935b801..ae5341ddec1 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -284,7 +284,7 @@ fn error(
 ) -> Result<!, ErrorGuaranteed> {
     let reported = tcx.dcx().emit_err(GenericConstantTooComplex {
         span: root_span,
-        maybe_supported: None,
+        maybe_supported: false,
         sub,
     });
 
@@ -298,7 +298,7 @@ fn maybe_supported_error(
 ) -> Result<!, ErrorGuaranteed> {
     let reported = tcx.dcx().emit_err(GenericConstantTooComplex {
         span: root_span,
-        maybe_supported: Some(()),
+        maybe_supported: true,
         sub,
     });
 
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index bfbb45f0cb5..42ecaaeafa9 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -18,7 +18,7 @@ pub struct GenericConstantTooComplex {
     #[primary_span]
     pub span: Span,
     #[note(ty_utils_maybe_supported)]
-    pub maybe_supported: Option<()>,
+    pub maybe_supported: bool,
     #[subdiagnostic]
     pub sub: GenericConstantTooComplexSub,
 }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 3e44adf73f0..5e4b08df6cb 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -131,7 +131,6 @@
 #![feature(inplace_iteration)]
 #![feature(iter_advance_by)]
 #![feature(iter_next_chunk)]
-#![feature(iter_repeat_n)]
 #![feature(layout_for_ptr)]
 #![feature(local_waker)]
 #![feature(maybe_uninit_slice)]
diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs
index 549a4bc6727..ad3f9d80878 100644
--- a/library/core/src/alloc/layout.rs
+++ b/library/core/src/alloc/layout.rs
@@ -6,7 +6,7 @@
 
 use crate::error::Error;
 use crate::ptr::{Alignment, NonNull};
-use crate::{cmp, fmt, mem};
+use crate::{assert_unsafe_precondition, cmp, fmt, mem};
 
 // While this function is used in one place and its implementation
 // could be inlined, the previous attempts to do so made rustc
@@ -66,12 +66,20 @@ impl Layout {
     #[inline]
     #[rustc_allow_const_fn_unstable(ptr_alignment_type)]
     pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
-        if !align.is_power_of_two() {
-            return Err(LayoutError);
+        if Layout::is_size_align_valid(size, align) {
+            // SAFETY: Layout::is_size_align_valid checks the preconditions for this call.
+            unsafe { Ok(Layout { size, align: mem::transmute(align) }) }
+        } else {
+            Err(LayoutError)
         }
+    }
 
-        // SAFETY: just checked that align is a power of two.
-        Layout::from_size_alignment(size, unsafe { Alignment::new_unchecked(align) })
+    const fn is_size_align_valid(size: usize, align: usize) -> bool {
+        let Some(align) = Alignment::new(align) else { return false };
+        if size > Self::max_size_for_align(align) {
+            return false;
+        }
+        true
     }
 
     #[inline(always)]
@@ -116,8 +124,17 @@ impl Layout {
     #[inline]
     #[rustc_allow_const_fn_unstable(ptr_alignment_type)]
     pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
+        assert_unsafe_precondition!(
+            check_library_ub,
+            "Layout::from_size_align_unchecked requires that align is a power of 2 \
+            and the rounded-up allocation size does not exceed isize::MAX",
+            (
+                size: usize = size,
+                align: usize = align,
+            ) => Layout::is_size_align_valid(size, align)
+        );
         // SAFETY: the caller is required to uphold the preconditions.
-        unsafe { Layout { size, align: Alignment::new_unchecked(align) } }
+        unsafe { Layout { size, align: mem::transmute(align) } }
     }
 
     /// The minimum size in bytes for a memory block of this layout.
diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs
index 375358dddf5..ce09a0b444d 100644
--- a/library/core/src/ascii/ascii_char.rs
+++ b/library/core/src/ascii/ascii_char.rs
@@ -3,8 +3,8 @@
 //! suggestions from rustc if you get anything slightly wrong in here, and overall
 //! helps with clarity as we're also referring to `char` intentionally in here.
 
-use crate::fmt;
 use crate::mem::transmute;
+use crate::{assert_unsafe_precondition, fmt};
 
 /// One of the 128 Unicode characters from U+0000 through U+007F,
 /// often known as the [ASCII] subset.
@@ -497,14 +497,18 @@ impl AsciiChar {
     /// Notably, it should not be expected to return hex digits, or any other
     /// reasonable extension of the decimal digits.
     ///
-    /// (This lose safety condition is intended to simplify soundness proofs
+    /// (This loose safety condition is intended to simplify soundness proofs
     /// when writing code using this method, since the implementation doesn't
     /// need something really specific, not to make those other arguments do
     /// something useful. It might be tightened before stabilization.)
     #[unstable(feature = "ascii_char", issue = "110998")]
     #[inline]
     pub const unsafe fn digit_unchecked(d: u8) -> Self {
-        debug_assert!(d < 10);
+        assert_unsafe_precondition!(
+            check_language_ub,
+            "`AsciiChar::digit_unchecked` input cannot exceed 9.",
+            (d: u8 = d) => d < 10
+        );
 
         // SAFETY: `'0'` through `'9'` are U+00030 through U+0039,
         // so because `d` must be 64 or less the addition can return at most
diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs
index 097fa86c938..87df8a4e272 100644
--- a/library/core/src/cell/once.rs
+++ b/library/core/src/cell/once.rs
@@ -309,7 +309,8 @@ impl<T> OnceCell<T> {
     /// ```
     #[inline]
     #[stable(feature = "once_cell", since = "1.70.0")]
-    pub fn into_inner(self) -> Option<T> {
+    #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")]
+    pub const fn into_inner(self) -> Option<T> {
         // Because `into_inner` takes `self` by value, the compiler statically verifies
         // that it is not currently borrowed. So it is safe to move out `Option<T>`.
         self.inner.into_inner()
diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs
index 467fa17a6f3..c7c462a4df1 100644
--- a/library/core/src/fmt/builders.rs
+++ b/library/core/src/fmt/builders.rs
@@ -78,7 +78,7 @@ impl fmt::Write for PadAdapter<'_, '_> {
 ///
 /// assert_eq!(
 ///     format!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }),
-///     "Foo { bar: 10, baz: \"Hello World\" }",
+///     r#"Foo { bar: 10, baz: "Hello World" }"#,
 /// );
 /// ```
 #[must_use = "must eventually call `finish()` on Debug builders"]
@@ -125,7 +125,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
     ///
     /// assert_eq!(
     ///     format!("{:?}", Bar { bar: 10, another: "Hello World".to_string() }),
-    ///     "Bar { bar: 10, another: \"Hello World\", nonexistent_field: 1 }",
+    ///     r#"Bar { bar: 10, another: "Hello World", nonexistent_field: 1 }"#,
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
@@ -237,7 +237,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
     ///
     /// assert_eq!(
     ///     format!("{:?}", Bar { bar: 10, baz: "Hello World".to_string() }),
-    ///     "Bar { bar: 10, baz: \"Hello World\" }",
+    ///     r#"Bar { bar: 10, baz: "Hello World" }"#,
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
@@ -280,7 +280,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
 ///
 /// assert_eq!(
 ///     format!("{:?}", Foo(10, "Hello World".to_string())),
-///     "Foo(10, \"Hello World\")",
+///     r#"Foo(10, "Hello World")"#,
 /// );
 /// ```
 #[must_use = "must eventually call `finish()` on Debug builders"]
@@ -322,7 +322,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
     ///
     /// assert_eq!(
     ///     format!("{:?}", Foo(10, "Hello World".to_string())),
-    ///     "Foo(10, \"Hello World\")",
+    ///     r#"Foo(10, "Hello World")"#,
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
@@ -360,6 +360,51 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
         self
     }
 
+    /// Marks the tuple struct as non-exhaustive, indicating to the reader that there are some
+    /// other fields that are not shown in the debug representation.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(debug_more_non_exhaustive)]
+    ///
+    /// use std::fmt;
+    ///
+    /// struct Foo(i32, String);
+    ///
+    /// impl fmt::Debug for Foo {
+    ///     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+    ///         fmt.debug_tuple("Foo")
+    ///            .field(&self.0)
+    ///            .finish_non_exhaustive() // Show that some other field(s) exist.
+    ///     }
+    /// }
+    ///
+    /// assert_eq!(
+    ///     format!("{:?}", Foo(10, "secret!".to_owned())),
+    ///     "Foo(10, ..)",
+    /// );
+    /// ```
+    #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")]
+    pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
+        self.result = self.result.and_then(|_| {
+            if self.fields > 0 {
+                if self.is_pretty() {
+                    let mut slot = None;
+                    let mut state = Default::default();
+                    let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
+                    writer.write_str("..\n")?;
+                    self.fmt.write_str(")")
+                } else {
+                    self.fmt.write_str(", ..)")
+                }
+            } else {
+                self.fmt.write_str("(..)")
+            }
+        });
+        self.result
+    }
+
     /// Finishes output and returns any error encountered.
     ///
     /// # Examples
@@ -381,7 +426,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
     ///
     /// assert_eq!(
     ///     format!("{:?}", Foo(10, "Hello World".to_string())),
-    ///     "Foo(10, \"Hello World\")",
+    ///     r#"Foo(10, "Hello World")"#,
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
@@ -555,6 +600,56 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
         self
     }
 
+    /// Marks the set as non-exhaustive, indicating to the reader that there are some other
+    /// elements that are not shown in the debug representation.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(debug_more_non_exhaustive)]
+    ///
+    /// use std::fmt;
+    ///
+    /// struct Foo(Vec<i32>);
+    ///
+    /// impl fmt::Debug for Foo {
+    ///     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+    ///         // Print at most two elements, abbreviate the rest
+    ///         let mut f = fmt.debug_set();
+    ///         let mut f = f.entries(self.0.iter().take(2));
+    ///         if self.0.len() > 2 {
+    ///             f.finish_non_exhaustive()
+    ///         } else {
+    ///             f.finish()
+    ///         }
+    ///     }
+    /// }
+    ///
+    /// assert_eq!(
+    ///     format!("{:?}", Foo(vec![1, 2, 3, 4])),
+    ///     "{1, 2, ..}",
+    /// );
+    /// ```
+    #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")]
+    pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
+        self.inner.result = self.inner.result.and_then(|_| {
+            if self.inner.has_fields {
+                if self.inner.is_pretty() {
+                    let mut slot = None;
+                    let mut state = Default::default();
+                    let mut writer = PadAdapter::wrap(self.inner.fmt, &mut slot, &mut state);
+                    writer.write_str("..\n")?;
+                    self.inner.fmt.write_str("}")
+                } else {
+                    self.inner.fmt.write_str(", ..}")
+                }
+            } else {
+                self.inner.fmt.write_str("..}")
+            }
+        });
+        self.inner.result
+    }
+
     /// Finishes output and returns any error encountered.
     ///
     /// # Examples
@@ -699,6 +794,55 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
         self
     }
 
+    /// Marks the list as non-exhaustive, indicating to the reader that there are some other
+    /// elements that are not shown in the debug representation.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(debug_more_non_exhaustive)]
+    ///
+    /// use std::fmt;
+    ///
+    /// struct Foo(Vec<i32>);
+    ///
+    /// impl fmt::Debug for Foo {
+    ///     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+    ///         // Print at most two elements, abbreviate the rest
+    ///         let mut f = fmt.debug_list();
+    ///         let mut f = f.entries(self.0.iter().take(2));
+    ///         if self.0.len() > 2 {
+    ///             f.finish_non_exhaustive()
+    ///         } else {
+    ///             f.finish()
+    ///         }
+    ///     }
+    /// }
+    ///
+    /// assert_eq!(
+    ///     format!("{:?}", Foo(vec![1, 2, 3, 4])),
+    ///     "[1, 2, ..]",
+    /// );
+    /// ```
+    #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")]
+    pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
+        self.inner.result.and_then(|_| {
+            if self.inner.has_fields {
+                if self.inner.is_pretty() {
+                    let mut slot = None;
+                    let mut state = Default::default();
+                    let mut writer = PadAdapter::wrap(self.inner.fmt, &mut slot, &mut state);
+                    writer.write_str("..\n")?;
+                    self.inner.fmt.write_str("]")
+                } else {
+                    self.inner.fmt.write_str(", ..]")
+                }
+            } else {
+                self.inner.fmt.write_str("..]")
+            }
+        })
+    }
+
     /// Finishes output and returns any error encountered.
     ///
     /// # Examples
@@ -750,7 +894,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
 ///
 /// assert_eq!(
 ///     format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
-///     "{\"A\": 10, \"B\": 11}",
+///     r#"{"A": 10, "B": 11}"#,
 /// );
 /// ```
 #[must_use = "must eventually call `finish()` on Debug builders"]
@@ -790,7 +934,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
     ///
     /// assert_eq!(
     ///     format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
-    ///     "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
+    ///     r#"{"whole": [("A", 10), ("B", 11)]}"#,
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
@@ -826,7 +970,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
     ///
     /// assert_eq!(
     ///     format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
-    ///     "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
+    ///     r#"{"whole": [("A", 10), ("B", 11)]}"#,
     /// );
     /// ```
     #[stable(feature = "debug_map_key_value", since = "1.42.0")]
@@ -902,7 +1046,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
     ///
     /// assert_eq!(
     ///     format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
-    ///     "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
+    ///     r#"{"whole": [("A", 10), ("B", 11)]}"#,
     /// );
     /// ```
     #[stable(feature = "debug_map_key_value", since = "1.42.0")]
@@ -960,7 +1104,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
     ///
     /// assert_eq!(
     ///     format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
-    ///     "{\"A\": 10, \"B\": 11}",
+    ///     r#"{"A": 10, "B": 11}"#,
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
@@ -976,6 +1120,62 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
         self
     }
 
+    /// Marks the map as non-exhaustive, indicating to the reader that there are some other
+    /// entries that are not shown in the debug representation.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(debug_more_non_exhaustive)]
+    ///
+    /// use std::fmt;
+    ///
+    /// struct Foo(Vec<(String, i32)>);
+    ///
+    /// impl fmt::Debug for Foo {
+    ///     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+    ///         // Print at most two elements, abbreviate the rest
+    ///         let mut f = fmt.debug_map();
+    ///         let mut f = f.entries(self.0.iter().take(2).map(|&(ref k, ref v)| (k, v)));
+    ///         if self.0.len() > 2 {
+    ///             f.finish_non_exhaustive()
+    ///         } else {
+    ///             f.finish()
+    ///         }
+    ///     }
+    /// }
+    ///
+    /// assert_eq!(
+    ///     format!("{:?}", Foo(vec![
+    ///         ("A".to_string(), 10),
+    ///         ("B".to_string(), 11),
+    ///         ("C".to_string(), 12),
+    ///     ])),
+    ///     r#"{"A": 10, "B": 11, ..}"#,
+    /// );
+    /// ```
+    #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")]
+    pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
+        self.result = self.result.and_then(|_| {
+            assert!(!self.has_key, "attempted to finish a map with a partial entry");
+
+            if self.has_fields {
+                if self.is_pretty() {
+                    let mut slot = None;
+                    let mut state = Default::default();
+                    let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
+                    writer.write_str("..\n")?;
+                    self.fmt.write_str("}")
+                } else {
+                    self.fmt.write_str(", ..}")
+                }
+            } else {
+                self.fmt.write_str("..}")
+            }
+        });
+        self.result
+    }
+
     /// Finishes output and returns any error encountered.
     ///
     /// # Panics
@@ -1000,7 +1200,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
     ///
     /// assert_eq!(
     ///     format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
-    ///     "{\"A\": 10, \"B\": 11}",
+    ///     r#"{"A": 10, "B": 11}"#,
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index 1f2bf49d2b7..5dad9e1a75e 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -436,7 +436,7 @@ pub use self::sources::{once, Once};
 pub use self::sources::{once_with, OnceWith};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::sources::{repeat, Repeat};
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 pub use self::sources::{repeat_n, RepeatN};
 #[stable(feature = "iterator_repeat_with", since = "1.28.0")]
 pub use self::sources::{repeat_with, RepeatWith};
diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs
index 6a94051b7c7..55901e1e50b 100644
--- a/library/core/src/iter/sources.rs
+++ b/library/core/src/iter/sources.rs
@@ -24,7 +24,7 @@ pub use self::once::{once, Once};
 pub use self::once_with::{once_with, OnceWith};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::repeat::{repeat, Repeat};
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 pub use self::repeat_n::{repeat_n, RepeatN};
 #[stable(feature = "iterator_repeat_with", since = "1.28.0")]
 pub use self::repeat_with::{repeat_with, RepeatWith};
diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs
index 4c4ae39f836..2e247a34075 100644
--- a/library/core/src/iter/sources/repeat_n.rs
+++ b/library/core/src/iter/sources/repeat_n.rs
@@ -18,7 +18,6 @@ use crate::num::NonZero;
 /// Basic usage:
 ///
 /// ```
-/// #![feature(iter_repeat_n)]
 /// use std::iter;
 ///
 /// // four of the number four:
@@ -36,7 +35,6 @@ use crate::num::NonZero;
 /// For non-`Copy` types,
 ///
 /// ```
-/// #![feature(iter_repeat_n)]
 /// use std::iter;
 ///
 /// let v: Vec<i32> = Vec::with_capacity(123);
@@ -58,7 +56,7 @@ use crate::num::NonZero;
 /// assert_eq!(None, it.next());
 /// ```
 #[inline]
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 pub fn repeat_n<T: Clone>(element: T, count: usize) -> RepeatN<T> {
     let mut element = ManuallyDrop::new(element);
 
@@ -77,7 +75,7 @@ pub fn repeat_n<T: Clone>(element: T, count: usize) -> RepeatN<T> {
 /// This `struct` is created by the [`repeat_n()`] function.
 /// See its documentation for more.
 #[derive(Clone, Debug)]
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 pub struct RepeatN<A> {
     count: usize,
     // Invariant: has been dropped iff count == 0.
@@ -101,14 +99,14 @@ impl<A> RepeatN<A> {
     }
 }
 
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 impl<A> Drop for RepeatN<A> {
     fn drop(&mut self) {
         self.take_element();
     }
 }
 
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 impl<A: Clone> Iterator for RepeatN<A> {
     type Item = A;
 
@@ -156,14 +154,14 @@ impl<A: Clone> Iterator for RepeatN<A> {
     }
 }
 
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 impl<A: Clone> ExactSizeIterator for RepeatN<A> {
     fn len(&self) -> usize {
         self.count
     }
 }
 
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 impl<A: Clone> DoubleEndedIterator for RepeatN<A> {
     #[inline]
     fn next_back(&mut self) -> Option<A> {
@@ -181,12 +179,12 @@ impl<A: Clone> DoubleEndedIterator for RepeatN<A> {
     }
 }
 
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 impl<A: Clone> FusedIterator for RepeatN<A> {}
 
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<A: Clone> TrustedLen for RepeatN<A> {}
-#[unstable(feature = "trusted_len_next_unchecked", issue = "37572")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 impl<A: Clone> UncheckedIterator for RepeatN<A> {
     #[inline]
     unsafe fn next_unchecked(&mut self) -> Self::Item {
diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs
index c97cd042ab4..5b7d95c2f65 100644
--- a/library/core/src/iter/traits/accum.rs
+++ b/library/core/src/iter/traits/accum.rs
@@ -104,7 +104,7 @@ macro_rules! float_sum_product {
         impl Sum for $a {
             fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
                 iter.fold(
-                    0.0,
+                    -0.0,
                     #[rustc_inherit_overflow_checks]
                     |a, b| a + b,
                 )
@@ -126,7 +126,7 @@ macro_rules! float_sum_product {
         impl<'a> Sum<&'a $a> for $a {
             fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
                 iter.fold(
-                    0.0,
+                    -0.0,
                     #[rustc_inherit_overflow_checks]
                     |a, b| a + b,
                 )
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 7f278296b7b..73b11f803d9 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1481,7 +1481,6 @@ impl<T, E> Result<T, E> {
     #[track_caller]
     #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")]
     pub unsafe fn unwrap_unchecked(self) -> T {
-        debug_assert!(self.is_ok());
         match self {
             Ok(t) => t,
             // SAFETY: the safety contract must be upheld by the caller.
@@ -1513,7 +1512,6 @@ impl<T, E> Result<T, E> {
     #[track_caller]
     #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")]
     pub unsafe fn unwrap_err_unchecked(self) -> E {
-        debug_assert!(self.is_err());
         match self {
             // SAFETY: the safety contract must be upheld by the caller.
             Ok(_) => unsafe { hint::unreachable_unchecked() },
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 56517348dc7..cf9f1bfc0eb 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -2818,5 +2818,5 @@ impl_fn_for_zst! {
 }
 
 // This is required to make `impl From<&str> for Box<dyn Error>` and `impl<E> From<E> for Box<dyn Error>` not overlap.
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "error_in_core_neg_impl", since = "1.65.0")]
 impl !crate::error::Error for &str {}
diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs
index b65b48c162d..c1a8c34539e 100644
--- a/library/core/src/ub_checks.rs
+++ b/library/core/src/ub_checks.rs
@@ -10,7 +10,7 @@ use crate::intrinsics::{self, const_eval_select};
 /// macro for language UB are always ignored.
 ///
 /// This macro should be called as
-/// `assert_unsafe_precondition!(check_{library,lang}_ub, "message", (ident: type = expr, ident: type = expr) => check_expr)`
+/// `assert_unsafe_precondition!(check_{library,language}_ub, "message", (ident: type = expr, ident: type = expr) => check_expr)`
 /// where each `expr` will be evaluated and passed in as function argument `ident: type`. Then all
 /// those arguments are passed to a function with the body `check_expr`.
 /// Pick `check_language_ub` when this is guarding a violation of language UB, i.e., immediate UB
diff --git a/library/core/tests/fmt/builders.rs b/library/core/tests/fmt/builders.rs
index 2bdc334b7c0..ba4801f5912 100644
--- a/library/core/tests/fmt/builders.rs
+++ b/library/core/tests/fmt/builders.rs
@@ -79,23 +79,23 @@ mod debug_struct {
         }
 
         assert_eq!(
-            "Bar { foo: Foo { bar: true, baz: 10/20 }, hello: \"world\" }",
+            r#"Bar { foo: Foo { bar: true, baz: 10/20 }, hello: "world" }"#,
             format!("{Bar:?}")
         );
         assert_eq!(
-            "Bar {
+            r#"Bar {
     foo: Foo {
         bar: true,
         baz: 10/20,
     },
-    hello: \"world\",
-}",
+    hello: "world",
+}"#,
             format!("{Bar:#?}")
         );
     }
 
     #[test]
-    fn test_only_non_exhaustive() {
+    fn test_empty_non_exhaustive() {
         struct Foo;
 
         impl fmt::Debug for Foo {
@@ -157,19 +157,19 @@ mod debug_struct {
         }
 
         assert_eq!(
-            "Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: \"world\", .. }",
+            r#"Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: "world", .. }"#,
             format!("{Bar:?}")
         );
         assert_eq!(
-            "Bar {
+            r#"Bar {
     foo: Foo {
         bar: true,
         baz: 10/20,
         ..
     },
-    hello: \"world\",
+    hello: "world",
     ..
-}",
+}"#,
             format!("{Bar:#?}")
         );
     }
@@ -249,15 +249,89 @@ mod debug_tuple {
             }
         }
 
-        assert_eq!("Bar(Foo(true, 10/20), \"world\")", format!("{Bar:?}"));
+        assert_eq!(r#"Bar(Foo(true, 10/20), "world")"#, format!("{Bar:?}"));
         assert_eq!(
-            "Bar(
+            r#"Bar(
     Foo(
         true,
         10/20,
     ),
-    \"world\",
+    "world",
+)"#,
+            format!("{Bar:#?}")
+        );
+    }
+
+    #[test]
+    fn test_empty_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_tuple("Foo").finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!("Foo(..)", format!("{Foo:?}"));
+        assert_eq!("Foo(..)", format!("{Foo:#?}"));
+    }
+
+    #[test]
+    fn test_multiple_and_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_tuple("Foo")
+                    .field(&true)
+                    .field(&format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!("Foo(true, 10/20, ..)", format!("{Foo:?}"));
+        assert_eq!(
+            "Foo(
+    true,
+    10/20,
+    ..
 )",
+            format!("{Foo:#?}")
+        );
+    }
+
+    #[test]
+    fn test_nested_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_tuple("Foo")
+                    .field(&true)
+                    .field(&format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_tuple("Bar").field(&Foo).field(&"world").finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!(r#"Bar(Foo(true, 10/20, ..), "world", ..)"#, format!("{Bar:?}"));
+        assert_eq!(
+            r#"Bar(
+    Foo(
+        true,
+        10/20,
+        ..
+    ),
+    "world",
+    ..
+)"#,
             format!("{Bar:#?}")
         );
     }
@@ -301,11 +375,11 @@ mod debug_map {
         assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}"));
         assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}"));
 
-        assert_eq!("{\"bar\": true}", format!("{Entry:?}"));
+        assert_eq!(r#"{"bar": true}"#, format!("{Entry:?}"));
         assert_eq!(
-            "{
-    \"bar\": true,
-}",
+            r#"{
+    "bar": true,
+}"#,
             format!("{Entry:#?}")
         );
     }
@@ -339,12 +413,12 @@ mod debug_map {
         assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}"));
         assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}"));
 
-        assert_eq!("{\"bar\": true, 10: 10/20}", format!("{Entry:?}"));
+        assert_eq!(r#"{"bar": true, 10: 10/20}"#, format!("{Entry:?}"));
         assert_eq!(
-            "{
-    \"bar\": true,
+            r#"{
+    "bar": true,
     10: 10/20,
-}",
+}"#,
             format!("{Entry:#?}")
         );
     }
@@ -371,21 +445,20 @@ mod debug_map {
         }
 
         assert_eq!(
-            "{\"foo\": {\"bar\": true, 10: 10/20}, \
-                    {\"bar\": true, 10: 10/20}: \"world\"}",
+            r#"{"foo": {"bar": true, 10: 10/20}, {"bar": true, 10: 10/20}: "world"}"#,
             format!("{Bar:?}")
         );
         assert_eq!(
-            "{
-    \"foo\": {
-        \"bar\": true,
+            r#"{
+    "foo": {
+        "bar": true,
         10: 10/20,
     },
     {
-        \"bar\": true,
+        "bar": true,
         10: 10/20,
-    }: \"world\",
-}",
+    }: "world",
+}"#,
             format!("{Bar:#?}")
         );
     }
@@ -471,6 +544,103 @@ mod debug_map {
 
         let _ = format!("{Foo:?}");
     }
+
+    #[test]
+    fn test_empty_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_map().finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!("{..}", format!("{Foo:?}"));
+        assert_eq!("{..}", format!("{Foo:#?}"));
+    }
+
+    #[test]
+    fn test_multiple_and_non_exhaustive() {
+        struct Entry;
+
+        impl fmt::Debug for Entry {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_map()
+                    .entry(&"bar", &true)
+                    .entry(&10, &format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        struct KeyValue;
+
+        impl fmt::Debug for KeyValue {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_map()
+                    .key(&"bar")
+                    .value(&true)
+                    .key(&10)
+                    .value(&format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}"));
+        assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}"));
+
+        assert_eq!(r#"{"bar": true, 10: 10/20, ..}"#, format!("{Entry:?}"));
+        assert_eq!(
+            r#"{
+    "bar": true,
+    10: 10/20,
+    ..
+}"#,
+            format!("{Entry:#?}")
+        );
+    }
+
+    #[test]
+    fn test_nested_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_map()
+                    .entry(&"bar", &true)
+                    .entry(&10, &format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_map().entry(&"foo", &Foo).entry(&Foo, &"world").finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!(
+            r#"{"foo": {"bar": true, 10: 10/20, ..}, {"bar": true, 10: 10/20, ..}: "world", ..}"#,
+            format!("{Bar:?}")
+        );
+        assert_eq!(
+            r#"{
+    "foo": {
+        "bar": true,
+        10: 10/20,
+        ..
+    },
+    {
+        "bar": true,
+        10: 10/20,
+        ..
+    }: "world",
+    ..
+}"#,
+            format!("{Bar:#?}")
+        );
+    }
 }
 
 mod debug_set {
@@ -547,15 +717,89 @@ mod debug_set {
             }
         }
 
-        assert_eq!("{{true, 10/20}, \"world\"}", format!("{Bar:?}"));
+        assert_eq!(r#"{{true, 10/20}, "world"}"#, format!("{Bar:?}"));
         assert_eq!(
-            "{
+            r#"{
     {
         true,
         10/20,
     },
-    \"world\",
+    "world",
+}"#,
+            format!("{Bar:#?}")
+        );
+    }
+
+    #[test]
+    fn test_empty_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_set().finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!("{..}", format!("{Foo:?}"));
+        assert_eq!("{..}", format!("{Foo:#?}"));
+    }
+
+    #[test]
+    fn test_multiple_and_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_set()
+                    .entry(&true)
+                    .entry(&format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!("{true, 10/20, ..}", format!("{Foo:?}"));
+        assert_eq!(
+            "{
+    true,
+    10/20,
+    ..
 }",
+            format!("{Foo:#?}")
+        );
+    }
+
+    #[test]
+    fn test_nested_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_set()
+                    .entry(&true)
+                    .entry(&format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_set().entry(&Foo).entry(&"world").finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!(r#"{{true, 10/20, ..}, "world", ..}"#, format!("{Bar:?}"));
+        assert_eq!(
+            r#"{
+    {
+        true,
+        10/20,
+        ..
+    },
+    "world",
+    ..
+}"#,
             format!("{Bar:#?}")
         );
     }
@@ -635,15 +879,89 @@ mod debug_list {
             }
         }
 
-        assert_eq!("[[true, 10/20], \"world\"]", format!("{Bar:?}"));
+        assert_eq!(r#"[[true, 10/20], "world"]"#, format!("{Bar:?}"));
         assert_eq!(
-            "[
+            r#"[
     [
         true,
         10/20,
     ],
-    \"world\",
+    "world",
+]"#,
+            format!("{Bar:#?}")
+        );
+    }
+
+    #[test]
+    fn test_empty_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_list().finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!("[..]", format!("{Foo:?}"));
+        assert_eq!("[..]", format!("{Foo:#?}"));
+    }
+
+    #[test]
+    fn test_multiple_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_list()
+                    .entry(&true)
+                    .entry(&format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!("[true, 10/20, ..]", format!("{Foo:?}"));
+        assert_eq!(
+            "[
+    true,
+    10/20,
+    ..
 ]",
+            format!("{Foo:#?}")
+        );
+    }
+
+    #[test]
+    fn test_nested_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_list()
+                    .entry(&true)
+                    .entry(&format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_list().entry(&Foo).entry(&"world").finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!(r#"[[true, 10/20, ..], "world", ..]"#, format!("{Bar:?}"));
+        assert_eq!(
+            r#"[
+    [
+        true,
+        10/20,
+        ..
+    ],
+    "world",
+    ..
+]"#,
             format!("{Bar:#?}")
         );
     }
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 8872b4cbfd5..073429c7628 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -43,6 +43,7 @@
 #![feature(core_io_borrowed_buf)]
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
+#![feature(debug_more_non_exhaustive)]
 #![feature(dec2flt)]
 #![feature(duration_constants)]
 #![feature(duration_constructors)]
@@ -73,7 +74,6 @@
 #![feature(iter_next_chunk)]
 #![feature(iter_order_by)]
 #![feature(iter_partition_in_place)]
-#![feature(iter_repeat_n)]
 #![feature(iterator_try_collect)]
 #![feature(iterator_try_reduce)]
 #![feature(layout_for_ptr)]
diff --git a/library/core/tests/num/float_iter_sum_identity.rs b/library/core/tests/num/float_iter_sum_identity.rs
new file mode 100644
index 00000000000..6d3224522a8
--- /dev/null
+++ b/library/core/tests/num/float_iter_sum_identity.rs
@@ -0,0 +1,27 @@
+#[test]
+fn f32_ref() {
+    let x: f32 = -0.0;
+    let still_x: f32 = [x].iter().sum();
+    assert_eq!(1. / x, 1. / still_x)
+}
+
+#[test]
+fn f32_own() {
+    let x: f32 = -0.0;
+    let still_x: f32 = [x].into_iter().sum();
+    assert_eq!(1. / x, 1. / still_x)
+}
+
+#[test]
+fn f64_ref() {
+    let x: f64 = -0.0;
+    let still_x: f64 = [x].iter().sum();
+    assert_eq!(1. / x, 1. / still_x)
+}
+
+#[test]
+fn f64_own() {
+    let x: f64 = -0.0;
+    let still_x: f64 = [x].into_iter().sum();
+    assert_eq!(1. / x, 1. / still_x)
+}
diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
index 9d2912c4b22..53ff5ab1ced 100644
--- a/library/core/tests/num/mod.rs
+++ b/library/core/tests/num/mod.rs
@@ -30,6 +30,7 @@ mod int_log;
 mod ops;
 mod wrapping;
 
+mod float_iter_sum_identity;
 mod ieee754;
 mod nan;
 
diff --git a/library/std/src/os/wasi/fs.rs b/library/std/src/os/wasi/fs.rs
index a58ca543d67..9ec3e387e2b 100644
--- a/library/std/src/os/wasi/fs.rs
+++ b/library/std/src/os/wasi/fs.rs
@@ -2,7 +2,6 @@
 //!
 //! [`std::fs`]: crate::fs
 
-#![deny(unsafe_op_in_unsafe_fn)]
 #![unstable(feature = "wasi_ext", issue = "71213")]
 
 // Used for `File::read` on intra-doc links
diff --git a/library/std/src/os/wasi/mod.rs b/library/std/src/os/wasi/mod.rs
index e36b93e60ea..33b50c9e53b 100644
--- a/library/std/src/os/wasi/mod.rs
+++ b/library/std/src/os/wasi/mod.rs
@@ -30,7 +30,7 @@
 
 #![cfg_attr(not(target_env = "p2"), stable(feature = "rust1", since = "1.0.0"))]
 #![cfg_attr(target_env = "p2", unstable(feature = "wasip2", issue = "none"))]
-#![deny(unsafe_op_in_unsafe_fn)]
+#![forbid(unsafe_op_in_unsafe_fn)]
 #![doc(cfg(target_os = "wasi"))]
 
 pub mod ffi;
diff --git a/library/std/src/os/wasip2/mod.rs b/library/std/src/os/wasip2/mod.rs
index 1d44dd72814..809a288f20d 100644
--- a/library/std/src/os/wasip2/mod.rs
+++ b/library/std/src/os/wasip2/mod.rs
@@ -2,4 +2,5 @@
 //!
 //! This module is currently empty, but will be filled over time as wasi-libc support for WASI Preview 2 is stabilized.
 
+#![forbid(unsafe_op_in_unsafe_fn)]
 #![stable(feature = "raw_ext", since = "1.1.0")]
diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs
index b62129f4cdd..10df3306f92 100644
--- a/library/std/src/sys/pal/unix/mod.rs
+++ b/library/std/src/sys/pal/unix/mod.rs
@@ -116,7 +116,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
                 if pfd.revents & libc::POLLNVAL == 0 {
                     continue;
                 }
-                if open64(c"/dev/null".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
+                if open64(c"/dev/null".as_ptr(), libc::O_RDWR, 0) == -1 {
                     // If the stream is closed but we failed to reopen it, abort the
                     // process. Otherwise we wouldn't preserve the safety of
                     // operations on the corresponding Rust object Stdin, Stdout, or
@@ -147,7 +147,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
             use crate::sys::os::errno;
             for fd in 0..3 {
                 if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
-                    if open64(c"/dev/null".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
+                    if open64(c"/dev/null".as_ptr(), libc::O_RDWR, 0) == -1 {
                         // If the stream is closed but we failed to reopen it, abort the
                         // process. Otherwise we wouldn't preserve the safety of
                         // operations on the corresponding Rust object Stdin, Stdout, or
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index 0fa610eebb4..c9dcc5ad97a 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -267,14 +267,32 @@ impl Thread {
 
     #[cfg(target_os = "espidf")]
     pub fn sleep(dur: Duration) {
-        let mut micros = dur.as_micros();
-        unsafe {
-            while micros > 0 {
-                let st = if micros > u32::MAX as u128 { u32::MAX } else { micros as u32 };
+        // ESP-IDF does not have `nanosleep`, so we use `usleep` instead.
+        // As per the documentation of `usleep`, it is expected to support
+        // sleep times as big as at least up to 1 second.
+        //
+        // ESP-IDF does support almost up to `u32::MAX`, but due to a potential integer overflow in its
+        // `usleep` implementation
+        // (https://github.com/espressif/esp-idf/blob/d7ca8b94c852052e3bc33292287ef4dd62c9eeb1/components/newlib/time.c#L210),
+        // we limit the sleep time to the maximum one that would not cause the underlying `usleep` implementation to overflow
+        // (`portTICK_PERIOD_MS` can be anything between 1 to 1000, and is 10 by default).
+        const MAX_MICROS: u32 = u32::MAX - 1_000_000 - 1;
+
+        // Add any nanoseconds smaller than a microsecond as an extra microsecond
+        // so as to comply with the `std::thread::sleep` contract which mandates
+        // implementations to sleep for _at least_ the provided `dur`.
+        // We can't overflow `micros` as it is a `u128`, while `Duration` is a pair of
+        // (`u64` secs, `u32` nanos), where the nanos are strictly smaller than 1 second
+        // (i.e. < 1_000_000_000)
+        let mut micros = dur.as_micros() + if dur.subsec_nanos() % 1_000 > 0 { 1 } else { 0 };
+
+        while micros > 0 {
+            let st = if micros > MAX_MICROS as u128 { MAX_MICROS } else { micros as u32 };
+            unsafe {
                 libc::usleep(st);
-
-                micros -= st as u128;
             }
+
+            micros -= st as u128;
         }
     }
 
diff --git a/library/std/src/sys/pal/wasi/args.rs b/library/std/src/sys/pal/wasi/args.rs
index 6b6d1b8ff4e..52cfa202af8 100644
--- a/library/std/src/sys/pal/wasi/args.rs
+++ b/library/std/src/sys/pal/wasi/args.rs
@@ -1,4 +1,4 @@
-#![deny(unsafe_op_in_unsafe_fn)]
+#![forbid(unsafe_op_in_unsafe_fn)]
 
 use crate::ffi::{CStr, OsStr, OsString};
 use crate::os::wasi::ffi::OsStrExt;
diff --git a/library/std/src/sys/pal/wasi/env.rs b/library/std/src/sys/pal/wasi/env.rs
index 730e356d7fe..8d444982673 100644
--- a/library/std/src/sys/pal/wasi/env.rs
+++ b/library/std/src/sys/pal/wasi/env.rs
@@ -1,3 +1,5 @@
+#![forbid(unsafe_op_in_unsafe_fn)]
+
 pub mod os {
     pub const FAMILY: &str = "";
     pub const OS: &str = "";
diff --git a/library/std/src/sys/pal/wasi/fd.rs b/library/std/src/sys/pal/wasi/fd.rs
index 8966e4b80ad..19b60157e2e 100644
--- a/library/std/src/sys/pal/wasi/fd.rs
+++ b/library/std/src/sys/pal/wasi/fd.rs
@@ -1,4 +1,4 @@
-#![deny(unsafe_op_in_unsafe_fn)]
+#![forbid(unsafe_op_in_unsafe_fn)]
 #![allow(dead_code)]
 
 use super::err2io;
diff --git a/library/std/src/sys/pal/wasi/fs.rs b/library/std/src/sys/pal/wasi/fs.rs
index 11900886f0b..6a97621ad50 100644
--- a/library/std/src/sys/pal/wasi/fs.rs
+++ b/library/std/src/sys/pal/wasi/fs.rs
@@ -1,4 +1,4 @@
-#![deny(unsafe_op_in_unsafe_fn)]
+#![forbid(unsafe_op_in_unsafe_fn)]
 
 use super::fd::WasiFd;
 use crate::ffi::{CStr, OsStr, OsString};
diff --git a/library/std/src/sys/pal/wasi/helpers.rs b/library/std/src/sys/pal/wasi/helpers.rs
index 4b770ee23bc..d047bf2fce8 100644
--- a/library/std/src/sys/pal/wasi/helpers.rs
+++ b/library/std/src/sys/pal/wasi/helpers.rs
@@ -1,3 +1,5 @@
+#![forbid(unsafe_op_in_unsafe_fn)]
+
 use crate::{io as std_io, mem};
 
 #[inline]
diff --git a/library/std/src/sys/pal/wasi/io.rs b/library/std/src/sys/pal/wasi/io.rs
index 2cd45df88fa..b7c2f03daa0 100644
--- a/library/std/src/sys/pal/wasi/io.rs
+++ b/library/std/src/sys/pal/wasi/io.rs
@@ -1,4 +1,4 @@
-#![deny(unsafe_op_in_unsafe_fn)]
+#![forbid(unsafe_op_in_unsafe_fn)]
 
 use crate::marker::PhantomData;
 use crate::os::fd::{AsFd, AsRawFd};
diff --git a/library/std/src/sys/pal/wasi/net.rs b/library/std/src/sys/pal/wasi/net.rs
index b4cf94c8781..a6486799828 100644
--- a/library/std/src/sys/pal/wasi/net.rs
+++ b/library/std/src/sys/pal/wasi/net.rs
@@ -1,4 +1,4 @@
-#![deny(unsafe_op_in_unsafe_fn)]
+#![forbid(unsafe_op_in_unsafe_fn)]
 
 use super::err2io;
 use super::fd::WasiFd;
diff --git a/library/std/src/sys/pal/wasi/os.rs b/library/std/src/sys/pal/wasi/os.rs
index f5b17d9df94..f7701360f5a 100644
--- a/library/std/src/sys/pal/wasi/os.rs
+++ b/library/std/src/sys/pal/wasi/os.rs
@@ -1,4 +1,4 @@
-#![deny(unsafe_op_in_unsafe_fn)]
+#![forbid(unsafe_op_in_unsafe_fn)]
 
 use core::slice::memchr;
 
diff --git a/library/std/src/sys/pal/wasi/stdio.rs b/library/std/src/sys/pal/wasi/stdio.rs
index 4cc0e4ed5a4..ca49f871e19 100644
--- a/library/std/src/sys/pal/wasi/stdio.rs
+++ b/library/std/src/sys/pal/wasi/stdio.rs
@@ -1,4 +1,4 @@
-#![deny(unsafe_op_in_unsafe_fn)]
+#![forbid(unsafe_op_in_unsafe_fn)]
 
 use super::fd::WasiFd;
 use crate::io::{self, IoSlice, IoSliceMut};
diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs
index c37acd8dfee..31c9cbd4699 100644
--- a/library/std/src/sys/pal/wasi/thread.rs
+++ b/library/std/src/sys/pal/wasi/thread.rs
@@ -1,3 +1,5 @@
+#![forbid(unsafe_op_in_unsafe_fn)]
+
 use crate::ffi::CStr;
 use crate::num::NonZero;
 use crate::sys::unsupported;
@@ -73,13 +75,13 @@ impl Thread {
         if #[cfg(target_feature = "atomics")] {
             pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
                 let p = Box::into_raw(Box::new(p));
-                let mut native: libc::pthread_t = mem::zeroed();
-                let mut attr: libc::pthread_attr_t = mem::zeroed();
-                assert_eq!(libc::pthread_attr_init(&mut attr), 0);
+                let mut native: libc::pthread_t = unsafe { mem::zeroed() };
+                let mut attr: libc::pthread_attr_t = unsafe { mem::zeroed() };
+                assert_eq!(unsafe { libc::pthread_attr_init(&mut attr) }, 0);
 
                 let stack_size = cmp::max(stack, DEFAULT_MIN_STACK_SIZE);
 
-                match libc::pthread_attr_setstacksize(&mut attr, stack_size) {
+                match unsafe { libc::pthread_attr_setstacksize(&mut attr, stack_size) } {
                     0 => {}
                     n => {
                         assert_eq!(n, libc::EINVAL);
@@ -90,20 +92,20 @@ impl Thread {
                         let page_size = os::page_size();
                         let stack_size =
                             (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1);
-                        assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0);
+                        assert_eq!(unsafe { libc::pthread_attr_setstacksize(&mut attr, stack_size) }, 0);
                     }
                 };
 
-                let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _);
+                let ret = unsafe { libc::pthread_create(&mut native, &attr, thread_start, p as *mut _) };
                 // Note: if the thread creation fails and this assert fails, then p will
                 // be leaked. However, an alternative design could cause double-free
                 // which is clearly worse.
-                assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
+                assert_eq!(unsafe {libc::pthread_attr_destroy(&mut attr) }, 0);
 
                 return if ret != 0 {
                     // The thread failed to start and as a result p was not consumed. Therefore, it is
                     // safe to reconstruct the box so that it gets deallocated.
-                    drop(Box::from_raw(p));
+                    unsafe { drop(Box::from_raw(p)); }
                     Err(io::Error::from_raw_os_error(ret))
                 } else {
                     Ok(Thread { id: native })
diff --git a/library/std/src/sys/pal/wasi/time.rs b/library/std/src/sys/pal/wasi/time.rs
index 016b06efbdc..0d8d0b59ac1 100644
--- a/library/std/src/sys/pal/wasi/time.rs
+++ b/library/std/src/sys/pal/wasi/time.rs
@@ -1,4 +1,4 @@
-#![deny(unsafe_op_in_unsafe_fn)]
+#![forbid(unsafe_op_in_unsafe_fn)]
 
 use crate::time::Duration;
 
diff --git a/library/stdarch b/library/stdarch
-Subproject 47b929ddc521a78b0f699ba8d5c274d28593448
+Subproject d9466edb4c53cece8686ee6e17b028436ddf415
diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs
index f608e5d715e..bcbe490c36a 100644
--- a/src/bootstrap/src/core/build_steps/clean.rs
+++ b/src/bootstrap/src/core/build_steps/clean.rs
@@ -6,7 +6,6 @@
 //! directory unless the `--all` flag is present.
 
 use std::fs;
-use std::io::{self, ErrorKind};
 use std::path::Path;
 
 use crate::core::builder::{crate_description, Builder, RunConfig, ShouldRun, Step};
@@ -101,11 +100,11 @@ fn clean(build: &Build, all: bool, stage: Option<u32>) {
         return;
     }
 
-    rm_rf("tmp".as_ref());
+    remove_dir_recursive("tmp");
 
     // Clean the entire build directory
     if all {
-        rm_rf(&build.out);
+        remove_dir_recursive(&build.out);
         return;
     }
 
@@ -136,17 +135,17 @@ fn clean_specific_stage(build: &Build, stage: u32) {
             }
 
             let path = t!(entry.path().canonicalize());
-            rm_rf(&path);
+            remove_dir_recursive(&path);
         }
     }
 }
 
 fn clean_default(build: &Build) {
-    rm_rf(&build.out.join("tmp"));
-    rm_rf(&build.out.join("dist"));
-    rm_rf(&build.out.join("bootstrap").join(".last-warned-change-id"));
-    rm_rf(&build.out.join("bootstrap-shims-dump"));
-    rm_rf(&build.out.join("rustfmt.stamp"));
+    remove_dir_recursive(build.out.join("tmp"));
+    remove_dir_recursive(build.out.join("dist"));
+    remove_dir_recursive(build.out.join("bootstrap").join(".last-warned-change-id"));
+    remove_dir_recursive(build.out.join("bootstrap-shims-dump"));
+    remove_dir_recursive(build.out.join("rustfmt.stamp"));
 
     let mut hosts: Vec<_> = build.hosts.iter().map(|t| build.out.join(t)).collect();
     // After cross-compilation, artifacts of the host architecture (which may differ from build.host)
@@ -166,78 +165,16 @@ fn clean_default(build: &Build) {
                 continue;
             }
             let path = t!(entry.path().canonicalize());
-            rm_rf(&path);
+            remove_dir_recursive(&path);
         }
     }
 }
 
-fn rm_rf(path: &Path) {
-    match path.symlink_metadata() {
-        Err(e) => {
-            if e.kind() == ErrorKind::NotFound {
-                return;
-            }
-            panic!("failed to get metadata for file {}: {}", path.display(), e);
-        }
-        Ok(metadata) => {
-            if metadata.file_type().is_file() || metadata.file_type().is_symlink() {
-                do_op(path, "remove file", |p| match fs::remove_file(p) {
-                    #[cfg(windows)]
-                    Err(e)
-                        if e.kind() == std::io::ErrorKind::PermissionDenied
-                            && p.file_name().and_then(std::ffi::OsStr::to_str)
-                                == Some("bootstrap.exe") =>
-                    {
-                        eprintln!("WARNING: failed to delete '{}'.", p.display());
-                        Ok(())
-                    }
-                    r => r,
-                });
-
-                return;
-            }
-
-            for file in t!(fs::read_dir(path)) {
-                rm_rf(&t!(file).path());
-            }
-
-            do_op(path, "remove dir", |p| match fs::remove_dir(p) {
-                // Check for dir not empty on Windows
-                // FIXME: Once `ErrorKind::DirectoryNotEmpty` is stabilized,
-                // match on `e.kind()` instead.
-                #[cfg(windows)]
-                Err(e) if e.raw_os_error() == Some(145) => Ok(()),
-                r => r,
-            });
-        }
-    };
-}
-
-fn do_op<F>(path: &Path, desc: &str, mut f: F)
-where
-    F: FnMut(&Path) -> io::Result<()>,
-{
-    match f(path) {
-        Ok(()) => {}
-        // On windows we can't remove a readonly file, and git will often clone files as readonly.
-        // As a result, we have some special logic to remove readonly files on windows.
-        // This is also the reason that we can't use things like fs::remove_dir_all().
-        #[cfg(windows)]
-        Err(ref e) if e.kind() == ErrorKind::PermissionDenied => {
-            let m = t!(path.symlink_metadata());
-            let mut p = m.permissions();
-            p.set_readonly(false);
-            t!(fs::set_permissions(path, p));
-            f(path).unwrap_or_else(|e| {
-                // Delete symlinked directories on Windows
-                if m.file_type().is_symlink() && path.is_dir() && fs::remove_dir(path).is_ok() {
-                    return;
-                }
-                panic!("failed to {} {}: {}", desc, path.display(), e);
-            });
-        }
-        Err(e) => {
-            panic!("failed to {} {}: {}", desc, path.display(), e);
-        }
+/// Wrapper for [`std::fs::remove_dir_all`] that panics on failure and prints the `path` we failed
+/// on.
+fn remove_dir_recursive<P: AsRef<Path>>(path: P) {
+    let path = path.as_ref();
+    if let Err(e) = fs::remove_dir_all(path) {
+        panic!("failed to `remove_dir_all` at `{}`: {e}", path.display());
     }
 }
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index c5a1ab78801..e1eea31b3bb 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -110,7 +110,7 @@ pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> L
 
     // Initialize the llvm submodule if not initialized already.
     // If submodules are disabled, this does nothing.
-    builder.update_submodule("src/llvm-project");
+    builder.config.update_submodule("src/llvm-project");
 
     let root = "src/llvm-project/llvm";
     let out_dir = builder.llvm_out(target);
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index bdd9fd755aa..ce23b7735f8 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -14,7 +14,7 @@ use std::sync::OnceLock;
 use std::{cmp, env, fs};
 
 use build_helper::exit;
-use build_helper::git::GitConfig;
+use build_helper::git::{output_result, GitConfig};
 use serde::{Deserialize, Deserializer};
 use serde_derive::Deserialize;
 
@@ -2509,6 +2509,123 @@ impl Config {
         }
     }
 
+    /// Given a path to the directory of a submodule, update it.
+    ///
+    /// `relative_path` should be relative to the root of the git repository, not an absolute path.
+    ///
+    /// This *does not* update the submodule if `config.toml` explicitly says
+    /// not to, or if we're not in a git repository (like a plain source
+    /// tarball). Typically [`crate::Build::require_submodule`] should be
+    /// used instead to provide a nice error to the user if the submodule is
+    /// missing.
+    pub(crate) fn update_submodule(&self, relative_path: &str) {
+        if !self.submodules() {
+            return;
+        }
+
+        let absolute_path = self.src.join(relative_path);
+
+        // NOTE: The check for the empty directory is here because when running x.py the first time,
+        // the submodule won't be checked out. Check it out now so we can build it.
+        if !GitInfo::new(false, &absolute_path).is_managed_git_subrepository()
+            && !helpers::dir_is_empty(&absolute_path)
+        {
+            return;
+        }
+
+        // Submodule updating actually happens during in the dry run mode. We need to make sure that
+        // all the git commands below are actually executed, because some follow-up code
+        // in bootstrap might depend on the submodules being checked out. Furthermore, not all
+        // the command executions below work with an empty output (produced during dry run).
+        // Therefore, all commands below are marked with `run_always()`, so that they also run in
+        // dry run mode.
+        let submodule_git = || {
+            let mut cmd = helpers::git(Some(&absolute_path));
+            cmd.run_always();
+            cmd
+        };
+
+        // Determine commit checked out in submodule.
+        let checked_out_hash = output(submodule_git().args(["rev-parse", "HEAD"]).as_command_mut());
+        let checked_out_hash = checked_out_hash.trim_end();
+        // Determine commit that the submodule *should* have.
+        let recorded = output(
+            helpers::git(Some(&self.src))
+                .run_always()
+                .args(["ls-tree", "HEAD"])
+                .arg(relative_path)
+                .as_command_mut(),
+        );
+
+        let actual_hash = recorded
+            .split_whitespace()
+            .nth(2)
+            .unwrap_or_else(|| panic!("unexpected output `{}`", recorded));
+
+        if actual_hash == checked_out_hash {
+            // already checked out
+            return;
+        }
+
+        println!("Updating submodule {relative_path}");
+        self.check_run(
+            helpers::git(Some(&self.src))
+                .run_always()
+                .args(["submodule", "-q", "sync"])
+                .arg(relative_path),
+        );
+
+        // Try passing `--progress` to start, then run git again without if that fails.
+        let update = |progress: bool| {
+            // Git is buggy and will try to fetch submodules from the tracking branch for *this* repository,
+            // even though that has no relation to the upstream for the submodule.
+            let current_branch = output_result(
+                helpers::git(Some(&self.src))
+                    .allow_failure()
+                    .run_always()
+                    .args(["symbolic-ref", "--short", "HEAD"])
+                    .as_command_mut(),
+            )
+            .map(|b| b.trim().to_owned());
+
+            let mut git = helpers::git(Some(&self.src)).allow_failure();
+            git.run_always();
+            if let Ok(branch) = current_branch {
+                // If there is a tag named after the current branch, git will try to disambiguate by prepending `heads/` to the branch name.
+                // This syntax isn't accepted by `branch.{branch}`. Strip it.
+                let branch = branch.strip_prefix("heads/").unwrap_or(&branch);
+                git.arg("-c").arg(format!("branch.{branch}.remote=origin"));
+            }
+            git.args(["submodule", "update", "--init", "--recursive", "--depth=1"]);
+            if progress {
+                git.arg("--progress");
+            }
+            git.arg(relative_path);
+            git
+        };
+        if !self.check_run(&mut update(true)) {
+            self.check_run(&mut update(false));
+        }
+
+        // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error).
+        // diff-index reports the modifications through the exit status
+        let has_local_modifications = !self.check_run(submodule_git().allow_failure().args([
+            "diff-index",
+            "--quiet",
+            "HEAD",
+        ]));
+        if has_local_modifications {
+            self.check_run(submodule_git().args(["stash", "push"]));
+        }
+
+        self.check_run(submodule_git().args(["reset", "-q", "--hard"]));
+        self.check_run(submodule_git().args(["clean", "-qdfx"]));
+
+        if has_local_modifications {
+            self.check_run(submodule_git().args(["stash", "pop"]));
+        }
+    }
+
     #[cfg(feature = "bootstrap-self-test")]
     pub fn check_stage0_version(&self, _program_path: &Path, _component_name: &'static str) {}
 
@@ -2613,19 +2730,23 @@ impl Config {
         asserts: bool,
     ) -> bool {
         let if_unchanged = || {
-            // Git is needed to track modifications here, but tarball source is not available.
-            // If not modified here or built through tarball source, we maintain consistency
-            // with '"if available"'.
-            if !self.rust_info.is_from_tarball()
-                && self
-                    .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true)
-                    .is_none()
-            {
-                // there are some untracked changes in the given paths.
-                false
-            } else {
-                llvm::is_ci_llvm_available(self, asserts)
+            if self.rust_info.is_from_tarball() {
+                // Git is needed for running "if-unchanged" logic.
+                println!(
+                    "WARNING: 'if-unchanged' has no effect on tarball sources; ignoring `download-ci-llvm`."
+                );
+                return false;
             }
+
+            self.update_submodule("src/llvm-project");
+
+            // Check for untracked changes in `src/llvm-project`.
+            let has_changes = self
+                .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true)
+                .is_none();
+
+            // Return false if there are untracked changes, otherwise check if CI LLVM is available.
+            if has_changes { false } else { llvm::is_ci_llvm_available(self, asserts) }
         };
 
         match download_ci_llvm {
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index dd0309733ae..c225cc30146 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -56,7 +56,7 @@ impl Config {
     /// Returns false if do not execute at all, otherwise returns its
     /// `status.success()`.
     pub(crate) fn check_run(&self, cmd: &mut BootstrapCommand) -> bool {
-        if self.dry_run() {
+        if self.dry_run() && !cmd.run_always {
             return true;
         }
         self.verbose(|| println!("running: {cmd:?}"));
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 784519a20a2..268392c5fb1 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -473,117 +473,6 @@ impl Build {
         build
     }
 
-    /// Given a path to the directory of a submodule, update it.
-    ///
-    /// `relative_path` should be relative to the root of the git repository, not an absolute path.
-    ///
-    /// This *does not* update the submodule if `config.toml` explicitly says
-    /// not to, or if we're not in a git repository (like a plain source
-    /// tarball). Typically [`Build::require_submodule`] should be
-    /// used instead to provide a nice error to the user if the submodule is
-    /// missing.
-    fn update_submodule(&self, relative_path: &str) {
-        if !self.config.submodules() {
-            return;
-        }
-
-        let absolute_path = self.config.src.join(relative_path);
-
-        // NOTE: The check for the empty directory is here because when running x.py the first time,
-        // the submodule won't be checked out. Check it out now so we can build it.
-        if !GitInfo::new(false, &absolute_path).is_managed_git_subrepository()
-            && !dir_is_empty(&absolute_path)
-        {
-            return;
-        }
-
-        // Submodule updating actually happens during in the dry run mode. We need to make sure that
-        // all the git commands below are actually executed, because some follow-up code
-        // in bootstrap might depend on the submodules being checked out. Furthermore, not all
-        // the command executions below work with an empty output (produced during dry run).
-        // Therefore, all commands below are marked with `run_always()`, so that they also run in
-        // dry run mode.
-        let submodule_git = || {
-            let mut cmd = helpers::git(Some(&absolute_path));
-            cmd.run_always();
-            cmd
-        };
-
-        // Determine commit checked out in submodule.
-        let checked_out_hash =
-            submodule_git().args(["rev-parse", "HEAD"]).run_capture_stdout(self).stdout();
-        let checked_out_hash = checked_out_hash.trim_end();
-        // Determine commit that the submodule *should* have.
-        let recorded = helpers::git(Some(&self.src))
-            .run_always()
-            .args(["ls-tree", "HEAD"])
-            .arg(relative_path)
-            .run_capture_stdout(self)
-            .stdout();
-        let actual_hash = recorded
-            .split_whitespace()
-            .nth(2)
-            .unwrap_or_else(|| panic!("unexpected output `{}`", recorded));
-
-        if actual_hash == checked_out_hash {
-            // already checked out
-            return;
-        }
-
-        println!("Updating submodule {relative_path}");
-        helpers::git(Some(&self.src))
-            .run_always()
-            .args(["submodule", "-q", "sync"])
-            .arg(relative_path)
-            .run(self);
-
-        // Try passing `--progress` to start, then run git again without if that fails.
-        let update = |progress: bool| {
-            // Git is buggy and will try to fetch submodules from the tracking branch for *this* repository,
-            // even though that has no relation to the upstream for the submodule.
-            let current_branch = helpers::git(Some(&self.src))
-                .allow_failure()
-                .run_always()
-                .args(["symbolic-ref", "--short", "HEAD"])
-                .run_capture_stdout(self)
-                .stdout_if_ok()
-                .map(|s| s.trim().to_owned());
-
-            let mut git = helpers::git(Some(&self.src)).allow_failure();
-            git.run_always();
-            if let Some(branch) = current_branch {
-                // If there is a tag named after the current branch, git will try to disambiguate by prepending `heads/` to the branch name.
-                // This syntax isn't accepted by `branch.{branch}`. Strip it.
-                let branch = branch.strip_prefix("heads/").unwrap_or(&branch);
-                git.arg("-c").arg(format!("branch.{branch}.remote=origin"));
-            }
-            git.args(["submodule", "update", "--init", "--recursive", "--depth=1"]);
-            if progress {
-                git.arg("--progress");
-            }
-            git.arg(relative_path);
-            git
-        };
-        if !update(true).run(self) {
-            update(false).run(self);
-        }
-
-        // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error).
-        // diff-index reports the modifications through the exit status
-        let has_local_modifications =
-            !submodule_git().allow_failure().args(["diff-index", "--quiet", "HEAD"]).run(self);
-        if has_local_modifications {
-            submodule_git().args(["stash", "push"]).run(self);
-        }
-
-        submodule_git().args(["reset", "-q", "--hard"]).run(self);
-        submodule_git().args(["clean", "-qdfx"]).run(self);
-
-        if has_local_modifications {
-            submodule_git().args(["stash", "pop"]).run(self);
-        }
-    }
-
     /// Updates a submodule, and exits with a failure if submodule management
     /// is disabled and the submodule does not exist.
     ///
@@ -598,7 +487,7 @@ impl Build {
         if cfg!(test) && !self.config.submodules() {
             return;
         }
-        self.update_submodule(submodule);
+        self.config.update_submodule(submodule);
         let absolute_path = self.config.src.join(submodule);
         if dir_is_empty(&absolute_path) {
             let maybe_enable = if !self.config.submodules()
@@ -646,7 +535,7 @@ impl Build {
             let path = Path::new(submodule);
             // Don't update the submodule unless it's already been cloned.
             if GitInfo::new(false, path).is_managed_git_subrepository() {
-                self.update_submodule(submodule);
+                self.config.update_submodule(submodule);
             }
         }
     }
@@ -659,7 +548,7 @@ impl Build {
         }
 
         if GitInfo::new(false, Path::new(submodule)).is_managed_git_subrepository() {
-            self.update_submodule(submodule);
+            self.config.update_submodule(submodule);
         }
     }
 
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index ff5c16f2b3e..63d71a73cdf 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -12,7 +12,7 @@ use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel, StableS
 use rustc_const_eval::const_eval::is_unstable_const_fn;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{BodyId, Mutability};
 use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety;
@@ -89,6 +89,11 @@ impl ItemId {
     }
 
     #[inline]
+    pub(crate) fn as_local_def_id(self) -> Option<LocalDefId> {
+        self.as_def_id().and_then(|id| id.as_local())
+    }
+
+    #[inline]
     pub(crate) fn krate(self) -> CrateNum {
         match self {
             ItemId::Auto { for_: id, .. }
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index abd66f15dc0..5c0898f28fc 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -136,7 +136,7 @@ impl<'a, 'tcx> HirCollector<'a, 'tcx> {
                 self.enable_per_target_ignores,
                 Some(&crate::html::markdown::ExtraInfo::new(
                     self.tcx,
-                    def_id.to_def_id(),
+                    def_id,
                     span_of_fragments(&attrs.doc_strings).unwrap_or(sp),
                 )),
             );
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 7bfe5d87d39..364d4e077b1 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -40,7 +40,7 @@ use pulldown_cmark::{
 };
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Diag, DiagMessage};
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::TyCtxt;
 pub(crate) use rustc_resolve::rustdoc::main_body_opts;
 use rustc_resolve::rustdoc::may_be_doc_link;
@@ -818,27 +818,25 @@ pub(crate) fn find_codes<T: doctest::DocTestVisitor>(
 }
 
 pub(crate) struct ExtraInfo<'tcx> {
-    def_id: DefId,
+    def_id: LocalDefId,
     sp: Span,
     tcx: TyCtxt<'tcx>,
 }
 
 impl<'tcx> ExtraInfo<'tcx> {
-    pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: DefId, sp: Span) -> ExtraInfo<'tcx> {
+    pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId, sp: Span) -> ExtraInfo<'tcx> {
         ExtraInfo { def_id, sp, tcx }
     }
 
     fn error_invalid_codeblock_attr(&self, msg: impl Into<DiagMessage>) {
-        if let Some(def_id) = self.def_id.as_local() {
-            self.tcx.node_span_lint(
-                crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
-                self.tcx.local_def_id_to_hir_id(def_id),
-                self.sp,
-                |lint| {
-                    lint.primary_message(msg);
-                },
-            );
-        }
+        self.tcx.node_span_lint(
+            crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
+            self.tcx.local_def_id_to_hir_id(self.def_id),
+            self.sp,
+            |lint| {
+                lint.primary_message(msg);
+            },
+        );
     }
 
     fn error_invalid_codeblock_attr_with_help(
@@ -846,17 +844,15 @@ impl<'tcx> ExtraInfo<'tcx> {
         msg: impl Into<DiagMessage>,
         f: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
     ) {
-        if let Some(def_id) = self.def_id.as_local() {
-            self.tcx.node_span_lint(
-                crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
-                self.tcx.local_def_id_to_hir_id(def_id),
-                self.sp,
-                |lint| {
-                    lint.primary_message(msg);
-                    f(lint);
-                },
-            );
-        }
+        self.tcx.node_span_lint(
+            crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
+            self.tcx.local_def_id_to_hir_id(self.def_id),
+            self.sp,
+            |lint| {
+                lint.primary_message(msg);
+                f(lint);
+            },
+        );
     }
 }
 
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index eb5a5d935e2..28df8d3f011 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1547,10 +1547,23 @@ instead, we check that it's not a "finger" cursor.
 	margin-left: 24px;
 }
 
+@keyframes targetfadein {
+	from {
+		background-color: var(--main-background-color);
+	}
+	10% {
+		background-color: var(--target-border-color);
+	}
+	to {
+		background-color: var(--target-background-color);
+	}
+}
+
 :target {
 	padding-right: 3px;
 	background-color: var(--target-background-color);
 	border-right: 3px solid var(--target-border-color);
+	animation: 0.65s cubic-bezier(0, 0, 0.1, 1.0) 0.1s targetfadein;
 }
 
 .code-header a.tooltip {
diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs
index ef05befdddc..977c0953336 100644
--- a/src/librustdoc/passes/lint/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs
@@ -16,9 +16,11 @@ use crate::core::DocContext;
 use crate::html::markdown::{self, RustCodeBlock};
 
 pub(crate) fn visit_item(cx: &DocContext<'_>, item: &clean::Item) {
-    if let Some(dox) = &item.opt_doc_value() {
+    if let Some(def_id) = item.item_id.as_local_def_id()
+        && let Some(dox) = &item.opt_doc_value()
+    {
         let sp = item.attr_span(cx.tcx);
-        let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, item.item_id.expect_def_id(), sp);
+        let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, def_id, sp);
         for code_block in markdown::rust_code_blocks(dox, &extra) {
             check_rust_syntax(cx, item, dox, code_block);
         }
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index eca21e55989..6d45040345a 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -3265,7 +3265,7 @@ impl<'test> TestCx<'test> {
 
         let tmpdir = cwd.join(self.output_base_name());
         if tmpdir.exists() {
-            self.aggressive_rm_rf(&tmpdir).unwrap();
+            fs::remove_dir_all(&tmpdir).unwrap();
         }
         create_dir_all(&tmpdir).unwrap();
 
@@ -3404,29 +3404,6 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    fn aggressive_rm_rf(&self, path: &Path) -> io::Result<()> {
-        for e in path.read_dir()? {
-            let entry = e?;
-            let path = entry.path();
-            if entry.file_type()?.is_dir() {
-                self.aggressive_rm_rf(&path)?;
-            } else {
-                // Remove readonly files as well on windows (by default we can't)
-                fs::remove_file(&path).or_else(|e| {
-                    if cfg!(windows) && e.kind() == io::ErrorKind::PermissionDenied {
-                        let mut meta = entry.metadata()?.permissions();
-                        meta.set_readonly(false);
-                        fs::set_permissions(&path, meta)?;
-                        fs::remove_file(&path)
-                    } else {
-                        Err(e)
-                    }
-                })?;
-            }
-        }
-        fs::remove_dir(path)
-    }
-
     fn run_rmake_v2_test(&self) {
         // For `run-make` V2, we need to perform 2 steps to build and run a `run-make` V2 recipe
         // (`rmake.rs`) to run the actual tests. The support library is already built as a tool rust
@@ -3475,7 +3452,7 @@ impl<'test> TestCx<'test> {
         // This setup intentionally diverges from legacy Makefile run-make tests.
         let base_dir = self.output_base_name();
         if base_dir.exists() {
-            self.aggressive_rm_rf(&base_dir).unwrap();
+            fs::remove_dir_all(&base_dir).unwrap();
         }
         let rmake_out_dir = base_dir.join("rmake_out");
         create_dir_all(&rmake_out_dir).unwrap();
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index e0aef13ca79..72bb9db7e74 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -444,6 +444,7 @@ impl<'a> LintExtractor<'a> {
         let mut cmd = Command::new(self.rustc_path);
         if options.contains(&"edition2024") {
             cmd.arg("--edition=2024");
+            cmd.arg("-Zunstable-options");
         } else if options.contains(&"edition2021") {
             cmd.arg("--edition=2021");
         } else if options.contains(&"edition2018") {
diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs
index 12088e5d3b5..3eeba6fd526 100644
--- a/src/tools/run-make-support/src/run.rs
+++ b/src/tools/run-make-support/src/run.rs
@@ -29,6 +29,7 @@ fn run_common(name: &str, args: Option<&[&str]>) -> Command {
         }
         env::join_paths(paths.iter()).unwrap()
     });
+    cmd.env("LC_ALL", "C"); // force english locale
 
     if is_windows() {
         let mut paths = vec![];
@@ -84,5 +85,6 @@ pub fn run_fail(name: &str) -> CompletedProcess {
 pub fn cmd<S: AsRef<OsStr>>(program: S) -> Command {
     let mut command = Command::new(program);
     set_host_rpath(&mut command);
+    command.env("LC_ALL", "C"); // force english locale
     command
 }
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 57310977704..5205fa14294 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -1289,8 +1289,7 @@ ui/imports/auxiliary/issue-52891.rs
 ui/imports/auxiliary/issue-55811.rs
 ui/imports/auxiliary/issue-56125.rs
 ui/imports/auxiliary/issue-59764.rs
-ui/imports/auxiliary/issue-85992-extern-1.rs
-ui/imports/auxiliary/issue-85992-extern-2.rs
+ui/imports/auxiliary/issue-85992-extern.rs
 ui/imports/issue-109148.rs
 ui/imports/issue-109343.rs
 ui/imports/issue-113953.rs
diff --git a/tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs b/tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs
new file mode 100644
index 00000000000..a54a6d84a80
--- /dev/null
+++ b/tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs
@@ -0,0 +1,10 @@
+// Verifies that "cfi-normalize-integers" module flag is added.
+//
+//@ needs-sanitizer-cfi
+//@ compile-flags: -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers
+
+#![crate_type = "lib"]
+
+pub fn foo() {}
+
+// CHECK: !{{[0-9]+}} = !{i32 4, !"cfi-normalize-integers", i32 1}
diff --git a/tests/codegen/sanitizer/kcfi/add-cfi-normalize-integers-flag.rs b/tests/codegen/sanitizer/kcfi/add-cfi-normalize-integers-flag.rs
new file mode 100644
index 00000000000..d48e4016a16
--- /dev/null
+++ b/tests/codegen/sanitizer/kcfi/add-cfi-normalize-integers-flag.rs
@@ -0,0 +1,21 @@
+// Verifies that "cfi-normalize-integers" module flag is added.
+//
+//@ revisions: aarch64 x86_64
+//@ [aarch64] compile-flags: --target aarch64-unknown-none
+//@ [aarch64] needs-llvm-components: aarch64
+//@ [x86_64] compile-flags: --target x86_64-unknown-none
+//@ [x86_64] needs-llvm-components: x86
+//@ compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers
+
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+pub fn foo() {}
+
+// CHECK: !{{[0-9]+}} = !{i32 4, !"cfi-normalize-integers", i32 1}
diff --git a/tests/codegen/sanitizer/kcfi/add-kcfi-offset-flag.rs b/tests/codegen/sanitizer/kcfi/add-kcfi-offset-flag.rs
new file mode 100644
index 00000000000..b4924719f4c
--- /dev/null
+++ b/tests/codegen/sanitizer/kcfi/add-kcfi-offset-flag.rs
@@ -0,0 +1,21 @@
+// Verifies that "kcfi-offset" module flag is added.
+//
+//@ revisions: aarch64 x86_64
+//@ [aarch64] compile-flags: --target aarch64-unknown-none
+//@ [aarch64] needs-llvm-components: aarch64
+//@ [x86_64] compile-flags: --target x86_64-unknown-none
+//@ [x86_64] needs-llvm-components: x86
+//@ compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi -Z patchable-function-entry=4,3
+
+#![feature(no_core, lang_items, patchable_function_entry)]
+#![crate_type = "lib"]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+pub fn foo() {}
+
+// CHECK: !{{[0-9]+}} = !{i32 4, !"kcfi-offset", i32 3}
diff --git a/tests/debuginfo/dummy_span.rs b/tests/debuginfo/dummy_span.rs
new file mode 100644
index 00000000000..d02eead470f
--- /dev/null
+++ b/tests/debuginfo/dummy_span.rs
@@ -0,0 +1,45 @@
+//@ min-lldb-version: 310
+
+//@ compile-flags:-g
+
+// === GDB TESTS ===================================================================================
+
+// gdb-command:run 7
+
+// gdb-command:next
+// gdb-command:next
+// gdb-check:[...]#loc1[...]
+// gdb-command:next
+// gdb-check:[...]#loc2[...]
+
+// === LLDB TESTS ==================================================================================
+
+// lldb-command:run 7
+
+// lldb-command:next
+// lldb-command:next
+// lldb-command:frame select
+// lldb-check:[...]#loc1[...]
+// lldb-command:next
+// lldb-command:frame select
+// lldb-check:[...]#loc2[...]
+
+use std::env;
+use std::num::ParseIntError;
+
+fn main() -> Result<(), ParseIntError> {
+    let args = env::args();
+    let number_str = args.skip(1).next().unwrap();
+    let number = number_str.parse::<i32>()?;
+    zzz(); // #break
+    if number % 7 == 0 {
+        // This generates code with a dummy span for
+        // some reason. If that ever changes this
+        // test will not test what it wants to test.
+        return Ok(()); // #loc1
+    }
+    println!("{}", number);
+    Ok(())
+} // #loc2
+
+fn zzz() { () }
diff --git a/tests/incremental/decl_macro.rs b/tests/incremental/decl_macro.rs
new file mode 100644
index 00000000000..74810ae4227
--- /dev/null
+++ b/tests/incremental/decl_macro.rs
@@ -0,0 +1,34 @@
+//@ revisions: rpass1 rpass2
+
+// issue#112680
+
+#![feature(decl_macro)]
+
+pub trait T {
+    type Key;
+    fn index_from_key(key: Self::Key) -> usize;
+}
+
+pub macro m($key_ty:ident, $val_ty:ident) {
+    struct $key_ty {
+        inner: usize,
+    }
+
+    impl T for $val_ty {
+        type Key = $key_ty;
+
+        fn index_from_key(key: Self::Key) -> usize {
+            key.inner
+        }
+    }
+}
+
+m!(TestId, Test);
+
+#[cfg(rpass1)]
+struct Test(u32);
+
+#[cfg(rpass2)]
+struct Test;
+
+fn main() {}
diff --git a/tests/run-make/debugger-visualizer-dep-info/foo.py b/tests/run-make/debugger-visualizer-dep-info/foo.py
deleted file mode 100644
index 1bb8bf6d7fd..00000000000
--- a/tests/run-make/debugger-visualizer-dep-info/foo.py
+++ /dev/null
@@ -1 +0,0 @@
-# empty
diff --git a/tests/run-make/debugger-visualizer-dep-info/main.rs b/tests/run-make/debugger-visualizer-dep-info/main.rs
index 3aede2215ea..3539b305be3 100644
--- a/tests/run-make/debugger-visualizer-dep-info/main.rs
+++ b/tests/run-make/debugger-visualizer-dep-info/main.rs
@@ -1,4 +1,4 @@
-#![debugger_visualizer(gdb_script_file = "foo.py")]
+#![debugger_visualizer(gdb_script_file = "my_gdb_script.py")]
 
 fn main() {
     const _UNUSED: u32 = {
diff --git a/tests/run-make/debugger-visualizer-dep-info/my_gdb_script.py b/tests/run-make/debugger-visualizer-dep-info/my_gdb_script.py
new file mode 100644
index 00000000000..d319792657e
--- /dev/null
+++ b/tests/run-make/debugger-visualizer-dep-info/my_gdb_script.py
@@ -0,0 +1,6 @@
+# This is a Python script, but we don't actually run it.
+# So if you're trying to remove Python scripts from the test suite,
+# be aware that there's no value in trying to get rid of this one.
+#
+# It just needs to exist so that the compiler can embed it via
+# `#![debugger_visualizer(gdb_script_file = "...")]`.
diff --git a/tests/run-make/debugger-visualizer-dep-info/rmake.rs b/tests/run-make/debugger-visualizer-dep-info/rmake.rs
index 65ffb2373e7..f5cf39157ac 100644
--- a/tests/run-make/debugger-visualizer-dep-info/rmake.rs
+++ b/tests/run-make/debugger-visualizer-dep-info/rmake.rs
@@ -6,6 +6,6 @@ use run_make_support::{invalid_utf8_contains, rustc};
 
 fn main() {
     rustc().emit("dep-info").input("main.rs").run();
-    invalid_utf8_contains("main.d", "foo.py");
+    invalid_utf8_contains("main.d", "my_gdb_script.py");
     invalid_utf8_contains("main.d", "my_visualizers/bar.natvis");
 }
diff --git a/tests/run-make/libtest-junit/validate_junit.py b/tests/run-make/libtest-junit/validate_junit.py
index 0d9b34a3cf7..f92473751b0 100755
--- a/tests/run-make/libtest-junit/validate_junit.py
+++ b/tests/run-make/libtest-junit/validate_junit.py
@@ -1,5 +1,15 @@
 #!/usr/bin/env python
 
+# Trivial Python script that reads lines from stdin, and checks that each line
+# is a well-formed XML document.
+#
+# This takes advantage of the fact that Python has a built-in XML parser,
+# whereas doing the same check in Rust would require us to pull in an XML
+# crate just for this relatively-minor test.
+#
+# If you're trying to remove Python scripts from the test suite, think twice
+# before removing this one. You could do so, but it's probably not worth it.
+
 import sys
 import xml.etree.ElementTree as ET
 
diff --git a/tests/rustdoc-gui/target.goml b/tests/rustdoc-gui/target.goml
index 82bd34ed274..92846f8e01d 100644
--- a/tests/rustdoc-gui/target.goml
+++ b/tests/rustdoc-gui/target.goml
@@ -11,7 +11,7 @@ define-function: (
     [theme, background, border],
     block {
         call-function: ("switch-theme", {"theme": |theme|})
-        assert-css: ("#method\.a_method:target", {
+        wait-for-css: ("#method\.a_method:target", {
             "background-color": |background|,
             "border-right": "3px solid " + |border|,
         })
diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs
index 5fcff74064a..442f9d72c3f 100644
--- a/tests/ui-fulldeps/internal-lints/diagnostics.rs
+++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs
@@ -117,4 +117,11 @@ pub fn skipped_because_of_annotation<'a>(dcx: DiagCtxtHandle<'a>) {
 fn f(_x: impl Into<DiagMessage>, _y: impl Into<SubdiagMessage>) {}
 fn g() {
     f(crate::fluent_generated::no_crate_example, crate::fluent_generated::no_crate_example);
+    f("untranslatable diagnostic", crate::fluent_generated::no_crate_example);
+    //~^ ERROR diagnostics should be created using translatable messages
+    f(crate::fluent_generated::no_crate_example, "untranslatable diagnostic");
+    //~^ ERROR diagnostics should be created using translatable messages
+    f("untranslatable diagnostic", "untranslatable diagnostic");
+    //~^ ERROR diagnostics should be created using translatable messages
+    //~^^ ERROR diagnostics should be created using translatable messages
 }
diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr
index 669324ce5d4..36dd3cf4be7 100644
--- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr
+++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr
@@ -1,8 +1,8 @@
 error: diagnostics should be created using translatable messages
-  --> $DIR/diagnostics.rs:43:9
+  --> $DIR/diagnostics.rs:43:31
    |
 LL |         Diag::new(dcx, level, "untranslatable diagnostic")
-   |         ^^^^^^^^^
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/diagnostics.rs:7:9
@@ -11,16 +11,16 @@ LL | #![deny(rustc::untranslatable_diagnostic)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostics should be created using translatable messages
-  --> $DIR/diagnostics.rs:64:14
+  --> $DIR/diagnostics.rs:64:19
    |
 LL |         diag.note("untranslatable diagnostic");
-   |              ^^^^
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostics should be created using translatable messages
-  --> $DIR/diagnostics.rs:85:14
+  --> $DIR/diagnostics.rs:85:19
    |
 LL |         diag.note("untranslatable diagnostic");
-   |              ^^^^
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls
   --> $DIR/diagnostics.rs:99:21
@@ -41,10 +41,34 @@ LL |     let _diag = dcx.struct_err("untranslatable diagnostic");
    |                     ^^^^^^^^^^
 
 error: diagnostics should be created using translatable messages
-  --> $DIR/diagnostics.rs:102:21
+  --> $DIR/diagnostics.rs:102:32
    |
 LL |     let _diag = dcx.struct_err("untranslatable diagnostic");
-   |                     ^^^^^^^^^^
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: diagnostics should be created using translatable messages
+  --> $DIR/diagnostics.rs:120:7
+   |
+LL |     f("untranslatable diagnostic", crate::fluent_generated::no_crate_example);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: diagnostics should be created using translatable messages
+  --> $DIR/diagnostics.rs:122:50
+   |
+LL |     f(crate::fluent_generated::no_crate_example, "untranslatable diagnostic");
+   |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: diagnostics should be created using translatable messages
+  --> $DIR/diagnostics.rs:124:7
+   |
+LL |     f("untranslatable diagnostic", "untranslatable diagnostic");
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: diagnostics should be created using translatable messages
+  --> $DIR/diagnostics.rs:124:36
+   |
+LL |     f("untranslatable diagnostic", "untranslatable diagnostic");
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 10 previous errors
 
diff --git a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
index 54d8f26f4ea..5f0347bdb4d 100644
--- a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
+++ b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
@@ -30,9 +30,9 @@ note: the lifetime `'c` as defined here...
 LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
    |                        ^^
 note: ...does not necessarily outlive the lifetime `'c` as defined here
-  --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:12:24
    |
-LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+LL |     fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
    |                        ^^
 
 error[E0308]: method not compatible with trait
@@ -44,16 +44,15 @@ LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d
    = note: expected signature `fn(&'a _, Inv<'c>, Inv<'c>, Inv<'_>)`
               found signature `fn(&'a _, Inv<'_>, Inv<'c>, Inv<'_>)`
 note: the lifetime `'c` as defined here...
-  --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:12:24
    |
-LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+LL |     fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
    |                        ^^
 note: ...does not necessarily outlive the lifetime `'c` as defined here
   --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
    |
 LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
    |                        ^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not match the trait declaration
   --> $DIR/regions-bound-missing-bound-in-impl.rs:42:20
diff --git a/tests/ui/consts/packed_pattern.stderr b/tests/ui/consts/packed_pattern.stderr
index a0b434b2d78..dc26078fb63 100644
--- a/tests/ui/consts/packed_pattern.stderr
+++ b/tests/ui/consts/packed_pattern.stderr
@@ -2,9 +2,9 @@ warning: unreachable pattern
   --> $DIR/packed_pattern.rs:16:9
    |
 LL |         Foo { field: (5, 6, 7, 8) } => {},
-   |         --------------------------- matches all the values already
+   |         --------------------------- matches all the relevant values
 LL |         FOO => unreachable!(),
-   |         ^^^ unreachable pattern
+   |         ^^^ no value can reach this
    |
    = note: `#[warn(unreachable_patterns)]` on by default
 
diff --git a/tests/ui/consts/packed_pattern2.stderr b/tests/ui/consts/packed_pattern2.stderr
index 4785f4d0297..013f61f733c 100644
--- a/tests/ui/consts/packed_pattern2.stderr
+++ b/tests/ui/consts/packed_pattern2.stderr
@@ -2,9 +2,9 @@ warning: unreachable pattern
   --> $DIR/packed_pattern2.rs:24:9
    |
 LL |         Bar { a: Foo { field: (5, 6) } } => {},
-   |         -------------------------------- matches all the values already
+   |         -------------------------------- matches all the relevant values
 LL |         FOO => unreachable!(),
-   |         ^^^ unreachable pattern
+   |         ^^^ no value can reach this
    |
    = note: `#[warn(unreachable_patterns)]` on by default
 
diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr
index d4fc1717538..ec01225c6bf 100644
--- a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr
+++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr
@@ -48,10 +48,10 @@ LL |     const STATIC: &str = "";
    = note: expected reference `&'static _`
               found reference `&_`
 note: the anonymous lifetime as defined here...
-  --> $DIR/elided-lifetime.rs:15:18
+  --> $DIR/elided-lifetime.rs:16:19
    |
-LL | impl Bar for Foo<'_> {
-   |                  ^^
+LL |     const STATIC: &str = "";
+   |                   ^
    = note: ...does not necessarily outlive the static lifetime
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr
index 8e4c27875ab..b8e2f412b49 100644
--- a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr
+++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr
@@ -30,10 +30,10 @@ LL |     const STATIC: &str = "";
    = note: expected reference `&_`
               found reference `&_`
 note: the anonymous lifetime as defined here...
-  --> $DIR/static-trait-impl.rs:8:10
+  --> $DIR/static-trait-impl.rs:9:19
    |
-LL | impl Bar<'_> for A {
-   |          ^^
+LL |     const STATIC: &str = "";
+   |                   ^
 note: ...does not necessarily outlive the anonymous lifetime as defined here
   --> $DIR/static-trait-impl.rs:8:10
    |
diff --git a/tests/ui/drop/lint-tail-expr-drop-order-gated.rs b/tests/ui/drop/lint-tail-expr-drop-order-gated.rs
new file mode 100644
index 00000000000..b22e72bcfad
--- /dev/null
+++ b/tests/ui/drop/lint-tail-expr-drop-order-gated.rs
@@ -0,0 +1,35 @@
+// This test ensures that `tail_expr_drop_order` does not activate in case Edition 2024 is not used
+// or the feature gate `shorter_tail_lifetimes` is disabled.
+
+//@ revisions: neither no_feature_gate edition_less_than_2024
+//@ check-pass
+//@ [neither] edition: 2021
+//@ [no_feature_gate] compile-flags: -Z unstable-options
+//@ [no_feature_gate] edition: 2024
+//@ [edition_less_than_2024] edition: 2021
+
+#![deny(tail_expr_drop_order)]
+#![cfg_attr(edition_less_than_2024, feature(shorter_tail_lifetimes))]
+
+struct LoudDropper;
+impl Drop for LoudDropper {
+    fn drop(&mut self) {
+        // This destructor should be considered significant because it is a custom destructor
+        // and we will assume that the destructor can generate side effects arbitrarily so that
+        // a change in drop order is visible.
+        println!("loud drop");
+    }
+}
+impl LoudDropper {
+    fn get(&self) -> i32 {
+        0
+    }
+}
+
+fn should_not_lint() -> i32 {
+    let x = LoudDropper;
+    x.get() + LoudDropper.get()
+    // Lint should not action
+}
+
+fn main() {}
diff --git a/tests/ui/drop/lint-tail-expr-drop-order.rs b/tests/ui/drop/lint-tail-expr-drop-order.rs
new file mode 100644
index 00000000000..0aa0ef02610
--- /dev/null
+++ b/tests/ui/drop/lint-tail-expr-drop-order.rs
@@ -0,0 +1,71 @@
+//@ compile-flags: -Z unstable-options
+//@ edition: 2024
+
+// Edition 2024 lint for change in drop order at tail expression
+// This lint is to capture potential change in program semantics
+// due to implementation of RFC 3606 <https://github.com/rust-lang/rfcs/pull/3606>
+
+#![deny(tail_expr_drop_order)]
+#![feature(shorter_tail_lifetimes)]
+
+struct LoudDropper;
+impl Drop for LoudDropper {
+    fn drop(&mut self) {
+        // This destructor should be considered significant because it is a custom destructor
+        // and we will assume that the destructor can generate side effects arbitrarily so that
+        // a change in drop order is visible.
+        println!("loud drop");
+    }
+}
+impl LoudDropper {
+    fn get(&self) -> i32 {
+        0
+    }
+}
+
+fn should_lint() -> i32 {
+    let x = LoudDropper;
+    // Should lint
+    x.get() + LoudDropper.get()
+    //~^ ERROR: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021
+    //~| WARN: this changes meaning in Rust 2024
+}
+
+fn should_lint_closure() -> impl FnOnce() -> i32 {
+    let x = LoudDropper;
+    move || x.get() + LoudDropper.get()
+    //~^ ERROR: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021
+    //~| WARN: this changes meaning in Rust 2024
+}
+
+fn should_not_lint() -> i32 {
+    let x = LoudDropper;
+    // Should not lint
+    x.get()
+}
+
+fn should_not_lint_in_nested_block() -> i32 {
+    let x = LoudDropper;
+    // Should not lint because Edition 2021 drops temporaries in blocks earlier already
+    { LoudDropper.get() }
+}
+
+fn should_not_lint_in_match_arm() -> i32 {
+    let x = LoudDropper;
+    // Should not lint because Edition 2021 drops temporaries in blocks earlier already
+    match &x {
+        _ => LoudDropper.get(),
+    }
+}
+
+fn should_lint_in_nested_items() {
+    fn should_lint_me() -> i32 {
+        let x = LoudDropper;
+        // Should lint
+        x.get() + LoudDropper.get()
+        //~^ ERROR: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021
+        //~| WARN: this changes meaning in Rust 2024
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/drop/lint-tail-expr-drop-order.stderr b/tests/ui/drop/lint-tail-expr-drop-order.stderr
new file mode 100644
index 00000000000..630f0a80f09
--- /dev/null
+++ b/tests/ui/drop/lint-tail-expr-drop-order.stderr
@@ -0,0 +1,42 @@
+error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021
+  --> $DIR/lint-tail-expr-drop-order.rs:29:15
+   |
+LL |     let x = LoudDropper;
+   |         - these values have significant drop implementation and will observe changes in drop order under Edition 2024
+LL |     // Should lint
+LL |     x.get() + LoudDropper.get()
+   |               ^^^^^^^^^^^
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see issue #123739 <https://github.com/rust-lang/rust/issues/123739>
+note: the lint level is defined here
+  --> $DIR/lint-tail-expr-drop-order.rs:8:9
+   |
+LL | #![deny(tail_expr_drop_order)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021
+  --> $DIR/lint-tail-expr-drop-order.rs:36:23
+   |
+LL |     let x = LoudDropper;
+   |         - these values have significant drop implementation and will observe changes in drop order under Edition 2024
+LL |     move || x.get() + LoudDropper.get()
+   |                       ^^^^^^^^^^^
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see issue #123739 <https://github.com/rust-lang/rust/issues/123739>
+
+error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021
+  --> $DIR/lint-tail-expr-drop-order.rs:65:19
+   |
+LL |         let x = LoudDropper;
+   |             - these values have significant drop implementation and will observe changes in drop order under Edition 2024
+LL |         // Should lint
+LL |         x.get() + LoudDropper.get()
+   |                   ^^^^^^^^^^^
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see issue #123739 <https://github.com/rust-lang/rust/issues/123739>
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/error-codes/E0001.stderr b/tests/ui/error-codes/E0001.stderr
index 40008230ec8..30d0df960f3 100644
--- a/tests/ui/error-codes/E0001.stderr
+++ b/tests/ui/error-codes/E0001.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/E0001.rs:8:9
    |
 LL |         _ => {/* ... */}
-   |         ^ unreachable pattern
+   |         ^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/E0001.rs:8:9
    |
 LL |         Some(_) => {/* ... */}
diff --git a/tests/ui/feature-gates/feature-gate-repr-simd.stderr b/tests/ui/feature-gates/feature-gate-repr-simd.stderr
index 5b490c0c0c3..5a0ceb2dd74 100644
--- a/tests/ui/feature-gates/feature-gate-repr-simd.stderr
+++ b/tests/ui/feature-gates/feature-gate-repr-simd.stderr
@@ -35,3 +35,17 @@ error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0566, E0658.
 For more information about an error, try `rustc --explain E0566`.
+Future incompatibility report: Future breakage diagnostic:
+error[E0566]: conflicting representation hints
+  --> $DIR/feature-gate-repr-simd.rs:4:8
+   |
+LL | #[repr(C)]
+   |        ^
+LL |
+LL | #[repr(simd)]
+   |        ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
+   = note: `#[deny(conflicting_repr_hints)]` on by default
+
diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr
index d1decc0c3f1..37491ca12b0 100644
--- a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr
+++ b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr
@@ -51,7 +51,7 @@ LL |     type A<'a> where Self: 'a;
    = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
              Fooy
              Fooer<T>
-   = note: required for the cast from `Box<Fooer<{integer}>>` to `Box<(dyn Foo<A = &'a ()> + 'static)>`
+   = note: required for the cast from `Box<Fooer<{integer}>>` to `Box<(dyn Foo<A<'a> = &'a ()> + 'static)>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/generic-associated-types/issue-76535.base.stderr b/tests/ui/generic-associated-types/issue-76535.base.stderr
index bb14e297174..88c08051da7 100644
--- a/tests/ui/generic-associated-types/issue-76535.base.stderr
+++ b/tests/ui/generic-associated-types/issue-76535.base.stderr
@@ -47,7 +47,7 @@ LL |     type SubType<'a>: SubTrait where Self: 'a;
    = help: consider moving `SubType` to another trait
    = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead
    = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
-   = note: required for the cast from `Box<SuperStruct>` to `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
+   = note: required for the cast from `Box<SuperStruct>` to `Box<dyn SuperTrait<SubType<'_> = SubStruct<'_>>>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/generic-associated-types/issue-79422.base.stderr b/tests/ui/generic-associated-types/issue-79422.base.stderr
index bcc6382cf7c..551ad2a8fdf 100644
--- a/tests/ui/generic-associated-types/issue-79422.base.stderr
+++ b/tests/ui/generic-associated-types/issue-79422.base.stderr
@@ -49,7 +49,7 @@ LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead:
              std::collections::BTreeMap<K, V>
              Source
-   = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
+   = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont<'_> = (dyn RefCont<'_, u8> + 'static)>>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/generic-associated-types/issue-79422.extended.stderr b/tests/ui/generic-associated-types/issue-79422.extended.stderr
index ae1526296a7..031f8d8d851 100644
--- a/tests/ui/generic-associated-types/issue-79422.extended.stderr
+++ b/tests/ui/generic-associated-types/issue-79422.extended.stderr
@@ -28,7 +28,7 @@ LL |     type VRefCont<'a> = &'a V where Self: 'a;
    = note: expected trait object `(dyn RefCont<'_, u8> + 'static)`
                  found reference `&u8`
    = help: `&u8` implements `RefCont` so you could box the found value and coerce it to the trait object `Box<dyn RefCont>`, you will have to change the expected type as well
-   = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
+   = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont<'_> = (dyn RefCont<'_, u8> + 'static)>>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr
index c8d1614a7f3..f498257e12f 100644
--- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr
+++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr
@@ -5,9 +5,9 @@ LL |     fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first, the lifetime cannot outlive the lifetime `'s` as defined here...
-  --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:11:12
+  --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:8:12
    |
-LL |     fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str {
+LL |     fn get<'s>(s: &'s str, _: ()) -> &'static str;
    |            ^^
 note: ...so that the method type is compatible with trait
   --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:11:5
diff --git a/tests/ui/imports/auxiliary/issue-85992-extern-2.rs b/tests/ui/imports/auxiliary/empty.rs
index e9b6a44cfe2..e9b6a44cfe2 100644
--- a/tests/ui/imports/auxiliary/issue-85992-extern-2.rs
+++ b/tests/ui/imports/auxiliary/empty.rs
diff --git a/tests/ui/imports/auxiliary/issue-85992-extern-1.rs b/tests/ui/imports/auxiliary/issue-85992-extern.rs
index a2d0e206065..076d6045190 100644
--- a/tests/ui/imports/auxiliary/issue-85992-extern-1.rs
+++ b/tests/ui/imports/auxiliary/issue-85992-extern.rs
@@ -1,6 +1,6 @@
 #[macro_export]
 macro_rules! m {
    () => {
-        use issue_85992_extern_2::Outcome;
+        use empty::Outcome;
    }
 }
diff --git a/tests/ui/imports/issue-85992.rs b/tests/ui/imports/issue-85992.rs
index 321c3a9218d..38cf0384501 100644
--- a/tests/ui/imports/issue-85992.rs
+++ b/tests/ui/imports/issue-85992.rs
@@ -1,11 +1,11 @@
 //@ edition: 2021
-//@ compile-flags: --extern issue_85992_extern_1 --extern issue_85992_extern_2
-//@ aux-build: issue-85992-extern-1.rs
-//@ aux-build: issue-85992-extern-2.rs
+//@ compile-flags: --extern issue_85992_extern --extern empty
+//@ aux-build: issue-85992-extern.rs
+//@ aux-build: empty.rs
 
-issue_85992_extern_1::m!();
+issue_85992_extern::m!();
 
-use crate::issue_85992_extern_2;
-//~^ ERROR unresolved import `crate::issue_85992_extern_2`
+use crate::empty;
+//~^ ERROR unresolved import `crate::empty`
 
 fn main() {}
diff --git a/tests/ui/imports/issue-85992.stderr b/tests/ui/imports/issue-85992.stderr
index 6c75b45d926..490b2d4d88b 100644
--- a/tests/ui/imports/issue-85992.stderr
+++ b/tests/ui/imports/issue-85992.stderr
@@ -1,8 +1,8 @@
-error[E0432]: unresolved import `crate::issue_85992_extern_2`
+error[E0432]: unresolved import `crate::empty`
   --> $DIR/issue-85992.rs:8:5
    |
-LL | use crate::issue_85992_extern_2;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `issue_85992_extern_2` in the root
+LL | use crate::empty;
+   |     ^^^^^^^^^^^^ no `empty` in the root
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-buitlin.rs b/tests/ui/imports/multiple-extern-by-macro-for-buitlin.rs
new file mode 100644
index 00000000000..f0e5e4b4325
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-buitlin.rs
@@ -0,0 +1,18 @@
+//@ edition: 2021
+
+// issue#128813
+
+extern crate core;
+
+macro_rules! m {
+    () => {
+        extern crate std as core;
+        //~^ ERROR: the name `core` is defined multiple times
+    };
+}
+
+m!();
+
+fn main() {
+    use ::core;
+}
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr b/tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr
new file mode 100644
index 00000000000..a84a6c42aa8
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr
@@ -0,0 +1,22 @@
+error[E0259]: the name `core` is defined multiple times
+  --> $DIR/multiple-extern-by-macro-for-buitlin.rs:9:9
+   |
+LL | extern crate core;
+   | ------------------ previous import of the extern crate `core` here
+...
+LL |         extern crate std as core;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ `core` reimported here
+...
+LL | m!();
+   | ---- in this macro invocation
+   |
+   = note: `core` must be defined only once in the type namespace of this module
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you can use `as` to change the binding name of the import
+   |
+LL |         extern crate std as other_core;
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-custom.rs b/tests/ui/imports/multiple-extern-by-macro-for-custom.rs
new file mode 100644
index 00000000000..6bf544566e3
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-custom.rs
@@ -0,0 +1,19 @@
+//@ edition: 2021
+//@ aux-build: empty.rs
+
+// issue#128813
+
+extern crate empty;
+
+macro_rules! m {
+    () => {
+        extern crate std as empty;
+        //~^ ERROR: the name `empty` is defined multiple times
+    };
+}
+
+m!();
+
+fn main() {
+    use ::empty;
+}
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-custom.stderr b/tests/ui/imports/multiple-extern-by-macro-for-custom.stderr
new file mode 100644
index 00000000000..556d75a4dbb
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-custom.stderr
@@ -0,0 +1,22 @@
+error[E0259]: the name `empty` is defined multiple times
+  --> $DIR/multiple-extern-by-macro-for-custom.rs:10:9
+   |
+LL | extern crate empty;
+   | ------------------- previous import of the extern crate `empty` here
+...
+LL |         extern crate std as empty;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ `empty` reimported here
+...
+LL | m!();
+   | ---- in this macro invocation
+   |
+   = note: `empty` must be defined only once in the type namespace of this module
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you can use `as` to change the binding name of the import
+   |
+LL |         extern crate std as other_empty;
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-inexist.rs b/tests/ui/imports/multiple-extern-by-macro-for-inexist.rs
new file mode 100644
index 00000000000..c23f275b9ff
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-inexist.rs
@@ -0,0 +1,19 @@
+//@ edition: 2021
+
+// issue#128813
+
+extern crate non_existent;
+//~^ ERROR: can't find crate for `non_existent`
+
+macro_rules! m {
+    () => {
+        extern crate std as non_existent;
+        //~^ ERROR: the name `non_existent` is defined multiple times
+    };
+}
+
+m!();
+
+fn main() {
+    use ::non_existent;
+}
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr b/tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr
new file mode 100644
index 00000000000..ec34489f232
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr
@@ -0,0 +1,29 @@
+error[E0463]: can't find crate for `non_existent`
+  --> $DIR/multiple-extern-by-macro-for-inexist.rs:5:1
+   |
+LL | extern crate non_existent;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate
+
+error[E0259]: the name `non_existent` is defined multiple times
+  --> $DIR/multiple-extern-by-macro-for-inexist.rs:10:9
+   |
+LL | extern crate non_existent;
+   | -------------------------- previous import of the extern crate `non_existent` here
+...
+LL |         extern crate std as non_existent;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `non_existent` reimported here
+...
+LL | m!();
+   | ---- in this macro invocation
+   |
+   = note: `non_existent` must be defined only once in the type namespace of this module
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you can use `as` to change the binding name of the import
+   |
+LL |         extern crate std as other_non_existent;
+   |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0259, E0463.
+For more information about an error, try `rustc --explain E0259`.
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs b/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs
new file mode 100644
index 00000000000..ddf735d8947
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs
@@ -0,0 +1,18 @@
+//@ edition: 2021
+
+// issue#128813
+
+extern crate core as _;
+
+macro_rules! m {
+    () => {
+        extern crate std as _;
+    };
+}
+
+m!();
+
+fn main() {
+    use ::_;
+    //~^ ERROR: expected identifier, found reserved identifier `_`
+}
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr b/tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr
new file mode 100644
index 00000000000..1da5aa87070
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/multiple-extern-by-macro-for-underscore.rs:16:11
+   |
+LL |     use ::_;
+   |           ^ expected identifier, found reserved identifier
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/issues/issue-20831-debruijn.stderr b/tests/ui/issues/issue-20831-debruijn.stderr
index 60721f001b7..fe310998f09 100644
--- a/tests/ui/issues/issue-20831-debruijn.stderr
+++ b/tests/ui/issues/issue-20831-debruijn.stderr
@@ -5,10 +5,10 @@ LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first, the lifetime cannot outlive the anonymous lifetime as defined here...
-  --> $DIR/issue-20831-debruijn.rs:28:18
+  --> $DIR/issue-20831-debruijn.rs:28:67
    |
 LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-   |                  ^
+   |                                                                   ^^^^^^^^^
 note: ...but the lifetime must also be valid for the lifetime `'a` as defined here...
   --> $DIR/issue-20831-debruijn.rs:26:6
    |
diff --git a/tests/ui/issues/issue-37884.stderr b/tests/ui/issues/issue-37884.stderr
index b7c0095d682..17037d2180d 100644
--- a/tests/ui/issues/issue-37884.stderr
+++ b/tests/ui/issues/issue-37884.stderr
@@ -7,10 +7,7 @@ LL |     fn next(&'a mut self) -> Option<Self::Item>
    = note: expected signature `fn(&mut RepeatMut<'_, _>) -> Option<_>`
               found signature `fn(&'a mut RepeatMut<'_, _>) -> Option<_>`
 note: the anonymous lifetime as defined here...
-  --> $DIR/issue-37884.rs:6:5
-   |
-LL |     fn next(&'a mut self) -> Option<Self::Item>
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 note: ...does not necessarily outlive the lifetime `'a` as defined here
   --> $DIR/issue-37884.rs:3:6
    |
diff --git a/tests/ui/issues/issue-47094.stderr b/tests/ui/issues/issue-47094.stderr
index 970e3184710..1c6693403b8 100644
--- a/tests/ui/issues/issue-47094.stderr
+++ b/tests/ui/issues/issue-47094.stderr
@@ -23,3 +23,28 @@ LL | #[repr(u8)]
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0566`.
+Future incompatibility report: Future breakage diagnostic:
+error[E0566]: conflicting representation hints
+  --> $DIR/issue-47094.rs:1:8
+   |
+LL | #[repr(C, u8)]
+   |        ^  ^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
+   = note: `#[deny(conflicting_repr_hints)]` on by default
+
+Future breakage diagnostic:
+error[E0566]: conflicting representation hints
+  --> $DIR/issue-47094.rs:8:8
+   |
+LL | #[repr(C)]
+   |        ^
+LL |
+LL | #[repr(u8)]
+   |        ^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
+   = note: `#[deny(conflicting_repr_hints)]` on by default
+
diff --git a/tests/ui/lint/issue-30302.stderr b/tests/ui/lint/issue-30302.stderr
index baf6c0d7a59..317fefee466 100644
--- a/tests/ui/lint/issue-30302.stderr
+++ b/tests/ui/lint/issue-30302.stderr
@@ -13,7 +13,7 @@ LL |         Nil => true,
    |         --- matches any value
 LL |
 LL |         _ => false
-   |         ^ unreachable pattern
+   |         ^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/issue-30302.rs:4:9
diff --git a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
index 5570390b21c..6ddc0595665 100644
--- a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
+++ b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:8:9
    |
 LL |         (1 | 2,) => {}
-   |         -------- matches all the values already
+   |         -------- matches all the relevant values
 LL |         (1,) => {}
-   |         ^^^^ unreachable pattern
+   |         ^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/exhaustiveness-unreachable-pattern.rs:1:9
@@ -16,17 +16,17 @@ error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:13:9
    |
 LL |         (1 | 2,) => {}
-   |         -------- matches all the values already
+   |         -------- matches all the relevant values
 LL |         (2,) => {}
-   |         ^^^^ unreachable pattern
+   |         ^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:19:9
    |
 LL |         (1 | 2,) => {}
-   |         ^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/exhaustiveness-unreachable-pattern.rs:19:9
    |
 LL |         (1,) => {}
@@ -40,44 +40,44 @@ error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:24:9
    |
 LL |         (1 | 2, 3 | 4) => {}
-   |         -------------- matches all the values already
+   |         -------------- matches all the relevant values
 LL |         (1, 3) => {}
-   |         ^^^^^^ unreachable pattern
+   |         ^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:25:9
    |
 LL |         (1 | 2, 3 | 4) => {}
-   |         -------------- matches all the values already
+   |         -------------- matches all the relevant values
 LL |         (1, 3) => {}
 LL |         (1, 4) => {}
-   |         ^^^^^^ unreachable pattern
+   |         ^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:26:9
    |
 LL |         (1 | 2, 3 | 4) => {}
-   |         -------------- matches all the values already
+   |         -------------- matches all the relevant values
 ...
 LL |         (2, 4) => {}
-   |         ^^^^^^ unreachable pattern
+   |         ^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:27:9
    |
 LL |         (1 | 2, 3 | 4) => {}
-   |         -------------- matches all the values already
+   |         -------------- matches all the relevant values
 ...
 LL |         (2 | 1, 4) => {}
-   |         ^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:29:9
    |
 LL |         (1, 4 | 5) => {}
-   |         ^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/exhaustiveness-unreachable-pattern.rs:29:9
    |
 LL |         (1 | 2, 3 | 4) => {}
@@ -92,107 +92,107 @@ error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:34:13
    |
 LL |         (0, 0, 0) => {}
-   |             - matches all the values already
+   |             - matches all the relevant values
 LL |         (0, 0 | 1, 0) => {}
-   |             ^ unreachable pattern
+   |             ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:42:9
    |
 LL |         (None | Some(1 | 2),) => {}
-   |         --------------------- matches all the values already
+   |         --------------------- matches all the relevant values
 LL |         (Some(1),) => {}
-   |         ^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:43:9
    |
 LL |         (None | Some(1 | 2),) => {}
-   |         --------------------- matches all the values already
+   |         --------------------- matches all the relevant values
 LL |         (Some(1),) => {}
 LL |         (None,) => {}
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:48:9
    |
 LL |         ((1 | 2,) | (3 | 4,),) => {}
-   |         ---------------------- matches all the values already
+   |         ---------------------- matches all the relevant values
 LL |         ((1..=4,),) => {}
-   |         ^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:53:14
    |
 LL |         (1 | 1,) => {}
-   |          -   ^ unreachable pattern
+   |          -   ^ no value can reach this
    |          |
-   |          matches all the values already
+   |          matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:57:19
    |
 LL |         (0 | 1) | 1 => {}
-   |              -    ^ unreachable pattern
+   |              -    ^ no value can reach this
    |              |
-   |              matches all the values already
+   |              matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:63:14
    |
 LL |         0 | (0 | 0) => {}
-   |         -    ^ unreachable pattern
+   |         -    ^ no value can reach this
    |         |
-   |         matches all the values already
+   |         matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:63:18
    |
 LL |         0 | (0 | 0) => {}
-   |         -        ^ unreachable pattern
+   |         -        ^ no value can reach this
    |         |
-   |         matches all the values already
+   |         matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:71:13
    |
 LL |           Some(0) |
-   |           ------- matches all the values already
+   |           ------- matches all the relevant values
 LL | /             Some(
 LL | |                 0 | 0) => {}
-   | |______________________^ unreachable pattern
+   | |______________________^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:77:15
    |
 LL |         [0
-   |          - matches all the values already
+   |          - matches all the relevant values
 LL |             | 0
-   |               ^ unreachable pattern
+   |               ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:79:15
    |
 LL |         , 0
-   |           - matches all the values already
+   |           - matches all the relevant values
 LL |             | 0] => {}
-   |               ^ unreachable pattern
+   |               ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:83:20
    |
 LL |         (true, 0 | 0) => {}
-   |                -   ^ unreachable pattern
+   |                -   ^ no value can reach this
    |                |
-   |                matches all the values already
+   |                matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:84:17
    |
 LL |         (_, 0 | 0) => {}
-   |                 ^ unreachable pattern
+   |                 ^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/exhaustiveness-unreachable-pattern.rs:84:17
    |
 LL |         (true, 0 | 0) => {}
@@ -206,25 +206,25 @@ error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:92:10
    |
 LL |         [1, ..] => {}
-   |          - matches all the values already
+   |          - matches all the relevant values
 LL |         [1
-   |          ^ unreachable pattern
+   |          ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:104:10
    |
 LL |         [true, ..] => {}
-   |          ---- matches all the values already
+   |          ---- matches all the relevant values
 LL |         [true
-   |          ^^^^ unreachable pattern
+   |          ^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:111:36
    |
 LL |         (true | false, None | Some(true
-   |                                    ^^^^ unreachable pattern
+   |                                    ^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/exhaustiveness-unreachable-pattern.rs:111:36
    |
 LL |         (true, Some(_)) => {}
@@ -238,12 +238,12 @@ error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:116:14
    |
 LL |             (true
-   |              ^^^^ unreachable pattern
+   |              ^^^^ no value can reach this
 ...
 LL |         (true | false, None | Some(t_or_f!())) => {}
    |                                    --------- in this macro invocation
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/exhaustiveness-unreachable-pattern.rs:116:14
    |
 LL |             (true
@@ -261,26 +261,26 @@ error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:127:14
    |
 LL |         Some(0) => {}
-   |              - matches all the values already
+   |              - matches all the relevant values
 LL |         Some(0
-   |              ^ unreachable pattern
+   |              ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:146:19
    |
 LL |         Some(false) => {}
-   |              ----- matches all the values already
+   |              ----- matches all the relevant values
 LL |         None | Some(true
 LL |                 | false) => {}
-   |                   ^^^^^ unreachable pattern
+   |                   ^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:154:15
    |
 LL |             | true) => {}
-   |               ^^^^ unreachable pattern
+   |               ^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/exhaustiveness-unreachable-pattern.rs:154:15
    |
 LL |         (false, true) => {}
@@ -295,9 +295,9 @@ error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:160:15
    |
 LL |             | true,
-   |               ^^^^ unreachable pattern
+   |               ^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/exhaustiveness-unreachable-pattern.rs:160:15
    |
 LL |         (true, false) => {}
@@ -314,13 +314,13 @@ error: unreachable pattern
 LL |         (x, y)
    |         ------ matches any value
 LL |             | (y, x) => {}
-   |               ^^^^^^ unreachable pattern
+   |               ^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:169:30
    |
 LL | fn unreachable_in_param((_ | (_, _)): (bool, bool)) {}
-   |                          -   ^^^^^^ unreachable pattern
+   |                          -   ^^^^^^ no value can reach this
    |                          |
    |                          matches any value
 
@@ -328,7 +328,7 @@ error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:176:14
    |
 LL |     let (_ | (_, _)) = bool_pair;
-   |          -   ^^^^^^ unreachable pattern
+   |          -   ^^^^^^ no value can reach this
    |          |
    |          matches any value
 
@@ -336,7 +336,7 @@ error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:178:14
    |
 LL |     for (_ | (_, _)) in [bool_pair] {}
-   |          -   ^^^^^^ unreachable pattern
+   |          -   ^^^^^^ no value can reach this
    |          |
    |          matches any value
 
@@ -344,25 +344,25 @@ error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:181:20
    |
 LL |     let (Some(_) | Some(true)) = bool_option else { return };
-   |          -------   ^^^^^^^^^^ unreachable pattern
+   |          -------   ^^^^^^^^^^ no value can reach this
    |          |
-   |          matches all the values already
+   |          matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:183:22
    |
 LL |     if let Some(_) | Some(true) = bool_option {}
-   |            -------   ^^^^^^^^^^ unreachable pattern
+   |            -------   ^^^^^^^^^^ no value can reach this
    |            |
-   |            matches all the values already
+   |            matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/exhaustiveness-unreachable-pattern.rs:185:25
    |
 LL |     while let Some(_) | Some(true) = bool_option {}
-   |               -------   ^^^^^^^^^^ unreachable pattern
+   |               -------   ^^^^^^^^^^ no value can reach this
    |               |
-   |               matches all the values already
+   |               matches all the relevant values
 
 error: aborting due to 36 previous errors
 
diff --git a/tests/ui/pattern/issue-14221.stderr b/tests/ui/pattern/issue-14221.stderr
index 7ea51b5f804..44b2923d606 100644
--- a/tests/ui/pattern/issue-14221.stderr
+++ b/tests/ui/pattern/issue-14221.stderr
@@ -19,7 +19,7 @@ LL |             A => "A",
    |             - matches any value
 LL |
 LL |             B => "B",
-   |             ^ unreachable pattern
+   |             ^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/issue-14221.rs:1:9
diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr
index 9d3a35321ca..32d385eecb4 100644
--- a/tests/ui/pattern/usefulness/consts-opaque.stderr
+++ b/tests/ui/pattern/usefulness/consts-opaque.stderr
@@ -52,7 +52,7 @@ error: unreachable pattern
 LL |         Bar => {}
    |         --- matches any value
 LL |         BAR => {}
-   |         ^^^ unreachable pattern
+   |         ^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/consts-opaque.rs:6:9
@@ -67,7 +67,7 @@ LL |         Bar => {}
    |         --- matches any value
 ...
 LL |         _ => {}
-   |         ^ unreachable pattern
+   |         ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:56:9
@@ -75,7 +75,7 @@ error: unreachable pattern
 LL |         BAR => {}
    |         --- matches any value
 LL |         Bar => {}
-   |         ^^^ unreachable pattern
+   |         ^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:58:9
@@ -84,7 +84,7 @@ LL |         BAR => {}
    |         --- matches any value
 ...
 LL |         _ => {}
-   |         ^ unreachable pattern
+   |         ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:64:9
@@ -92,7 +92,7 @@ error: unreachable pattern
 LL |         BAR => {}
    |         --- matches any value
 LL |         BAR => {} // should not be emitting unreachable warning
-   |         ^^^ unreachable pattern
+   |         ^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:66:9
@@ -101,31 +101,31 @@ LL |         BAR => {}
    |         --- matches any value
 ...
 LL |         _ => {} // should not be emitting unreachable warning
-   |         ^ unreachable pattern
+   |         ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:72:9
    |
 LL |         BAZ => {}
-   |         --- matches all the values already
+   |         --- matches all the relevant values
 LL |         Baz::Baz1 => {} // should not be emitting unreachable warning
-   |         ^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:79:9
    |
 LL |         Baz::Baz1 => {}
-   |         --------- matches all the values already
+   |         --------- matches all the relevant values
 LL |         BAZ => {}
-   |         ^^^ unreachable pattern
+   |         ^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:87:9
    |
 LL |         _ => {} // should not be emitting unreachable warning
-   |         ^ unreachable pattern
+   |         ^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/consts-opaque.rs:87:9
    |
 LL |         BAZ => {}
diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr
index 1b65ff7aa57..60ab4d52c30 100644
--- a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/empty-match-check-notes.rs:17:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `EmptyEnum` is uninhabited
    |
-   = note: this pattern matches no values because `EmptyEnum` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
   --> $DIR/empty-match-check-notes.rs:7:9
    |
@@ -12,31 +12,31 @@ LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-match-check-notes.rs:21:9
+  --> $DIR/empty-match-check-notes.rs:22:9
    |
 LL |         _ if false => {}
-   |         ^
+   |         ^ matches no values because `EmptyEnum` is uninhabited
    |
-   = note: this pattern matches no values because `EmptyEnum` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-match-check-notes.rs:29:9
+  --> $DIR/empty-match-check-notes.rs:31:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `EmptyForeignEnum` is uninhabited
    |
-   = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-match-check-notes.rs:33:9
+  --> $DIR/empty-match-check-notes.rs:36:9
    |
 LL |         _ if false => {}
-   |         ^
+   |         ^ matches no values because `EmptyForeignEnum` is uninhabited
    |
-   = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-match-check-notes.rs:39:9
+  --> $DIR/empty-match-check-notes.rs:43:9
    |
 LL |     let None = *x;
    |         ^^^^ pattern `Some(_)` not covered
@@ -51,7 +51,7 @@ LL |     if let None = *x { todo!() };
    |     ++               +++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered
-  --> $DIR/empty-match-check-notes.rs:49:11
+  --> $DIR/empty-match-check-notes.rs:53:11
    |
 LL |     match 0u8 {
    |           ^^^ pattern `0_u8..=u8::MAX` not covered
diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr
index 1b65ff7aa57..60ab4d52c30 100644
--- a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr
+++ b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/empty-match-check-notes.rs:17:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `EmptyEnum` is uninhabited
    |
-   = note: this pattern matches no values because `EmptyEnum` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
   --> $DIR/empty-match-check-notes.rs:7:9
    |
@@ -12,31 +12,31 @@ LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-match-check-notes.rs:21:9
+  --> $DIR/empty-match-check-notes.rs:22:9
    |
 LL |         _ if false => {}
-   |         ^
+   |         ^ matches no values because `EmptyEnum` is uninhabited
    |
-   = note: this pattern matches no values because `EmptyEnum` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-match-check-notes.rs:29:9
+  --> $DIR/empty-match-check-notes.rs:31:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `EmptyForeignEnum` is uninhabited
    |
-   = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-match-check-notes.rs:33:9
+  --> $DIR/empty-match-check-notes.rs:36:9
    |
 LL |         _ if false => {}
-   |         ^
+   |         ^ matches no values because `EmptyForeignEnum` is uninhabited
    |
-   = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-match-check-notes.rs:39:9
+  --> $DIR/empty-match-check-notes.rs:43:9
    |
 LL |     let None = *x;
    |         ^^^^ pattern `Some(_)` not covered
@@ -51,7 +51,7 @@ LL |     if let None = *x { todo!() };
    |     ++               +++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered
-  --> $DIR/empty-match-check-notes.rs:49:11
+  --> $DIR/empty-match-check-notes.rs:53:11
    |
 LL |     match 0u8 {
    |           ^^^ pattern `0_u8..=u8::MAX` not covered
diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.rs b/tests/ui/pattern/usefulness/empty-match-check-notes.rs
index 61a75e6c801..48d20fd2d5c 100644
--- a/tests/ui/pattern/usefulness/empty-match-check-notes.rs
+++ b/tests/ui/pattern/usefulness/empty-match-check-notes.rs
@@ -16,10 +16,12 @@ fn empty_enum(x: EmptyEnum) {
     match x {
         _ => {} //~ ERROR unreachable pattern
                 //~^ NOTE matches no values
+                //~| NOTE to learn more about uninhabited types, see
     }
     match x {
         _ if false => {} //~ ERROR unreachable pattern
                          //~^ NOTE matches no values
+                         //~| NOTE to learn more about uninhabited types, see
     }
 }
 
@@ -28,10 +30,12 @@ fn empty_foreign_enum(x: empty::EmptyForeignEnum) {
     match x {
         _ => {} //~ ERROR unreachable pattern
                 //~^ NOTE matches no values
+                //~| NOTE to learn more about uninhabited types, see
     }
     match x {
         _ if false => {} //~ ERROR unreachable pattern
                          //~^ NOTE matches no values
+                         //~| NOTE to learn more about uninhabited types, see
     }
 }
 
diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
index f6f341d6f2f..9decddfe5de 100644
--- a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:49:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
   --> $DIR/empty-types.rs:15:9
    |
@@ -15,9 +15,9 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:52:9
    |
 LL |         _x => {}
-   |         ^^
+   |         ^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `&!` is non-empty
   --> $DIR/empty-types.rs:56:11
@@ -38,33 +38,33 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:70:9
    |
 LL |         (_, _) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `(u32, !)` is uninhabited
    |
-   = note: this pattern matches no values because `(u32, !)` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:76:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `(!, !)` is uninhabited
    |
-   = note: this pattern matches no values because `(!, !)` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:79:9
    |
 LL |         (_, _) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `(!, !)` is uninhabited
    |
-   = note: this pattern matches no values because `(!, !)` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:83:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
   --> $DIR/empty-types.rs:87:11
@@ -89,17 +89,17 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:94:9
    |
 LL |         Err(_) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:99:9
    |
 LL |         Err(_) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
   --> $DIR/empty-types.rs:96:11
@@ -137,153 +137,153 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:112:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:115:9
    |
 LL |         Ok(_) => {}
-   |         ^^^^^
+   |         ^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:118:9
    |
 LL |         Ok(_) => {}
-   |         ^^^^^
+   |         ^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:119:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:122:9
    |
 LL |         Ok(_) => {}
-   |         ^^^^^
+   |         ^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:123:9
    |
 LL |         Err(_) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:132:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:135:13
    |
 LL |             _ if false => {}
-   |             ^
+   |             ^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:143:13
    |
 LL |             Some(_) => {}
-   |             ^^^^^^^
+   |             ^^^^^^^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:147:13
    |
 LL |             None => {}
-   |             ---- matches all the values already
+   |             ---- matches all the relevant values
 LL |             _ => {}
-   |             ^ unreachable pattern
+   |             ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:199:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:204:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:209:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:214:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:220:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:281:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:284:9
    |
 LL |         (_, _) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `(!, !)` is uninhabited
    |
-   = note: this pattern matches no values because `(!, !)` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:287:9
    |
 LL |         Ok(_) => {}
-   |         ^^^^^
+   |         ^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:288:9
    |
 LL |         Err(_) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
   --> $DIR/empty-types.rs:327:11
@@ -344,25 +344,25 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:368:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `[!; 3]` is uninhabited
    |
-   = note: this pattern matches no values because `[!; 3]` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:371:9
    |
 LL |         [_, _, _] => {}
-   |         ^^^^^^^^^
+   |         ^^^^^^^^^ matches no values because `[!; 3]` is uninhabited
    |
-   = note: this pattern matches no values because `[!; 3]` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:374:9
    |
 LL |         [_, ..] => {}
-   |         ^^^^^^^
+   |         ^^^^^^^ matches no values because `[!; 3]` is uninhabited
    |
-   = note: this pattern matches no values because `[!; 3]` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
   --> $DIR/empty-types.rs:388:11
@@ -382,9 +382,9 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:395:9
    |
 LL |         [] => {}
-   |         -- matches all the values already
+   |         -- matches all the relevant values
 LL |         _ => {}
-   |         ^ unreachable pattern
+   |         ^ no value can reach this
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
   --> $DIR/empty-types.rs:397:11
@@ -404,67 +404,67 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:416:9
    |
 LL |         Some(_) => {}
-   |         ^^^^^^^
+   |         ^^^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:421:9
    |
 LL |         Some(_a) => {}
-   |         ^^^^^^^^
+   |         ^^^^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:426:9
    |
 LL |         None => {}
-   |         ---- matches all the values already
+   |         ---- matches all the relevant values
 LL |         // !useful, !reachable
 LL |         _ => {}
-   |         ^ unreachable pattern
+   |         ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:431:9
    |
 LL |         None => {}
-   |         ---- matches all the values already
+   |         ---- matches all the relevant values
 LL |         // !useful, !reachable
 LL |         _a => {}
-   |         ^^ unreachable pattern
+   |         ^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:603:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:606:9
    |
 LL |         _x => {}
-   |         ^^
+   |         ^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:609:9
    |
 LL |         _ if false => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:612:9
    |
 LL |         _x if false => {}
-   |         ^^
+   |         ^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: aborting due to 49 previous errors
 
diff --git a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr
index 55a138c2d1c..68213a2d661 100644
--- a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr
@@ -11,9 +11,9 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:49:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
   --> $DIR/empty-types.rs:15:9
    |
@@ -24,9 +24,9 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:52:9
    |
 LL |         _x => {}
-   |         ^^
+   |         ^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `&!` is non-empty
   --> $DIR/empty-types.rs:56:11
@@ -47,33 +47,33 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:70:9
    |
 LL |         (_, _) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `(u32, !)` is uninhabited
    |
-   = note: this pattern matches no values because `(u32, !)` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:76:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `(!, !)` is uninhabited
    |
-   = note: this pattern matches no values because `(!, !)` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:79:9
    |
 LL |         (_, _) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `(!, !)` is uninhabited
    |
-   = note: this pattern matches no values because `(!, !)` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:83:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
   --> $DIR/empty-types.rs:87:11
@@ -98,17 +98,17 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:94:9
    |
 LL |         Err(_) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:99:9
    |
 LL |         Err(_) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
   --> $DIR/empty-types.rs:96:11
@@ -160,81 +160,81 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:112:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:115:9
    |
 LL |         Ok(_) => {}
-   |         ^^^^^
+   |         ^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:118:9
    |
 LL |         Ok(_) => {}
-   |         ^^^^^
+   |         ^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:119:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:122:9
    |
 LL |         Ok(_) => {}
-   |         ^^^^^
+   |         ^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:123:9
    |
 LL |         Err(_) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:132:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:135:13
    |
 LL |             _ if false => {}
-   |             ^
+   |             ^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:143:13
    |
 LL |             Some(_) => {}
-   |             ^^^^^^^
+   |             ^^^^^^^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:147:13
    |
 LL |             None => {}
-   |             ---- matches all the values already
+   |             ---- matches all the relevant values
 LL |             _ => {}
-   |             ^ unreachable pattern
+   |             ^ no value can reach this
 
 error[E0004]: non-exhaustive patterns: `Some(!)` not covered
   --> $DIR/empty-types.rs:156:15
@@ -259,73 +259,73 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:199:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:204:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:209:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:214:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:220:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:281:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:284:9
    |
 LL |         (_, _) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `(!, !)` is uninhabited
    |
-   = note: this pattern matches no values because `(!, !)` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:287:9
    |
 LL |         Ok(_) => {}
-   |         ^^^^^
+   |         ^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:288:9
    |
 LL |         Err(_) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0005]: refutable pattern in local binding
   --> $DIR/empty-types.rs:297:13
@@ -478,25 +478,25 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:368:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `[!; 3]` is uninhabited
    |
-   = note: this pattern matches no values because `[!; 3]` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:371:9
    |
 LL |         [_, _, _] => {}
-   |         ^^^^^^^^^
+   |         ^^^^^^^^^ matches no values because `[!; 3]` is uninhabited
    |
-   = note: this pattern matches no values because `[!; 3]` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:374:9
    |
 LL |         [_, ..] => {}
-   |         ^^^^^^^
+   |         ^^^^^^^ matches no values because `[!; 3]` is uninhabited
    |
-   = note: this pattern matches no values because `[!; 3]` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
   --> $DIR/empty-types.rs:388:11
@@ -516,9 +516,9 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:395:9
    |
 LL |         [] => {}
-   |         -- matches all the values already
+   |         -- matches all the relevant values
 LL |         _ => {}
-   |         ^ unreachable pattern
+   |         ^ no value can reach this
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
   --> $DIR/empty-types.rs:397:11
@@ -538,35 +538,35 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:416:9
    |
 LL |         Some(_) => {}
-   |         ^^^^^^^
+   |         ^^^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:421:9
    |
 LL |         Some(_a) => {}
-   |         ^^^^^^^^
+   |         ^^^^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:426:9
    |
 LL |         None => {}
-   |         ---- matches all the values already
+   |         ---- matches all the relevant values
 LL |         // !useful, !reachable
 LL |         _ => {}
-   |         ^ unreachable pattern
+   |         ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:431:9
    |
 LL |         None => {}
-   |         ---- matches all the values already
+   |         ---- matches all the relevant values
 LL |         // !useful, !reachable
 LL |         _a => {}
-   |         ^^ unreachable pattern
+   |         ^^ no value can reach this
 
 error[E0004]: non-exhaustive patterns: `&Some(!)` not covered
   --> $DIR/empty-types.rs:451:11
@@ -662,33 +662,33 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:603:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:606:9
    |
 LL |         _x => {}
-   |         ^^
+   |         ^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:609:9
    |
 LL |         _ if false => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:612:9
    |
 LL |         _x if false => {}
-   |         ^^
+   |         ^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `&!` not covered
   --> $DIR/empty-types.rs:637:11
diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr
index 83b3989ffde..8f60dad4467 100644
--- a/tests/ui/pattern/usefulness/empty-types.normal.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:49:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
   --> $DIR/empty-types.rs:15:9
    |
@@ -15,9 +15,9 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:52:9
    |
 LL |         _x => {}
-   |         ^^
+   |         ^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `&!` is non-empty
   --> $DIR/empty-types.rs:56:11
@@ -38,33 +38,33 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:70:9
    |
 LL |         (_, _) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `(u32, !)` is uninhabited
    |
-   = note: this pattern matches no values because `(u32, !)` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:76:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `(!, !)` is uninhabited
    |
-   = note: this pattern matches no values because `(!, !)` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:79:9
    |
 LL |         (_, _) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `(!, !)` is uninhabited
    |
-   = note: this pattern matches no values because `(!, !)` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:83:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
   --> $DIR/empty-types.rs:87:11
@@ -89,17 +89,17 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:94:9
    |
 LL |         Err(_) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:99:9
    |
 LL |         Err(_) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
   --> $DIR/empty-types.rs:96:11
@@ -151,81 +151,81 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:112:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:115:9
    |
 LL |         Ok(_) => {}
-   |         ^^^^^
+   |         ^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:118:9
    |
 LL |         Ok(_) => {}
-   |         ^^^^^
+   |         ^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:119:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:122:9
    |
 LL |         Ok(_) => {}
-   |         ^^^^^
+   |         ^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:123:9
    |
 LL |         Err(_) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:132:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:135:13
    |
 LL |             _ if false => {}
-   |             ^
+   |             ^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:143:13
    |
 LL |             Some(_) => {}
-   |             ^^^^^^^
+   |             ^^^^^^^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:147:13
    |
 LL |             None => {}
-   |             ---- matches all the values already
+   |             ---- matches all the relevant values
 LL |             _ => {}
-   |             ^ unreachable pattern
+   |             ^ no value can reach this
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
   --> $DIR/empty-types.rs:156:15
@@ -250,73 +250,73 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:199:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:204:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:209:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:214:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:220:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:281:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:284:9
    |
 LL |         (_, _) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `(!, !)` is uninhabited
    |
-   = note: this pattern matches no values because `(!, !)` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:287:9
    |
 LL |         Ok(_) => {}
-   |         ^^^^^
+   |         ^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:288:9
    |
 LL |         Err(_) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `Result<!, !>` is uninhabited
    |
-   = note: this pattern matches no values because `Result<!, !>` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0005]: refutable pattern in local binding
   --> $DIR/empty-types.rs:297:13
@@ -469,25 +469,25 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:368:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `[!; 3]` is uninhabited
    |
-   = note: this pattern matches no values because `[!; 3]` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:371:9
    |
 LL |         [_, _, _] => {}
-   |         ^^^^^^^^^
+   |         ^^^^^^^^^ matches no values because `[!; 3]` is uninhabited
    |
-   = note: this pattern matches no values because `[!; 3]` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:374:9
    |
 LL |         [_, ..] => {}
-   |         ^^^^^^^
+   |         ^^^^^^^ matches no values because `[!; 3]` is uninhabited
    |
-   = note: this pattern matches no values because `[!; 3]` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
   --> $DIR/empty-types.rs:388:11
@@ -507,9 +507,9 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:395:9
    |
 LL |         [] => {}
-   |         -- matches all the values already
+   |         -- matches all the relevant values
 LL |         _ => {}
-   |         ^ unreachable pattern
+   |         ^ no value can reach this
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
   --> $DIR/empty-types.rs:397:11
@@ -529,35 +529,35 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:416:9
    |
 LL |         Some(_) => {}
-   |         ^^^^^^^
+   |         ^^^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:421:9
    |
 LL |         Some(_a) => {}
-   |         ^^^^^^^^
+   |         ^^^^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:426:9
    |
 LL |         None => {}
-   |         ---- matches all the values already
+   |         ---- matches all the relevant values
 LL |         // !useful, !reachable
 LL |         _ => {}
-   |         ^ unreachable pattern
+   |         ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:431:9
    |
 LL |         None => {}
-   |         ---- matches all the values already
+   |         ---- matches all the relevant values
 LL |         // !useful, !reachable
 LL |         _a => {}
-   |         ^^ unreachable pattern
+   |         ^^ no value can reach this
 
 error[E0004]: non-exhaustive patterns: `&Some(_)` not covered
   --> $DIR/empty-types.rs:451:11
@@ -653,33 +653,33 @@ error: unreachable pattern
   --> $DIR/empty-types.rs:603:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:606:9
    |
 LL |         _x => {}
-   |         ^^
+   |         ^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:609:9
    |
 LL |         _ if false => {}
-   |         ^
+   |         ^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/empty-types.rs:612:9
    |
 LL |         _x if false => {}
-   |         ^^
+   |         ^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `&_` not covered
   --> $DIR/empty-types.rs:637:11
diff --git a/tests/ui/pattern/usefulness/explain-unreachable-pats.rs b/tests/ui/pattern/usefulness/explain-unreachable-pats.rs
index 44d194055d9..1cfa5212414 100644
--- a/tests/ui/pattern/usefulness/explain-unreachable-pats.rs
+++ b/tests/ui/pattern/usefulness/explain-unreachable-pats.rs
@@ -6,10 +6,10 @@
 fn main() {
     match (0u8,) {
         (1 | 2,) => {}
-        //~^ NOTE matches all the values already
+        //~^ NOTE matches all the relevant values
         (2,) => {}
         //~^ ERROR unreachable pattern
-        //~| NOTE unreachable pattern
+        //~| NOTE no value can reach this
         _ => {}
     }
 
@@ -20,18 +20,38 @@ fn main() {
         //~^ NOTE matches some of the same values
         (1 | 2,) => {}
         //~^ ERROR unreachable pattern
-        //~| NOTE unreachable pattern
-        //~| NOTE these patterns collectively make the last one unreachable
+        //~| NOTE no value can reach this
+        //~| NOTE multiple earlier patterns match some of the same values
         //~| NOTE collectively making this unreachable
         _ => {}
     }
 
+    match 0u8 {
+        1 => {}
+        //~^ NOTE matches some of the same values
+        2 => {}
+        //~^ NOTE matches some of the same values
+        3 => {}
+        //~^ NOTE matches some of the same values
+        4 => {}
+        //~^ NOTE matches some of the same values
+        5 => {}
+        6 => {}
+        1 ..= 6 => {}
+        //~^ ERROR unreachable pattern
+        //~| NOTE no value can reach this
+        //~| NOTE multiple earlier patterns match some of the same values
+        //~| NOTE ...and 2 other patterns
+        _ => {}
+    }
+
     let res: Result<(),!> = Ok(());
     match res {
         Ok(_) => {}
         Err(_) => {}
         //~^ ERROR unreachable pattern
-        //~| NOTE this pattern matches no values because `!` is uninhabited
+        //~| NOTE matches no values because `!` is uninhabited
+        //~| NOTE to learn more about uninhabited types, see
     }
 
     #[derive(Copy, Clone)]
@@ -44,22 +64,24 @@ fn main() {
     match (&res1, res2) {
         (Err(_), Err(_)) => {}
         //~^ ERROR unreachable pattern
-        //~| NOTE this pattern matches no values because `Void2` is uninhabited
+        //~| NOTE matches no values because `Void2` is uninhabited
+        //~| NOTE to learn more about uninhabited types, see
         _ => {}
     }
     match (res1, &res2) {
         (Err(_), Err(_)) => {}
         //~^ ERROR unreachable pattern
-        //~| NOTE this pattern matches no values because `Void1` is uninhabited
+        //~| NOTE matches no values because `Void1` is uninhabited
+        //~| NOTE to learn more about uninhabited types, see
         _ => {}
     }
 
 
     if let (0
-        //~^ NOTE matches all the values already
+        //~^ NOTE matches all the relevant values
         | 0, _) = (0, 0) {}
         //~^ ERROR unreachable pattern
-        //~| NOTE unreachable pattern
+        //~| NOTE no value can reach this
 
     match (true, true) {
         (_, true) if false => {} // Guarded patterns don't cover others
@@ -69,20 +91,20 @@ fn main() {
         //~^ NOTE matches some of the same values
         (_, true) => {}
         //~^ ERROR unreachable pattern
-        //~| NOTE unreachable pattern
-        //~| NOTE these patterns collectively make the last one unreachable
+        //~| NOTE no value can reach this
+        //~| NOTE multiple earlier patterns match some of the same values
         //~| NOTE collectively making this unreachable
     }
 
     match (true, true) {
         (true, _) => {}
-        //~^ NOTE matches all the values already
+        //~^ NOTE matches all the relevant values
         (false, _) => {}
         #[allow(unreachable_patterns)]
         (_, true) => {} // Doesn't cover below because it's already unreachable.
         (true, true) => {}
         //~^ ERROR unreachable pattern
-        //~| NOTE unreachable pattern
+        //~| NOTE no value can reach this
     }
 
     // Despite skipping some irrelevant cases, we still report a set of rows that covers the
@@ -90,11 +112,11 @@ fn main() {
     match (true, true, 0) {
         (true, _, _) => {}
         (_, true, 0..10) => {}
-        //~^ NOTE matches all the values already
+        //~^ NOTE matches all the relevant values
         (_, true, 10..) => {}
         (_, true, 3) => {}
         //~^ ERROR unreachable pattern
-        //~| NOTE unreachable pattern
+        //~| NOTE no value can reach this
         _ => {}
     }
 }
diff --git a/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr b/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr
index 105d4f73f66..7023c2775e9 100644
--- a/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr
+++ b/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr
@@ -2,10 +2,10 @@ error: unreachable pattern
   --> $DIR/explain-unreachable-pats.rs:10:9
    |
 LL |         (1 | 2,) => {}
-   |         -------- matches all the values already
+   |         -------- matches all the relevant values
 LL |
 LL |         (2,) => {}
-   |         ^^^^ unreachable pattern
+   |         ^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/explain-unreachable-pats.rs:2:9
@@ -17,9 +17,9 @@ error: unreachable pattern
   --> $DIR/explain-unreachable-pats.rs:21:9
    |
 LL |         (1 | 2,) => {}
-   |         ^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/explain-unreachable-pats.rs:21:9
    |
 LL |         (1,) => {}
@@ -32,46 +32,70 @@ LL |         (1 | 2,) => {}
    |         ^^^^^^^^ collectively making this unreachable
 
 error: unreachable pattern
-  --> $DIR/explain-unreachable-pats.rs:32:9
+  --> $DIR/explain-unreachable-pats.rs:40:9
+   |
+LL |         1 ..= 6 => {}
+   |         ^^^^^^^ no value can reach this
+   |
+note: multiple earlier patterns match some of the same values
+  --> $DIR/explain-unreachable-pats.rs:40:9
+   |
+LL |         1 => {}
+   |         - matches some of the same values
+LL |
+LL |         2 => {}
+   |         - matches some of the same values
+LL |
+LL |         3 => {}
+   |         - matches some of the same values
+LL |
+LL |         4 => {}
+   |         - matches some of the same values
+...
+LL |         1 ..= 6 => {}
+   |         ^^^^^^^ ...and 2 other patterns collectively make this unreachable
+
+error: unreachable pattern
+  --> $DIR/explain-unreachable-pats.rs:51:9
    |
 LL |         Err(_) => {}
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/explain-unreachable-pats.rs:45:9
+  --> $DIR/explain-unreachable-pats.rs:65:9
    |
 LL |         (Err(_), Err(_)) => {}
-   |         ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^ matches no values because `Void2` is uninhabited
    |
-   = note: this pattern matches no values because `Void2` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/explain-unreachable-pats.rs:51:9
+  --> $DIR/explain-unreachable-pats.rs:72:9
    |
 LL |         (Err(_), Err(_)) => {}
-   |         ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^ matches no values because `Void1` is uninhabited
    |
-   = note: this pattern matches no values because `Void1` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/explain-unreachable-pats.rs:60:11
+  --> $DIR/explain-unreachable-pats.rs:82:11
    |
 LL |     if let (0
-   |             - matches all the values already
+   |             - matches all the relevant values
 LL |
 LL |         | 0, _) = (0, 0) {}
-   |           ^ unreachable pattern
+   |           ^ no value can reach this
 
 error: unreachable pattern
-  --> $DIR/explain-unreachable-pats.rs:70:9
+  --> $DIR/explain-unreachable-pats.rs:92:9
    |
 LL |         (_, true) => {}
-   |         ^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
-  --> $DIR/explain-unreachable-pats.rs:70:9
+note: multiple earlier patterns match some of the same values
+  --> $DIR/explain-unreachable-pats.rs:92:9
    |
 LL |         (true, _) => {}
    |         --------- matches some of the same values
@@ -83,22 +107,22 @@ LL |         (_, true) => {}
    |         ^^^^^^^^^ collectively making this unreachable
 
 error: unreachable pattern
-  --> $DIR/explain-unreachable-pats.rs:83:9
+  --> $DIR/explain-unreachable-pats.rs:105:9
    |
 LL |         (true, _) => {}
-   |         --------- matches all the values already
+   |         --------- matches all the relevant values
 ...
 LL |         (true, true) => {}
-   |         ^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
-  --> $DIR/explain-unreachable-pats.rs:95:9
+  --> $DIR/explain-unreachable-pats.rs:117:9
    |
 LL |         (_, true, 0..10) => {}
-   |         ---------------- matches all the values already
+   |         ---------------- matches all the relevant values
 ...
 LL |         (_, true, 3) => {}
-   |         ^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^ no value can reach this
 
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
 
diff --git a/tests/ui/pattern/usefulness/floats.stderr b/tests/ui/pattern/usefulness/floats.stderr
index d0a8841d6a8..61aaa2c7626 100644
--- a/tests/ui/pattern/usefulness/floats.stderr
+++ b/tests/ui/pattern/usefulness/floats.stderr
@@ -15,9 +15,9 @@ error: unreachable pattern
   --> $DIR/floats.rs:18:9
    |
 LL |         0.01f16..=6.5f16 => {}
-   |         ---------------- matches all the values already
+   |         ---------------- matches all the relevant values
 LL |         0.01f16 => {}
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/floats.rs:1:9
@@ -29,117 +29,117 @@ error: unreachable pattern
   --> $DIR/floats.rs:19:9
    |
 LL |         0.01f16..=6.5f16 => {}
-   |         ---------------- matches all the values already
+   |         ---------------- matches all the relevant values
 LL |         0.01f16 => {}
 LL |         0.02f16 => {}
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/floats.rs:20:9
    |
 LL |         0.01f16..=6.5f16 => {}
-   |         ---------------- matches all the values already
+   |         ---------------- matches all the relevant values
 ...
 LL |         6.5f16 => {}
-   |         ^^^^^^ unreachable pattern
+   |         ^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/floats.rs:31:9
    |
 LL |         0.01f32..=6.5f32 => {}
-   |         ---------------- matches all the values already
+   |         ---------------- matches all the relevant values
 LL |         0.01f32 => {}
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/floats.rs:32:9
    |
 LL |         0.01f32..=6.5f32 => {}
-   |         ---------------- matches all the values already
+   |         ---------------- matches all the relevant values
 LL |         0.01f32 => {}
 LL |         0.02f32 => {}
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/floats.rs:33:9
    |
 LL |         0.01f32..=6.5f32 => {}
-   |         ---------------- matches all the values already
+   |         ---------------- matches all the relevant values
 ...
 LL |         6.5f32 => {}
-   |         ^^^^^^ unreachable pattern
+   |         ^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/floats.rs:45:9
    |
 LL |         0.01f64..=6.5f64 => {}
-   |         ---------------- matches all the values already
+   |         ---------------- matches all the relevant values
 LL |         0.005f64 => {}
 LL |         0.01f64 => {}
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/floats.rs:46:9
    |
 LL |         0.01f64..=6.5f64 => {}
-   |         ---------------- matches all the values already
+   |         ---------------- matches all the relevant values
 ...
 LL |         0.02f64 => {}
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/floats.rs:47:9
    |
 LL |         0.01f64..=6.5f64 => {}
-   |         ---------------- matches all the values already
+   |         ---------------- matches all the relevant values
 ...
 LL |         6.5f64 => {}
-   |         ^^^^^^ unreachable pattern
+   |         ^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/floats.rs:49:9
    |
 LL |         0.01f64..=6.5f64 => {}
-   |         ---------------- matches all the values already
+   |         ---------------- matches all the relevant values
 ...
 LL |         1.0f64..=4.0f64 => {}
-   |         ^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/floats.rs:62:9
    |
 LL |         0.01f128..=6.5f128 => {}
-   |         ------------------ matches all the values already
+   |         ------------------ matches all the relevant values
 LL |         0.005f128 => {}
 LL |         0.01f128 => {}
-   |         ^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/floats.rs:63:9
    |
 LL |         0.01f128..=6.5f128 => {}
-   |         ------------------ matches all the values already
+   |         ------------------ matches all the relevant values
 ...
 LL |         0.02f128 => {}
-   |         ^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/floats.rs:64:9
    |
 LL |         0.01f128..=6.5f128 => {}
-   |         ------------------ matches all the values already
+   |         ------------------ matches all the relevant values
 ...
 LL |         6.5f128 => {}
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/floats.rs:66:9
    |
 LL |         0.01f128..=6.5f128 => {}
-   |         ------------------ matches all the values already
+   |         ------------------ matches all the relevant values
 ...
 LL |         1.0f128..=4.0f128 => {}
-   |         ^^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^^ no value can reach this
 
 error: aborting due to 15 previous errors
 
diff --git a/tests/ui/pattern/usefulness/impl-trait.stderr b/tests/ui/pattern/usefulness/impl-trait.stderr
index 92932e48538..34b157f0fc4 100644
--- a/tests/ui/pattern/usefulness/impl-trait.stderr
+++ b/tests/ui/pattern/usefulness/impl-trait.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/impl-trait.rs:16:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
   --> $DIR/impl-trait.rs:4:9
    |
@@ -15,49 +15,49 @@ error: unreachable pattern
   --> $DIR/impl-trait.rs:30:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/impl-trait.rs:44:13
    |
 LL |             Some(_) => {}
-   |             ^^^^^^^
+   |             ^^^^^^^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/impl-trait.rs:48:13
    |
 LL |             None => {}
-   |             ---- matches all the values already
+   |             ---- matches all the relevant values
 LL |             _ => {}
-   |             ^ unreachable pattern
+   |             ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/impl-trait.rs:58:13
    |
 LL |             Some(_) => {}
-   |             ^^^^^^^
+   |             ^^^^^^^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/impl-trait.rs:62:13
    |
 LL |             None => {}
-   |             ---- matches all the values already
+   |             ---- matches all the relevant values
 LL |             _ => {}
-   |             ^ unreachable pattern
+   |             ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/impl-trait.rs:75:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/impl-trait.rs:85:9
@@ -65,23 +65,23 @@ error: unreachable pattern
 LL |         _ => {}
    |         - matches any value
 LL |         Some((a, b)) => {}
-   |         ^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/impl-trait.rs:93:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/impl-trait.rs:104:9
    |
 LL |         Some((a, b)) => {}
-   |         ------------ matches all the values already
+   |         ------------ matches all the relevant values
 LL |         Some((mut x, mut y)) => {
-   |         ^^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/impl-trait.rs:123:13
@@ -89,23 +89,23 @@ error: unreachable pattern
 LL |             _ => {}
    |             - matches any value
 LL |             Rec { n: 0, w: Some(Rec { n: 0, w: _ }) } => {}
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/impl-trait.rs:137:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `SecretelyVoid` is uninhabited
    |
-   = note: this pattern matches no values because `SecretelyVoid` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/impl-trait.rs:150:13
    |
 LL |             _ => {}
-   |             ^
+   |             ^ matches no values because `SecretelyDoubleVoid` is uninhabited
    |
-   = note: this pattern matches no values because `SecretelyDoubleVoid` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty
   --> $DIR/impl-trait.rs:22:11
diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr
index 5d86007a853..0d495bcbec1 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr
+++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/reachability.rs:18:17
    |
 LL |     m!(0u8, 42, 42);
-   |             --  ^^ unreachable pattern
+   |             --  ^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
    |
 note: the lint level is defined here
   --> $DIR/reachability.rs:3:9
@@ -16,129 +16,129 @@ error: unreachable pattern
   --> $DIR/reachability.rs:22:22
    |
 LL |     m!(0u8, 20..=30, 20);
-   |             -------  ^^ unreachable pattern
+   |             -------  ^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:23:22
    |
 LL |     m!(0u8, 20..=30, 21);
-   |             -------  ^^ unreachable pattern
+   |             -------  ^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:24:22
    |
 LL |     m!(0u8, 20..=30, 25);
-   |             -------  ^^ unreachable pattern
+   |             -------  ^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:25:22
    |
 LL |     m!(0u8, 20..=30, 29);
-   |             -------  ^^ unreachable pattern
+   |             -------  ^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:26:22
    |
 LL |     m!(0u8, 20..=30, 30);
-   |             -------  ^^ unreachable pattern
+   |             -------  ^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:29:21
    |
 LL |     m!(0u8, 20..30, 20);
-   |             ------  ^^ unreachable pattern
+   |             ------  ^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:30:21
    |
 LL |     m!(0u8, 20..30, 21);
-   |             ------  ^^ unreachable pattern
+   |             ------  ^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:31:21
    |
 LL |     m!(0u8, 20..30, 25);
-   |             ------  ^^ unreachable pattern
+   |             ------  ^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:32:21
    |
 LL |     m!(0u8, 20..30, 29);
-   |             ------  ^^ unreachable pattern
+   |             ------  ^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:36:22
    |
 LL |     m!(0u8, 20..=30, 20..=30);
-   |             -------  ^^^^^^^ unreachable pattern
+   |             -------  ^^^^^^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:37:22
    |
 LL |     m!(0u8, 20.. 30, 20.. 30);
-   |             -------  ^^^^^^^ unreachable pattern
+   |             -------  ^^^^^^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:38:22
    |
 LL |     m!(0u8, 20..=30, 20.. 30);
-   |             -------  ^^^^^^^ unreachable pattern
+   |             -------  ^^^^^^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:40:22
    |
 LL |     m!(0u8, 20..=30, 21..=30);
-   |             -------  ^^^^^^^ unreachable pattern
+   |             -------  ^^^^^^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:41:22
    |
 LL |     m!(0u8, 20..=30, 20..=29);
-   |             -------  ^^^^^^^ unreachable pattern
+   |             -------  ^^^^^^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:43:24
    |
 LL |     m!('a', 'A'..='z', 'a'..='z');
-   |             ---------  ^^^^^^^^^ unreachable pattern
+   |             ---------  ^^^^^^^^^ no value can reach this
    |             |
-   |             matches all the values already
+   |             matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/reachability.rs:50:9
    |
 LL |         5..=8 => {},
-   |         ^^^^^ unreachable pattern
+   |         ^^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/reachability.rs:50:9
    |
 LL |         5 => {},
@@ -156,9 +156,9 @@ error: unreachable pattern
   --> $DIR/reachability.rs:56:9
    |
 LL |         5..15 => {},
-   |         ^^^^^ unreachable pattern
+   |         ^^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/reachability.rs:56:9
    |
 LL |         0..10 => {},
@@ -172,9 +172,9 @@ error: unreachable pattern
   --> $DIR/reachability.rs:63:9
    |
 LL |         5..25 => {},
-   |         ^^^^^ unreachable pattern
+   |         ^^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/reachability.rs:63:9
    |
 LL |         0..10 => {},
@@ -190,9 +190,9 @@ error: unreachable pattern
   --> $DIR/reachability.rs:71:9
    |
 LL |         5..25 => {},
-   |         ^^^^^ unreachable pattern
+   |         ^^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/reachability.rs:71:9
    |
 LL |         0..10 => {},
@@ -210,9 +210,9 @@ error: unreachable pattern
   --> $DIR/reachability.rs:77:9
    |
 LL |         5..15 => {},
-   |         ^^^^^ unreachable pattern
+   |         ^^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/reachability.rs:77:9
    |
 LL |         0..10 => {},
@@ -228,15 +228,15 @@ error: unreachable pattern
 LL |         _ => {},
    |         - matches any value
 LL |         '\u{D7FF}'..='\u{E000}' => {},
-   |         ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/reachability.rs:89:9
    |
 LL |         '\u{D7FF}'..='\u{E000}' => {},
-   |         ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/reachability.rs:89:9
    |
 LL |         '\u{0}'..='\u{D7FF}' => {},
@@ -250,18 +250,18 @@ error: unreachable pattern
   --> $DIR/reachability.rs:105:9
    |
 LL |         &42 => {}
-   |         --- matches all the values already
+   |         --- matches all the relevant values
 LL |         &FOO => {}
-   |         ^^^^ unreachable pattern
+   |         ^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/reachability.rs:106:9
    |
 LL |         &42 => {}
-   |         --- matches all the values already
+   |         --- matches all the relevant values
 LL |         &FOO => {}
 LL |         BAR => {}
-   |         ^^^ unreachable pattern
+   |         ^^^ no value can reach this
 
 error: aborting due to 25 previous errors
 
diff --git a/tests/ui/pattern/usefulness/issue-12116.stderr b/tests/ui/pattern/usefulness/issue-12116.stderr
index b2c2be97563..5929b81f6c2 100644
--- a/tests/ui/pattern/usefulness/issue-12116.stderr
+++ b/tests/ui/pattern/usefulness/issue-12116.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/issue-12116.rs:15:9
    |
 LL |         &IntList::Cons(val, box ref next_list) => tail(next_list),
-   |         -------------------------------------- matches all the values already
+   |         -------------------------------------- matches all the relevant values
 LL |         &IntList::Cons(val, box IntList::Nil)  => IntList::Cons(val, Box::new(IntList::Nil)),
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/issue-12116.rs:4:9
diff --git a/tests/ui/pattern/usefulness/issue-12369.stderr b/tests/ui/pattern/usefulness/issue-12369.stderr
index 7754cbc2484..fb6f89379f8 100644
--- a/tests/ui/pattern/usefulness/issue-12369.stderr
+++ b/tests/ui/pattern/usefulness/issue-12369.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/issue-12369.rs:9:9
    |
 LL |         &[10,a, ref rest @ ..] => 10
-   |         ^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/issue-12369.rs:9:9
    |
 LL |         &[a,b,c] => 3,
diff --git a/tests/ui/pattern/usefulness/issue-13727.stderr b/tests/ui/pattern/usefulness/issue-13727.stderr
index ca8533b33a4..fdba8c87015 100644
--- a/tests/ui/pattern/usefulness/issue-13727.stderr
+++ b/tests/ui/pattern/usefulness/issue-13727.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/issue-13727.rs:7:5
    |
 LL |     256 => print!("0b1110\n"),
-   |     --- matches all the values already
+   |     --- matches all the relevant values
 LL |     512 => print!("0b1111\n"),
-   |     ^^^ unreachable pattern
+   |     ^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/issue-13727.rs:2:9
diff --git a/tests/ui/pattern/usefulness/issue-30240-b.stderr b/tests/ui/pattern/usefulness/issue-30240-b.stderr
index 749515fc94b..4805083c129 100644
--- a/tests/ui/pattern/usefulness/issue-30240-b.stderr
+++ b/tests/ui/pattern/usefulness/issue-30240-b.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/issue-30240-b.rs:12:9
    |
 LL |         "hello" => {}
-   |         ------- matches all the values already
+   |         ------- matches all the relevant values
 LL |         "hello" => {}
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/issue-30240-b.rs:1:9
diff --git a/tests/ui/pattern/usefulness/issue-31221.stderr b/tests/ui/pattern/usefulness/issue-31221.stderr
index 596f4d8096d..e198a9397ee 100644
--- a/tests/ui/pattern/usefulness/issue-31221.stderr
+++ b/tests/ui/pattern/usefulness/issue-31221.stderr
@@ -4,7 +4,7 @@ error: unreachable pattern
 LL |         Var3 => (),
    |         ---- matches any value
 LL |         Var2 => (),
-   |         ^^^^ unreachable pattern
+   |         ^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/issue-31221.rs:4:9
@@ -18,15 +18,15 @@ error: unreachable pattern
 LL |         &Var3 => (),
    |         ----- matches any value
 LL |         &Var2 => (),
-   |         ^^^^^ unreachable pattern
+   |         ^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/issue-31221.rs:31:9
    |
 LL |         anything => ()
-   |         ^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/issue-31221.rs:31:9
    |
 LL |         (Var1, b) => (),
diff --git a/tests/ui/pattern/usefulness/issue-57472.stderr b/tests/ui/pattern/usefulness/issue-57472.stderr
index 68b5b7cb791..5a35dbd7f93 100644
--- a/tests/ui/pattern/usefulness/issue-57472.stderr
+++ b/tests/ui/pattern/usefulness/issue-57472.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/issue-57472.rs:15:13
    |
 LL |             Punned { foo: [_], .. } => println!("foo"),
-   |             ----------------------- matches all the values already
+   |             ----------------------- matches all the relevant values
 LL |             Punned { bar: [_], .. } => println!("bar"),
-   |             ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/issue-57472.rs:2:9
@@ -16,9 +16,9 @@ error: unreachable pattern
   --> $DIR/issue-57472.rs:32:17
    |
 LL |                 Punned { foo: [_] } => println!("foo"),
-   |                 ------------------- matches all the values already
+   |                 ------------------- matches all the relevant values
 LL |                 Punned { bar: [_] } => println!("bar"),
-   |                 ^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |                 ^^^^^^^^^^^^^^^^^^^ no value can reach this
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/pattern/usefulness/match-arm-statics.stderr b/tests/ui/pattern/usefulness/match-arm-statics.stderr
index b6f2b47047d..d5b8a4e6d79 100644
--- a/tests/ui/pattern/usefulness/match-arm-statics.stderr
+++ b/tests/ui/pattern/usefulness/match-arm-statics.stderr
@@ -2,10 +2,10 @@ error: unreachable pattern
   --> $DIR/match-arm-statics.rs:25:9
    |
 LL |         TRUE_TRUE => (),
-   |         --------- matches all the values already
+   |         --------- matches all the relevant values
 ...
 LL |         (true, true) => ()
-   |         ^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/match-arm-statics.rs:2:9
@@ -17,18 +17,18 @@ error: unreachable pattern
   --> $DIR/match-arm-statics.rs:40:9
    |
 LL |         Some(Some(EAST)) => (),
-   |         ---------------- matches all the values already
+   |         ---------------- matches all the relevant values
 ...
 LL |         Some(Some(East)) => (),
-   |         ^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/match-arm-statics.rs:60:9
    |
 LL |         Foo { bar: Some(EAST), baz: NewBool(false) } => ()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/match-arm-statics.rs:60:9
    |
 LL |         Foo { bar: _, baz: NEW_FALSE } => (),
diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr b/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr
index 39675e2bdd4..79a0fb9a8dd 100644
--- a/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr
+++ b/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/match-byte-array-patterns.rs:8:9
    |
 LL |         b"AAAA" => {},
-   |         ------- matches all the values already
+   |         ------- matches all the relevant values
 LL |         &[0x41, 0x41, 0x41, 0x41] => {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/match-byte-array-patterns.rs:1:9
@@ -16,57 +16,57 @@ error: unreachable pattern
   --> $DIR/match-byte-array-patterns.rs:14:9
    |
 LL |         &[0x41, 0x41, 0x41, 0x41] => {}
-   |         ------------------------- matches all the values already
+   |         ------------------------- matches all the relevant values
 LL |         b"AAAA" => {},
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/match-byte-array-patterns.rs:20:9
    |
 LL |         &[_, 0x41, 0x41, 0x41] => {},
-   |         ---------------------- matches all the values already
+   |         ---------------------- matches all the relevant values
 LL |         b"AAAA" => {},
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/match-byte-array-patterns.rs:26:9
    |
 LL |         &[0x41, .., 0x41] => {}
-   |         ----------------- matches all the values already
+   |         ----------------- matches all the relevant values
 LL |         b"AAAA" => {},
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/match-byte-array-patterns.rs:34:9
    |
 LL |         b"AAAA" => {},
-   |         ------- matches all the values already
+   |         ------- matches all the relevant values
 LL |         &[0x41, 0x41, 0x41, 0x41] => {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/match-byte-array-patterns.rs:40:9
    |
 LL |         &[0x41, 0x41, 0x41, 0x41] => {}
-   |         ------------------------- matches all the values already
+   |         ------------------------- matches all the relevant values
 LL |         b"AAAA" => {},
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/match-byte-array-patterns.rs:46:9
    |
 LL |         &[_, 0x41, 0x41, 0x41] => {},
-   |         ---------------------- matches all the values already
+   |         ---------------------- matches all the relevant values
 LL |         b"AAAA" => {},
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/match-byte-array-patterns.rs:52:9
    |
 LL |         &[0x41, .., 0x41] => {}
-   |         ----------------- matches all the values already
+   |         ----------------- matches all the relevant values
 LL |         b"AAAA" => {},
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/pattern/usefulness/match-ref-ice.stderr b/tests/ui/pattern/usefulness/match-ref-ice.stderr
index 9c5af47cc1e..c5f8a95b16b 100644
--- a/tests/ui/pattern/usefulness/match-ref-ice.stderr
+++ b/tests/ui/pattern/usefulness/match-ref-ice.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/match-ref-ice.rs:13:9
    |
 LL |         [1, ref _madoka, 3] => (),
-   |         ------------------- matches all the values already
+   |         ------------------- matches all the relevant values
 LL |         [1, 2, 3] => (),
-   |         ^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/match-ref-ice.rs:1:9
diff --git a/tests/ui/pattern/usefulness/match-vec-fixed.stderr b/tests/ui/pattern/usefulness/match-vec-fixed.stderr
index 04507a22856..b0b8cdf887a 100644
--- a/tests/ui/pattern/usefulness/match-vec-fixed.stderr
+++ b/tests/ui/pattern/usefulness/match-vec-fixed.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/match-vec-fixed.rs:7:9
    |
 LL |         [_, _, _] => {}
-   |         --------- matches all the values already
+   |         --------- matches all the relevant values
 LL |         [_, _, _] => {}
-   |         ^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/match-vec-fixed.rs:1:9
@@ -16,9 +16,9 @@ error: unreachable pattern
   --> $DIR/match-vec-fixed.rs:11:9
    |
 LL |         [_, 1, _] => {}
-   |         --------- matches all the values already
+   |         --------- matches all the relevant values
 LL |         [_, 1, _] => {}
-   |         ^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^ no value can reach this
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/pattern/usefulness/match-vec-unreachable.stderr b/tests/ui/pattern/usefulness/match-vec-unreachable.stderr
index 865f5b319a7..6ed8f0019fe 100644
--- a/tests/ui/pattern/usefulness/match-vec-unreachable.stderr
+++ b/tests/ui/pattern/usefulness/match-vec-unreachable.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/match-vec-unreachable.rs:8:9
    |
 LL |         [a, (2, 3), _] => (),
-   |         -------------- matches all the values already
+   |         -------------- matches all the relevant values
 LL |         [(1, 2), (2, 3), b] => (),
-   |         ^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/match-vec-unreachable.rs:1:9
@@ -16,17 +16,17 @@ error: unreachable pattern
   --> $DIR/match-vec-unreachable.rs:18:9
    |
 LL |         [ref a, _, _, ..] => { println!("{}", a); }
-   |         ----------------- matches all the values already
+   |         ----------------- matches all the relevant values
 LL |         [_, _, _, _, _] => { }
-   |         ^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/match-vec-unreachable.rs:26:9
    |
 LL |         ['a', 'b', 'c', ref _tail @ ..] => {}
-   |         ------------------------------- matches all the values already
+   |         ------------------------------- matches all the relevant values
 LL |         ['a', 'b', 'c'] => {}
-   |         ^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^ no value can reach this
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr b/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr
index 12db48590a4..a6031eaa730 100644
--- a/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr
+++ b/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr
@@ -2,10 +2,10 @@ error: unreachable pattern
   --> $DIR/slice-pattern-const-2.rs:9:9
    |
 LL |         MAGIC_TEST => (),
-   |         ---------- matches all the values already
+   |         ---------- matches all the relevant values
 LL |         [0x00, 0x00, 0x00, 0x00] => (),
 LL |         [4, 5, 6, 7] => (),
-   |         ^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/slice-pattern-const-2.rs:1:9
@@ -17,25 +17,25 @@ error: unreachable pattern
   --> $DIR/slice-pattern-const-2.rs:15:9
    |
 LL |         MAGIC_TEST => (),
-   |         ---------- matches all the values already
+   |         ---------- matches all the relevant values
 LL |         [4, 5, 6, 7] => (),
-   |         ^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-pattern-const-2.rs:21:9
    |
 LL |         [4, 5, 6, 7] => (),
-   |         ------------ matches all the values already
+   |         ------------ matches all the relevant values
 LL |         MAGIC_TEST => (),
-   |         ^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-pattern-const-2.rs:28:9
    |
 LL |         [4] => (),
-   |         --- matches all the values already
+   |         --- matches all the relevant values
 LL |         FOO => (),
-   |         ^^^ unreachable pattern
+   |         ^^^ no value can reach this
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr b/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr
index 5a66799d9c9..bbec9f23602 100644
--- a/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr
+++ b/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr
@@ -2,10 +2,10 @@ error: unreachable pattern
   --> $DIR/slice-pattern-const-3.rs:9:9
    |
 LL |         MAGIC_TEST => (),
-   |         ---------- matches all the values already
+   |         ---------- matches all the relevant values
 LL |         ["0x00", "0x00", "0x00", "0x00"] => (),
 LL |         ["4", "5", "6", "7"] => (),
-   |         ^^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/slice-pattern-const-3.rs:1:9
@@ -17,25 +17,25 @@ error: unreachable pattern
   --> $DIR/slice-pattern-const-3.rs:15:9
    |
 LL |         MAGIC_TEST => (),
-   |         ---------- matches all the values already
+   |         ---------- matches all the relevant values
 LL |         ["4", "5", "6", "7"] => (),
-   |         ^^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-pattern-const-3.rs:21:9
    |
 LL |         ["4", "5", "6", "7"] => (),
-   |         -------------------- matches all the values already
+   |         -------------------- matches all the relevant values
 LL |         MAGIC_TEST => (),
-   |         ^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-pattern-const-3.rs:28:9
    |
 LL |         ["boo"] => (),
-   |         ------- matches all the values already
+   |         ------- matches all the relevant values
 LL |         FOO => (),
-   |         ^^^ unreachable pattern
+   |         ^^^ no value can reach this
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/pattern/usefulness/slice-pattern-const.stderr b/tests/ui/pattern/usefulness/slice-pattern-const.stderr
index 87a85acc4c5..09bbee73577 100644
--- a/tests/ui/pattern/usefulness/slice-pattern-const.stderr
+++ b/tests/ui/pattern/usefulness/slice-pattern-const.stderr
@@ -2,10 +2,10 @@ error: unreachable pattern
   --> $DIR/slice-pattern-const.rs:9:9
    |
 LL |         MAGIC_TEST => (),
-   |         ---------- matches all the values already
+   |         ---------- matches all the relevant values
 LL |         [0x00, 0x00, 0x00, 0x00] => (),
 LL |         [84, 69, 83, 84] => (),
-   |         ^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/slice-pattern-const.rs:1:9
@@ -17,67 +17,67 @@ error: unreachable pattern
   --> $DIR/slice-pattern-const.rs:15:9
    |
 LL |         MAGIC_TEST => (),
-   |         ---------- matches all the values already
+   |         ---------- matches all the relevant values
 LL |         [84, 69, 83, 84] => (),
-   |         ^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-pattern-const.rs:21:9
    |
 LL |         [84, 69, 83, 84] => (),
-   |         ---------------- matches all the values already
+   |         ---------------- matches all the relevant values
 LL |         MAGIC_TEST => (),
-   |         ^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-pattern-const.rs:28:9
    |
 LL |         [4] => (),
-   |         --- matches all the values already
+   |         --- matches all the relevant values
 LL |         FOO => (),
-   |         ^^^ unreachable pattern
+   |         ^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-pattern-const.rs:35:9
    |
 LL |         [4] => (),
-   |         --- matches all the values already
+   |         --- matches all the relevant values
 LL |         BAR => (),
-   |         ^^^ unreachable pattern
+   |         ^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-pattern-const.rs:43:9
    |
 LL |         [] => (),
-   |         -- matches all the values already
+   |         -- matches all the relevant values
 LL |         BOO => (),
-   |         ^^^ unreachable pattern
+   |         ^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-pattern-const.rs:44:9
    |
 LL |         [] => (),
-   |         -- matches all the values already
+   |         -- matches all the relevant values
 LL |         BOO => (),
 LL |         b"" => (),
-   |         ^^^ unreachable pattern
+   |         ^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-pattern-const.rs:45:9
    |
 LL |         [] => (),
-   |         -- matches all the values already
+   |         -- matches all the relevant values
 ...
 LL |         _ => (),
-   |         ^ unreachable pattern
+   |         ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-pattern-const.rs:51:9
    |
 LL |         CONST1 => {}
-   |         ------ matches all the values already
+   |         ------ matches all the relevant values
 LL |         [true] => {}
-   |         ^^^^^^ unreachable pattern
+   |         ^^^^^^ no value can reach this
 
 error: aborting due to 9 previous errors
 
diff --git a/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr b/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr
index 40fbb00de1f..d45779f09a5 100644
--- a/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr
+++ b/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/slice-patterns-reachability.rs:8:9
    |
 LL |         [true, ..] => {}
-   |         ---------- matches all the values already
+   |         ---------- matches all the relevant values
 LL |         [true, ..] => {}
-   |         ^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/slice-patterns-reachability.rs:1:9
@@ -16,44 +16,44 @@ error: unreachable pattern
   --> $DIR/slice-patterns-reachability.rs:9:9
    |
 LL |         [true, ..] => {}
-   |         ---------- matches all the values already
+   |         ---------- matches all the relevant values
 LL |         [true, ..] => {}
 LL |         [true] => {}
-   |         ^^^^^^ unreachable pattern
+   |         ^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-patterns-reachability.rs:14:9
    |
 LL |         [.., true] => {}
-   |         ---------- matches all the values already
+   |         ---------- matches all the relevant values
 LL |         [.., true] => {}
-   |         ^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-patterns-reachability.rs:15:9
    |
 LL |         [.., true] => {}
-   |         ---------- matches all the values already
+   |         ---------- matches all the relevant values
 LL |         [.., true] => {}
 LL |         [true] => {}
-   |         ^^^^^^ unreachable pattern
+   |         ^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-patterns-reachability.rs:20:9
    |
 LL |         [false, .., true] => {}
-   |         ----------------- matches all the values already
+   |         ----------------- matches all the relevant values
 LL |         [false, .., true] => {}
-   |         ^^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/slice-patterns-reachability.rs:21:9
    |
 LL |         [false, .., true] => {}
-   |         ----------------- matches all the values already
+   |         ----------------- matches all the relevant values
 LL |         [false, .., true] => {}
 LL |         [false, true] => {}
-   |         ^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^ no value can reach this
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr b/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr
index cc29c42e4d6..502fa2deda9 100644
--- a/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr
+++ b/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr
@@ -4,7 +4,7 @@ error: unreachable pattern
 LL |         Foo { x: _x, y: _y } => (),
    |         -------------------- matches any value
 LL |         Foo { .. } => ()
-   |         ^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/struct-pattern-match-useless.rs:1:9
diff --git a/tests/ui/pattern/usefulness/top-level-alternation.stderr b/tests/ui/pattern/usefulness/top-level-alternation.stderr
index ad846f23155..7fc03143bc3 100644
--- a/tests/ui/pattern/usefulness/top-level-alternation.stderr
+++ b/tests/ui/pattern/usefulness/top-level-alternation.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/top-level-alternation.rs:4:23
    |
 LL |     while let 0..=2 | 1 = 0 {}
-   |               -----   ^ unreachable pattern
+   |               -----   ^ no value can reach this
    |               |
-   |               matches all the values already
+   |               matches all the relevant values
    |
 note: the lint level is defined here
   --> $DIR/top-level-alternation.rs:1:9
@@ -16,66 +16,66 @@ error: unreachable pattern
   --> $DIR/top-level-alternation.rs:5:20
    |
 LL |     if let 0..=2 | 1 = 0 {}
-   |            -----   ^ unreachable pattern
+   |            -----   ^ no value can reach this
    |            |
-   |            matches all the values already
+   |            matches all the relevant values
 
 error: unreachable pattern
   --> $DIR/top-level-alternation.rs:9:15
    |
 LL |         0
-   |         - matches all the values already
+   |         - matches all the relevant values
 LL |             | 0 => {}
-   |               ^ unreachable pattern
+   |               ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/top-level-alternation.rs:14:15
    |
 LL |         Some(0)
-   |         ------- matches all the values already
+   |         ------- matches all the relevant values
 LL |             | Some(0) => {}
-   |               ^^^^^^^ unreachable pattern
+   |               ^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/top-level-alternation.rs:19:9
    |
 LL |         (0, _) | (_, 0) => {}
-   |         --------------- matches all the values already
+   |         --------------- matches all the relevant values
 LL |         (0, 0) => {}
-   |         ^^^^^^ unreachable pattern
+   |         ^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/top-level-alternation.rs:39:9
    |
 LL |         None | Some(_) => {}
-   |         -------------- matches all the values already
+   |         -------------- matches all the relevant values
 LL |         _ => {}
-   |         ^ unreachable pattern
+   |         ^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/top-level-alternation.rs:43:9
    |
 LL |         None | Some(_) => {}
-   |         -------------- matches all the values already
+   |         -------------- matches all the relevant values
 LL |         Some(_) => {}
-   |         ^^^^^^^ unreachable pattern
+   |         ^^^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/top-level-alternation.rs:44:9
    |
 LL |         None | Some(_) => {}
-   |         -------------- matches all the values already
+   |         -------------- matches all the relevant values
 LL |         Some(_) => {}
 LL |         None => {}
-   |         ^^^^ unreachable pattern
+   |         ^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/top-level-alternation.rs:49:9
    |
 LL |         None | Some(_) => {}
-   |         ^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^ no value can reach this
    |
-note: these patterns collectively make the last one unreachable
+note: multiple earlier patterns match some of the same values
   --> $DIR/top-level-alternation.rs:49:9
    |
 LL |         Some(_) => {}
@@ -89,17 +89,17 @@ error: unreachable pattern
   --> $DIR/top-level-alternation.rs:53:9
    |
 LL |         1 | 2 => {},
-   |         ----- matches all the values already
+   |         ----- matches all the relevant values
 LL |         1..=2 => {},
-   |         ^^^^^ unreachable pattern
+   |         ^^^^^ no value can reach this
 
 error: unreachable pattern
   --> $DIR/top-level-alternation.rs:56:14
    |
 LL |     let (0 | 0) = 0 else { return };
-   |          -   ^ unreachable pattern
+   |          -   ^ no value can reach this
    |          |
-   |          matches all the values already
+   |          matches all the relevant values
 
 error: aborting due to 11 previous errors
 
diff --git a/tests/ui/reachable/unreachable-arm.stderr b/tests/ui/reachable/unreachable-arm.stderr
index 79627404030..50c29b30c69 100644
--- a/tests/ui/reachable/unreachable-arm.stderr
+++ b/tests/ui/reachable/unreachable-arm.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/unreachable-arm.rs:11:9
    |
 LL |         Foo::B(_) | Foo::A(box _, 1) => { }
-   |         ---------------------------- matches all the values already
+   |         ---------------------------- matches all the relevant values
 LL |         Foo::A(_, 1) => { }
-   |         ^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/unreachable-arm.rs:4:9
diff --git a/tests/ui/reachable/unreachable-loop-patterns.stderr b/tests/ui/reachable/unreachable-loop-patterns.stderr
index 9b7c2ba4acd..03959ac1606 100644
--- a/tests/ui/reachable/unreachable-loop-patterns.stderr
+++ b/tests/ui/reachable/unreachable-loop-patterns.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/unreachable-loop-patterns.rs:16:9
    |
 LL |     for _ in unimplemented!() as Void {}
-   |         ^
+   |         ^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
   --> $DIR/unreachable-loop-patterns.rs:3:9
    |
diff --git a/tests/ui/reachable/unreachable-try-pattern.stderr b/tests/ui/reachable/unreachable-try-pattern.stderr
index bc1a6fffda6..b082bc11603 100644
--- a/tests/ui/reachable/unreachable-try-pattern.stderr
+++ b/tests/ui/reachable/unreachable-try-pattern.stderr
@@ -17,9 +17,9 @@ warning: unreachable pattern
   --> $DIR/unreachable-try-pattern.rs:19:24
    |
 LL |     let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?;
-   |                        ^^^^^
+   |                        ^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
   --> $DIR/unreachable-try-pattern.rs:4:9
    |
@@ -30,9 +30,9 @@ warning: unreachable pattern
   --> $DIR/unreachable-try-pattern.rs:30:40
    |
 LL |     let y = (match x { Ok(n) => Ok(n), Err(e) => Err(e) })?;
-   |                                        ^^^^^^
+   |                                        ^^^^^^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/regions/explicit-static-bound-on-trait.rs b/tests/ui/regions/explicit-static-bound-on-trait.rs
new file mode 100644
index 00000000000..835da34d1bb
--- /dev/null
+++ b/tests/ui/regions/explicit-static-bound-on-trait.rs
@@ -0,0 +1,13 @@
+struct Hello<'a> {
+    value: Box<dyn std::any::Any + 'a>,
+    //~^ ERROR lifetime bound not satisfied
+}
+
+impl<'a> Hello<'a> {
+    fn new<T: 'a>(value: T) -> Self {
+        Self { value: Box::new(value) }
+        //~^ ERROR the parameter type `T` may not live long enough
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/regions/explicit-static-bound-on-trait.stderr b/tests/ui/regions/explicit-static-bound-on-trait.stderr
new file mode 100644
index 00000000000..30d39c6e86e
--- /dev/null
+++ b/tests/ui/regions/explicit-static-bound-on-trait.stderr
@@ -0,0 +1,32 @@
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/explicit-static-bound-on-trait.rs:2:12
+   |
+LL |     value: Box<dyn std::any::Any + 'a>,
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime `'a` as defined here
+  --> $DIR/explicit-static-bound-on-trait.rs:1:14
+   |
+LL | struct Hello<'a> {
+   |              ^^
+note: but lifetime parameter must outlive the static lifetime
+  --> $SRC_DIR/core/src/any.rs:LL:COL
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/explicit-static-bound-on-trait.rs:8:23
+   |
+LL |         Self { value: Box::new(value) }
+   |                       ^^^^^^^^^^^^^^^
+   |                       |
+   |                       the parameter type `T` must be valid for the static lifetime...
+   |                       ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL |     fn new<T: 'a + 'static>(value: T) -> Self {
+   |                  +++++++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0310, E0478.
+For more information about an error, try `rustc --explain E0310`.
diff --git a/tests/ui/repr/conflicting-repr-hints.stderr b/tests/ui/repr/conflicting-repr-hints.stderr
index 4dcd8f4fc28..fbfa69e7fb1 100644
--- a/tests/ui/repr/conflicting-repr-hints.stderr
+++ b/tests/ui/repr/conflicting-repr-hints.stderr
@@ -81,3 +81,25 @@ error: aborting due to 12 previous errors
 
 Some errors have detailed explanations: E0566, E0587, E0634.
 For more information about an error, try `rustc --explain E0566`.
+Future incompatibility report: Future breakage diagnostic:
+error[E0566]: conflicting representation hints
+  --> $DIR/conflicting-repr-hints.rs:13:8
+   |
+LL | #[repr(C, u64)]
+   |        ^  ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
+   = note: `#[deny(conflicting_repr_hints)]` on by default
+
+Future breakage diagnostic:
+error[E0566]: conflicting representation hints
+  --> $DIR/conflicting-repr-hints.rs:19:8
+   |
+LL | #[repr(u32, u64)]
+   |        ^^^  ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
+   = note: `#[deny(conflicting_repr_hints)]` on by default
+
diff --git a/tests/ui/resolve/local-shadows-inner-generic.rs b/tests/ui/resolve/local-shadows-inner-generic.rs
new file mode 100644
index 00000000000..d9145b9fe2c
--- /dev/null
+++ b/tests/ui/resolve/local-shadows-inner-generic.rs
@@ -0,0 +1,8 @@
+//@ check-pass
+
+#![allow(non_camel_case_types)]
+
+pub fn main() {
+    let a = 1;
+    struct Foo<a> { field: a, };
+}
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr
index 79b640d9f41..6b3f303eeab 100644
--- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/unreachable.rs:14:9
    |
 LL |         Err(!),
-   |         ^^^^^^
+   |         ^^^^^^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
   --> $DIR/unreachable.rs:4:9
    |
@@ -15,41 +15,41 @@ error: unreachable pattern
   --> $DIR/unreachable.rs:17:19
    |
 LL |     let (Ok(_x) | Err(!)) = res_void;
-   |                   ^^^^^^
+   |                   ^^^^^^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/unreachable.rs:19:12
    |
 LL |     if let Err(!) = res_void {}
-   |            ^^^^^^
+   |            ^^^^^^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/unreachable.rs:21:24
    |
 LL |     if let (Ok(true) | Err(!)) = res_void {}
-   |                        ^^^^^^
+   |                        ^^^^^^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/unreachable.rs:23:23
    |
 LL |     for (Ok(mut _x) | Err(!)) in [res_void] {}
-   |                       ^^^^^^
+   |                       ^^^^^^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/unreachable.rs:27:18
    |
 LL | fn foo((Ok(_x) | Err(!)): Result<bool, Void>) {}
-   |                  ^^^^^^
+   |                  ^^^^^^ matches no values because `Void` is uninhabited
    |
-   = note: this pattern matches no values because `Void` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
index d5f58e436c5..dfd7f9d6300 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/enum_same_crate_empty_match.rs:28:9
    |
 LL |         _ => {}
-   |         ^
+   |         ^ matches no values because `EmptyNonExhaustiveEnum` is uninhabited
    |
-   = note: this pattern matches no values because `EmptyNonExhaustiveEnum` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
   --> $DIR/enum_same_crate_empty_match.rs:1:9
    |
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr
index 4ec4ec9705a..956725fc10e 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/issue-65157-repeated-match-arm.rs:15:9
    |
 LL |         PartiallyInhabitedVariants::Struct { .. } => {},
-   |         ----------------------------------------- matches all the values already
+   |         ----------------------------------------- matches all the relevant values
 LL |         PartiallyInhabitedVariants::Struct { .. } => {},
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
    |
 note: the lint level is defined here
   --> $DIR/issue-65157-repeated-match-arm.rs:2:9
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr
index c399bb9083f..7e7dc802e7f 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/patterns_same_crate.rs:51:9
    |
 LL |         Some(_x) => (),
-   |         ^^^^^^^^
+   |         ^^^^^^^^ matches no values because `UninhabitedEnum` is uninhabited
    |
-   = note: this pattern matches no values because `UninhabitedEnum` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
   --> $DIR/patterns_same_crate.rs:1:9
    |
@@ -15,33 +15,33 @@ error: unreachable pattern
   --> $DIR/patterns_same_crate.rs:56:9
    |
 LL |         Some(_x) => (),
-   |         ^^^^^^^^
+   |         ^^^^^^^^ matches no values because `UninhabitedVariants` is uninhabited
    |
-   = note: this pattern matches no values because `UninhabitedVariants` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/patterns_same_crate.rs:60:15
    |
 LL |     while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() {
-   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `!` is uninhabited
    |
-   = note: this pattern matches no values because `!` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/patterns_same_crate.rs:64:15
    |
 LL |     while let Some(_x) = uninhabited_struct() {
-   |               ^^^^^^^^
+   |               ^^^^^^^^ matches no values because `UninhabitedStruct` is uninhabited
    |
-   = note: this pattern matches no values because `UninhabitedStruct` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/patterns_same_crate.rs:67:15
    |
 LL |     while let Some(_x) = uninhabited_tuple_struct() {
-   |               ^^^^^^^^
+   |               ^^^^^^^^ matches no values because `UninhabitedTupleStruct` is uninhabited
    |
-   = note: this pattern matches no values because `UninhabitedTupleStruct` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr
index 8d0874fa900..693a06a2297 100644
--- a/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr
@@ -16,9 +16,9 @@ error: unreachable pattern
   --> $DIR/warns.rs:15:25
    |
 LL |         x if let None | None = x => {}
-   |                  ----   ^^^^ unreachable pattern
+   |                  ----   ^^^^ no value can reach this
    |                  |
-   |                  matches all the values already
+   |                  matches all the relevant values
    |
 note: the lint level is defined here
   --> $DIR/warns.rs:12:8
diff --git a/tests/ui/sanitizer/cfi/transparent-has-regions.rs b/tests/ui/sanitizer/cfi/transparent-has-regions.rs
new file mode 100644
index 00000000000..b70e1ea1791
--- /dev/null
+++ b/tests/ui/sanitizer/cfi/transparent-has-regions.rs
@@ -0,0 +1,18 @@
+//@ needs-sanitizer-cfi
+//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi
+//@ no-prefer-dynamic
+//@ only-x86_64-unknown-linux-gnu
+//@ build-pass
+
+pub trait Trait {}
+
+impl Trait for i32 {}
+
+#[repr(transparent)]
+struct BoxedTrait(Box<dyn Trait + 'static>);
+
+fn hello(x: BoxedTrait) {}
+
+fn main() {
+    hello(BoxedTrait(Box::new(1)));
+}
diff --git a/tests/ui/traits/object/pretty.rs b/tests/ui/traits/object/pretty.rs
index 8958871ed5d..6660ff040f7 100644
--- a/tests/ui/traits/object/pretty.rs
+++ b/tests/ui/traits/object/pretty.rs
@@ -18,6 +18,10 @@ trait FixedHrtb: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> {}
 trait AnyDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super {}
 trait FixedDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super<Assoc = u8> {}
 
+trait HasGat<Outer> {
+    type Assoc<Inner> where Self: Sized;
+}
+
 fn dyn_super(x: &dyn Super<Assoc = u8>) { x } //~ERROR mismatched types
 fn dyn_any(x: &dyn Any<Assoc = u8>) { x } //~ERROR mismatched types
 fn dyn_fixed(x: &dyn Fixed) { x } //~ERROR mismatched types
@@ -34,4 +38,7 @@ fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } //~ERROR mismatched types
 fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x } //~ERROR mismatched types
 fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } //~ERROR mismatched types
 
+fn dyn_has_gat(x: &dyn HasGat<u8, Assoc<bool> = ()>) { x } //~ERROR mismatched types
+//~^ WARN unnecessary associated type bound
+
 fn main() {}
diff --git a/tests/ui/traits/object/pretty.stderr b/tests/ui/traits/object/pretty.stderr
index bc645e5f967..6964d97c08e 100644
--- a/tests/ui/traits/object/pretty.stderr
+++ b/tests/ui/traits/object/pretty.stderr
@@ -1,5 +1,14 @@
+warning: unnecessary associated type bound for not object safe associated type
+  --> $DIR/pretty.rs:41:35
+   |
+LL | fn dyn_has_gat(x: &dyn HasGat<u8, Assoc<bool> = ()>) { x }
+   |                                   ^^^^^^^^^^^^^^^^ help: remove this bound
+   |
+   = note: this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized`
+   = note: `#[warn(unused_associated_type_bounds)]` on by default
+
 error[E0308]: mismatched types
-  --> $DIR/pretty.rs:21:43
+  --> $DIR/pretty.rs:25:43
    |
 LL | fn dyn_super(x: &dyn Super<Assoc = u8>) { x }
    |                                        -  ^ expected `()`, found `&dyn Super<Assoc = u8>`
@@ -10,7 +19,7 @@ LL | fn dyn_super(x: &dyn Super<Assoc = u8>) { x }
               found reference `&dyn Super<Assoc = u8>`
 
 error[E0308]: mismatched types
-  --> $DIR/pretty.rs:22:39
+  --> $DIR/pretty.rs:26:39
    |
 LL | fn dyn_any(x: &dyn Any<Assoc = u8>) { x }
    |                                    -  ^ expected `()`, found `&dyn Any<Assoc = u8>`
@@ -21,7 +30,7 @@ LL | fn dyn_any(x: &dyn Any<Assoc = u8>) { x }
               found reference `&dyn Any<Assoc = u8>`
 
 error[E0308]: mismatched types
-  --> $DIR/pretty.rs:23:31
+  --> $DIR/pretty.rs:27:31
    |
 LL | fn dyn_fixed(x: &dyn Fixed) { x }
    |                            -  ^ expected `()`, found `&dyn Fixed`
@@ -32,7 +41,7 @@ LL | fn dyn_fixed(x: &dyn Fixed) { x }
               found reference `&dyn Fixed`
 
 error[E0308]: mismatched types
-  --> $DIR/pretty.rs:24:50
+  --> $DIR/pretty.rs:28:50
    |
 LL | fn dyn_fixed_multi(x: &dyn Fixed<Assoc = u16>) { x }
    |                                               -  ^ expected `()`, found `&dyn Fixed<Assoc = u16>`
@@ -43,7 +52,7 @@ LL | fn dyn_fixed_multi(x: &dyn Fixed<Assoc = u16>) { x }
               found reference `&dyn Fixed<Assoc = u16>`
 
 error[E0308]: mismatched types
-  --> $DIR/pretty.rs:25:38
+  --> $DIR/pretty.rs:29:38
    |
 LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x }
    |                                   -  ^ expected `()`, found `&dyn FixedSub`
@@ -54,7 +63,7 @@ LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x }
               found reference `&dyn FixedSub`
 
 error[E0308]: mismatched types
-  --> $DIR/pretty.rs:26:44
+  --> $DIR/pretty.rs:30:44
    |
 LL | fn dyn_fixed_static(x: &dyn FixedStatic) { x }
    |                                         -  ^ expected `()`, found `&dyn FixedStatic`
@@ -65,7 +74,7 @@ LL | fn dyn_fixed_static(x: &dyn FixedStatic) { x }
               found reference `&dyn FixedStatic`
 
 error[E0308]: mismatched types
-  --> $DIR/pretty.rs:28:75
+  --> $DIR/pretty.rs:32:75
    |
 LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x }
    |                                                                        -  ^ expected `()`, found `&dyn SuperGeneric<'a, Assoc2 = &u8>`
@@ -76,7 +85,7 @@ LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x
               found reference `&dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>`
 
 error[E0308]: mismatched types
-  --> $DIR/pretty.rs:29:71
+  --> $DIR/pretty.rs:33:71
    |
 LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x }
    |                                                                    -  ^ expected `()`, found `&dyn AnyGeneric<'a, Assoc2 = &u8>`
@@ -87,7 +96,7 @@ LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x }
               found reference `&dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>`
 
 error[E0308]: mismatched types
-  --> $DIR/pretty.rs:30:60
+  --> $DIR/pretty.rs:34:60
    |
 LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x }
    |                                                         -  ^ expected `()`, found `&dyn FixedGeneric1<'a>`
@@ -98,7 +107,7 @@ LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x }
               found reference `&dyn for<'a> FixedGeneric1<'a>`
 
 error[E0308]: mismatched types
-  --> $DIR/pretty.rs:31:60
+  --> $DIR/pretty.rs:35:60
    |
 LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x }
    |                                                         -  ^ expected `()`, found `&dyn FixedGeneric2<'a>`
@@ -109,7 +118,7 @@ LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x }
               found reference `&dyn for<'a> FixedGeneric2<'a>`
 
 error[E0308]: mismatched types
-  --> $DIR/pretty.rs:32:79
+  --> $DIR/pretty.rs:36:79
    |
 LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x }
    |                                                                            -  ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc2 = ...>`
@@ -120,7 +129,7 @@ LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>)
               found reference `&dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>`
 
 error[E0308]: mismatched types
-  --> $DIR/pretty.rs:33:40
+  --> $DIR/pretty.rs:37:40
    |
 LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x }
    |                                     -  ^ expected `()`, found `&dyn FixedHrtb`
@@ -131,7 +140,7 @@ LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x }
               found reference `&dyn FixedHrtb`
 
 error[E0308]: mismatched types
-  --> $DIR/pretty.rs:34:73
+  --> $DIR/pretty.rs:38:73
    |
 LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x }
    |                                                                      -  ^ expected `()`, found `&dyn AnyDifferentBinders<Assoc = ...>`
@@ -142,7 +151,7 @@ LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x }
               found reference `&dyn AnyDifferentBinders<Assoc = u8>`
 
 error[E0308]: mismatched types
-  --> $DIR/pretty.rs:35:65
+  --> $DIR/pretty.rs:39:65
    |
 LL | fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x }
    |                                                              -  ^ expected `()`, found `&dyn FixedDifferentBinders`
@@ -152,6 +161,17 @@ LL | fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x }
    = note: expected unit type `()`
               found reference `&dyn FixedDifferentBinders`
 
-error: aborting due to 14 previous errors
+error[E0308]: mismatched types
+  --> $DIR/pretty.rs:41:56
+   |
+LL | fn dyn_has_gat(x: &dyn HasGat<u8, Assoc<bool> = ()>) { x }
+   |                                                     -  ^ expected `()`, found `&dyn HasGat<u8, Assoc<bool> = ()>`
+   |                                                     |
+   |                                                     help: try adding a return type: `-> &dyn HasGat<u8, Assoc<bool> = ()>`
+   |
+   = note: expected unit type `()`
+              found reference `&dyn HasGat<u8, Assoc<bool> = ()>`
+
+error: aborting due to 15 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/transmutability/arrays/huge-len.stderr b/tests/ui/transmutability/arrays/huge-len.stderr
index 3fc652f47c1..37160c5c959 100644
--- a/tests/ui/transmutability/arrays/huge-len.stderr
+++ b/tests/ui/transmutability/arrays/huge-len.stderr
@@ -2,7 +2,7 @@ error[E0277]: `()` cannot be safely transmuted into `ExplicitlyPadded`
   --> $DIR/huge-len.rs:21:41
    |
 LL |     assert::is_maybe_transmutable::<(), ExplicitlyPadded>();
-   |                                         ^^^^^^^^^^^^^^^^ analyzing the transmutability of `ExplicitlyPadded` is not yet supported
+   |                                         ^^^^^^^^^^^^^^^^ values of the type `ExplicitlyPadded` are too big for the current architecture
    |
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/huge-len.rs:8:14
@@ -17,7 +17,7 @@ error[E0277]: `ExplicitlyPadded` cannot be safely transmuted into `()`
   --> $DIR/huge-len.rs:24:55
    |
 LL |     assert::is_maybe_transmutable::<ExplicitlyPadded, ()>();
-   |                                                       ^^ analyzing the transmutability of `ExplicitlyPadded` is not yet supported
+   |                                                       ^^ values of the type `ExplicitlyPadded` are too big for the current architecture
    |
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/huge-len.rs:8:14
diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs
new file mode 100644
index 00000000000..8c18de11196
--- /dev/null
+++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs
@@ -0,0 +1,26 @@
+// An unknown destination type should be gracefully handled.
+
+#![crate_type = "lib"]
+#![feature(transmutability)]
+#![allow(incomplete_features)]
+
+mod assert {
+    use std::mem::BikeshedIntrinsicFrom;
+
+    pub fn is_transmutable<Src, Dst>()
+    where
+        Dst: BikeshedIntrinsicFrom<Src>
+    {}
+}
+
+fn should_gracefully_handle_unknown_dst_field() {
+    #[repr(C)] struct Src;
+    #[repr(C)] struct Dst(Missing); //~ cannot find type
+    assert::is_transmutable::<Src, Dst>(); //~ ERROR cannot be safely transmuted
+}
+
+fn should_gracefully_handle_unknown_dst_ref_field() {
+    #[repr(C)] struct Src(&'static Src);
+    #[repr(C)] struct Dst(&'static Missing); //~ cannot find type
+    assert::is_transmutable::<Src, Dst>(); //~ ERROR cannot be safely transmuted
+}
diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.stderr
new file mode 100644
index 00000000000..df10919f6d3
--- /dev/null
+++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.stderr
@@ -0,0 +1,46 @@
+error[E0412]: cannot find type `Missing` in this scope
+  --> $DIR/unknown_dst_field.rs:18:27
+   |
+LL |     #[repr(C)] struct Dst(Missing);
+   |                           ^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `Missing` in this scope
+  --> $DIR/unknown_dst_field.rs:24:36
+   |
+LL |     #[repr(C)] struct Dst(&'static Missing);
+   |                                    ^^^^^^^ not found in this scope
+
+error[E0277]: `should_gracefully_handle_unknown_dst_field::Src` cannot be safely transmuted into `should_gracefully_handle_unknown_dst_field::Dst`
+  --> $DIR/unknown_dst_field.rs:19:36
+   |
+LL |     assert::is_transmutable::<Src, Dst>();
+   |                                    ^^^ `should_gracefully_handle_unknown_dst_field::Dst` has an unknown layout
+   |
+note: required by a bound in `is_transmutable`
+  --> $DIR/unknown_dst_field.rs:12:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `should_gracefully_handle_unknown_dst_ref_field::Src` cannot be safely transmuted into `should_gracefully_handle_unknown_dst_ref_field::Dst`
+  --> $DIR/unknown_dst_field.rs:25:36
+   |
+LL |     assert::is_transmutable::<Src, Dst>();
+   |                                    ^^^ `should_gracefully_handle_unknown_dst_ref_field::Dst` has an unknown layout
+   |
+note: required by a bound in `is_transmutable`
+  --> $DIR/unknown_dst_field.rs:12:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0412.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs
index 58c16d773e1..1da16e67223 100644
--- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs
+++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs
@@ -13,8 +13,14 @@ mod assert {
     {}
 }
 
-fn should_gracefully_handle_unknown_dst_field() {
-    #[repr(C)] struct Src;
-    #[repr(C)] struct Dst(Missing); //~ cannot find type
+fn should_gracefully_handle_unknown_src_field() {
+    #[repr(C)] struct Src(Missing); //~ cannot find type
+    #[repr(C)] struct Dst();
+    assert::is_transmutable::<Src, Dst>(); //~ ERROR cannot be safely transmuted
+}
+
+fn should_gracefully_handle_unknown_src_ref_field() {
+    #[repr(C)] struct Src(&'static Missing); //~ cannot find type
+    #[repr(C)] struct Dst(&'static Dst);
     assert::is_transmutable::<Src, Dst>(); //~ ERROR cannot be safely transmuted
 }
diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr
index cabc7bcfef7..6ec66e17061 100644
--- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr
+++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr
@@ -1,14 +1,35 @@
 error[E0412]: cannot find type `Missing` in this scope
-  --> $DIR/unknown_src_field.rs:18:27
+  --> $DIR/unknown_src_field.rs:17:27
    |
-LL |     #[repr(C)] struct Dst(Missing);
+LL |     #[repr(C)] struct Src(Missing);
    |                           ^^^^^^^ not found in this scope
 
-error[E0277]: `Src` cannot be safely transmuted into `Dst`
+error[E0412]: cannot find type `Missing` in this scope
+  --> $DIR/unknown_src_field.rs:23:36
+   |
+LL |     #[repr(C)] struct Src(&'static Missing);
+   |                                    ^^^^^^^ not found in this scope
+
+error[E0277]: `should_gracefully_handle_unknown_src_field::Src` cannot be safely transmuted into `should_gracefully_handle_unknown_src_field::Dst`
   --> $DIR/unknown_src_field.rs:19:36
    |
 LL |     assert::is_transmutable::<Src, Dst>();
-   |                                    ^^^ analyzing the transmutability of `Dst` is not yet supported
+   |                                    ^^^ `should_gracefully_handle_unknown_src_field::Src` has an unknown layout
+   |
+note: required by a bound in `is_transmutable`
+  --> $DIR/unknown_src_field.rs:12:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `should_gracefully_handle_unknown_src_ref_field::Src` cannot be safely transmuted into `should_gracefully_handle_unknown_src_ref_field::Dst`
+  --> $DIR/unknown_src_field.rs:25:36
+   |
+LL |     assert::is_transmutable::<Src, Dst>();
+   |                                    ^^^ `should_gracefully_handle_unknown_src_ref_field::Src` has an unknown layout
    |
 note: required by a bound in `is_transmutable`
   --> $DIR/unknown_src_field.rs:12:14
@@ -19,7 +40,7 @@ LL |     where
 LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0277, E0412.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs
index 64110753832..4c285a616b3 100644
--- a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs
+++ b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs
@@ -22,5 +22,4 @@ fn should_pad_explicitly_packed_field() {
     //~^ ERROR: recursive type
 
     assert::is_maybe_transmutable::<ExplicitlyPadded, ()>();
-    //~^ ERROR: cannot be safely transmuted
 }
diff --git a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr
index ebfb5361143..7fb051f6625 100644
--- a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr
+++ b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr
@@ -15,22 +15,7 @@ error[E0391]: cycle detected when computing layout of `should_pad_explicitly_pac
    = note: cycle used when evaluating trait selection obligation `(): core::mem::transmutability::BikeshedIntrinsicFrom<should_pad_explicitly_packed_field::ExplicitlyPadded, core::mem::transmutability::Assume { alignment: false, lifetimes: false, safety: false, validity: false }>`
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
-error[E0277]: `ExplicitlyPadded` cannot be safely transmuted into `()`
-  --> $DIR/transmute_infinitely_recursive_type.rs:24:55
-   |
-LL |     assert::is_maybe_transmutable::<ExplicitlyPadded, ()>();
-   |                                                       ^^ analyzing the transmutability of `ExplicitlyPadded` is not yet supported
-   |
-note: required by a bound in `is_maybe_transmutable`
-  --> $DIR/transmute_infinitely_recursive_type.rs:14:14
-   |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this function
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src>,
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0072, E0277, E0391.
+Some errors have detailed explanations: E0072, E0391.
 For more information about an error, try `rustc --explain E0072`.
diff --git a/tests/ui/uninhabited/uninhabited-patterns.stderr b/tests/ui/uninhabited/uninhabited-patterns.stderr
index 4e4aaa93f80..0e1c9d31a73 100644
--- a/tests/ui/uninhabited/uninhabited-patterns.stderr
+++ b/tests/ui/uninhabited/uninhabited-patterns.stderr
@@ -2,9 +2,9 @@ error: unreachable pattern
   --> $DIR/uninhabited-patterns.rs:29:9
    |
 LL |         Ok(box _) => (),
-   |         ^^^^^^^^^
+   |         ^^^^^^^^^ matches no values because `NotSoSecretlyEmpty` is uninhabited
    |
-   = note: this pattern matches no values because `NotSoSecretlyEmpty` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
   --> $DIR/uninhabited-patterns.rs:3:9
    |
@@ -15,17 +15,17 @@ error: unreachable pattern
   --> $DIR/uninhabited-patterns.rs:38:9
    |
 LL |         Err(Ok(_y)) => (),
-   |         ^^^^^^^^^^^
+   |         ^^^^^^^^^^^ matches no values because `NotSoSecretlyEmpty` is uninhabited
    |
-   = note: this pattern matches no values because `NotSoSecretlyEmpty` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
   --> $DIR/uninhabited-patterns.rs:41:15
    |
 LL |     while let Some(_y) = foo() {
-   |               ^^^^^^^^
+   |               ^^^^^^^^ matches no values because `NotSoSecretlyEmpty` is uninhabited
    |
-   = note: this pattern matches no values because `NotSoSecretlyEmpty` is uninhabited
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: aborting due to 3 previous errors