about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules2
-rw-r--r--Cargo.lock1
-rw-r--r--RELEASES.md2
-rw-r--r--compiler/rustc_borrowck/src/borrowck_errors.rs7
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs1
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs6
-rw-r--r--compiler/rustc_borrowck/src/renumber.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs96
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs83
-rw-r--r--compiler/rustc_const_eval/src/interpret/mod.rs2
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs18
-rw-r--r--compiler/rustc_data_structures/src/sync.rs7
-rw-r--r--compiler/rustc_driver/src/lib.rs2
-rw-r--r--compiler/rustc_error_messages/locales/en-US/privacy.ftl12
-rw-r--r--compiler/rustc_error_messages/src/lib.rs1
-rw-r--r--compiler/rustc_errors/src/emitter.rs5
-rw-r--r--compiler/rustc_expand/src/base.rs3
-rw-r--r--compiler/rustc_expand/src/lib.rs1
-rw-r--r--compiler/rustc_hir/src/intravisit.rs24
-rw-r--r--compiler/rustc_hir/src/itemlikevisit.rs9
-rw-r--r--compiler/rustc_hir/src/lib.rs1
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs2
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs14
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs13
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs9
-rw-r--r--compiler/rustc_lint/src/internal.rs9
-rw-r--r--compiler/rustc_lint/src/types.rs148
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs21
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs17
-rw-r--r--compiler/rustc_middle/src/query/mod.rs19
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs69
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs8
-rw-r--r--compiler/rustc_parse/src/lib.rs1
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs2
-rw-r--r--compiler/rustc_privacy/Cargo.toml7
-rw-r--r--compiler/rustc_privacy/src/errors.rs75
-rw-r--r--compiler/rustc_privacy/src/lib.rs92
-rw-r--r--compiler/rustc_session/src/session.rs23
-rw-r--r--compiler/rustc_target/src/lib.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_darwin.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs11
-rw-r--r--compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs12
-rw-r--r--compiler/rustc_target/src/spec/armv7_linux_androideabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs6
-rw-r--r--compiler/rustc_target/src/spec/avr_gnu_base.rs9
-rw-r--r--compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs2
-rw-r--r--compiler/rustc_target/src/spec/fuchsia_base.rs33
-rw-r--r--compiler/rustc_target/src/spec/hermit_base.rs9
-rw-r--r--compiler/rustc_target/src/spec/i686_apple_darwin.rs2
-rw-r--r--compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs9
-rw-r--r--compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs28
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_freebsd.rs4
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_haiku.rs2
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs3
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_netbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_openbsd.rs3
-rw-r--r--compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs9
-rw-r--r--compiler/rustc_target/src/spec/i686_wrs_vxworks.rs2
-rw-r--r--compiler/rustc_target/src/spec/illumos_base.rs11
-rw-r--r--compiler/rustc_target/src/spec/mipsel_sony_psp.rs6
-rw-r--r--compiler/rustc_target/src/spec/mod.rs38
-rw-r--r--compiler/rustc_target/src/spec/msvc_base.rs13
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs2
-rw-r--r--compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs6
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs2
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs3
-rw-r--r--compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs3
-rw-r--r--compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs2
-rw-r--r--compiler/rustc_target/src/spec/tests/tests_impl.rs97
-rw-r--r--compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs9
-rw-r--r--compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/uefi_msvc_base.rs40
-rw-r--r--compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs23
-rw-r--r--compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs45
-rw-r--r--compiler/rustc_target/src/spec/wasm32_wasi.rs6
-rw-r--r--compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs30
-rw-r--r--compiler/rustc_target/src/spec/wasm_base.rs105
-rw-r--r--compiler/rustc_target/src/spec/windows_gnu_base.rs82
-rw-r--r--compiler/rustc_target/src/spec/windows_gnullvm_base.rs33
-rw-r--r--compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs31
-rw-r--r--compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs9
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_darwin.rs3
-rw-r--r--compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs73
-rw-r--r--compiler/rustc_target/src/spec/x86_64_linux_android.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_solaris.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs9
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs3
-rw-r--r--compiler/rustc_target/src/spec/x86_64_sun_solaris.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_redox.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs9
-rw-r--r--compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs78
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs21
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/check.rs13
-rw-r--r--compiler/rustc_typeck/src/check/generator_interior.rs2
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs10
-rw-r--r--compiler/rustc_typeck/src/check/regionck.rs1
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs174
-rw-r--r--compiler/rustc_typeck/src/coherence/mod.rs19
-rw-r--r--compiler/rustc_typeck/src/coherence/orphan.rs176
-rw-r--r--compiler/rustc_typeck/src/coherence/unsafety.rs35
-rw-r--r--compiler/rustc_typeck/src/collect.rs4
-rw-r--r--compiler/rustc_typeck/src/collect/type_of.rs2
-rw-r--r--compiler/rustc_typeck/src/impl_wf_check.rs54
-rw-r--r--compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs41
-rw-r--r--compiler/rustc_typeck/src/lib.rs18
-rw-r--r--library/alloc/src/boxed/thin.rs8
-rw-r--r--library/alloc/tests/fmt.rs2
-rw-r--r--library/core/src/iter/adapters/chain.rs72
-rw-r--r--library/core/src/iter/adapters/flatten.rs41
-rw-r--r--library/core/src/iter/adapters/fuse.rs60
-rw-r--r--library/core/src/num/nonzero.rs4
-rw-r--r--library/core/tests/alloc.rs4
-rw-r--r--library/core/tests/hash/mod.rs5
-rw-r--r--library/core/tests/ptr.rs26
-rw-r--r--library/core/tests/waker.rs4
-rw-r--r--library/std/src/io/cursor.rs126
-rw-r--r--library/std/src/io/cursor/tests.rs48
-rw-r--r--library/std/src/sys/hermit/condvar.rs19
-rw-r--r--library/std/src/sys/hermit/mutex.rs4
-rw-r--r--library/std/src/sys/hermit/rwlock.rs11
-rw-r--r--src/bootstrap/native.rs2
-rw-r--r--src/librustdoc/config.rs24
-rw-r--r--src/librustdoc/json/conversions.rs7
-rw-r--r--src/librustdoc/lib.rs2
m---------src/llvm-project0
-rw-r--r--src/test/run-make/issue-88756-default-output/Makefile4
-rw-r--r--src/test/run-make/issue-88756-default-output/README.md1
-rw-r--r--src/test/run-make/issue-88756-default-output/output-default.stdout193
-rw-r--r--src/test/run-make/issue-88756-default-output/x.rs1
-rw-r--r--src/test/run-make/issue-88756-opt-help/Makefile4
-rw-r--r--src/test/run-make/issue-88756-opt-help/README.md1
-rw-r--r--src/test/run-make/issue-88756-opt-help/output-default.stdout193
-rw-r--r--src/test/run-make/issue-88756-opt-help/x.rs1
-rw-r--r--src/test/rustdoc-json/assoc_items.rs29
-rw-r--r--src/test/rustdoc-ui/issue-83883-describe-lints.stdout216
-rw-r--r--src/test/ui/associated-item/associated-item-duplicate-names-2.stderr2
-rw-r--r--src/test/ui/associated-item/issue-48027.stderr24
-rw-r--r--src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr12
-rw-r--r--src/test/ui/associated-types/hr-associated-type-bound-2.rs2
-rw-r--r--src/test/ui/associated-types/hr-associated-type-bound-2.stderr17
-rw-r--r--src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr12
-rw-r--r--src/test/ui/associated-types/impl-wf-cycle-1.rs4
-rw-r--r--src/test/ui/associated-types/impl-wf-cycle-1.stderr34
-rw-r--r--src/test/ui/associated-types/impl-wf-cycle-2.rs3
-rw-r--r--src/test/ui/associated-types/impl-wf-cycle-2.stderr16
-rw-r--r--src/test/ui/associated-types/issue-59324.stderr12
-rw-r--r--src/test/ui/chalkify/bugs/async.rs2
-rw-r--r--src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr24
-rw-r--r--src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr24
-rw-r--r--src/test/ui/coherence/coherence-impls-copy.stderr42
-rw-r--r--src/test/ui/coherence/coherence-impls-send.stderr22
-rw-r--r--src/test/ui/coherence/coherence-impls-sized.stderr66
-rw-r--r--src/test/ui/coherence/coherence-with-closure.stderr18
-rw-r--r--src/test/ui/coherence/coherence-with-generator.stderr18
-rw-r--r--src/test/ui/const-generics/const-param-elided-lifetime.min.stderr18
-rw-r--r--src/test/ui/error-codes/E0201.stderr8
-rw-r--r--src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr20
-rw-r--r--src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr12
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-80626.rs2
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-80626.stderr13
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-86218.rs2
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-87735.rs2
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-87748.rs2
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-87755.rs2
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-87803.rs2
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-88382.rs2
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-88460.rs2
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-88526.rs2
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-89008.rs2
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr36
-rw-r--r--src/test/ui/hrtb/issue-95034.rs2
-rw-r--r--src/test/ui/impl-duplicate-methods.stderr4
-rw-r--r--src/test/ui/impl-trait/auto-trait.stderr18
-rw-r--r--src/test/ui/impl-trait/negative-reasoning.stderr22
-rw-r--r--src/test/ui/impl-trait/nested-return-type2.rs8
-rw-r--r--src/test/ui/impl-trait/nested-return-type2.stderr16
-rw-r--r--src/test/ui/issues/issue-20413.rs9
-rw-r--r--src/test/ui/issues/issue-20413.stderr69
-rw-r--r--src/test/ui/issues/issue-4265.stderr13
-rw-r--r--src/test/ui/issues/issue-47511.rs2
-rw-r--r--src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr44
-rw-r--r--src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs32
-rw-r--r--src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr126
-rw-r--r--src/test/ui/lint/lint-invalid-atomic-ordering-exchange.rs32
-rw-r--r--src/test/ui/lint/lint-invalid-atomic-ordering-exchange.stderr126
-rw-r--r--src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs32
-rw-r--r--src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr126
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs9
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout29
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs32
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout147
-rw-r--r--src/test/ui/methods/method-macro-backtrace.stderr4
-rw-r--r--src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr52
-rw-r--r--src/test/ui/suggestions/auxiliary/not-object-safe.rs6
-rw-r--r--src/test/ui/suggestions/issue-98500.rs14
-rw-r--r--src/test/ui/suggestions/issue-98500.stderr24
-rw-r--r--src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed2
-rw-r--r--src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr22
-rw-r--r--src/test/ui/trait-bounds/select-param-env-instead-of-blanket.rs2
-rw-r--r--src/test/ui/traits/alias/issue-83613.stderr16
-rw-r--r--src/test/ui/traits/issue-78372.rs1
-rw-r--r--src/test/ui/traits/issue-78372.stderr15
-rw-r--r--src/test/ui/traits/issue-8153.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs2
-rw-r--r--src/test/ui/union/issue-81199.stderr20
-rw-r--r--src/test/ui/wf/issue-96810.rs12
-rw-r--r--src/test/ui/wf/issue-96810.stderr19
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_flatten.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/diagnostics.rs91
-rw-r--r--src/tools/clippy/tests/ui/map_flatten.stderr25
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.stderr54
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.fixed6
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.stderr46
-rw-r--r--src/tools/compiletest/src/header.rs24
-rwxr-xr-xsrc/tools/publish_toolstate.py2
-rw-r--r--triagebot.toml105
255 files changed, 3179 insertions, 2315 deletions
diff --git a/.gitmodules b/.gitmodules
index 21bce3c7fa0..a524098845a 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -34,7 +34,7 @@
 [submodule "src/llvm-project"]
 	path = src/llvm-project
 	url = https://github.com/rust-lang/llvm-project.git
-	branch = rustc/14.0-2022-03-22
+	branch = rustc/14.0-2022-06-20
 [submodule "src/doc/embedded-book"]
 	path = src/doc/embedded-book
 	url = https://github.com/rust-embedded/book.git
diff --git a/Cargo.lock b/Cargo.lock
index 347341b5ff7..96d9449db57 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4280,6 +4280,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_errors",
  "rustc_hir",
+ "rustc_macros",
  "rustc_middle",
  "rustc_session",
  "rustc_span",
diff --git a/RELEASES.md b/RELEASES.md
index 3d88891ad21..7479735012c 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -29,7 +29,6 @@ Compiler
 Libraries
 ---------
 
-- [Move `CStr` to libcore, and `CString` to liballoc][94079]
 - [Windows: Use a pipe relay for chaining pipes][95841]
 - [Replace Linux Mutex and Condvar with futex based ones.][95035]
 - [Replace RwLock by a futex based one on Linux][95801]
@@ -90,7 +89,6 @@ and related tools.
 
 [93313]: https://github.com/rust-lang/rust/pull/93313/
 [93969]: https://github.com/rust-lang/rust/pull/93969/
-[94079]: https://github.com/rust-lang/rust/pull/94079/
 [94206]: https://github.com/rust-lang/rust/pull/94206/
 [94457]: https://github.com/rust-lang/rust/pull/94457/
 [94775]: https://github.com/rust-lang/rust/pull/94775/
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index a1233d62cb0..708fe8719a1 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -1,4 +1,6 @@
-use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{
+    struct_span_err, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
+};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
 
@@ -476,10 +478,11 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",)
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     fn struct_span_err_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
         code: DiagnosticId,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         self.infcx.tcx.sess.struct_span_err_with_code(sp, msg, code)
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 8f3699553d9..e60e11f11df 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -879,7 +879,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         }
 
         let mut found = false;
-        tcx.fold_regions(tcx.type_of(body_parent_did), &mut true, |r: ty::Region<'tcx>, _| {
+        tcx.fold_regions(tcx.type_of(body_parent_did), |r: ty::Region<'tcx>, _| {
             if *r == ty::ReEarlyBound(region) {
                 found = true;
             }
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 8ef2974c372..a2df072aa31 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(let_else)]
 #![feature(min_specialization)]
 #![feature(never_type)]
+#![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![feature(trusted_step)]
 #![feature(try_blocks)]
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 0fe3b45bc7c..f5c9392948b 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1009,7 +1009,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         debug!("try_promote_type_test_subject(ty = {:?})", ty);
 
-        let ty = tcx.fold_regions(ty, &mut false, |r, _depth| {
+        let ty = tcx.fold_regions(ty, |r, _depth| {
             let region_vid = self.to_region_vid(r);
 
             // The challenge if this. We have some region variable `r`
@@ -1289,7 +1289,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
-        tcx.fold_regions(value, &mut false, |r, _db| {
+        tcx.fold_regions(value, |r, _db| {
             let vid = self.to_region_vid(r);
             let scc = self.constraint_sccs.scc(vid);
             let repr = self.scc_representatives[scc];
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 81073758791..d182c0cf4e8 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -59,7 +59,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             debug!(?concrete_type, ?substs);
 
             let mut subst_regions = vec![self.universal_regions.fr_static];
-            let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| {
+            let universal_substs = infcx.tcx.fold_regions(substs, |region, _| {
                 if let ty::RePlaceholder(..) = region.kind() {
                     // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
                     return region;
@@ -91,7 +91,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             subst_regions.dedup();
 
             let universal_concrete_type =
-                infcx.tcx.fold_regions(concrete_type, &mut false, |region, _| match *region {
+                infcx.tcx.fold_regions(concrete_type, |region, _| match *region {
                     ty::ReVar(vid) => subst_regions
                         .iter()
                         .find(|ur_vid| self.eval_equal(vid, **ur_vid))
@@ -146,7 +146,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
-        tcx.fold_regions(ty, &mut false, |region, _| match *region {
+        tcx.fold_regions(ty, |region, _| match *region {
             ty::ReVar(vid) => {
                 // Find something that we can name
                 let upper_bound = self.approx_universal_upper_bound(vid);
diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index 2876d60527f..7a8ce621c5d 100644
--- a/compiler/rustc_borrowck/src/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -31,7 +31,7 @@ pub fn renumber_regions<'tcx, T>(infcx: &InferCtxt<'_, 'tcx>, value: T) -> T
 where
     T: TypeFoldable<'tcx>,
 {
-    infcx.tcx.fold_regions(value, &mut false, |_region, _depth| {
+    infcx.tcx.fold_regions(value, |_region, _depth| {
         let origin = NllRegionVariableOrigin::Existential { from_forall: false };
         infcx.next_nll_region_var(origin)
     })
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 3c9e3870aea..5e33d9d25c2 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -23,7 +23,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     universal_regions: &'a UniversalRegions<'tcx>,
     region_bound_pairs: &'a RegionBoundPairs<'tcx>,
-    implicit_region_bound: Option<ty::Region<'tcx>>,
+    implicit_region_bound: ty::Region<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     locations: Locations,
     span: Span,
@@ -36,7 +36,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
         infcx: &'a InferCtxt<'a, 'tcx>,
         universal_regions: &'a UniversalRegions<'tcx>,
         region_bound_pairs: &'a RegionBoundPairs<'tcx>,
-        implicit_region_bound: Option<ty::Region<'tcx>>,
+        implicit_region_bound: ty::Region<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         locations: Locations,
         span: Span,
@@ -108,7 +108,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
                 // create new region variables, which can't be done later when
                 // verifying these bounds.
                 if t1.has_placeholders() {
-                    t1 = tcx.fold_regions(t1, &mut false, |r, _| match *r {
+                    t1 = tcx.fold_regions(t1, |r, _| match *r {
                         ty::RePlaceholder(placeholder) => {
                             self.constraints.placeholder_region(self.infcx, placeholder)
                         }
@@ -120,7 +120,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
                     &mut *self,
                     tcx,
                     region_bound_pairs,
-                    implicit_region_bound,
+                    Some(implicit_region_bound),
                     param_env,
                 )
                 .type_must_outlive(origin, t1, r2);
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 813307356c4..421ef5be812 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -61,7 +61,7 @@ pub(crate) struct CreateResult<'tcx> {
 pub(crate) fn create<'tcx>(
     infcx: &InferCtxt<'_, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    implicit_region_bound: Option<ty::Region<'tcx>>,
+    implicit_region_bound: ty::Region<'tcx>,
     universal_regions: &Rc<UniversalRegions<'tcx>>,
     constraints: &mut MirTypeckRegionConstraints<'tcx>,
 ) -> CreateResult<'tcx> {
@@ -223,7 +223,7 @@ struct UniversalRegionRelationsBuilder<'this, 'tcx> {
     infcx: &'this InferCtxt<'this, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     universal_regions: Rc<UniversalRegions<'tcx>>,
-    implicit_region_bound: Option<ty::Region<'tcx>>,
+    implicit_region_bound: ty::Region<'tcx>,
     constraints: &'this mut MirTypeckRegionConstraints<'tcx>,
 
     // outputs:
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 2259a59e195..2a6ca5246da 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -230,7 +230,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 self.infcx,
                 &self.borrowck_context.universal_regions,
                 &self.region_bound_pairs,
-                Some(self.implicit_region_bound),
+                self.implicit_region_bound,
                 self.param_env,
                 Locations::All(DUMMY_SP),
                 DUMMY_SP,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 355254fe942..542fc6b0f48 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -157,7 +157,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
     } = free_region_relations::create(
         infcx,
         param_env,
-        Some(implicit_region_bound),
+        implicit_region_bound,
         universal_regions,
         &mut constraints,
     );
@@ -1142,7 +1142,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             self.infcx,
             self.borrowck_context.universal_regions,
             self.region_bound_pairs,
-            Some(self.implicit_region_bound),
+            self.implicit_region_bound,
             self.param_env,
             locations,
             locations.span(self.body),
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index c2c093f9f2f..89d84fcf09c 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -725,7 +725,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
-        self.tcx.fold_regions(value, &mut false, |_region, _depth| self.next_nll_region_var(origin))
+        self.tcx.fold_regions(value, |_region, _depth| self.next_nll_region_var(origin))
     }
 
     #[instrument(level = "debug", skip(self, indices))]
@@ -817,9 +817,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
-        tcx.fold_regions(value, &mut false, |region, _| {
-            tcx.mk_region(ty::ReVar(self.to_region_vid(region)))
-        })
+        tcx.fold_regions(value, |region, _| tcx.mk_region(ty::ReVar(self.to_region_vid(region))))
     }
 }
 
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index cad30181212..9e50d33486c 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -1,11 +1,10 @@
-use crate::assert::expr_if_not;
 use rustc_ast::{
     attr,
     ptr::P,
     token,
     tokenstream::{DelimSpan, TokenStream, TokenTree},
-    BorrowKind, Expr, ExprKind, ItemKind, MacArgs, MacCall, MacDelimiter, Mutability, Path,
-    PathSegment, Stmt, StructRest, UseTree, UseTreeKind, DUMMY_NODE_ID,
+    BinOpKind, BorrowKind, Expr, ExprKind, ItemKind, MacArgs, MacCall, MacDelimiter, Mutability,
+    Path, PathSegment, Stmt, StructRest, UnOp, UseTree, UseTreeKind, DUMMY_NODE_ID,
 };
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
@@ -16,11 +15,19 @@ use rustc_span::{
 };
 
 pub(super) struct Context<'cx, 'a> {
+    // An optimization.
+    //
+    // Elements that aren't consumed (PartialEq, PartialOrd, ...) can be copied **after** the
+    // `assert!` expression fails rather than copied on-the-fly.
+    best_case_captures: Vec<Stmt>,
     // Top-level `let captureN = Capture::new()` statements
     capture_decls: Vec<Capture>,
     cx: &'cx ExtCtxt<'a>,
     // Formatting string used for debugging
     fmt_string: String,
+    // If the current expression being visited consumes itself. Used to construct
+    // `best_case_captures`.
+    is_consumed: bool,
     // Top-level `let __local_bindN = &expr` statements
     local_bind_decls: Vec<Stmt>,
     // Used to avoid capturing duplicated paths
@@ -36,9 +43,11 @@ pub(super) struct Context<'cx, 'a> {
 impl<'cx, 'a> Context<'cx, 'a> {
     pub(super) fn new(cx: &'cx ExtCtxt<'a>, span: Span) -> Self {
         Self {
+            best_case_captures: <_>::default(),
             capture_decls: <_>::default(),
             cx,
             fmt_string: <_>::default(),
+            is_consumed: true,
             local_bind_decls: <_>::default(),
             paths: <_>::default(),
             span,
@@ -69,14 +78,22 @@ impl<'cx, 'a> Context<'cx, 'a> {
         self.manage_cond_expr(&mut cond_expr);
         let initial_imports = self.build_initial_imports();
         let panic = self.build_panic(&expr_str, panic_path);
+        let cond_expr_with_unlikely = self.build_unlikely(cond_expr);
+
+        let Self { best_case_captures, capture_decls, cx, local_bind_decls, span, .. } = self;
 
-        let Self { capture_decls, cx, local_bind_decls, span, .. } = self;
+        let mut assert_then_stmts = Vec::with_capacity(2);
+        assert_then_stmts.extend(best_case_captures);
+        assert_then_stmts.push(self.cx.stmt_expr(panic));
+        let assert_then = self.cx.block(span, assert_then_stmts);
 
         let mut stmts = Vec::with_capacity(4);
         stmts.push(initial_imports);
         stmts.extend(capture_decls.into_iter().map(|c| c.decl));
         stmts.extend(local_bind_decls);
-        stmts.push(cx.stmt_expr(expr_if_not(cx, span, cond_expr, panic, None)));
+        stmts.push(
+            cx.stmt_expr(cx.expr(span, ExprKind::If(cond_expr_with_unlikely, assert_then, None))),
+        );
         cx.expr_block(cx.block(span, stmts))
     }
 
@@ -115,6 +132,16 @@ impl<'cx, 'a> Context<'cx, 'a> {
         )
     }
 
+    /// Takes the conditional expression of `assert!` and then wraps it inside `unlikely`
+    fn build_unlikely(&self, cond_expr: P<Expr>) -> P<Expr> {
+        let unlikely_path = self.cx.std_path(&[sym::intrinsics, sym::unlikely]);
+        self.cx.expr_call(
+            self.span,
+            self.cx.expr_path(self.cx.path(self.span, unlikely_path)),
+            vec![self.cx.expr(self.span, ExprKind::Unary(UnOp::Not, cond_expr))],
+        )
+    }
+
     /// The necessary custom `panic!(...)` expression.
     ///
     /// panic!(
@@ -167,17 +194,39 @@ impl<'cx, 'a> Context<'cx, 'a> {
     /// See [Self::manage_initial_capture] and [Self::manage_try_capture]
     fn manage_cond_expr(&mut self, expr: &mut P<Expr>) {
         match (*expr).kind {
-            ExprKind::AddrOf(_, _, ref mut local_expr) => {
-                self.manage_cond_expr(local_expr);
+            ExprKind::AddrOf(_, mutability, ref mut local_expr) => {
+                self.with_is_consumed_management(
+                    matches!(mutability, Mutability::Mut),
+                    |this| this.manage_cond_expr(local_expr)
+                );
             }
             ExprKind::Array(ref mut local_exprs) => {
                 for local_expr in local_exprs {
                     self.manage_cond_expr(local_expr);
                 }
             }
-            ExprKind::Binary(_, ref mut lhs, ref mut rhs) => {
-                self.manage_cond_expr(lhs);
-                self.manage_cond_expr(rhs);
+            ExprKind::Binary(ref op, ref mut lhs, ref mut rhs) => {
+                self.with_is_consumed_management(
+                    matches!(
+                        op.node,
+                        BinOpKind::Add
+                            | BinOpKind::And
+                            | BinOpKind::BitAnd
+                            | BinOpKind::BitOr
+                            | BinOpKind::BitXor
+                            | BinOpKind::Div
+                            | BinOpKind::Mul
+                            | BinOpKind::Or
+                            | BinOpKind::Rem
+                            | BinOpKind::Shl
+                            | BinOpKind::Shr
+                            | BinOpKind::Sub
+                    ),
+                    |this| {
+                        this.manage_cond_expr(lhs);
+                        this.manage_cond_expr(rhs);
+                    }
+                );
             }
             ExprKind::Call(_, ref mut local_exprs) => {
                 for local_expr in local_exprs {
@@ -228,8 +277,11 @@ impl<'cx, 'a> Context<'cx, 'a> {
                     self.manage_cond_expr(local_expr);
                 }
             }
-            ExprKind::Unary(_, ref mut local_expr) => {
-                self.manage_cond_expr(local_expr);
+            ExprKind::Unary(un_op, ref mut local_expr) => {
+                self.with_is_consumed_management(
+                    matches!(un_op, UnOp::Neg | UnOp::Not),
+                    |this| this.manage_cond_expr(local_expr)
+                );
             }
             // Expressions that are not worth or can not be captured.
             //
@@ -337,9 +389,23 @@ impl<'cx, 'a> Context<'cx, 'a> {
             ))
             .add_trailing_semicolon();
         let local_bind_path = self.cx.expr_path(Path::from_ident(local_bind));
-        let ret = self.cx.stmt_expr(local_bind_path);
-        let block = self.cx.expr_block(self.cx.block(self.span, vec![try_capture_call, ret]));
-        *expr = self.cx.expr_deref(self.span, block);
+        let rslt = if self.is_consumed {
+            let ret = self.cx.stmt_expr(local_bind_path);
+            self.cx.expr_block(self.cx.block(self.span, vec![try_capture_call, ret]))
+        } else {
+            self.best_case_captures.push(try_capture_call);
+            local_bind_path
+        };
+        *expr = self.cx.expr_deref(self.span, rslt);
+    }
+
+    // Calls `f` with the internal `is_consumed` set to `curr_is_consumed` and then
+    // sets the internal `is_consumed` back to its original value.
+    fn with_is_consumed_management(&mut self, curr_is_consumed: bool, f: impl FnOnce(&mut Self)) {
+        let prev_is_consumed = self.is_consumed;
+        self.is_consumed = curr_is_consumed;
+        f(self);
+        self.is_consumed = prev_is_consumed;
     }
 }
 
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index d46f2f38d3a..d5e68dbd5b7 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -56,15 +56,14 @@ impl<T: fmt::Display> fmt::Display for MemoryKind<T> {
     }
 }
 
-/// Used by `get_size_and_align` to indicate whether the allocation needs to be live.
-#[derive(Debug, Copy, Clone)]
-pub enum AllocCheck {
-    /// Allocation must be live and not a function pointer.
-    Dereferenceable,
-    /// Allocations needs to be live, but may be a function pointer.
-    Live,
-    /// Allocation may be dead.
-    MaybeDead,
+/// The return value of `get_alloc_info` indicates the "kind" of the allocation.
+pub enum AllocKind {
+    /// A regular live data allocation.
+    LiveData,
+    /// A function allocation (that fn ptrs point to).
+    Function,
+    /// A dead allocation.
+    Dead,
 }
 
 /// The value of a function pointer.
@@ -360,8 +359,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             align,
             CheckInAllocMsg::MemoryAccessTest,
             |alloc_id, offset, tag| {
-                let (size, align) =
-                    self.get_alloc_size_and_align(alloc_id, AllocCheck::Dereferenceable)?;
+                let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
                 Ok((size, align, (alloc_id, offset, tag)))
             },
         )
@@ -379,15 +377,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         msg: CheckInAllocMsg,
     ) -> InterpResult<'tcx> {
         self.check_and_deref_ptr(ptr, size, Some(align), msg, |alloc_id, _, _| {
-            let check = match msg {
-                CheckInAllocMsg::DerefTest | CheckInAllocMsg::MemoryAccessTest => {
-                    AllocCheck::Dereferenceable
-                }
-                CheckInAllocMsg::PointerArithmeticTest
-                | CheckInAllocMsg::OffsetFromTest
-                | CheckInAllocMsg::InboundsTest => AllocCheck::Live,
-            };
-            let (size, align) = self.get_alloc_size_and_align(alloc_id, check)?;
+            let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
             Ok((size, align, ()))
         })?;
         Ok(())
@@ -655,30 +645,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     /// Obtain the size and alignment of an allocation, even if that allocation has
     /// been deallocated.
-    ///
-    /// If `liveness` is `AllocCheck::MaybeDead`, this function always returns `Ok`.
-    pub fn get_alloc_size_and_align(
-        &self,
-        id: AllocId,
-        liveness: AllocCheck,
-    ) -> InterpResult<'tcx, (Size, Align)> {
+    pub fn get_alloc_info(&self, id: AllocId) -> (Size, Align, AllocKind) {
         // # Regular allocations
         // Don't use `self.get_raw` here as that will
         // a) cause cycles in case `id` refers to a static
         // b) duplicate a global's allocation in miri
         if let Some((_, alloc)) = self.memory.alloc_map.get(id) {
-            return Ok((alloc.size(), alloc.align));
+            return (alloc.size(), alloc.align, AllocKind::LiveData);
         }
 
         // # Function pointers
         // (both global from `alloc_map` and local from `extra_fn_ptr_map`)
         if self.get_fn_alloc(id).is_some() {
-            return if let AllocCheck::Dereferenceable = liveness {
-                // The caller requested no function pointers.
-                throw_ub!(DerefFunctionPointer(id))
-            } else {
-                Ok((Size::ZERO, Align::ONE))
-            };
+            return (Size::ZERO, Align::ONE, AllocKind::Function);
         }
 
         // # Statics
@@ -690,32 +669,38 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // Use size and align of the type.
                 let ty = self.tcx.type_of(did);
                 let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
-                Ok((layout.size, layout.align.abi))
+                (layout.size, layout.align.abi, AllocKind::LiveData)
             }
             Some(GlobalAlloc::Memory(alloc)) => {
                 // Need to duplicate the logic here, because the global allocations have
                 // different associated types than the interpreter-local ones.
                 let alloc = alloc.inner();
-                Ok((alloc.size(), alloc.align))
+                (alloc.size(), alloc.align, AllocKind::LiveData)
             }
             Some(GlobalAlloc::Function(_)) => bug!("We already checked function pointers above"),
             // The rest must be dead.
             None => {
-                if let AllocCheck::MaybeDead = liveness {
-                    // Deallocated pointers are allowed, we should be able to find
-                    // them in the map.
-                    Ok(*self
-                        .memory
-                        .dead_alloc_map
-                        .get(&id)
-                        .expect("deallocated pointers should all be recorded in `dead_alloc_map`"))
-                } else {
-                    throw_ub!(PointerUseAfterFree(id))
-                }
+                // Deallocated pointers are allowed, we should be able to find
+                // them in the map.
+                let (size, align) = *self
+                    .memory
+                    .dead_alloc_map
+                    .get(&id)
+                    .expect("deallocated pointers should all be recorded in `dead_alloc_map`");
+                (size, align, AllocKind::Dead)
             }
         }
     }
 
+    /// Obtain the size and alignment of a live allocation.
+    pub fn get_live_alloc_size_and_align(&self, id: AllocId) -> InterpResult<'tcx, (Size, Align)> {
+        let (size, align, kind) = self.get_alloc_info(id);
+        if matches!(kind, AllocKind::Dead) {
+            throw_ub!(PointerUseAfterFree(id))
+        }
+        Ok((size, align))
+    }
+
     fn get_fn_alloc(&self, id: AllocId) -> Option<FnVal<'tcx, M::ExtraFnVal>> {
         if let Some(extra) = self.memory.extra_fn_ptr_map.get(&id) {
             Some(FnVal::Other(*extra))
@@ -1187,9 +1172,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let ptr = self.scalar_to_ptr(scalar)?;
                 match self.ptr_try_get_alloc_id(ptr) {
                     Ok((alloc_id, offset, _)) => {
-                        let (size, _align) = self
-                            .get_alloc_size_and_align(alloc_id, AllocCheck::MaybeDead)
-                            .expect("alloc info with MaybeDead cannot fail");
+                        let (size, _align, _kind) = self.get_alloc_info(alloc_id);
                         // If the pointer is out-of-bounds, it may be null.
                         // Note that one-past-the-end (offset == size) is still inbounds, and never null.
                         offset > size
diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs
index 2b73ad568e0..92f0a7498e3 100644
--- a/compiler/rustc_const_eval/src/interpret/mod.rs
+++ b/compiler/rustc_const_eval/src/interpret/mod.rs
@@ -23,7 +23,7 @@ pub use self::eval_context::{
 };
 pub use self::intern::{intern_const_alloc_recursive, InternKind};
 pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump};
-pub use self::memory::{AllocCheck, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
+pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
 pub use self::operand::{ImmTy, Immediate, OpTy, Operand};
 pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy};
 pub use self::validity::{CtfeValidationMode, RefTracking};
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 88ff33b4d09..d8b26f9840b 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -826,6 +826,24 @@ cfg_if! {
                 }
             }
         }
+    } else if #[cfg(target_os = "macos")] {
+        pub fn get_resident_set_size() -> Option<usize> {
+            use libc::{c_int, c_void, getpid, proc_pidinfo, proc_taskinfo, PROC_PIDTASKINFO};
+            use std::mem;
+            const PROC_TASKINFO_SIZE: c_int = mem::size_of::<proc_taskinfo>() as c_int;
+
+            unsafe {
+                let mut info: proc_taskinfo = mem::zeroed();
+                let info_ptr = &mut info as *mut proc_taskinfo as *mut c_void;
+                let pid = getpid() as c_int;
+                let ret = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, info_ptr, PROC_TASKINFO_SIZE);
+                if ret == PROC_TASKINFO_SIZE {
+                    Some(info.pti_resident_size as usize)
+                } else {
+                    None
+                }
+            }
+        }
     } else if #[cfg(unix)] {
         pub fn get_resident_set_size() -> Option<usize> {
             let field = 1;
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index feb82cb0938..4437c0b1b69 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -21,6 +21,7 @@ use crate::owning_ref::{Erased, OwningRef};
 use std::collections::HashMap;
 use std::hash::{BuildHasher, Hash};
 use std::ops::{Deref, DerefMut};
+use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
 
 pub use std::sync::atomic::Ordering;
 pub use std::sync::atomic::Ordering::SeqCst;
@@ -41,7 +42,6 @@ cfg_if! {
         }
 
         use std::ops::Add;
-        use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe};
 
         /// This is a single threaded variant of `AtomicU64`, `AtomicUsize`, etc.
         /// It has explicit ordering arguments and is only intended for use with
@@ -339,7 +339,10 @@ cfg_if! {
             t: T,
             for_each: impl Fn(T::Item) + Sync + Send,
         ) {
-            t.into_par_iter().for_each(for_each)
+            let ps: Vec<_> = t.into_par_iter().map(|i| catch_unwind(AssertUnwindSafe(|| for_each(i)))).collect();
+            ps.into_iter().for_each(|p| if let Err(panic) = p {
+                resume_unwind(panic)
+            });
         }
 
         pub type MetadataRef = OwningRef<Box<dyn Erased + Send + Sync>, [u8]>;
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index caa92e74808..3096af90d47 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -932,7 +932,7 @@ fn describe_codegen_flags() {
     print_flag_list("-C", config::CG_OPTIONS);
 }
 
-fn print_flag_list<T>(
+pub fn print_flag_list<T>(
     cmdline_opt: &str,
     flag_list: &[(&'static str, T, &'static str, &'static str)],
 ) {
diff --git a/compiler/rustc_error_messages/locales/en-US/privacy.ftl b/compiler/rustc_error_messages/locales/en-US/privacy.ftl
new file mode 100644
index 00000000000..2b0778f48ca
--- /dev/null
+++ b/compiler/rustc_error_messages/locales/en-US/privacy.ftl
@@ -0,0 +1,12 @@
+privacy-field-is-private = field `{$field_name}` of {$variant_descr} `{$def_path_str}` is private
+privacy-field-is-private-is-update-syntax-label = field `{$field_name}` is private
+privacy-field-is-private-label = private field
+
+privacy-item-is-private = {$kind} `{$descr}` is private
+    .label = private {$kind}
+privacy-unnamed-item-is-private = {$kind} is private
+    .label = private {$kind}
+
+privacy-in-public-interface = {$vis_descr} {$kind} `{$descr}` in public interface
+    .label = can't leak {$vis_descr} {$kind}
+    .visibility-label = `{$descr}` declared as {$vis_descr}
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 673e160cc1e..90eb5ef5446 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -32,6 +32,7 @@ pub use unic_langid::{langid, LanguageIdentifier};
 // Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module.
 fluent_messages! {
     parser => "../locales/en-US/parser.ftl",
+    privacy => "../locales/en-US/privacy.ftl",
     typeck => "../locales/en-US/typeck.ftl",
     builtin_macros => "../locales/en-US/builtin_macros.ftl",
 }
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index a4cbc73978d..8b2a995f1c5 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -656,11 +656,6 @@ impl Emitter for SilentEmitter {
     }
 }
 
-/// Maximum number of lines we will print for a multiline suggestion; arbitrary.
-///
-/// This should be replaced with a more involved mechanism to output multiline suggestions that
-/// more closely mimics the regular diagnostic output, where irrelevant code lines are elided.
-pub const MAX_SUGGESTION_HIGHLIGHT_LINES: usize = 6;
 /// Maximum number of suggestions to be shown
 ///
 /// Arbitrary, but taken from trait import suggestion limit
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 245719bff12..1e57d66dd9f 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1077,6 +1077,7 @@ impl<'a> ExtCtxt<'a> {
         self.current_expansion.id.expansion_cause()
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -1101,9 +1102,11 @@ impl<'a> ExtCtxt<'a> {
     ///
     /// Compilation will be stopped in the near future (at the end of
     /// the macro expansion phase).
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.sess.parse_sess.span_diagnostic.span_err(sp, msg);
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.sess.parse_sess.span_diagnostic.span_warn(sp, msg);
     }
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index 86ff110eec1..c18147592dc 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -9,6 +9,7 @@
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_span)]
+#![feature(rustc_attrs)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
 
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index e68274e2ad9..384a0f9c225 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -65,7 +65,6 @@
 //! example generator inference, and possibly also HIR borrowck.
 
 use crate::hir::*;
-use crate::itemlikevisit::ParItemLikeVisitor;
 use rustc_ast::walk_list;
 use rustc_ast::{Attribute, Label};
 use rustc_span::symbol::{Ident, Symbol};
@@ -76,29 +75,6 @@ pub trait IntoVisitor<'hir> {
     fn into_visitor(&self) -> Self::Visitor;
 }
 
-pub struct ParDeepVisitor<V>(pub V);
-
-impl<'hir, V> ParItemLikeVisitor<'hir> for ParDeepVisitor<V>
-where
-    V: IntoVisitor<'hir>,
-{
-    fn visit_item(&self, item: &'hir Item<'hir>) {
-        self.0.into_visitor().visit_item(item);
-    }
-
-    fn visit_trait_item(&self, trait_item: &'hir TraitItem<'hir>) {
-        self.0.into_visitor().visit_trait_item(trait_item);
-    }
-
-    fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>) {
-        self.0.into_visitor().visit_impl_item(impl_item);
-    }
-
-    fn visit_foreign_item(&self, foreign_item: &'hir ForeignItem<'hir>) {
-        self.0.into_visitor().visit_foreign_item(foreign_item);
-    }
-}
-
 #[derive(Copy, Clone, Debug)]
 pub enum FnKind<'a> {
     /// `#[xxx] pub async/const/extern "Abi" fn foo()`
diff --git a/compiler/rustc_hir/src/itemlikevisit.rs b/compiler/rustc_hir/src/itemlikevisit.rs
deleted file mode 100644
index a490268dc9f..00000000000
--- a/compiler/rustc_hir/src/itemlikevisit.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-use super::{ForeignItem, ImplItem, Item, TraitItem};
-
-/// A parallel variant of `ItemLikeVisitor`.
-pub trait ParItemLikeVisitor<'hir> {
-    fn visit_item(&self, item: &'hir Item<'hir>);
-    fn visit_trait_item(&self, trait_item: &'hir TraitItem<'hir>);
-    fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>);
-    fn visit_foreign_item(&self, foreign_item: &'hir ForeignItem<'hir>);
-}
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index d845c433d8c..9f32a7da159 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -27,7 +27,6 @@ pub use rustc_span::def_id;
 mod hir;
 pub mod hir_id;
 pub mod intravisit;
-pub mod itemlikevisit;
 pub mod lang_items;
 pub mod pat_util;
 mod stable_hash_impls;
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
index b9596cd10ed..42d52446ab6 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
@@ -79,7 +79,7 @@ pub fn find_param_with_region<'tcx>(
             // May return None; sometimes the tables are not yet populated.
             let ty = fn_sig.inputs()[index];
             let mut found_anon_region = false;
-            let new_param_ty = tcx.fold_regions(ty, &mut false, |r, _| {
+            let new_param_ty = tcx.fold_regions(ty, |r, _| {
                 if r == anon_region {
                     found_anon_region = true;
                     replace_region
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index 455de47acef..68c709a2e24 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -868,7 +868,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
-        tcx.fold_regions(value, &mut false, |r, _db| match *r {
+        tcx.fold_regions(value, |r, _db| match *r {
             ty::ReVar(rid) => self.resolve_var(rid),
             _ => r,
         })
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 7684d861f3c..ebb8d443421 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -39,21 +39,19 @@ pub struct OpaqueTypeDecl<'tcx> {
 }
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    /// This is a backwards compatibility hack to prevent breaking changes from
-    /// lazy TAIT around RPIT handling.
-    pub fn replace_opaque_types_with_inference_vars<T: TypeFoldable<'tcx>>(
+    pub fn replace_opaque_types_with_inference_vars(
         &self,
-        value: T,
+        ty: Ty<'tcx>,
         body_id: HirId,
         span: Span,
         code: ObligationCauseCode<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-    ) -> InferOk<'tcx, T> {
-        if !value.has_opaque_types() {
-            return InferOk { value, obligations: vec![] };
+    ) -> InferOk<'tcx, Ty<'tcx>> {
+        if !ty.has_opaque_types() {
+            return InferOk { value: ty, obligations: vec![] };
         }
         let mut obligations = vec![];
-        let value = value.fold_with(&mut ty::fold::BottomUpFolder {
+        let value = ty.fold_with(&mut ty::fold::BottomUpFolder {
             tcx: self.tcx,
             lt_op: |lt| lt,
             ct_op: |ct| ct,
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index a268493b28f..1c1906f3375 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -141,9 +141,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     ///   `('a, K)` in this list tells us that the bounds in scope
     ///   indicate that `K: 'a`, where `K` is either a generic
     ///   parameter like `T` or a projection like `T::Item`.
-    /// - `implicit_region_bound`: if some, this is a region bound
-    ///   that is considered to hold for all type parameters (the
-    ///   function body).
     /// - `param_env` is the parameter environment for the enclosing function.
     /// - `body_id` is the body-id whose region obligations are being
     ///   processed.
@@ -151,7 +148,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     pub fn process_registered_region_obligations(
         &self,
         region_bound_pairs_map: &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>,
-        implicit_region_bound: Option<ty::Region<'tcx>>,
         param_env: ty::ParamEnv<'tcx>,
     ) {
         assert!(
@@ -170,13 +166,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
             let sup_type = self.resolve_vars_if_possible(sup_type);
 
             if let Some(region_bound_pairs) = region_bound_pairs_map.get(&body_id) {
-                let outlives = &mut TypeOutlives::new(
-                    self,
-                    self.tcx,
-                    &region_bound_pairs,
-                    implicit_region_bound,
-                    param_env,
-                );
+                let outlives =
+                    &mut TypeOutlives::new(self, self.tcx, &region_bound_pairs, None, param_env);
                 outlives.type_must_outlive(origin, sup_type, sub_region);
             } else {
                 self.tcx.sess.delay_span_bug(
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 191f5f18ec2..86b025dce5e 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -16,6 +16,11 @@ use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
 pub struct VerifyBoundCx<'cx, 'tcx> {
     tcx: TyCtxt<'tcx>,
     region_bound_pairs: &'cx RegionBoundPairs<'tcx>,
+    /// During borrowck, if there are no outlives bounds on a generic
+    /// parameter `T`, we assume that `T: 'in_fn_body` holds.
+    ///
+    /// Outside of borrowck the only way to prove `T: '?0` is by
+    /// setting  `'?0` to `'empty`.
     implicit_region_bound: Option<ty::Region<'tcx>>,
     param_env: ty::ParamEnv<'tcx>,
 }
@@ -263,8 +268,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         //     fn foo<'a, A>(x: &'a A) { x.bar() }
         //
         // The problem is that the type of `x` is `&'a A`. To be
-        // well-formed, then, A must be lower-generic by `'a`, but we
-        // don't know that this holds from first principles.
+        // well-formed, then, A must outlive `'a`, but we don't know that
+        // this holds from first principles.
         let from_region_bound_pairs = self.region_bound_pairs.iter().filter_map(|&(r, p)| {
             debug!(
                 "declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}",
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index fadb1c87933..56c8635a189 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -406,9 +406,12 @@ impl LateLintPass<'_> for Diagnostics {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         let Some((span, def_id, substs)) = typeck_results_of_method_fn(cx, expr) else { return };
         debug!(?span, ?def_id, ?substs);
-        if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) &&
-            !cx.tcx.has_attr(instance.def_id(), sym::rustc_lint_diagnostics)
-        {
+        let has_attr = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs)
+            .ok()
+            .and_then(|inst| inst)
+            .map(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics))
+            .unwrap_or(false);
+        if !has_attr {
             return;
         }
 
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 2a2dc6822ce..5579e4d19cf 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -4,7 +4,6 @@ use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
 use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
 use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
 use rustc_middle::ty::subst::SubstsRef;
@@ -1483,39 +1482,32 @@ impl InvalidAtomicOrdering {
         None
     }
 
-    fn matches_ordering(cx: &LateContext<'_>, did: DefId, orderings: &[Symbol]) -> bool {
+    fn match_ordering(cx: &LateContext<'_>, ord_arg: &Expr<'_>) -> Option<Symbol> {
+        let ExprKind::Path(ref ord_qpath) = ord_arg.kind else { return None };
+        let did = cx.qpath_res(ord_qpath, ord_arg.hir_id).opt_def_id()?;
         let tcx = cx.tcx;
         let atomic_ordering = tcx.get_diagnostic_item(sym::Ordering);
-        orderings.iter().any(|ordering| {
-            tcx.item_name(did) == *ordering && {
-                let parent = tcx.parent(did);
-                Some(parent) == atomic_ordering
-                    // needed in case this is a ctor, not a variant
-                    || tcx.opt_parent(parent) == atomic_ordering
-            }
-        })
-    }
-
-    fn opt_ordering_defid(cx: &LateContext<'_>, ord_arg: &Expr<'_>) -> Option<DefId> {
-        if let ExprKind::Path(ref ord_qpath) = ord_arg.kind {
-            cx.qpath_res(ord_qpath, ord_arg.hir_id).opt_def_id()
-        } else {
-            None
-        }
+        let name = tcx.item_name(did);
+        let parent = tcx.parent(did);
+        [sym::Relaxed, sym::Release, sym::Acquire, sym::AcqRel, sym::SeqCst].into_iter().find(
+            |&ordering| {
+                name == ordering
+                    && (Some(parent) == atomic_ordering
+                            // needed in case this is a ctor, not a variant
+                            || tcx.opt_parent(parent) == atomic_ordering)
+            },
+        )
     }
 
     fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) {
-        use rustc_hir::def::{DefKind, Res};
-        use rustc_hir::QPath;
         if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::load, sym::store])
             && let Some((ordering_arg, invalid_ordering)) = match method {
                 sym::load => Some((&args[1], sym::Release)),
                 sym::store => Some((&args[2], sym::Acquire)),
                 _ => None,
             }
-            && let ExprKind::Path(QPath::Resolved(_, path)) = ordering_arg.kind
-            && let Res::Def(DefKind::Ctor(..), ctor_id) = path.res
-            && Self::matches_ordering(cx, ctor_id, &[invalid_ordering, sym::AcqRel])
+            && let Some(ordering) = Self::match_ordering(cx, ordering_arg)
+            && (ordering == invalid_ordering || ordering == sym::AcqRel)
         {
             cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, |diag| {
                 if method == sym::load {
@@ -1537,9 +1529,7 @@ impl InvalidAtomicOrdering {
             && let ExprKind::Path(ref func_qpath) = func.kind
             && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id()
             && matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence))
-            && let ExprKind::Path(ref ordering_qpath) = &args[0].kind
-            && let Some(ordering_def_id) = cx.qpath_res(ordering_qpath, args[0].hir_id).opt_def_id()
-            && Self::matches_ordering(cx, ordering_def_id, &[sym::Relaxed])
+            && Self::match_ordering(cx, &args[0]) == Some(sym::Relaxed)
         {
             cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, |diag| {
                 diag.build("memory fences cannot have `Relaxed` ordering")
@@ -1550,62 +1540,56 @@ impl InvalidAtomicOrdering {
     }
 
     fn check_atomic_compare_exchange(cx: &LateContext<'_>, expr: &Expr<'_>) {
-        if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::fetch_update, sym::compare_exchange, sym::compare_exchange_weak])
-            && let Some((success_order_arg, failure_order_arg)) = match method {
-                sym::fetch_update => Some((&args[1], &args[2])),
-                sym::compare_exchange | sym::compare_exchange_weak => Some((&args[3], &args[4])),
-                _ => None,
-            }
-            && let Some(fail_ordering_def_id) = Self::opt_ordering_defid(cx, failure_order_arg)
-        {
-            // Helper type holding on to some checking and error reporting data. Has
-            // - (success ordering,
-            // - list of failure orderings forbidden by the success order,
-            // - suggestion message)
-            type OrdLintInfo = (Symbol, &'static [Symbol], &'static str);
-            const RELAXED: OrdLintInfo = (sym::Relaxed, &[sym::SeqCst, sym::Acquire], "ordering mode `Relaxed`");
-            const ACQUIRE: OrdLintInfo = (sym::Acquire, &[sym::SeqCst], "ordering modes `Acquire` or `Relaxed`");
-            const SEQ_CST: OrdLintInfo = (sym::SeqCst, &[], "ordering modes `Acquire`, `SeqCst` or `Relaxed`");
-            const RELEASE: OrdLintInfo = (sym::Release, RELAXED.1, RELAXED.2);
-            const ACQREL: OrdLintInfo = (sym::AcqRel, ACQUIRE.1, ACQUIRE.2);
-            const SEARCH: [OrdLintInfo; 5] = [RELAXED, ACQUIRE, SEQ_CST, RELEASE, ACQREL];
-
-            let success_lint_info = Self::opt_ordering_defid(cx, success_order_arg)
-                .and_then(|success_ord_def_id| -> Option<OrdLintInfo> {
-                    SEARCH
-                        .iter()
-                        .copied()
-                        .find(|(ordering, ..)| {
-                            Self::matches_ordering(cx, success_ord_def_id, &[*ordering])
-                        })
-                });
-            if Self::matches_ordering(cx, fail_ordering_def_id, &[sym::Release, sym::AcqRel]) {
-                // If we don't know the success order is, use what we'd suggest
-                // if it were maximally permissive.
-                let suggested = success_lint_info.unwrap_or(SEQ_CST).2;
-                cx.struct_span_lint(INVALID_ATOMIC_ORDERING, failure_order_arg.span, |diag| {
-                    let msg = format!(
-                        "{}'s failure ordering may not be `Release` or `AcqRel`",
-                        method,
-                    );
-                    diag.build(&msg)
-                        .help(&format!("consider using {} instead", suggested))
-                        .emit();
-                });
-            } else if let Some((success_ord, bad_ords_given_success, suggested)) = success_lint_info {
-                if Self::matches_ordering(cx, fail_ordering_def_id, bad_ords_given_success) {
-                    cx.struct_span_lint(INVALID_ATOMIC_ORDERING, failure_order_arg.span, |diag| {
-                        let msg = format!(
-                            "{}'s failure ordering may not be stronger than the success ordering of `{}`",
-                            method,
-                            success_ord,
-                        );
-                        diag.build(&msg)
-                            .help(&format!("consider using {} instead", suggested))
-                            .emit();
-                    });
-                }
-            }
+        let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::fetch_update, sym::compare_exchange, sym::compare_exchange_weak])
+            else {return };
+
+        let (success_order_arg, fail_order_arg) = match method {
+            sym::fetch_update => (&args[1], &args[2]),
+            sym::compare_exchange | sym::compare_exchange_weak => (&args[3], &args[4]),
+            _ => return,
+        };
+
+        let Some(fail_ordering) = Self::match_ordering(cx, fail_order_arg) else { return };
+
+        if matches!(fail_ordering, sym::Release | sym::AcqRel) {
+            cx.struct_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg.span, |diag| {
+                diag.build(&format!(
+                    "`{method}`'s failure ordering may not be `Release` or `AcqRel`, \
+                    since a failed `{method}` does not result in a write",
+                ))
+                .span_label(fail_order_arg.span, "invalid failure ordering")
+                .help("consider using `Acquire` or `Relaxed` failure ordering instead")
+                .emit();
+            });
+        }
+
+        let Some(success_ordering) = Self::match_ordering(cx, success_order_arg) else { return };
+
+        if matches!(
+            (success_ordering, fail_ordering),
+            (sym::Relaxed | sym::Release, sym::Acquire)
+                | (sym::Relaxed | sym::Release | sym::Acquire | sym::AcqRel, sym::SeqCst)
+        ) {
+            let success_suggestion =
+                if success_ordering == sym::Release && fail_ordering == sym::Acquire {
+                    sym::AcqRel
+                } else {
+                    fail_ordering
+                };
+            cx.struct_span_lint(INVALID_ATOMIC_ORDERING, success_order_arg.span, |diag| {
+                diag.build(&format!(
+                    "`{method}`'s success ordering must be at least as strong as its failure ordering"
+                ))
+                .span_label(fail_order_arg.span, format!("`{fail_ordering}` failure ordering"))
+                .span_label(success_order_arg.span, format!("`{success_ordering}` success ordering"))
+                .span_suggestion_short(
+                    success_order_arg.span,
+                    format!("consider using `{success_suggestion}` success ordering instead"),
+                    format!("std::sync::atomic::Ordering::{success_suggestion}"),
+                    Applicability::MaybeIncorrect,
+                )
+                .emit();
+            });
         }
     }
 }
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 738d47ba296..a27b8470e95 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -612,23 +612,6 @@ impl<'hir> Map<'hir> {
         }
     }
 
-    /// A parallel version of `visit_all_item_likes`.
-    pub fn par_visit_all_item_likes<V>(self, visitor: &V)
-    where
-        V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send,
-    {
-        let krate = self.krate();
-        par_for_each_in(&krate.owners.raw, |owner| match owner.map(OwnerInfo::node) {
-            MaybeOwner::Owner(OwnerNode::Item(item)) => visitor.visit_item(item),
-            MaybeOwner::Owner(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item),
-            MaybeOwner::Owner(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item),
-            MaybeOwner::Owner(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item),
-            MaybeOwner::Owner(OwnerNode::Crate(_))
-            | MaybeOwner::NonOwner(_)
-            | MaybeOwner::Phantom => {}
-        })
-    }
-
     /// If you don't care about nesting, you should use the
     /// `tcx.hir_module_items()` query or `module_items()` instead.
     /// Please see notes in `deep_visit_all_item_likes`.
@@ -867,6 +850,10 @@ impl<'hir> Map<'hir> {
         )
     }
 
+    pub fn expect_owner(self, id: LocalDefId) -> OwnerNode<'hir> {
+        self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)).node
+    }
+
     pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> {
         match self.tcx.hir_owner(id) {
             Some(Owner { node: OwnerNode::Item(item), .. }) => item,
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 09b142e0c41..8622a620721 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -10,6 +10,7 @@ use crate::ty::query::Providers;
 use crate::ty::{DefIdTree, ImplSubject, TyCtxt};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::*;
 use rustc_query_system::ich::StableHashingContext;
@@ -61,6 +62,22 @@ impl ModuleItems {
     pub fn foreign_items(&self) -> impl Iterator<Item = ForeignItemId> + '_ {
         self.foreign_items.iter().copied()
     }
+
+    pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) {
+        par_for_each_in(&self.items[..], |&id| f(id))
+    }
+
+    pub fn par_trait_items(&self, f: impl Fn(TraitItemId) + Send + Sync) {
+        par_for_each_in(&self.trait_items[..], |&id| f(id))
+    }
+
+    pub fn par_impl_items(&self, f: impl Fn(ImplItemId) + Send + Sync) {
+        par_for_each_in(&self.impl_items[..], |&id| f(id))
+    }
+
+    pub fn par_foreign_items(&self, f: impl Fn(ForeignItemId) + Send + Sync) {
+        par_for_each_in(&self.foreign_items[..], |&id| f(id))
+    }
 }
 
 impl<'tcx> TyCtxt<'tcx> {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index ca2c03cb614..2e68fc8a7c0 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -826,6 +826,10 @@ rustc_queries! {
         desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) }
     }
 
+    query check_mod_type_wf(key: LocalDefId) -> () {
+        desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) }
+    }
+
     query collect_mod_item_types(key: LocalDefId) -> () {
         desc { |tcx| "collecting item types in {}", describe_as_module(key, tcx) }
     }
@@ -906,9 +910,10 @@ rustc_queries! {
 
     /// Checks whether all impls in the crate pass the overlap check, returning
     /// which impls fail it. If all impls are correct, the returned slice is empty.
-    query orphan_check_crate(_: ()) -> &'tcx [LocalDefId] {
-        desc {
-            "checking whether the immpl in the this crate follow the orphan rules",
+    query orphan_check_impl(key: LocalDefId) -> Result<(), ErrorGuaranteed> {
+        desc { |tcx|
+            "checking whether impl `{}` follows the orphan rules",
+            tcx.def_path_str(key.to_def_id()),
         }
     }
 
@@ -1398,13 +1403,7 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    query check_item_well_formed(key: LocalDefId) -> () {
-        desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) }
-    }
-    query check_trait_item_well_formed(key: LocalDefId) -> () {
-        desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) }
-    }
-    query check_impl_item_well_formed(key: LocalDefId) -> () {
+    query check_well_formed(key: LocalDefId) -> () {
         desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) }
     }
 
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 5258d37a14c..ed8de24a65e 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -406,7 +406,7 @@ pub enum ObligationCauseCode<'tcx> {
     QuestionMark,
 
     /// Well-formed checking. If a `WellFormedLoc` is provided,
-    /// then it will be used to eprform HIR-based wf checking
+    /// then it will be used to perform HIR-based wf checking
     /// after an error occurs, in order to generate a more precise error span.
     /// This is purely for diagnostic purposes - it is always
     /// correct to use `MiscObligation` instead, or to specify
@@ -863,7 +863,7 @@ pub enum ObjectSafetyViolation {
 
 impl ObjectSafetyViolation {
     pub fn error_msg(&self) -> Cow<'static, str> {
-        match *self {
+        match self {
             ObjectSafetyViolation::SizedSelf(_) => "it requires `Self: Sized`".into(),
             ObjectSafetyViolation::SupertraitSelf(ref spans) => {
                 if spans.iter().any(|sp| *sp != DUMMY_SP) {
@@ -873,7 +873,7 @@ impl ObjectSafetyViolation {
                         .into()
                 }
             }
-            ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_, _, _), _) => {
+            ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => {
                 format!("associated function `{}` has no `self` parameter", name).into()
             }
             ObjectSafetyViolation::Method(
@@ -897,9 +897,11 @@ impl ObjectSafetyViolation {
             ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => {
                 format!("method `{}` has generic type parameters", name).into()
             }
-            ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => {
-                format!("method `{}`'s `self` parameter cannot be dispatched on", name).into()
-            }
+            ObjectSafetyViolation::Method(
+                name,
+                MethodViolationCode::UndispatchableReceiver(_),
+                _,
+            ) => format!("method `{}`'s `self` parameter cannot be dispatched on", name).into(),
             ObjectSafetyViolation::AssocConst(name, DUMMY_SP) => {
                 format!("it contains associated `const` `{}`", name).into()
             }
@@ -911,51 +913,40 @@ impl ObjectSafetyViolation {
     }
 
     pub fn solution(&self, err: &mut Diagnostic) {
-        match *self {
+        match self {
             ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) => {}
             ObjectSafetyViolation::Method(
                 name,
-                MethodViolationCode::StaticMethod(sugg, self_span, has_args),
+                MethodViolationCode::StaticMethod(Some((add_self_sugg, make_sized_sugg))),
                 _,
             ) => {
                 err.span_suggestion(
-                    self_span,
-                    &format!(
+                    add_self_sugg.1,
+                    format!(
                         "consider turning `{}` into a method by giving it a `&self` argument",
                         name
                     ),
-                    format!("&self{}", if has_args { ", " } else { "" }),
+                    add_self_sugg.0.to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+                err.span_suggestion(
+                    make_sized_sugg.1,
+                    format!(
+                        "alternatively, consider constraining `{}` so it does not apply to \
+                             trait objects",
+                        name
+                    ),
+                    make_sized_sugg.0.to_string(),
                     Applicability::MaybeIncorrect,
                 );
-                match sugg {
-                    Some((sugg, span)) => {
-                        err.span_suggestion(
-                            span,
-                            &format!(
-                                "alternatively, consider constraining `{}` so it does not apply to \
-                                 trait objects",
-                                name
-                            ),
-                            sugg,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                    None => {
-                        err.help(&format!(
-                            "consider turning `{}` into a method by giving it a `&self` \
-                             argument or constraining it so it does not apply to trait objects",
-                            name
-                        ));
-                    }
-                }
             }
             ObjectSafetyViolation::Method(
                 name,
-                MethodViolationCode::UndispatchableReceiver,
-                span,
+                MethodViolationCode::UndispatchableReceiver(Some(span)),
+                _,
             ) => {
                 err.span_suggestion(
-                    span,
+                    *span,
                     &format!(
                         "consider changing method `{}`'s `self` parameter to be `&self`",
                         name
@@ -991,13 +982,13 @@ impl ObjectSafetyViolation {
 }
 
 /// Reasons a method might not be object-safe.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
 pub enum MethodViolationCode {
     /// e.g., `fn foo()`
-    StaticMethod(Option<(&'static str, Span)>, Span, bool /* has args */),
+    StaticMethod(Option<(/* add &self */ (String, Span), /* add Self: Sized */ (String, Span))>),
 
     /// e.g., `fn foo(&self, x: Self)`
-    ReferencesSelfInput(usize),
+    ReferencesSelfInput(Option<Span>),
 
     /// e.g., `fn foo(&self) -> Self`
     ReferencesSelfOutput,
@@ -1009,7 +1000,7 @@ pub enum MethodViolationCode {
     Generic,
 
     /// the method's receiver (`self` argument) can't be dispatched on
-    UndispatchableReceiver,
+    UndispatchableReceiver(Option<Span>),
 }
 
 /// These are the error cases for `codegen_fulfill_obligation`.
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index b1b8bc13e2f..a6310ae5e66 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -465,13 +465,12 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn fold_regions<T>(
         self,
         value: T,
-        skipped_regions: &mut bool,
         mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
     ) -> T
     where
         T: TypeFoldable<'tcx>,
     {
-        value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f))
+        value.fold_with(&mut RegionFolder::new(self, &mut f))
     }
 
     /// Invoke `callback` on every region appearing free in `value`.
@@ -579,7 +578,6 @@ impl<'tcx> TyCtxt<'tcx> {
 
 pub struct RegionFolder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    skipped_regions: &'a mut bool,
 
     /// Stores the index of a binder *just outside* the stuff we have
     /// visited.  So this begins as INNERMOST; when we pass through a
@@ -597,10 +595,9 @@ impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
     #[inline]
     pub fn new(
         tcx: TyCtxt<'tcx>,
-        skipped_regions: &'a mut bool,
         fold_region_fn: &'a mut dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
     ) -> RegionFolder<'a, 'tcx> {
-        RegionFolder { tcx, skipped_regions, current_index: ty::INNERMOST, fold_region_fn }
+        RegionFolder { tcx, current_index: ty::INNERMOST, fold_region_fn }
     }
 }
 
@@ -624,7 +621,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
         match *r {
             ty::ReLateBound(debruijn, _) if debruijn < self.current_index => {
                 debug!(?self.current_index, "skipped bound region");
-                *self.skipped_regions = true;
                 r
             }
             _ => {
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index f3bdd63ee6d..113af328a91 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(let_chains)]
 #![feature(let_else)]
 #![feature(never_type)]
+#![feature(rustc_attrs)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 58d5d43cfbf..0869ed65ad2 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -357,6 +357,7 @@ impl<'a> DerefMut for SnapshotParser<'a> {
 }
 
 impl<'a> Parser<'a> {
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub(super) fn span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -365,6 +366,7 @@ impl<'a> Parser<'a> {
         err.span_err(sp, self.diagnostic())
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml
index d952e288a64..5785921fb1e 100644
--- a/compiler/rustc_privacy/Cargo.toml
+++ b/compiler/rustc_privacy/Cargo.toml
@@ -4,14 +4,15 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
-rustc_middle = { path = "../rustc_middle" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
+rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_hir = { path = "../rustc_hir" }
-rustc_typeck = { path = "../rustc_typeck" }
+rustc_macros = { path = "../rustc_macros" }
+rustc_middle = { path = "../rustc_middle" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
-rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
+rustc_typeck = { path = "../rustc_typeck" }
 tracing = "0.1"
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
new file mode 100644
index 00000000000..482721d373a
--- /dev/null
+++ b/compiler/rustc_privacy/src/errors.rs
@@ -0,0 +1,75 @@
+use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_span::{Span, Symbol};
+
+#[derive(SessionDiagnostic)]
+#[error(privacy::field_is_private, code = "E0451")]
+pub struct FieldIsPrivate {
+    #[primary_span]
+    pub span: Span,
+    pub field_name: Symbol,
+    pub variant_descr: &'static str,
+    pub def_path_str: String,
+    #[subdiagnostic]
+    pub label: FieldIsPrivateLabel,
+}
+
+#[derive(SessionSubdiagnostic)]
+pub enum FieldIsPrivateLabel {
+    #[label(privacy::field_is_private_is_update_syntax_label)]
+    IsUpdateSyntax {
+        #[primary_span]
+        span: Span,
+        field_name: Symbol,
+    },
+    #[label(privacy::field_is_private_label)]
+    Other {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(SessionDiagnostic)]
+#[error(privacy::item_is_private)]
+pub struct ItemIsPrivate<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub kind: &'a str,
+    pub descr: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(privacy::unnamed_item_is_private)]
+pub struct UnnamedItemIsPrivate {
+    #[primary_span]
+    pub span: Span,
+    pub kind: &'static str,
+}
+
+// Duplicate of `InPublicInterface` but with a different error code, shares the same slug.
+#[derive(SessionDiagnostic)]
+#[error(privacy::in_public_interface, code = "E0445")]
+pub struct InPublicInterfaceTraits<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub vis_descr: &'static str,
+    pub kind: &'a str,
+    pub descr: String,
+    #[label(privacy::visibility_label)]
+    pub vis_span: Span,
+}
+
+// Duplicate of `InPublicInterfaceTraits` but with a different error code, shares the same slug.
+#[derive(SessionDiagnostic)]
+#[error(privacy::in_public_interface, code = "E0446")]
+pub struct InPublicInterface<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub vis_descr: &'static str,
+    pub kind: &'a str,
+    pub descr: String,
+    #[label(privacy::visibility_label)]
+    pub vis_span: Span,
+}
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index b27c986d0f9..238c917bbc3 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1,15 +1,19 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(associated_type_defaults)]
 #![feature(control_flow_enum)]
+#![feature(rustc_private)]
 #![feature(try_blocks)]
-#![feature(associated_type_defaults)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
+#![cfg_attr(not(bootstrap), deny(rustc::untranslatable_diagnostic))]
+#![cfg_attr(not(bootstrap), deny(rustc::diagnostic_outside_of_impl))]
+
+mod errors;
 
 use rustc_ast::MacroDef;
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::intern::Interned;
-use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
@@ -34,6 +38,11 @@ use std::marker::PhantomData;
 use std::ops::ControlFlow;
 use std::{cmp, fmt, mem};
 
+use errors::{
+    FieldIsPrivate, FieldIsPrivateLabel, InPublicInterface, InPublicInterfaceTraits, ItemIsPrivate,
+    UnnamedItemIsPrivate,
+};
+
 ////////////////////////////////////////////////////////////////////////////////
 /// Generic infrastructure used to implement specific visitors below.
 ////////////////////////////////////////////////////////////////////////////////
@@ -935,23 +944,17 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
         let hir_id = self.tcx.hir().local_def_id_to_hir_id(self.current_item);
         let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id).1;
         if !field.vis.is_accessible_from(def_id, self.tcx) {
-            let label = if in_update_syntax {
-                format!("field `{}` is private", field.name)
-            } else {
-                "private field".to_string()
-            };
-
-            struct_span_err!(
-                self.tcx.sess,
+            self.tcx.sess.emit_err(FieldIsPrivate {
                 span,
-                E0451,
-                "field `{}` of {} `{}` is private",
-                field.name,
-                def.variant_descr(),
-                self.tcx.def_path_str(def.did())
-            )
-            .span_label(span, label)
-            .emit();
+                field_name: field.name,
+                variant_descr: def.variant_descr(),
+                def_path_str: self.tcx.def_path_str(def.did()),
+                label: if in_update_syntax {
+                    FieldIsPrivateLabel::IsUpdateSyntax { span, field_name: field.name }
+                } else {
+                    FieldIsPrivateLabel::Other { span }
+                },
+            });
         }
     }
 }
@@ -1075,11 +1078,11 @@ impl<'tcx> TypePrivacyVisitor<'tcx> {
     fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
         let is_error = !self.item_is_accessible(def_id);
         if is_error {
-            self.tcx
-                .sess
-                .struct_span_err(self.span, &format!("{} `{}` is private", kind, descr))
-                .span_label(self.span, &format!("private {}", kind))
-                .emit();
+            self.tcx.sess.emit_err(ItemIsPrivate {
+                span: self.span,
+                kind,
+                descr: descr.to_string(),
+            });
         }
         is_error
     }
@@ -1250,13 +1253,10 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
                     hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
                 };
                 let kind = kind.descr(def_id);
-                let msg = match name {
-                    Some(name) => format!("{} `{}` is private", kind, name),
-                    None => format!("{} is private", kind),
+                let _ = match name {
+                    Some(name) => sess.emit_err(ItemIsPrivate { span, kind, descr: name }),
+                    None => sess.emit_err(UnnamedItemIsPrivate { span, kind }),
                 };
-                sess.struct_span_err(span, &msg)
-                    .span_label(span, &format!("private {}", kind))
-                    .emit();
                 return;
             }
         }
@@ -1753,22 +1753,31 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
                     }
                 }
             };
-            let make_msg = || format!("{} {} `{}` in public interface", vis_descr, kind, descr);
             let span = self.tcx.def_span(self.item_def_id.to_def_id());
             if self.has_old_errors
                 || self.in_assoc_ty
                 || self.tcx.resolutions(()).has_pub_restricted
             {
-                let mut err = if kind == "trait" {
-                    struct_span_err!(self.tcx.sess, span, E0445, "{}", make_msg())
-                } else {
-                    struct_span_err!(self.tcx.sess, span, E0446, "{}", make_msg())
-                };
+                let descr = descr.to_string();
                 let vis_span =
                     self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id));
-                err.span_label(span, format!("can't leak {} {}", vis_descr, kind));
-                err.span_label(vis_span, format!("`{}` declared as {}", descr, vis_descr));
-                err.emit();
+                if kind == "trait" {
+                    self.tcx.sess.emit_err(InPublicInterfaceTraits {
+                        span,
+                        vis_descr,
+                        kind,
+                        descr,
+                        vis_span,
+                    });
+                } else {
+                    self.tcx.sess.emit_err(InPublicInterface {
+                        span,
+                        vis_descr,
+                        kind,
+                        descr,
+                        vis_span,
+                    });
+                }
             } else {
                 let err_code = if kind == "trait" { "E0445" } else { "E0446" };
                 self.tcx.struct_span_lint_hir(
@@ -1776,7 +1785,12 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
                     hir_id,
                     span,
                     |lint| {
-                        lint.build(&format!("{} (error {})", make_msg(), err_code)).emit();
+                        lint.build(&format!(
+                            "{} (error {})",
+                            format!("{} {} `{}` in public interface", vis_descr, kind, descr),
+                            err_code
+                        ))
+                        .emit();
                     },
                 );
             }
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index f1814eebfa6..b5058fd699a 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -280,6 +280,7 @@ impl Session {
         self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_warn<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -287,6 +288,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_span_warn(sp, msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_warn_with_expectation<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -295,6 +297,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_span_warn_with_expectation(sp, msg, id)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -303,9 +306,11 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_span_warn_with_code(sp, msg, code)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_warn(msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_warn_with_expectation(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -313,6 +318,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_warn_with_expectation(msg, id)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_allow<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -320,9 +326,11 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_span_allow(sp, msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_allow(msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_expect(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -330,6 +338,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_expect(msg, id)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -337,6 +346,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
         self.diagnostic().struct_span_err(sp, msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_err_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -346,12 +356,14 @@ impl Session {
         self.diagnostic().struct_span_err_with_code(sp, msg, code)
     }
     // FIXME: This method should be removed (every error should have an associated error code).
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_err(
         &self,
         msg: impl Into<DiagnosticMessage>,
     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
         self.parse_sess.struct_err(msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_err_with_code(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -359,6 +371,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
         self.diagnostic().struct_err_with_code(msg, code)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_warn_with_code(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -366,6 +379,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_warn_with_code(msg, code)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_fatal<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -373,6 +387,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, !> {
         self.diagnostic().struct_span_fatal(sp, msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -381,13 +396,16 @@ impl Session {
     ) -> DiagnosticBuilder<'_, !> {
         self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
         self.diagnostic().struct_fatal(msg)
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
         self.diagnostic().span_fatal(sp, msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_fatal_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -396,9 +414,11 @@ impl Session {
     ) -> ! {
         self.diagnostic().span_fatal_with_code(sp, msg, code)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> ! {
         self.diagnostic().fatal(msg).raise()
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_err_or_warn<S: Into<MultiSpan>>(
         &self,
         is_warning: bool,
@@ -411,6 +431,7 @@ impl Session {
             self.span_err(sp, msg);
         }
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -418,6 +439,7 @@ impl Session {
     ) -> ErrorGuaranteed {
         self.diagnostic().span_err(sp, msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_err_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -426,6 +448,7 @@ impl Session {
     ) {
         self.diagnostic().span_err_with_code(sp, msg, code)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
         self.diagnostic().err(msg)
     }
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index a8ddcc9bfac..59dbea70534 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -8,6 +8,7 @@
 //! LLVM.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(assert_matches)]
 #![feature(associated_type_bounds)]
 #![feature(exhaustive_patterns)]
 #![feature(let_else)]
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
index 86f76fdb6a7..9d36e37d7b8 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
@@ -8,7 +8,7 @@ pub fn target() -> Target {
     // FIXME: The leak sanitizer currently fails the tests, see #88132.
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD;
 
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".into(), "arm64".into()]);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-arch", "arm64"]);
     base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
 
     // Clang automatically chooses a more specific target based on
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
index 965b254c289..162b091b269 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
@@ -2,20 +2,13 @@
 // uefi-base module for generic UEFI options.
 
 use super::uefi_msvc_base;
-use crate::spec::{LinkerFlavor, LldFlavor, Target};
+use crate::spec::{LinkerFlavor, Target};
 
 pub fn target() -> Target {
     let mut base = uefi_msvc_base::opts();
 
     base.max_atomic_width = Some(64);
-
-    let pre_link_args_msvc = vec!["/machine:arm64".into()];
-
-    base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().extend(pre_link_args_msvc.clone());
-    base.pre_link_args
-        .get_mut(&LinkerFlavor::Lld(LldFlavor::Link))
-        .unwrap()
-        .extend(pre_link_args_msvc);
+    base.add_pre_link_args(LinkerFlavor::Msvc, &["/machine:arm64"]);
 
     Target {
         llvm_target: "aarch64-unknown-windows".into(),
diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
index 67df73fa935..8c2a9bcfde6 100644
--- a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
+++ b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
@@ -1,19 +1,13 @@
-use crate::spec::{cvs, LinkArgs, LinkerFlavor, RelocModel, Target, TargetOptions};
+use crate::spec::{cvs, LinkerFlavor, RelocModel, Target, TargetOptions};
 
 /// A base target for Nintendo 3DS devices using the devkitARM toolchain.
 ///
 /// Requires the devkitARM toolchain for 3DS targets on the host system.
 
 pub fn target() -> Target {
-    let mut pre_link_args = LinkArgs::new();
-    pre_link_args.insert(
+    let pre_link_args = TargetOptions::link_args(
         LinkerFlavor::Gcc,
-        vec![
-            "-specs=3dsx.specs".into(),
-            "-mtune=mpcore".into(),
-            "-mfloat-abi=hard".into(),
-            "-mtp=soft".into(),
-        ],
+        &["-specs=3dsx.specs", "-mtune=mpcore", "-mfloat-abi=hard", "-mtp=soft"],
     );
 
     Target {
diff --git a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs
index 2afd93fcad8..38c117a495e 100644
--- a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs
@@ -10,7 +10,7 @@ use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::android_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-march=armv7-a"]);
     Target {
         llvm_target: "armv7-none-linux-android".into(),
         pointer_width: 32,
diff --git a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs b/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs
index 269bf8b8bcd..b4cf2c5ee22 100644
--- a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs
+++ b/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs
@@ -2,10 +2,6 @@ use super::{wasm32_unknown_emscripten, LinkerFlavor, Target};
 
 pub fn target() -> Target {
     let mut target = wasm32_unknown_emscripten::target();
-    target.post_link_args.entry(LinkerFlavor::Em).or_default().extend(vec![
-        "-sWASM=0".into(),
-        "--memory-init-file".into(),
-        "0".into(),
-    ]);
+    target.add_post_link_args(LinkerFlavor::Em, &["-sWASM=0", "--memory-init-file", "0"]);
     target
 }
diff --git a/compiler/rustc_target/src/spec/avr_gnu_base.rs b/compiler/rustc_target/src/spec/avr_gnu_base.rs
index c288e8b0e9e..4fd6c06394d 100644
--- a/compiler/rustc_target/src/spec/avr_gnu_base.rs
+++ b/compiler/rustc_target/src/spec/avr_gnu_base.rs
@@ -3,7 +3,8 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 /// A base target for AVR devices using the GNU toolchain.
 ///
 /// Requires GNU avr-gcc and avr-binutils on the host system.
-pub fn target(target_cpu: &'static str) -> Target {
+/// FIXME: Remove the second parameter when const string concatenation is possible.
+pub fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {
     Target {
         arch: "avr".into(),
         data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(),
@@ -17,10 +18,8 @@ pub fn target(target_cpu: &'static str) -> Target {
             linker: Some("avr-gcc".into()),
             executables: true,
             eh_frame_header: false,
-            pre_link_args: [(LinkerFlavor::Gcc, vec![format!("-mmcu={}", target_cpu).into()])]
-                .into_iter()
-                .collect(),
-            late_link_args: [(LinkerFlavor::Gcc, vec!["-lgcc".into()])].into_iter().collect(),
+            pre_link_args: TargetOptions::link_args(LinkerFlavor::Gcc, &[mmcu]),
+            late_link_args: TargetOptions::link_args(LinkerFlavor::Gcc, &["-lgcc"]),
             max_atomic_width: Some(0),
             atomic_cas: false,
             ..TargetOptions::default()
diff --git a/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs b/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs
index 6871ca0f789..6c16b03cc28 100644
--- a/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs
+++ b/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs
@@ -1,5 +1,5 @@
 use crate::spec::Target;
 
 pub fn target() -> Target {
-    super::avr_gnu_base::target("atmega328")
+    super::avr_gnu_base::target("atmega328", "-mmcu=atmega328")
 }
diff --git a/compiler/rustc_target/src/spec/fuchsia_base.rs b/compiler/rustc_target/src/spec/fuchsia_base.rs
index b64875e32bd..b02b70f76ee 100644
--- a/compiler/rustc_target/src/spec/fuchsia_base.rs
+++ b/compiler/rustc_target/src/spec/fuchsia_base.rs
@@ -1,23 +1,20 @@
-use crate::spec::{
-    crt_objects, cvs, LinkArgs, LinkOutputKind, LinkerFlavor, LldFlavor, TargetOptions,
-};
+use crate::spec::{crt_objects, cvs, LinkOutputKind, LinkerFlavor, LldFlavor, TargetOptions};
 
 pub fn opts() -> TargetOptions {
-    let mut pre_link_args = LinkArgs::new();
-    pre_link_args.insert(
-        LinkerFlavor::Lld(LldFlavor::Ld),
-        vec![
-            "--build-id".into(),
-            "--hash-style=gnu".into(),
-            "-z".into(),
-            "max-page-size=4096".into(),
-            "-z".into(),
-            "now".into(),
-            "-z".into(),
-            "rodynamic".into(),
-            "-z".into(),
-            "separate-loadable-segments".into(),
-            "--pack-dyn-relocs=relr".into(),
+    let pre_link_args = TargetOptions::link_args(
+        LinkerFlavor::Ld,
+        &[
+            "--build-id",
+            "--hash-style=gnu",
+            "-z",
+            "max-page-size=4096",
+            "-z",
+            "now",
+            "-z",
+            "rodynamic",
+            "-z",
+            "separate-loadable-segments",
+            "--pack-dyn-relocs=relr",
         ],
     );
 
diff --git a/compiler/rustc_target/src/spec/hermit_base.rs b/compiler/rustc_target/src/spec/hermit_base.rs
index 7cbd42417e6..e43153177f0 100644
--- a/compiler/rustc_target/src/spec/hermit_base.rs
+++ b/compiler/rustc_target/src/spec/hermit_base.rs
@@ -1,10 +1,9 @@
-use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions, TlsModel};
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions, TlsModel};
 
 pub fn opts() -> TargetOptions {
-    let mut pre_link_args = LinkArgs::new();
-    pre_link_args.insert(
-        LinkerFlavor::Lld(LldFlavor::Ld),
-        vec!["--build-id".into(), "--hash-style=gnu".into(), "--Bstatic".into()],
+    let pre_link_args = TargetOptions::link_args(
+        LinkerFlavor::Ld,
+        &["--build-id", "--hash-style=gnu", "--Bstatic"],
     );
 
     TargetOptions {
diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs
index ad716a6cd5a..1718bd77b86 100644
--- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     let mut base = super::apple_base::opts("macos");
     base.cpu = "yonah".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".into()]);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
     base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs
index 554b0f34499..6318654399c 100644
--- a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs
@@ -1,19 +1,16 @@
-use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, Target};
+use crate::spec::{FramePointer, LinkerFlavor, Target};
 
 pub fn target() -> Target {
     let mut base = super::windows_gnu_base::opts();
     base.cpu = "pentium4".into();
-    base.pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".into(), "i386pe".into()]);
     base.max_atomic_width = Some(64);
     base.frame_pointer = FramePointer::Always; // Required for backtraces
     base.linker = Some("i686-w64-mingw32-gcc".into());
 
     // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
     // space available to x86 Windows binaries on x86_64.
-    base.pre_link_args
-        .entry(LinkerFlavor::Gcc)
-        .or_default()
-        .push("-Wl,--large-address-aware".into());
+    base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe", "--large-address-aware"]);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-Wl,--large-address-aware"]);
 
     Target {
         llvm_target: "i686-pc-windows-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs
index fb0cb6a6943..f4ceaa1ca4b 100644
--- a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs
@@ -1,24 +1,22 @@
-use crate::spec::{LinkerFlavor, LldFlavor, Target};
+use crate::spec::{LinkerFlavor, Target};
 
 pub fn target() -> Target {
     let mut base = super::windows_msvc_base::opts();
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
 
-    let pre_link_args_msvc = vec![
-        // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
-        // space available to x86 Windows binaries on x86_64.
-        "/LARGEADDRESSAWARE".into(),
-        // Ensure the linker will only produce an image if it can also produce a table of
-        // the image's safe exception handlers.
-        // https://docs.microsoft.com/en-us/cpp/build/reference/safeseh-image-has-safe-exception-handlers
-        "/SAFESEH".into(),
-    ];
-    base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone());
-    base.pre_link_args
-        .entry(LinkerFlavor::Lld(LldFlavor::Link))
-        .or_default()
-        .extend(pre_link_args_msvc);
+    base.add_pre_link_args(
+        LinkerFlavor::Msvc,
+        &[
+            // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
+            // space available to x86 Windows binaries on x86_64.
+            "/LARGEADDRESSAWARE",
+            // Ensure the linker will only produce an image if it can also produce a table of
+            // the image's safe exception handlers.
+            // https://docs.microsoft.com/en-us/cpp/build/reference/safeseh-image-has-safe-exception-handlers
+            "/SAFESEH",
+        ],
+    );
     // Workaround for #95429
     base.has_thread_local = false;
 
diff --git a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs
index 9f0cb04c65d..aff284bf2bc 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs
@@ -4,9 +4,7 @@ pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
-    let pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default();
-    pre_link_args.push("-m32".into());
-    pre_link_args.push("-Wl,-znotext".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "-Wl,-znotext"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
diff --git a/compiler/rustc_target/src/spec/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/i686_unknown_haiku.rs
index d1af163f1cf..87aa74e406c 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_haiku.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     let mut base = super::haiku_base::opts();
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".into()]);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs
index 0998c618f31..765803d1692 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs
index a697f292da0..d9492804349 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs
@@ -4,8 +4,7 @@ pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-Wl,-melf_i386".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "-Wl,-melf_i386"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
diff --git a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs
index 2807d328205..8de698b51f0 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     let mut base = super::netbsd_base::opts();
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
diff --git a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs
index 78462eb63b8..7f25a1a16c1 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs
@@ -4,8 +4,7 @@ pub fn target() -> Target {
     let mut base = super::openbsd_base::opts();
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-fuse-ld=lld".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "-fuse-ld=lld"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
diff --git a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs
index 75f7a2209c8..d52810d2fb0 100644
--- a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs
@@ -1,18 +1,15 @@
-use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, Target};
+use crate::spec::{FramePointer, LinkerFlavor, Target};
 
 pub fn target() -> Target {
     let mut base = super::windows_uwp_gnu_base::opts();
     base.cpu = "pentium4".into();
-    base.pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".into(), "i386pe".into()]);
     base.max_atomic_width = Some(64);
     base.frame_pointer = FramePointer::Always; // Required for backtraces
 
     // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
     // space available to x86 Windows binaries on x86_64.
-    base.pre_link_args
-        .entry(LinkerFlavor::Gcc)
-        .or_default()
-        .push("-Wl,--large-address-aware".into());
+    base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe", "--large-address-aware"]);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-Wl,--large-address-aware"]);
 
     Target {
         llvm_target: "i686-pc-windows-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs
index d51ed7c1f7a..f62404e8279 100644
--- a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     let mut base = super::vxworks_base::opts();
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
diff --git a/compiler/rustc_target/src/spec/illumos_base.rs b/compiler/rustc_target/src/spec/illumos_base.rs
index ef8f90a4da8..b0e1b109be1 100644
--- a/compiler/rustc_target/src/spec/illumos_base.rs
+++ b/compiler/rustc_target/src/spec/illumos_base.rs
@@ -1,10 +1,9 @@
-use crate::spec::{cvs, FramePointer, LinkArgs, LinkerFlavor, TargetOptions};
+use crate::spec::{cvs, FramePointer, LinkerFlavor, TargetOptions};
 
 pub fn opts() -> TargetOptions {
-    let mut late_link_args = LinkArgs::new();
-    late_link_args.insert(
+    let late_link_args = TargetOptions::link_args(
         LinkerFlavor::Gcc,
-        vec![
+        &[
             // The illumos libc contains a stack unwinding implementation, as
             // does libgcc_s.  The latter implementation includes several
             // additional symbols that are not always in base libc.  To force
@@ -15,13 +14,13 @@ pub fn opts() -> TargetOptions {
             // FIXME: This should be replaced by a more complete and generic
             // mechanism for controlling the order of library arguments passed
             // to the linker.
-            "-lc".into(),
+            "-lc",
             // LLVM will insert calls to the stack protector functions
             // "__stack_chk_fail" and "__stack_chk_guard" into code in native
             // object files.  Some platforms include these symbols directly in
             // libc, but at least historically these have been provided in
             // libssp.so on illumos and Solaris systems.
-            "-lssp".into(),
+            "-lssp",
         ],
     );
 
diff --git a/compiler/rustc_target/src/spec/mipsel_sony_psp.rs b/compiler/rustc_target/src/spec/mipsel_sony_psp.rs
index 03e0934ea5e..e3522de6de0 100644
--- a/compiler/rustc_target/src/spec/mipsel_sony_psp.rs
+++ b/compiler/rustc_target/src/spec/mipsel_sony_psp.rs
@@ -1,13 +1,11 @@
 use crate::spec::{cvs, Target, TargetOptions};
-use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, RelocModel};
+use crate::spec::{LinkerFlavor, LldFlavor, RelocModel};
 
 // The PSP has custom linker requirements.
 const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld");
 
 pub fn target() -> Target {
-    let mut pre_link_args = LinkArgs::new();
-    pre_link_args
-        .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["--emit-relocs".into(), "--nmagic".into()]);
+    let pre_link_args = TargetOptions::link_args(LinkerFlavor::Ld, &["--emit-relocs", "--nmagic"]);
 
     Target {
         llvm_target: "mipsel-sony-psp".into(),
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index da0589cdd20..a08603da040 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1459,6 +1459,44 @@ pub struct TargetOptions {
     pub supports_stack_protector: bool,
 }
 
+/// Add arguments for the given flavor and also for its "twin" flavors
+/// that have a compatible command line interface.
+fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
+    let mut insert = |flavor| {
+        link_args.entry(flavor).or_default().extend(args.iter().copied().map(Cow::Borrowed))
+    };
+    insert(flavor);
+    match flavor {
+        LinkerFlavor::Ld => insert(LinkerFlavor::Lld(LldFlavor::Ld)),
+        LinkerFlavor::Msvc => insert(LinkerFlavor::Lld(LldFlavor::Link)),
+        LinkerFlavor::Lld(LldFlavor::Wasm) => {}
+        LinkerFlavor::Lld(lld_flavor) => {
+            panic!("add_link_args: use non-LLD flavor for {:?}", lld_flavor)
+        }
+        LinkerFlavor::Gcc
+        | LinkerFlavor::Em
+        | LinkerFlavor::L4Bender
+        | LinkerFlavor::BpfLinker
+        | LinkerFlavor::PtxLinker => {}
+    }
+}
+
+impl TargetOptions {
+    fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
+        let mut link_args = LinkArgs::new();
+        add_link_args(&mut link_args, flavor, args);
+        link_args
+    }
+
+    fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
+        add_link_args(&mut self.pre_link_args, flavor, args);
+    }
+
+    fn add_post_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
+        add_link_args(&mut self.post_link_args, flavor, args);
+    }
+}
+
 impl Default for TargetOptions {
     /// Creates a set of "sane defaults" for any target. This is still
     /// incomplete, and if used for compilation, will certainly not work.
diff --git a/compiler/rustc_target/src/spec/msvc_base.rs b/compiler/rustc_target/src/spec/msvc_base.rs
index 00cc9620243..c4df4b546e3 100644
--- a/compiler/rustc_target/src/spec/msvc_base.rs
+++ b/compiler/rustc_target/src/spec/msvc_base.rs
@@ -1,14 +1,9 @@
-use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, SplitDebuginfo, TargetOptions};
+use crate::spec::{LinkerFlavor, LldFlavor, SplitDebuginfo, TargetOptions};
 
 pub fn opts() -> TargetOptions {
-    let pre_link_args_msvc = vec![
-        // Suppress the verbose logo and authorship debugging output, which would needlessly
-        // clog any log files.
-        "/NOLOGO".into(),
-    ];
-    let mut pre_link_args = LinkArgs::new();
-    pre_link_args.insert(LinkerFlavor::Msvc, pre_link_args_msvc.clone());
-    pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Link), pre_link_args_msvc);
+    // Suppress the verbose logo and authorship debugging output, which would needlessly
+    // clog any log files.
+    let pre_link_args = TargetOptions::link_args(LinkerFlavor::Msvc, &["/NOLOGO"]);
 
     TargetOptions {
         linker_flavor: LinkerFlavor::Msvc,
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
index 595769c4bfa..803453c4ac4 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
@@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
     base.cpu = "ppc64".into();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
index 24d5d187e1a..5413c4f33ff 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
@@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, RelroLevel, Target, TargetOptions};
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
     base.cpu = "ppc64".into();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
 
     // ld.so in at least RHEL6 on ppc64 has a bug related to BIND_NOW, so only enable partial RELRO
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
index 0f465ccfe77..159335eb607 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
@@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
     base.cpu = "ppc64".into();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
index 491d344aedb..b7420d232ca 100644
--- a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
@@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 pub fn target() -> Target {
     let mut base = super::vxworks_base::opts();
     base.cpu = "ppc64".into();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
index b198e667ccc..a3d18004371 100644
--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
@@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
     base.cpu = "ppc64le".into();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
index 09e3936db26..e18ff3be448 100644
--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
@@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
     base.cpu = "ppc64le".into();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
index 8a947b091cb..b84943d23a9 100644
--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
@@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
     base.cpu = "ppc64le".into();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
index c27b84775df..516b2de37ea 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
@@ -3,12 +3,8 @@ use crate::spec::{LinkerFlavor, RelocModel, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
     // Extra hint to linker that we are generating secure-PLT code.
-    base.pre_link_args
-        .entry(LinkerFlavor::Gcc)
-        .or_default()
-        .push("--target=powerpc-unknown-freebsd13.0".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "--target=powerpc-unknown-freebsd13.0"]);
     base.max_atomic_width = Some(32);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
index 88f61500e3c..6686a0bbf04 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
@@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
     base.max_atomic_width = Some(32);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
index 3ee548750b9..6a250f4b51c 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
@@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mspe".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-mspe"]);
     base.max_atomic_width = Some(32);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
index ce33c787f33..34200c67906 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
@@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
     base.max_atomic_width = Some(32);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
index 998225f4dae..60661ef9b5d 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
@@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::netbsd_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
     base.max_atomic_width = Some(32);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
index 76709cec591..3f24966e06e 100644
--- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
@@ -3,8 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::vxworks_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("--secure-plt".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "--secure-plt"]);
     base.max_atomic_width = Some(32);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
index 7b5d1242c52..0f04f41f9e5 100644
--- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
+++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
@@ -3,8 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::vxworks_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mspe".into());
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("--secure-plt".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-mspe", "--secure-plt"]);
     base.max_atomic_width = Some(32);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
index 718303a4b4d..836ab0e3728 100644
--- a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
@@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 pub fn target() -> Target {
     let mut base = super::netbsd_base::opts();
     base.cpu = "v9".into();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
index 2aaa0ca6df8..4a192df392f 100644
--- a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
     let mut base = super::openbsd_base::opts();
     base.endian = Endian::Big;
     base.cpu = "v9".into();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
index 71d3de0bfd1..ea4fafa4b06 100644
--- a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     base.endian = Endian::Big;
     base.cpu = "v9".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mv8plus".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-mv8plus"]);
 
     Target {
         llvm_target: "sparc-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
index 79ae54aa666..aac09181a74 100644
--- a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
+++ b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
@@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, Target};
 pub fn target() -> Target {
     let mut base = super::solaris_base::opts();
     base.endian = Endian::Big;
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into()]);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     // llvm calls this "v9"
     base.cpu = "v9".into();
     base.vendor = "sun".into();
diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs
index 0865ca7ea7d..c7c5a231901 100644
--- a/compiler/rustc_target/src/spec/tests/tests_impl.rs
+++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs
@@ -1,4 +1,5 @@
 use super::super::*;
+use std::assert_matches::assert_matches;
 
 // Test target self-consistency and JSON encoding/decoding roundtrip.
 pub(super) fn test_target(target: Target) {
@@ -14,35 +15,105 @@ impl Target {
         assert_eq!(self.is_like_wasm, self.arch == "wasm32" || self.arch == "wasm64");
         assert!(self.is_like_windows || !self.is_like_msvc);
 
-        // Check that LLD with the given flavor is treated identically to the linker it emulates.
-        // If your target really needs to deviate from the rules below, except it and document the
-        // reasons.
-        assert_eq!(
-            self.linker_flavor == LinkerFlavor::Msvc
-                || self.linker_flavor == LinkerFlavor::Lld(LldFlavor::Link),
-            self.lld_flavor == LldFlavor::Link,
-        );
-        assert_eq!(self.is_like_msvc, self.lld_flavor == LldFlavor::Link);
-        for args in &[
+        // Check that default linker flavor and lld flavor are compatible
+        // with some other key properties.
+        assert_eq!(self.is_like_osx, matches!(self.lld_flavor, LldFlavor::Ld64));
+        assert_eq!(self.is_like_msvc, matches!(self.lld_flavor, LldFlavor::Link));
+        assert_eq!(self.is_like_wasm, matches!(self.lld_flavor, LldFlavor::Wasm));
+        assert_eq!(self.os == "l4re", matches!(self.linker_flavor, LinkerFlavor::L4Bender));
+        assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::Em));
+        assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::BpfLinker));
+        assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::PtxLinker));
+
+        for args in [
             &self.pre_link_args,
             &self.late_link_args,
             &self.late_link_args_dynamic,
             &self.late_link_args_static,
             &self.post_link_args,
         ] {
+            for (&flavor, flavor_args) in args {
+                assert!(!flavor_args.is_empty());
+                // Check that flavors mentioned in link args are compatible with the default flavor.
+                match (self.linker_flavor, self.lld_flavor) {
+                    (
+                        LinkerFlavor::Ld | LinkerFlavor::Lld(LldFlavor::Ld) | LinkerFlavor::Gcc,
+                        LldFlavor::Ld,
+                    ) => {
+                        assert_matches!(
+                            flavor,
+                            LinkerFlavor::Ld | LinkerFlavor::Lld(LldFlavor::Ld) | LinkerFlavor::Gcc
+                        )
+                    }
+                    (LinkerFlavor::Gcc, LldFlavor::Ld64) => {
+                        assert_matches!(flavor, LinkerFlavor::Gcc)
+                    }
+                    (LinkerFlavor::Msvc | LinkerFlavor::Lld(LldFlavor::Link), LldFlavor::Link) => {
+                        assert_matches!(
+                            flavor,
+                            LinkerFlavor::Msvc | LinkerFlavor::Lld(LldFlavor::Link)
+                        )
+                    }
+                    (LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc, LldFlavor::Wasm) => {
+                        assert_matches!(
+                            flavor,
+                            LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc
+                        )
+                    }
+                    (LinkerFlavor::L4Bender, LldFlavor::Ld) => {
+                        assert_matches!(flavor, LinkerFlavor::L4Bender)
+                    }
+                    (LinkerFlavor::Em, LldFlavor::Wasm) => {
+                        assert_matches!(flavor, LinkerFlavor::Em)
+                    }
+                    (LinkerFlavor::BpfLinker, LldFlavor::Ld) => {
+                        assert_matches!(flavor, LinkerFlavor::BpfLinker)
+                    }
+                    (LinkerFlavor::PtxLinker, LldFlavor::Ld) => {
+                        assert_matches!(flavor, LinkerFlavor::PtxLinker)
+                    }
+                    flavors => unreachable!("unexpected flavor combination: {:?}", flavors),
+                }
+
+                // Check that link args for cc and non-cc versions of flavors are consistent.
+                let check_noncc = |noncc_flavor| {
+                    if let Some(noncc_args) = args.get(&noncc_flavor) {
+                        for arg in flavor_args {
+                            if let Some(suffix) = arg.strip_prefix("-Wl,") {
+                                assert!(noncc_args.iter().any(|a| a == suffix));
+                            }
+                        }
+                    }
+                };
+                match self.linker_flavor {
+                    LinkerFlavor::Gcc => match self.lld_flavor {
+                        LldFlavor::Ld => {
+                            check_noncc(LinkerFlavor::Ld);
+                            check_noncc(LinkerFlavor::Lld(LldFlavor::Ld));
+                        }
+                        LldFlavor::Wasm => check_noncc(LinkerFlavor::Lld(LldFlavor::Wasm)),
+                        LldFlavor::Ld64 | LldFlavor::Link => {}
+                    },
+                    _ => {}
+                }
+            }
+
+            // Check that link args for lld and non-lld versions of flavors are consistent.
+            assert_eq!(args.get(&LinkerFlavor::Ld), args.get(&LinkerFlavor::Lld(LldFlavor::Ld)));
             assert_eq!(
                 args.get(&LinkerFlavor::Msvc),
                 args.get(&LinkerFlavor::Lld(LldFlavor::Link)),
             );
-            if args.contains_key(&LinkerFlavor::Msvc) {
-                assert_eq!(self.lld_flavor, LldFlavor::Link);
-            }
         }
+
         assert!(
             (self.pre_link_objects_fallback.is_empty()
                 && self.post_link_objects_fallback.is_empty())
                 || self.crt_objects_fallback.is_some()
         );
+
+        // If your target really needs to deviate from the rules below,
+        // except it and document the reasons.
         // Keep the default "unknown" vendor instead.
         assert_ne!(self.vendor, "");
         if !self.can_use_os_unknown() {
diff --git a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs
index f6cbbd38cf4..4d09d3a4d10 100644
--- a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::windows_msvc_base::opts();
@@ -9,12 +9,7 @@ pub fn target() -> Target {
     // should be smart enough to insert branch islands only
     // where necessary, but this is not the observed behavior.
     // Disabling the LBR optimization works around the issue.
-    let pre_link_args_msvc = "/OPT:NOLBR";
-    base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().push(pre_link_args_msvc.into());
-    base.pre_link_args
-        .entry(LinkerFlavor::Lld(LldFlavor::Link))
-        .or_default()
-        .push(pre_link_args_msvc.into());
+    base.add_pre_link_args(LinkerFlavor::Msvc, &["/OPT:NOLBR"]);
 
     Target {
         llvm_target: "thumbv7a-pc-windows-msvc".into(),
diff --git a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
index 9a3e8b5c5f8..4cad9e18370 100644
--- a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
@@ -10,7 +10,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::android_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-march=armv7-a"]);
     Target {
         llvm_target: "armv7-none-linux-android".into(),
         pointer_width: 32,
diff --git a/compiler/rustc_target/src/spec/uefi_msvc_base.rs b/compiler/rustc_target/src/spec/uefi_msvc_base.rs
index bc7244b3a45..aee8eb2e31c 100644
--- a/compiler/rustc_target/src/spec/uefi_msvc_base.rs
+++ b/compiler/rustc_target/src/spec/uefi_msvc_base.rs
@@ -14,27 +14,25 @@ use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, StackProbeType, Target
 pub fn opts() -> TargetOptions {
     let mut base = super::msvc_base::opts();
 
-    let pre_link_args_msvc = vec![
-        // Non-standard subsystems have no default entry-point in PE+ files. We have to define
-        // one. "efi_main" seems to be a common choice amongst other implementations and the
-        // spec.
-        "/entry:efi_main".into(),
-        // COFF images have a "Subsystem" field in their header, which defines what kind of
-        // program it is. UEFI has 3 fields reserved, which are EFI_APPLICATION,
-        // EFI_BOOT_SERVICE_DRIVER, and EFI_RUNTIME_DRIVER. We default to EFI_APPLICATION,
-        // which is very likely the most common option. Individual projects can override this
-        // with custom linker flags.
-        // The subsystem-type only has minor effects on the application. It defines the memory
-        // regions the application is loaded into (runtime-drivers need to be put into
-        // reserved areas), as well as whether a return from the entry-point is treated as
-        // exit (default for applications).
-        "/subsystem:efi_application".into(),
-    ];
-    base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone());
-    base.pre_link_args
-        .entry(LinkerFlavor::Lld(LldFlavor::Link))
-        .or_default()
-        .extend(pre_link_args_msvc);
+    base.add_pre_link_args(
+        LinkerFlavor::Msvc,
+        &[
+            // Non-standard subsystems have no default entry-point in PE+ files. We have to define
+            // one. "efi_main" seems to be a common choice amongst other implementations and the
+            // spec.
+            "/entry:efi_main",
+            // COFF images have a "Subsystem" field in their header, which defines what kind of
+            // program it is. UEFI has 3 fields reserved, which are EFI_APPLICATION,
+            // EFI_BOOT_SERVICE_DRIVER, and EFI_RUNTIME_DRIVER. We default to EFI_APPLICATION,
+            // which is very likely the most common option. Individual projects can override this
+            // with custom linker flags.
+            // The subsystem-type only has minor effects on the application. It defines the memory
+            // regions the application is loaded into (runtime-drivers need to be put into
+            // reserved areas), as well as whether a return from the entry-point is treated as
+            // exit (default for applications).
+            "/subsystem:efi_application",
+        ],
+    );
 
     TargetOptions {
         os: "uefi".into(),
diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs
index 1b94c59b55f..c7e7d221086 100644
--- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs
+++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs
@@ -2,21 +2,11 @@ use super::{cvs, wasm_base};
 use super::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut options = wasm_base::options();
-
-    let clang_args = options.pre_link_args.entry(LinkerFlavor::Gcc).or_default();
-
-    // Rust really needs a way for users to specify exports and imports in
-    // the source code. --export-dynamic isn't the right tool for this job,
-    // however it does have the side effect of automatically exporting a lot
-    // of symbols, which approximates what people want when compiling for
-    // wasm32-unknown-unknown expect, so use it for now.
-    clang_args.push("--export-dynamic".into());
-
-    let mut post_link_args = LinkArgs::new();
-    post_link_args.insert(
+    // Reset flags for non-Em flavors back to empty to satisfy sanity checking tests.
+    let pre_link_args = LinkArgs::new();
+    let post_link_args = TargetOptions::link_args(
         LinkerFlavor::Em,
-        vec!["-sABORTING_MALLOC=0".into(), "-Wl,--fatal-warnings".into()],
+        &["-sABORTING_MALLOC=0", "-Wl,--fatal-warnings"],
     );
 
     let opts = TargetOptions {
@@ -26,12 +16,13 @@ pub fn target() -> Target {
         // functionality, and a .wasm file.
         exe_suffix: ".js".into(),
         linker: None,
+        pre_link_args,
+        post_link_args,
         relocation_model: RelocModel::Pic,
         panic_strategy: PanicStrategy::Unwind,
         no_default_libraries: false,
-        post_link_args,
         families: cvs!["unix", "wasm"],
-        ..options
+        ..wasm_base::options()
     };
     Target {
         llvm_target: "wasm32-unknown-emscripten".into(),
diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
index 214b5fce5a6..4e2927dd913 100644
--- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
@@ -29,27 +29,30 @@ pub fn target() -> Target {
     // code on this target due to this ABI mismatch.
     options.default_adjusted_cabi = Some(Abi::Wasm);
 
-    let clang_args = options.pre_link_args.entry(LinkerFlavor::Gcc).or_default();
-
-    // Make sure clang uses LLD as its linker and is configured appropriately
-    // otherwise
-    clang_args.push("--target=wasm32-unknown-unknown".into());
-
-    // For now this target just never has an entry symbol no matter the output
-    // type, so unconditionally pass this.
-    clang_args.push("-Wl,--no-entry".into());
-
-    // Rust really needs a way for users to specify exports and imports in
-    // the source code. --export-dynamic isn't the right tool for this job,
-    // however it does have the side effect of automatically exporting a lot
-    // of symbols, which approximates what people want when compiling for
-    // wasm32-unknown-unknown expect, so use it for now.
-    clang_args.push("-Wl,--export-dynamic".into());
-
-    // Add the flags to wasm-ld's args too.
-    let lld_args = options.pre_link_args.entry(LinkerFlavor::Lld(LldFlavor::Wasm)).or_default();
-    lld_args.push("--no-entry".into());
-    lld_args.push("--export-dynamic".into());
+    options.add_pre_link_args(
+        LinkerFlavor::Lld(LldFlavor::Wasm),
+        &[
+            // For now this target just never has an entry symbol no matter the output
+            // type, so unconditionally pass this.
+            "--no-entry",
+            // Rust really needs a way for users to specify exports and imports in
+            // the source code. --export-dynamic isn't the right tool for this job,
+            // however it does have the side effect of automatically exporting a lot
+            // of symbols, which approximates what people want when compiling for
+            // wasm32-unknown-unknown expect, so use it for now.
+            "--export-dynamic",
+        ],
+    );
+    options.add_pre_link_args(
+        LinkerFlavor::Gcc,
+        &[
+            // Make sure clang uses LLD as its linker and is configured appropriately
+            // otherwise
+            "--target=wasm32-unknown-unknown",
+            "-Wl,--no-entry",
+            "-Wl,--export-dynamic",
+        ],
+    );
 
     Target {
         llvm_target: "wasm32-unknown-unknown".into(),
diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs
index 10eb78e4e25..280457d68b9 100644
--- a/compiler/rustc_target/src/spec/wasm32_wasi.rs
+++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs
@@ -80,11 +80,7 @@ pub fn target() -> Target {
 
     options.os = "wasi".into();
     options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm);
-    options
-        .pre_link_args
-        .entry(LinkerFlavor::Gcc)
-        .or_insert(Vec::new())
-        .push("--target=wasm32-wasi".into());
+    options.add_pre_link_args(LinkerFlavor::Gcc, &["--target=wasm32-wasi"]);
 
     options.pre_link_objects_fallback = crt_objects::pre_wasi_fallback();
     options.post_link_objects_fallback = crt_objects::post_wasi_fallback();
diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
index 6826c0ac62b..5211f7707fb 100644
--- a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
@@ -14,19 +14,25 @@ pub fn target() -> Target {
     let mut options = wasm_base::options();
     options.os = "unknown".into();
     options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm);
-    let clang_args = options.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap();
 
-    // Make sure clang uses LLD as its linker and is configured appropriately
-    // otherwise
-    clang_args.push("--target=wasm64-unknown-unknown".into());
-
-    // For now this target just never has an entry symbol no matter the output
-    // type, so unconditionally pass this.
-    clang_args.push("-Wl,--no-entry".into());
-
-    let lld_args = options.pre_link_args.get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm)).unwrap();
-    lld_args.push("--no-entry".into());
-    lld_args.push("-mwasm64".into());
+    options.add_pre_link_args(
+        LinkerFlavor::Lld(LldFlavor::Wasm),
+        &[
+            // For now this target just never has an entry symbol no matter the output
+            // type, so unconditionally pass this.
+            "--no-entry",
+            "-mwasm64",
+        ],
+    );
+    options.add_pre_link_args(
+        LinkerFlavor::Gcc,
+        &[
+            // Make sure clang uses LLD as its linker and is configured appropriately
+            // otherwise
+            "--target=wasm64-unknown-unknown",
+            "-Wl,--no-entry",
+        ],
+    );
 
     // Any engine that implements wasm64 will surely implement the rest of these
     // features since they were all merged into the official spec by the time
diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs
index de7b7374af3..5736402ae14 100644
--- a/compiler/rustc_target/src/spec/wasm_base.rs
+++ b/compiler/rustc_target/src/spec/wasm_base.rs
@@ -1,63 +1,56 @@
 use super::crt_objects::CrtObjectsFallback;
 use super::{cvs, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel};
-use std::collections::BTreeMap;
 
 pub fn options() -> TargetOptions {
-    let mut lld_args = Vec::new();
-    let mut clang_args = Vec::new();
-    let mut arg = |arg: &'static str| {
-        lld_args.push(arg.into());
-        clang_args.push(format!("-Wl,{}", arg).into());
-    };
-
-    // By default LLD only gives us one page of stack (64k) which is a
-    // little small. Default to a larger stack closer to other PC platforms
-    // (1MB) and users can always inject their own link-args to override this.
-    arg("-z");
-    arg("stack-size=1048576");
-
-    // By default LLD's memory layout is:
-    //
-    // 1. First, a blank page
-    // 2. Next, all static data
-    // 3. Finally, the main stack (which grows down)
-    //
-    // This has the unfortunate consequence that on stack overflows you
-    // corrupt static data and can cause some exceedingly weird bugs. To
-    // help detect this a little sooner we instead request that the stack is
-    // placed before static data.
-    //
-    // This means that we'll generate slightly larger binaries as references
-    // to static data will take more bytes in the ULEB128 encoding, but
-    // stack overflow will be guaranteed to trap as it underflows instead of
-    // corrupting static data.
-    arg("--stack-first");
-
-    // FIXME we probably shouldn't pass this but instead pass an explicit list
-    // of symbols we'll allow to be undefined. We don't currently have a
-    // mechanism of knowing, however, which symbols are intended to be imported
-    // from the environment and which are intended to be imported from other
-    // objects linked elsewhere. This is a coarse approximation but is sure to
-    // hide some bugs and frustrate someone at some point, so we should ideally
-    // work towards a world where we can explicitly list symbols that are
-    // supposed to be imported and have all other symbols generate errors if
-    // they remain undefined.
-    arg("--allow-undefined");
-
-    // Rust code should never have warnings, and warnings are often
-    // indicative of bugs, let's prevent them.
-    arg("--fatal-warnings");
-
-    // LLD only implements C++-like demangling, which doesn't match our own
-    // mangling scheme. Tell LLD to not demangle anything and leave it up to
-    // us to demangle these symbols later. Currently rustc does not perform
-    // further demangling, but tools like twiggy and wasm-bindgen are intended
-    // to do so.
-    arg("--no-demangle");
-
-    let mut pre_link_args = BTreeMap::new();
-    pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Wasm), lld_args);
-    pre_link_args.insert(LinkerFlavor::Gcc, clang_args);
+    macro_rules! args {
+        ($prefix:literal) => {
+            &[
+                // By default LLD only gives us one page of stack (64k) which is a
+                // little small. Default to a larger stack closer to other PC platforms
+                // (1MB) and users can always inject their own link-args to override this.
+                concat!($prefix, "-z"),
+                concat!($prefix, "stack-size=1048576"),
+                // By default LLD's memory layout is:
+                //
+                // 1. First, a blank page
+                // 2. Next, all static data
+                // 3. Finally, the main stack (which grows down)
+                //
+                // This has the unfortunate consequence that on stack overflows you
+                // corrupt static data and can cause some exceedingly weird bugs. To
+                // help detect this a little sooner we instead request that the stack is
+                // placed before static data.
+                //
+                // This means that we'll generate slightly larger binaries as references
+                // to static data will take more bytes in the ULEB128 encoding, but
+                // stack overflow will be guaranteed to trap as it underflows instead of
+                // corrupting static data.
+                concat!($prefix, "--stack-first"),
+                // FIXME we probably shouldn't pass this but instead pass an explicit list
+                // of symbols we'll allow to be undefined. We don't currently have a
+                // mechanism of knowing, however, which symbols are intended to be imported
+                // from the environment and which are intended to be imported from other
+                // objects linked elsewhere. This is a coarse approximation but is sure to
+                // hide some bugs and frustrate someone at some point, so we should ideally
+                // work towards a world where we can explicitly list symbols that are
+                // supposed to be imported and have all other symbols generate errors if
+                // they remain undefined.
+                concat!($prefix, "--allow-undefined"),
+                // Rust code should never have warnings, and warnings are often
+                // indicative of bugs, let's prevent them.
+                concat!($prefix, "--fatal-warnings"),
+                // LLD only implements C++-like demangling, which doesn't match our own
+                // mangling scheme. Tell LLD to not demangle anything and leave it up to
+                // us to demangle these symbols later. Currently rustc does not perform
+                // further demangling, but tools like twiggy and wasm-bindgen are intended
+                // to do so.
+                concat!($prefix, "--no-demangle"),
+            ]
+        };
+    }
+
+    let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::Lld(LldFlavor::Wasm), args!(""));
+    super::add_link_args(&mut pre_link_args, LinkerFlavor::Gcc, args!("-Wl,"));
 
     TargetOptions {
         is_like_wasm: true,
diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/windows_gnu_base.rs
index d11f1f7d3f8..a0480f386f7 100644
--- a/compiler/rustc_target/src/spec/windows_gnu_base.rs
+++ b/compiler/rustc_target/src/spec/windows_gnu_base.rs
@@ -1,31 +1,35 @@
 use crate::spec::crt_objects::{self, CrtObjectsFallback};
-use crate::spec::{cvs, LinkArgs, LinkerFlavor, LldFlavor, TargetOptions};
+use crate::spec::{cvs, LinkerFlavor, TargetOptions};
 
 pub fn opts() -> TargetOptions {
-    let mut pre_link_args = LinkArgs::new();
-    pre_link_args.insert(
+    let mut pre_link_args = TargetOptions::link_args(
+        LinkerFlavor::Ld,
+        &[
+            // Enable ASLR
+            "--dynamicbase",
+            // ASLR will rebase it anyway so leaving that option enabled only leads to confusion
+            "--disable-auto-image-base",
+        ],
+    );
+    super::add_link_args(
+        &mut pre_link_args,
         LinkerFlavor::Gcc,
-        vec![
+        &[
             // Tell GCC to avoid linker plugins, because we are not bundling
             // them with Windows installer, and Rust does its own LTO anyways.
-            "-fno-use-linker-plugin".into(),
-            // Enable ASLR
-            "-Wl,--dynamicbase".into(),
-            // ASLR will rebase it anyway so leaving that option enabled only leads to confusion
-            "-Wl,--disable-auto-image-base".into(),
+            "-fno-use-linker-plugin",
+            "-Wl,--dynamicbase",
+            "-Wl,--disable-auto-image-base",
         ],
     );
 
-    let mut late_link_args = LinkArgs::new();
-    let mut late_link_args_dynamic = LinkArgs::new();
-    let mut late_link_args_static = LinkArgs::new();
     // Order of `late_link_args*` was found through trial and error to work with various
     // mingw-w64 versions (not tested on the CI). It's expected to change from time to time.
-    let mingw_libs = vec![
-        "-lmsvcrt".into(),
-        "-lmingwex".into(),
-        "-lmingw32".into(),
-        "-lgcc".into(), // alas, mingw* libraries above depend on libgcc
+    let mingw_libs = &[
+        "-lmsvcrt",
+        "-lmingwex",
+        "-lmingw32",
+        "-lgcc", // alas, mingw* libraries above depend on libgcc
         // mingw's msvcrt is a weird hybrid import library and static library.
         // And it seems that the linker fails to use import symbols from msvcrt
         // that are required from functions in msvcrt in certain cases. For example
@@ -33,31 +37,27 @@ pub fn opts() -> TargetOptions {
         // The library is purposely listed twice to fix that.
         //
         // See https://github.com/rust-lang/rust/pull/47483 for some more details.
-        "-lmsvcrt".into(),
-        "-luser32".into(),
-        "-lkernel32".into(),
-    ];
-    late_link_args.insert(LinkerFlavor::Gcc, mingw_libs.clone());
-    late_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), mingw_libs);
-    let dynamic_unwind_libs = vec![
-        // If any of our crates are dynamically linked then we need to use
-        // the shared libgcc_s-dw2-1.dll. This is required to support
-        // unwinding across DLL boundaries.
-        "-lgcc_s".into(),
-    ];
-    late_link_args_dynamic.insert(LinkerFlavor::Gcc, dynamic_unwind_libs.clone());
-    late_link_args_dynamic.insert(LinkerFlavor::Lld(LldFlavor::Ld), dynamic_unwind_libs);
-    let static_unwind_libs = vec![
-        // If all of our crates are statically linked then we can get away
-        // with statically linking the libgcc unwinding code. This allows
-        // binaries to be redistributed without the libgcc_s-dw2-1.dll
-        // dependency, but unfortunately break unwinding across DLL
-        // boundaries when unwinding across FFI boundaries.
-        "-lgcc_eh".into(),
-        "-l:libpthread.a".into(),
+        "-lmsvcrt",
+        "-luser32",
+        "-lkernel32",
     ];
-    late_link_args_static.insert(LinkerFlavor::Gcc, static_unwind_libs.clone());
-    late_link_args_static.insert(LinkerFlavor::Lld(LldFlavor::Ld), static_unwind_libs);
+    let mut late_link_args = TargetOptions::link_args(LinkerFlavor::Ld, mingw_libs);
+    super::add_link_args(&mut late_link_args, LinkerFlavor::Gcc, mingw_libs);
+    // If any of our crates are dynamically linked then we need to use
+    // the shared libgcc_s-dw2-1.dll. This is required to support
+    // unwinding across DLL boundaries.
+    let dynamic_unwind_libs = &["-lgcc_s"];
+    let mut late_link_args_dynamic =
+        TargetOptions::link_args(LinkerFlavor::Ld, dynamic_unwind_libs);
+    super::add_link_args(&mut late_link_args_dynamic, LinkerFlavor::Gcc, dynamic_unwind_libs);
+    // If all of our crates are statically linked then we can get away
+    // with statically linking the libgcc unwinding code. This allows
+    // binaries to be redistributed without the libgcc_s-dw2-1.dll
+    // dependency, but unfortunately break unwinding across DLL
+    // boundaries when unwinding across FFI boundaries.
+    let static_unwind_libs = &["-lgcc_eh", "-l:libpthread.a"];
+    let mut late_link_args_static = TargetOptions::link_args(LinkerFlavor::Ld, static_unwind_libs);
+    super::add_link_args(&mut late_link_args_static, LinkerFlavor::Gcc, static_unwind_libs);
 
     TargetOptions {
         os: "windows".into(),
diff --git a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs
index 9f9f8be8718..30f995007a9 100644
--- a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs
+++ b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs
@@ -1,28 +1,17 @@
-use crate::spec::{cvs, LinkArgs, LinkerFlavor, TargetOptions};
+use crate::spec::{cvs, LinkerFlavor, TargetOptions};
 
 pub fn opts() -> TargetOptions {
-    let pre_link_args = LinkArgs::from([(
+    // We cannot use `-nodefaultlibs` because compiler-rt has to be passed
+    // as a path since it's not added to linker search path by the default.
+    // There were attemts to make it behave like libgcc (so one can just use -l<name>)
+    // but LLVM maintainers rejected it: https://reviews.llvm.org/D51440
+    let pre_link_args =
+        TargetOptions::link_args(LinkerFlavor::Gcc, &["-nolibc", "--unwindlib=none"]);
+    // Order of `late_link_args*` does not matter with LLD.
+    let late_link_args = TargetOptions::link_args(
         LinkerFlavor::Gcc,
-        vec![
-            // We cannot use `-nodefaultlibs` because compiler-rt has to be passed
-            // as a path since it's not added to linker search path by the default.
-            // There were attemts to make it behave like libgcc (so one can just use -l<name>)
-            // but LLVM maintainers rejected it: https://reviews.llvm.org/D51440
-            "-nolibc".into(),
-            "--unwindlib=none".into(),
-        ],
-    )]);
-    let late_link_args = LinkArgs::from([(
-        LinkerFlavor::Gcc,
-        // Order of `late_link_args*` does not matter with LLD.
-        vec![
-            "-lmingw32".into(),
-            "-lmingwex".into(),
-            "-lmsvcrt".into(),
-            "-lkernel32".into(),
-            "-luser32".into(),
-        ],
-    )]);
+        &["-lmingw32", "-lmingwex", "-lmsvcrt", "-lkernel32", "-luser32"],
+    );
 
     TargetOptions {
         os: "windows".into(),
diff --git a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs b/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs
index 11968391776..334dec43ef7 100644
--- a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs
+++ b/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs
@@ -1,28 +1,25 @@
-use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, TargetOptions};
+use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     let base = super::windows_gnu_base::opts();
 
     // FIXME: This should be updated for the exception machinery changes from #67502
     // and inherit from `windows_gnu_base`, at least partially.
-    let mut late_link_args = LinkArgs::new();
+    let mingw_libs = &[
+        "-lwinstorecompat",
+        "-lruntimeobject",
+        "-lsynchronization",
+        "-lvcruntime140_app",
+        "-lucrt",
+        "-lwindowsapp",
+        "-lmingwex",
+        "-lmingw32",
+    ];
+    let mut late_link_args = TargetOptions::link_args(LinkerFlavor::Ld, mingw_libs);
+    super::add_link_args(&mut late_link_args, LinkerFlavor::Gcc, mingw_libs);
+    // Reset the flags back to empty until the FIXME above is addressed.
     let late_link_args_dynamic = LinkArgs::new();
     let late_link_args_static = LinkArgs::new();
-    let mingw_libs = vec![
-        //"-lwinstorecompat".into(),
-        //"-lmingwex".into(),
-        //"-lwinstorecompat".into(),
-        "-lwinstorecompat".into(),
-        "-lruntimeobject".into(),
-        "-lsynchronization".into(),
-        "-lvcruntime140_app".into(),
-        "-lucrt".into(),
-        "-lwindowsapp".into(),
-        "-lmingwex".into(),
-        "-lmingw32".into(),
-    ];
-    late_link_args.insert(LinkerFlavor::Gcc, mingw_libs.clone());
-    late_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), mingw_libs);
 
     TargetOptions {
         abi: "uwp".into(),
diff --git a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs
index d6b065b529a..f2573fc2d21 100644
--- a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs
+++ b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs
@@ -1,16 +1,11 @@
-use crate::spec::{LinkerFlavor, LldFlavor, TargetOptions};
+use crate::spec::{LinkerFlavor, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     let mut opts = super::windows_msvc_base::opts();
 
     opts.abi = "uwp".into();
     opts.vendor = "uwp".into();
-    let pre_link_args_msvc = vec!["/APPCONTAINER".into(), "mincore.lib".into()];
-    opts.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone());
-    opts.pre_link_args
-        .entry(LinkerFlavor::Lld(LldFlavor::Link))
-        .or_default()
-        .extend(pre_link_args_msvc);
+    opts.add_pre_link_args(LinkerFlavor::Msvc, &["/APPCONTAINER", "mincore.lib"]);
 
     opts
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
index 51d14f0403a..dbd26899c18 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
@@ -6,8 +6,7 @@ pub fn target() -> Target {
     base.cpu = "core2".into();
     base.max_atomic_width = Some(128); // core2 support cmpxchg16b
     base.frame_pointer = FramePointer::Always;
-    base.pre_link_args
-        .insert(LinkerFlavor::Gcc, vec!["-m64".into(), "-arch".into(), "x86_64".into()]);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-arch", "x86_64"]);
     base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
diff --git a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs
index 47c70513faf..4348d924579 100644
--- a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs
+++ b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs
@@ -1,41 +1,44 @@
-use std::{borrow::Cow, iter};
+use std::borrow::Cow;
 
 use crate::spec::cvs;
 
 use super::{LinkerFlavor, LldFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
-    const PRE_LINK_ARGS: &[&str] = &[
-        "-e",
-        "elf_entry",
-        "-Bstatic",
-        "--gc-sections",
-        "-z",
-        "text",
-        "-z",
-        "norelro",
-        "--no-undefined",
-        "--error-unresolved-symbols",
-        "--no-undefined-version",
-        "-Bsymbolic",
-        "--export-dynamic",
-        // The following symbols are needed by libunwind, which is linked after
-        // libstd. Make sure they're included in the link.
-        "-u",
-        "__rust_abort",
-        "-u",
-        "__rust_c_alloc",
-        "-u",
-        "__rust_c_dealloc",
-        "-u",
-        "__rust_print_err",
-        "-u",
-        "__rust_rwlock_rdlock",
-        "-u",
-        "__rust_rwlock_unlock",
-        "-u",
-        "__rust_rwlock_wrlock",
-    ];
+    let pre_link_args = TargetOptions::link_args(
+        LinkerFlavor::Ld,
+        &[
+            "-e",
+            "elf_entry",
+            "-Bstatic",
+            "--gc-sections",
+            "-z",
+            "text",
+            "-z",
+            "norelro",
+            "--no-undefined",
+            "--error-unresolved-symbols",
+            "--no-undefined-version",
+            "-Bsymbolic",
+            "--export-dynamic",
+            // The following symbols are needed by libunwind, which is linked after
+            // libstd. Make sure they're included in the link.
+            "-u",
+            "__rust_abort",
+            "-u",
+            "__rust_c_alloc",
+            "-u",
+            "__rust_c_dealloc",
+            "-u",
+            "__rust_print_err",
+            "-u",
+            "__rust_rwlock_rdlock",
+            "-u",
+            "__rust_rwlock_unlock",
+            "-u",
+            "__rust_rwlock_wrlock",
+        ],
+    );
 
     const EXPORT_SYMBOLS: &[&str] = &[
         "sgx_entry",
@@ -66,11 +69,7 @@ pub fn target() -> Target {
         features: "+rdrnd,+rdseed,+lvi-cfi,+lvi-load-hardening".into(),
         llvm_args: cvs!["--x86-experimental-lvi-inline-asm-hardening"],
         position_independent_executables: true,
-        pre_link_args: iter::once((
-            LinkerFlavor::Lld(LldFlavor::Ld),
-            PRE_LINK_ARGS.iter().cloned().map(Cow::from).collect(),
-        ))
-        .collect(),
+        pre_link_args,
         override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(Cow::from).collect()),
         relax_elf_relocations: true,
         ..Default::default()
diff --git a/compiler/rustc_target/src/spec/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/x86_64_linux_android.rs
index 049cab0d554..6d19cf26574 100644
--- a/compiler/rustc_target/src/spec/x86_64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/x86_64_linux_android.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     // https://developer.android.com/ndk/guides/abis.html#86-64
     base.features = "+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
index 2a697daeb28..0550b221fd9 100644
--- a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
+++ b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
@@ -2,7 +2,7 @@ use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
 
 pub fn target() -> Target {
     let mut base = super::solaris_base::opts();
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into()]);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.cpu = "x86-64".into();
     base.vendor = "pc".into();
     base.max_atomic_width = Some(64);
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs
index 0fa43481c9b..59a8cffca48 100644
--- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs
@@ -1,14 +1,11 @@
-use crate::spec::{LinkerFlavor, LldFlavor, Target};
+use crate::spec::{LinkerFlavor, Target};
 
 pub fn target() -> Target {
     let mut base = super::windows_gnu_base::opts();
     base.cpu = "x86-64".into();
-    let gcc_pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default();
-    gcc_pre_link_args.push("-m64".into());
     // Use high-entropy 64 bit address space for ASLR
-    gcc_pre_link_args.push("-Wl,--high-entropy-va".into());
-    base.pre_link_args
-        .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".into(), "i386pep".into()]);
+    base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep", "--high-entropy-va"]);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-Wl,--high-entropy-va"]);
     base.max_atomic_width = Some(64);
     base.linker = Some("x86_64-w64-mingw32-gcc".into());
 
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs
index b5ff63e0532..d3909b3895e 100644
--- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs
@@ -3,8 +3,7 @@ use crate::spec::{LinkerFlavor, Target};
 pub fn target() -> Target {
     let mut base = super::windows_gnullvm_base::opts();
     base.cpu = "x86-64".into();
-    let gcc_pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default();
-    gcc_pre_link_args.push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
     base.linker = Some("x86_64-w64-mingw32-clang".into());
 
diff --git a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs
index a02018266fb..cbe87589a70 100644
--- a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs
+++ b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs
@@ -2,7 +2,7 @@ use crate::spec::{LinkerFlavor, StackProbeType, Target};
 
 pub fn target() -> Target {
     let mut base = super::solaris_base::opts();
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into()]);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.cpu = "x86-64".into();
     base.vendor = "sun".into();
     base.max_atomic_width = Some(64);
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs
index 1f2b998a7ba..746f6478178 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     let mut base = super::dragonfly_base::opts();
     base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
index c9aedd6ea82..b30784ed692 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
     base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     base.supported_sanitizers =
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs
index aebbd18c66a..d6d03362982 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     let mut base = super::haiku_base::opts();
     base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into()]);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     // This option is required to build executables on Haiku x86_64
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
index 9529fa9640d..9f19c3a2b2a 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
@@ -2,7 +2,7 @@ use crate::spec::{LinkerFlavor, SanitizerSet, Target};
 
 pub fn target() -> Target {
     let mut base = super::illumos_base::opts();
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into(), "-std=c99".into()]);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-std=c99"]);
     base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
index e525cfdde14..956be0353fa 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
     base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     base.static_position_independent_executables = true;
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs
index 863b41633e2..140882747c2 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
     base.cpu = "x86-64".into();
     base.abi = "x32".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mx32".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-mx32"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     base.has_thread_local = false;
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs
index 8678f06e2cb..87e7784d1f9 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
     base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     base.static_position_independent_executables = true;
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
index a7115dace1c..d3a67619aa8 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     let mut base = super::netbsd_base::opts();
     base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     base.supported_sanitizers = SanitizerSet::ADDRESS
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs
index 0db88d64ac0..593345a5f1d 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
     base.features =
         "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float".into();
     base.code_model = Some(CodeModel::Kernel);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
 
     Target {
         // FIXME: Some dispute, the linux-on-clang folks think this should use
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
index 11e9cc4abc0..f50c6bceec9 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     let mut base = super::openbsd_base::opts();
     base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs
index af8b9673c30..668ae905417 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     let mut base = super::redox_base::opts();
     base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs
index a94bbbf6ede..76d2013cf7f 100644
--- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs
@@ -1,14 +1,11 @@
-use crate::spec::{LinkerFlavor, LldFlavor, Target};
+use crate::spec::{LinkerFlavor, Target};
 
 pub fn target() -> Target {
     let mut base = super::windows_uwp_gnu_base::opts();
     base.cpu = "x86-64".into();
-    let gcc_pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default();
-    gcc_pre_link_args.push("-m64".into());
     // Use high-entropy 64 bit address space for ASLR
-    gcc_pre_link_args.push("-Wl,--high-entropy-va".into());
-    base.pre_link_args
-        .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".into(), "i386pep".into()]);
+    base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep", "--high-entropy-va"]);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-Wl,--high-entropy-va"]);
     base.max_atomic_width = Some(64);
 
     Target {
diff --git a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs
index 16d29753e7d..1298974952f 100644
--- a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     let mut base = super::vxworks_base::opts();
     base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     base.disable_redzone = true;
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index a63790b594d..90ff07cba02 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -220,7 +220,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                 .map(|&(id, _)| (id, vec![]))
                 .collect();
 
-            infcx.process_registered_region_obligations(&body_id_map, None, full_env);
+            infcx.process_registered_region_obligations(&body_id_map, full_env);
 
             let region_data = infcx
                 .inner
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index b37db4b9e18..2b26b916d32 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -407,11 +407,7 @@ fn resolve_negative_obligation<'cx, 'tcx>(
     // function bodies with closures).
     outlives_env.save_implied_bounds(CRATE_HIR_ID);
 
-    infcx.process_registered_region_obligations(
-        outlives_env.region_bound_pairs_map(),
-        Some(tcx.lifetimes.re_root_empty),
-        param_env,
-    );
+    infcx.process_registered_region_obligations(outlives_env.region_bound_pairs_map(), param_env);
 
     let errors = infcx.resolve_regions(region_context, &outlives_env);
 
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 132c335a7e6..8d344591915 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -366,15 +366,9 @@ fn object_safety_violation_for_method(
     // Get an accurate span depending on the violation.
     violation.map(|v| {
         let node = tcx.hir().get_if_local(method.def_id);
-        let span = match (v, node) {
-            (MethodViolationCode::ReferencesSelfInput(arg), Some(node)) => node
-                .fn_decl()
-                .and_then(|decl| decl.inputs.get(arg + 1))
-                .map_or(method.ident(tcx).span, |arg| arg.span),
-            (MethodViolationCode::UndispatchableReceiver, Some(node)) => node
-                .fn_decl()
-                .and_then(|decl| decl.inputs.get(0))
-                .map_or(method.ident(tcx).span, |arg| arg.span),
+        let span = match (&v, node) {
+            (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
+            (MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span,
             (MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
                 node.fn_decl().map_or(method.ident(tcx).span, |decl| decl.output.span())
             }
@@ -397,32 +391,41 @@ fn virtual_call_violation_for_method<'tcx>(
 
     // The method's first parameter must be named `self`
     if !method.fn_has_self_parameter {
-        // We'll attempt to provide a structured suggestion for `Self: Sized`.
-        let sugg =
-            tcx.hir().get_if_local(method.def_id).as_ref().and_then(|node| node.generics()).map(
-                |generics| match generics.predicates {
-                    [] => (" where Self: Sized", generics.where_clause_span),
-                    [.., pred] => (", Self: Sized", pred.span().shrink_to_hi()),
-                },
-            );
-        // Get the span pointing at where the `self` receiver should be.
-        let sm = tcx.sess.source_map();
-        let self_span = method.ident(tcx).span.to(tcx
-            .hir()
-            .span_if_local(method.def_id)
-            .unwrap_or_else(|| sm.next_point(method.ident(tcx).span))
-            .shrink_to_hi());
-        let self_span = sm.span_through_char(self_span, '(').shrink_to_hi();
-        return Some(MethodViolationCode::StaticMethod(
-            sugg,
-            self_span,
-            !sig.inputs().skip_binder().is_empty(),
-        ));
+        let sugg = if let Some(hir::Node::TraitItem(hir::TraitItem {
+            generics,
+            kind: hir::TraitItemKind::Fn(sig, _),
+            ..
+        })) = tcx.hir().get_if_local(method.def_id).as_ref()
+        {
+            let sm = tcx.sess.source_map();
+            Some((
+                (
+                    format!("&self{}", if sig.decl.inputs.is_empty() { "" } else { ", " }),
+                    sm.span_through_char(sig.span, '(').shrink_to_hi(),
+                ),
+                (
+                    format!("{} Self: Sized", generics.add_where_or_trailing_comma()),
+                    generics.tail_span_for_predicate_suggestion(),
+                ),
+            ))
+        } else {
+            None
+        };
+        return Some(MethodViolationCode::StaticMethod(sugg));
     }
 
-    for (i, &input_ty) in sig.skip_binder().inputs()[1..].iter().enumerate() {
+    for (i, &input_ty) in sig.skip_binder().inputs().iter().enumerate().skip(1) {
         if contains_illegal_self_type_reference(tcx, trait_def_id, sig.rebind(input_ty)) {
-            return Some(MethodViolationCode::ReferencesSelfInput(i));
+            let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
+                kind: hir::TraitItemKind::Fn(sig, _),
+                ..
+            })) = tcx.hir().get_if_local(method.def_id).as_ref()
+            {
+                Some(sig.decl.inputs[i].span)
+            } else {
+                None
+            };
+            return Some(MethodViolationCode::ReferencesSelfInput(span));
         }
     }
     if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output()) {
@@ -456,7 +459,16 @@ fn virtual_call_violation_for_method<'tcx>(
     // `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
     if receiver_ty != tcx.types.self_param {
         if !receiver_is_dispatchable(tcx, method, receiver_ty) {
-            return Some(MethodViolationCode::UndispatchableReceiver);
+            let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
+                kind: hir::TraitItemKind::Fn(sig, _),
+                ..
+            })) = tcx.hir().get_if_local(method.def_id).as_ref()
+            {
+                Some(sig.decl.inputs[0].span)
+            } else {
+                None
+            };
+            return Some(MethodViolationCode::UndispatchableReceiver(span));
         } else {
             // Do sanity check to make sure the receiver actually has the layout of a pointer.
 
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 82c54291a5d..aba4f144d4b 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -28,7 +28,6 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
-use rustc_infer::traits::ObligationCauseCode;
 use rustc_middle::traits::select::OverflowError;
 use rustc_middle::ty::fold::{MaxUniverse, TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::subst::Subst;
@@ -252,22 +251,10 @@ fn project_and_unify_type<'cx, 'tcx>(
         Err(InProgress) => return ProjectAndUnifyResult::Recursive,
     };
     debug!(?normalized, ?obligations, "project_and_unify_type result");
-    let actual = obligation.predicate.term;
-    // HACK: lazy TAIT would regress src/test/ui/impl-trait/nested-return-type2.rs, so we add
-    // a back-compat hack hat converts the RPITs into inference vars, just like they were before
-    // lazy TAIT.
-    // This does not affect TAITs in general, as tested in the nested-return-type-tait* tests.
-    let InferOk { value: actual, obligations: new } =
-        selcx.infcx().replace_opaque_types_with_inference_vars(
-            actual,
-            obligation.cause.body_id,
-            obligation.cause.span,
-            ObligationCauseCode::MiscObligation,
-            obligation.param_env,
-        );
-    obligations.extend(new);
-
-    match infcx.at(&obligation.cause, obligation.param_env).eq(normalized, actual) {
+    match infcx
+        .at(&obligation.cause, obligation.param_env)
+        .eq(normalized, obligation.predicate.term)
+    {
         Ok(InferOk { obligations: inferred_obligations, value: () }) => {
             obligations.extend(inferred_obligations);
             ProjectAndUnifyResult::Holds(obligations)
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 95f1e224a4c..a1861529b59 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -452,7 +452,7 @@ fn report_conflicting_impls(
     match used_to_be_allowed {
         None => {
             let reported = if overlap.with_impl.is_local()
-                || !tcx.orphan_check_crate(()).contains(&impl_def_id)
+                || tcx.orphan_check_impl(impl_def_id).is_ok()
             {
                 let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
                 Some(decorate(
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 45c011b78e3..8ffffbed93c 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -32,11 +32,6 @@ use rustc_ty_utils::representability::{self, Representability};
 use std::iter;
 use std::ops::ControlFlow;
 
-pub fn check_wf_new(tcx: TyCtxt<'_>) {
-    let visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
-    tcx.hir().par_visit_all_item_likes(&visit);
-}
-
 pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
     match tcx.sess.target.is_abi_supported(abi) {
         Some(true) => (),
@@ -754,7 +749,7 @@ fn check_opaque_meets_bounds<'tcx>(
     });
 }
 
-pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
+fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
     debug!(
         "check_item_type(it.def_id={:?}, it.name={})",
         id.def_id,
@@ -1543,12 +1538,6 @@ pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     }
 }
 
-pub(super) use wfcheck::check_item_well_formed;
-
-pub(super) use wfcheck::check_trait_item as check_trait_item_well_formed;
-
-pub(super) use wfcheck::check_impl_item as check_impl_item_well_formed;
-
 fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed {
     struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing")
         .span_label(span, "recursive `async fn`")
diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs
index f09c7f51f47..6ee989070b4 100644
--- a/compiler/rustc_typeck/src/check/generator_interior.rs
+++ b/compiler/rustc_typeck/src/check/generator_interior.rs
@@ -225,7 +225,7 @@ pub fn resolve_interior<'a, 'tcx>(
                 // Note that each region slot in the types gets a new fresh late bound region,
                 // which means that none of the regions inside relate to any other, even if
                 // typeck had previously found constraints that would cause them to be related.
-                let folded = fcx.tcx.fold_regions(erased, &mut false, |_, current_depth| {
+                let folded = fcx.tcx.fold_regions(erased, |_, current_depth| {
                     let br = ty::BoundRegion {
                         var: ty::BoundVar::from_u32(counter),
                         kind: ty::BrAnon(counter),
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index e26f211c1c1..0ede9ef7756 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -93,11 +93,7 @@ mod upvar;
 mod wfcheck;
 pub mod writeback;
 
-use check::{
-    check_abi, check_fn, check_impl_item_well_formed, check_item_well_formed, check_mod_item_types,
-    check_trait_item_well_formed,
-};
-pub use check::{check_item_type, check_wf_new};
+use check::{check_abi, check_fn, check_mod_item_types};
 pub use diverges::Diverges;
 pub use expectation::Expectation;
 pub use fn_ctxt::*;
@@ -245,6 +241,7 @@ impl<'tcx> EnclosingBreakables<'tcx> {
 
 pub fn provide(providers: &mut Providers) {
     method::provide(providers);
+    wfcheck::provide(providers);
     *providers = Providers {
         typeck_item_bodies,
         typeck_const_arg,
@@ -253,9 +250,6 @@ pub fn provide(providers: &mut Providers) {
         has_typeck_results,
         adt_destructor,
         used_trait_imports,
-        check_item_well_formed,
-        check_trait_item_well_formed,
-        check_impl_item_well_formed,
         check_mod_item_types,
         region_scope_tree,
         ..*providers
diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs
index 161ec31793d..0ce63922098 100644
--- a/compiler/rustc_typeck/src/check/regionck.rs
+++ b/compiler/rustc_typeck/src/check/regionck.rs
@@ -366,7 +366,6 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
     fn resolve_regions_and_report_errors(&self) {
         self.infcx.process_registered_region_obligations(
             self.outlives_environment.region_bound_pairs_map(),
-            Some(self.tcx.lifetimes.re_root_empty),
             self.param_env,
         );
 
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 79312153895..67eb88b73fd 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -7,21 +7,18 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit as hir_visit;
-use rustc_hir::intravisit::Visitor;
-use rustc_hir::itemlikevisit::ParItemLikeVisitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::ItemKind;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::outlives::obligations::TypeOutlives;
 use rustc_infer::infer::region_constraints::GenericKind;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
-use rustc_middle::hir::nested_filter;
+use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
-    self, AdtKind, EarlyBinder, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable,
-    TypeSuperFoldable, TypeVisitor,
+    self, AdtKind, DefIdTree, EarlyBinder, GenericParamDefKind, ToPredicate, Ty, TyCtxt,
+    TypeFoldable, TypeSuperFoldable, TypeVisitor,
 };
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{sym, Ident, Symbol};
@@ -70,6 +67,23 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> {
     }
 }
 
+fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
+    let node = tcx.hir().expect_owner(def_id);
+    match node {
+        hir::OwnerNode::Crate(_) => {}
+        hir::OwnerNode::Item(item) => check_item(tcx, item),
+        hir::OwnerNode::TraitItem(item) => check_trait_item(tcx, item),
+        hir::OwnerNode::ImplItem(item) => check_impl_item(tcx, item),
+        hir::OwnerNode::ForeignItem(item) => check_foreign_item(tcx, item),
+    }
+
+    if let Some(generics) = node.generics() {
+        for param in generics.params {
+            check_param_wf(tcx, param)
+        }
+    }
+}
+
 /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
 /// well-formed, meaning that they do not require any constraints not declared in the struct
 /// definition itself. For example, this definition would be illegal:
@@ -84,8 +98,8 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> {
 /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
 /// the types first.
 #[instrument(skip(tcx), level = "debug")]
-pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let item = tcx.hir().expect_item(def_id);
+fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
+    let def_id = item.def_id;
 
     debug!(
         ?item.def_id,
@@ -156,20 +170,6 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         hir::ItemKind::Const(ty, ..) => {
             check_item_type(tcx, item.def_id, ty.span, false);
         }
-        hir::ItemKind::ForeignMod { items, .. } => {
-            for it in items.iter() {
-                let it = tcx.hir().foreign_item(it.id);
-                match it.kind {
-                    hir::ForeignItemKind::Fn(decl, ..) => {
-                        check_item_fn(tcx, it.def_id, it.ident, it.span, decl)
-                    }
-                    hir::ForeignItemKind::Static(ty, ..) => {
-                        check_item_type(tcx, it.def_id, ty.span, true)
-                    }
-                    hir::ForeignItemKind::Type => (),
-                }
-            }
-        }
         hir::ItemKind::Struct(ref struct_def, ref ast_generics) => {
             check_type_defn(tcx, item, false, |fcx| vec![fcx.non_enum_variant(struct_def)]);
 
@@ -191,13 +191,31 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         hir::ItemKind::TraitAlias(..) => {
             check_trait(tcx, item);
         }
+        // `ForeignItem`s are handled separately.
+        hir::ItemKind::ForeignMod { .. } => {}
         _ => {}
     }
 }
 
-pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    let trait_item = tcx.hir().expect_trait_item(def_id);
+fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
+    let def_id = item.def_id;
+
+    debug!(
+        ?item.def_id,
+        item.name = ? tcx.def_path_str(def_id.to_def_id())
+    );
+
+    match item.kind {
+        hir::ForeignItemKind::Fn(decl, ..) => {
+            check_item_fn(tcx, item.def_id, item.ident, item.span, decl)
+        }
+        hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, item.def_id, ty.span, true),
+        hir::ForeignItemKind::Type => (),
+    }
+}
+
+fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
+    let def_id = trait_item.def_id;
 
     let (method_sig, span) = match trait_item.kind {
         hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
@@ -207,7 +225,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     check_object_unsafe_self_trait_by_name(tcx, trait_item);
     check_associated_item(tcx, trait_item.def_id, span, method_sig);
 
-    let encl_trait_def_id = tcx.hir().get_parent_item(hir_id);
+    let encl_trait_def_id = tcx.local_parent(def_id);
     let encl_trait = tcx.hir().expect_item(encl_trait_def_id);
     let encl_trait_def_id = encl_trait.def_id.to_def_id();
     let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() {
@@ -596,13 +614,7 @@ fn ty_known_to_outlive<'tcx>(
 ) -> bool {
     resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |infcx, region_bound_pairs| {
         let origin = infer::RelateParamBound(DUMMY_SP, ty, None);
-        let outlives = &mut TypeOutlives::new(
-            infcx,
-            tcx,
-            region_bound_pairs,
-            Some(infcx.tcx.lifetimes.re_root_empty),
-            param_env,
-        );
+        let outlives = &mut TypeOutlives::new(infcx, tcx, region_bound_pairs, None, param_env);
         outlives.type_must_outlive(origin, ty, region);
     })
 }
@@ -770,8 +782,8 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
     }
 }
 
-pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let impl_item = tcx.hir().expect_impl_item(def_id);
+fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) {
+    let def_id = impl_item.def_id;
 
     let (method_sig, span) = match impl_item.kind {
         hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
@@ -780,7 +792,7 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         _ => (None, impl_item.span),
     };
 
-    check_associated_item(tcx, impl_item.def_id, span, method_sig);
+    check_associated_item(tcx, def_id, span, method_sig);
 }
 
 fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
@@ -990,6 +1002,15 @@ fn check_type_defn<'tcx, F>(
         let packed = tcx.adt_def(item.def_id).repr().packed();
 
         for variant in &variants {
+            // All field types must be well-formed.
+            for field in &variant.fields {
+                fcx.register_wf_obligation(
+                    field.ty.into(),
+                    field.span,
+                    ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(field.def_id))),
+                )
+            }
+
             // For DST, or when drop needs to copy things around, all
             // intermediate types must be sized.
             let needs_drop_copy = || {
@@ -1006,6 +1027,7 @@ fn check_type_defn<'tcx, F>(
                     }
                 }
             };
+            // All fields (except for possibly the last) should be sized.
             let all_sized = all_sized || variant.fields.is_empty() || needs_drop_copy();
             let unsized_len = if all_sized { 0 } else { 1 };
             for (idx, field) in
@@ -1030,15 +1052,6 @@ fn check_type_defn<'tcx, F>(
                 );
             }
 
-            // All field types must be well-formed.
-            for field in &variant.fields {
-                fcx.register_wf_obligation(
-                    field.ty.into(),
-                    field.span,
-                    ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(field.def_id))),
-                )
-            }
-
             // Explicit `enum` discriminant values must const-evaluate successfully.
             if let Some(discr_def_id) = variant.explicit_discr {
                 let discr_substs = InternalSubsts::identity_for_item(tcx, discr_def_id.to_def_id());
@@ -1827,67 +1840,12 @@ fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, mut span: Span, id: hir::HirI
     fcx.select_all_obligations_or_error();
 }
 
-#[derive(Clone, Copy)]
-pub struct CheckTypeWellFormedVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> CheckTypeWellFormedVisitor<'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>) -> CheckTypeWellFormedVisitor<'tcx> {
-        CheckTypeWellFormedVisitor { tcx }
-    }
-}
-
-impl<'tcx> ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> {
-    fn visit_item(&self, i: &'tcx hir::Item<'tcx>) {
-        Visitor::visit_item(&mut self.clone(), i);
-    }
-
-    fn visit_trait_item(&self, trait_item: &'tcx hir::TraitItem<'tcx>) {
-        Visitor::visit_trait_item(&mut self.clone(), trait_item);
-    }
-
-    fn visit_impl_item(&self, impl_item: &'tcx hir::ImplItem<'tcx>) {
-        Visitor::visit_impl_item(&mut self.clone(), impl_item);
-    }
-
-    fn visit_foreign_item(&self, foreign_item: &'tcx hir::ForeignItem<'tcx>) {
-        Visitor::visit_foreign_item(&mut self.clone(), foreign_item)
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> {
-    type NestedFilter = nested_filter::OnlyBodies;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
-    }
-
-    #[instrument(skip(self, i), level = "debug")]
-    fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
-        trace!(?i);
-        self.tcx.ensure().check_item_well_formed(i.def_id);
-        hir_visit::walk_item(self, i);
-    }
-
-    #[instrument(skip(self, trait_item), level = "debug")]
-    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
-        trace!(?trait_item);
-        self.tcx.ensure().check_trait_item_well_formed(trait_item.def_id);
-        hir_visit::walk_trait_item(self, trait_item);
-    }
-
-    #[instrument(skip(self, impl_item), level = "debug")]
-    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
-        trace!(?impl_item);
-        self.tcx.ensure().check_impl_item_well_formed(impl_item.def_id);
-        hir_visit::walk_impl_item(self, impl_item);
-    }
-
-    fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
-        check_param_wf(self.tcx, p);
-        hir_visit::walk_generic_param(self, p);
-    }
+fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalDefId) {
+    let items = tcx.hir_module_items(module);
+    items.par_items(|item| tcx.ensure().check_well_formed(item.def_id));
+    items.par_impl_items(|item| tcx.ensure().check_well_formed(item.def_id));
+    items.par_trait_items(|item| tcx.ensure().check_well_formed(item.def_id));
+    items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.def_id));
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -1972,3 +1930,7 @@ fn error_392(
     err.span_label(span, "unused parameter");
     err
 }
+
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { check_mod_type_wf, check_well_formed, ..*providers };
+}
diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_typeck/src/coherence/mod.rs
index 3903448a007..447ec87f302 100644
--- a/compiler/rustc_typeck/src/coherence/mod.rs
+++ b/compiler/rustc_typeck/src/coherence/mod.rs
@@ -146,7 +146,7 @@ pub fn provide(providers: &mut Providers) {
     use self::builtin::coerce_unsized_info;
     use self::inherent_impls::{crate_incoherent_impls, crate_inherent_impls, inherent_impls};
     use self::inherent_impls_overlap::crate_inherent_impls_overlap_check;
-    use self::orphan::orphan_check_crate;
+    use self::orphan::orphan_check_impl;
 
     *providers = Providers {
         coherent_trait,
@@ -155,7 +155,7 @@ pub fn provide(providers: &mut Providers) {
         inherent_impls,
         crate_inherent_impls_overlap_check,
         coerce_unsized_info,
-        orphan_check_crate,
+        orphan_check_impl,
         ..*providers
     };
 }
@@ -171,21 +171,12 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
 
         check_impl(tcx, impl_def_id, trait_ref);
         check_object_overlap(tcx, impl_def_id, trait_ref);
-    }
-    builtin::check_trait(tcx, def_id);
-}
 
-pub fn check_coherence(tcx: TyCtxt<'_>) {
-    tcx.sess.time("unsafety_checking", || unsafety::check(tcx));
-    tcx.ensure().orphan_check_crate(());
-
-    for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
-        tcx.ensure().coherent_trait(trait_def_id);
+        tcx.sess.time("unsafety_checking", || unsafety::check_item(tcx, impl_def_id));
+        tcx.sess.time("orphan_checking", || tcx.ensure().orphan_check_impl(impl_def_id));
     }
 
-    // these queries are executed for side-effects (error reporting):
-    tcx.ensure().crate_inherent_impls(());
-    tcx.ensure().crate_inherent_impls_overlap_check(());
+    builtin::check_trait(tcx, def_id);
 }
 
 /// Checks whether an impl overlaps with the automatic `impl Trait for dyn Trait`.
diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs
index 9ddfc8d5cc8..f3a043a08a3 100644
--- a/compiler/rustc_typeck/src/coherence/orphan.rs
+++ b/compiler/rustc_typeck/src/coherence/orphan.rs
@@ -18,26 +18,29 @@ use rustc_span::Span;
 use rustc_trait_selection::traits;
 use std::ops::ControlFlow;
 
-pub(super) fn orphan_check_crate(tcx: TyCtxt<'_>, (): ()) -> &[LocalDefId] {
-    let mut errors = Vec::new();
-    for (&trait_def_id, impls_of_trait) in tcx.all_local_trait_impls(()) {
-        for &impl_of_trait in impls_of_trait {
-            match orphan_check_impl(tcx, impl_of_trait) {
-                Ok(()) => {}
-                Err(_) => errors.push(impl_of_trait),
-            }
-        }
+#[instrument(skip(tcx), level = "debug")]
+pub(crate) fn orphan_check_impl(
+    tcx: TyCtxt<'_>,
+    impl_def_id: LocalDefId,
+) -> Result<(), ErrorGuaranteed> {
+    let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
+    if let Some(err) = trait_ref.error_reported() {
+        return Err(err);
+    }
 
-        if tcx.trait_is_auto(trait_def_id) {
-            lint_auto_trait_impls(tcx, trait_def_id, impls_of_trait);
-        }
+    let ret = do_orphan_check_impl(tcx, trait_ref, impl_def_id);
+    if tcx.trait_is_auto(trait_ref.def_id) {
+        lint_auto_trait_impl(tcx, trait_ref, impl_def_id);
     }
-    tcx.arena.alloc_slice(&errors)
+
+    ret
 }
 
-#[instrument(skip(tcx), level = "debug")]
-fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
-    let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
+fn do_orphan_check_impl<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::TraitRef<'tcx>,
+    def_id: LocalDefId,
+) -> Result<(), ErrorGuaranteed> {
     let trait_def_id = trait_ref.def_id;
 
     let item = tcx.hir().item(hir::ItemId { def_id });
@@ -329,89 +332,82 @@ fn emit_orphan_check_error<'tcx>(
 
 /// Lint impls of auto traits if they are likely to have
 /// unsound or surprising effects on auto impls.
-fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDefId]) {
-    let mut non_covering_impls = Vec::new();
-    for &impl_def_id in impls {
-        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
-        if trait_ref.references_error() {
-            return;
-        }
+fn lint_auto_trait_impl<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::TraitRef<'tcx>,
+    impl_def_id: LocalDefId,
+) {
+    if tcx.impl_polarity(impl_def_id) != ImplPolarity::Positive {
+        return;
+    }
 
-        if tcx.impl_polarity(impl_def_id) != ImplPolarity::Positive {
+    assert_eq!(trait_ref.substs.len(), 1);
+    let self_ty = trait_ref.self_ty();
+    let (self_type_did, substs) = match self_ty.kind() {
+        ty::Adt(def, substs) => (def.did(), substs),
+        _ => {
+            // FIXME: should also lint for stuff like `&i32` but
+            // considering that auto traits are unstable, that
+            // isn't too important for now as this only affects
+            // crates using `nightly`, and std.
             return;
         }
+    };
 
-        assert_eq!(trait_ref.substs.len(), 1);
-        let self_ty = trait_ref.self_ty();
-        let (self_type_did, substs) = match self_ty.kind() {
-            ty::Adt(def, substs) => (def.did(), substs),
-            _ => {
-                // FIXME: should also lint for stuff like `&i32` but
-                // considering that auto traits are unstable, that
-                // isn't too important for now as this only affects
-                // crates using `nightly`, and std.
-                continue;
-            }
-        };
+    // Impls which completely cover a given root type are fine as they
+    // disable auto impls entirely. So only lint if the substs
+    // are not a permutation of the identity substs.
+    let Err(arg) = tcx.uses_unique_generic_params(substs, IgnoreRegions::Yes) else {
+        // ok
+        return;
+    };
 
-        // Impls which completely cover a given root type are fine as they
-        // disable auto impls entirely. So only lint if the substs
-        // are not a permutation of the identity substs.
-        match tcx.uses_unique_generic_params(substs, IgnoreRegions::Yes) {
-            Ok(()) => {} // ok
-            Err(arg) => {
-                // Ideally:
-                //
-                // - compute the requirements for the auto impl candidate
-                // - check whether these are implied by the non covering impls
-                // - if not, emit the lint
-                //
-                // What we do here is a bit simpler:
-                //
-                // - badly check if an auto impl candidate definitely does not apply
-                //   for the given simplified type
-                // - if so, do not lint
-                if fast_reject_auto_impl(tcx, trait_def_id, self_ty) {
-                    // ok
-                } else {
-                    non_covering_impls.push((impl_def_id, self_type_did, arg));
-                }
-            }
-        }
+    // Ideally:
+    //
+    // - compute the requirements for the auto impl candidate
+    // - check whether these are implied by the non covering impls
+    // - if not, emit the lint
+    //
+    // What we do here is a bit simpler:
+    //
+    // - badly check if an auto impl candidate definitely does not apply
+    //   for the given simplified type
+    // - if so, do not lint
+    if fast_reject_auto_impl(tcx, trait_ref.def_id, self_ty) {
+        // ok
+        return;
     }
 
-    for &(impl_def_id, self_type_did, arg) in &non_covering_impls {
-        tcx.struct_span_lint_hir(
-            lint::builtin::SUSPICIOUS_AUTO_TRAIT_IMPLS,
-            tcx.hir().local_def_id_to_hir_id(impl_def_id),
-            tcx.def_span(impl_def_id),
-            |err| {
-                let item_span = tcx.def_span(self_type_did);
-                let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
-                let mut err = err.build(&format!(
-                    "cross-crate traits with a default impl, like `{}`, \
+    tcx.struct_span_lint_hir(
+        lint::builtin::SUSPICIOUS_AUTO_TRAIT_IMPLS,
+        tcx.hir().local_def_id_to_hir_id(impl_def_id),
+        tcx.def_span(impl_def_id),
+        |err| {
+            let item_span = tcx.def_span(self_type_did);
+            let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
+            let mut err = err.build(&format!(
+                "cross-crate traits with a default impl, like `{}`, \
                          should not be specialized",
-                    tcx.def_path_str(trait_def_id),
-                ));
-                match arg {
-                    ty::util::NotUniqueParam::DuplicateParam(arg) => {
-                        err.note(&format!("`{}` is mentioned multiple times", arg));
-                    }
-                    ty::util::NotUniqueParam::NotParam(arg) => {
-                        err.note(&format!("`{}` is not a generic parameter", arg));
-                    }
+                tcx.def_path_str(trait_ref.def_id),
+            ));
+            match arg {
+                ty::util::NotUniqueParam::DuplicateParam(arg) => {
+                    err.note(&format!("`{}` is mentioned multiple times", arg));
                 }
-                err.span_note(
-                    item_span,
-                    &format!(
-                        "try using the same sequence of generic parameters as the {} definition",
-                        self_descr,
-                    ),
-                );
-                err.emit();
-            },
-        );
-    }
+                ty::util::NotUniqueParam::NotParam(arg) => {
+                    err.note(&format!("`{}` is not a generic parameter", arg));
+                }
+            }
+            err.span_note(
+                item_span,
+                &format!(
+                    "try using the same sequence of generic parameters as the {} definition",
+                    self_descr,
+                ),
+            );
+            err.emit();
+        },
+    );
 }
 
 fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty: Ty<'tcx>) -> bool {
diff --git a/compiler/rustc_typeck/src/coherence/unsafety.rs b/compiler/rustc_typeck/src/coherence/unsafety.rs
index 3cfc96ccbfd..e45fb5fe41c 100644
--- a/compiler/rustc_typeck/src/coherence/unsafety.rs
+++ b/compiler/rustc_typeck/src/coherence/unsafety.rs
@@ -6,37 +6,18 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::Unsafety;
 use rustc_middle::ty::TyCtxt;
+use rustc_span::def_id::LocalDefId;
 
-pub fn check(tcx: TyCtxt<'_>) {
-    for id in tcx.hir().items() {
-        if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
-            let item = tcx.hir().item(id);
-            if let hir::ItemKind::Impl(ref impl_) = item.kind {
-                check_unsafety_coherence(
-                    tcx,
-                    item,
-                    Some(&impl_.generics),
-                    impl_.unsafety,
-                    impl_.polarity,
-                );
-            }
-        }
-    }
-}
+pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
+    debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Impl));
+    let item = tcx.hir().expect_item(def_id);
+    let hir::ItemKind::Impl(ref impl_) = item.kind else { bug!() };
 
-fn check_unsafety_coherence<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    item: &hir::Item<'_>,
-    impl_generics: Option<&hir::Generics<'_>>,
-    unsafety: hir::Unsafety,
-    polarity: hir::ImplPolarity,
-) {
     if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) {
         let trait_def = tcx.trait_def(trait_ref.def_id);
-        let unsafe_attr = impl_generics.and_then(|generics| {
-            generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
-        });
-        match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
+        let unsafe_attr =
+            impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle");
+        match (trait_def.unsafety, unsafe_attr, impl_.unsafety, impl_.polarity) {
             (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
                 struct_span_err!(
                     tcx.sess,
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 1f2e6ad86bd..2a52167c597 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -393,7 +393,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
     }
 
     fn ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
-        let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match *r {
+        let ty = self.tcx.fold_regions(ty, |r, _| match *r {
             ty::ReErased => self.tcx.lifetimes.re_static,
             _ => r,
         });
@@ -1917,7 +1917,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
         Some(ty) => {
             let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
             // Typeck doesn't expect erased regions to be returned from `type_of`.
-            let fn_sig = tcx.fold_regions(fn_sig, &mut false, |r, _| match *r {
+            let fn_sig = tcx.fold_regions(fn_sig, |r, _| match *r {
                 ty::ReErased => tcx.lifetimes.re_static,
                 _ => r,
             });
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index 7011dd6e15c..6ee2b544916 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -772,7 +772,7 @@ fn infer_placeholder_type<'a>(
     }
 
     // Typeck doesn't expect erased regions to be returned from `type_of`.
-    tcx.fold_regions(ty, &mut false, |r, _| match *r {
+    tcx.fold_regions(ty, |r, _| match *r {
         ty::ReErased => tcx.lifetimes.re_static,
         _ => r,
     })
diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs
index c089d25d222..981c35e184b 100644
--- a/compiler/rustc_typeck/src/impl_wf_check.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check.rs
@@ -13,7 +13,6 @@ use min_specialization::check_min_specialization;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::struct_span_err;
-use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::query::Providers;
@@ -54,25 +53,15 @@ mod min_specialization;
 /// impl<'a> Trait<Foo> for Bar { type X = &'a i32; }
 /// //   ^ 'a is unused and appears in assoc type, error
 /// ```
-pub fn impl_wf_check(tcx: TyCtxt<'_>) {
-    // We will tag this as part of the WF check -- logically, it is,
-    // but it's one that we must perform earlier than the rest of
-    // WfCheck.
-    tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module))
-}
-
 fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     let min_specialization = tcx.features().min_specialization;
     let module = tcx.hir_module_items(module_def_id);
     for id in module.items() {
         if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
-            let item = tcx.hir().item(id);
-            if let hir::ItemKind::Impl(ref impl_) = item.kind {
-                enforce_impl_params_are_constrained(tcx, item.def_id, impl_.items);
-                enforce_impl_items_are_distinct(tcx, impl_.items);
-                if min_specialization {
-                    check_min_specialization(tcx, item.def_id.to_def_id(), item.span);
-                }
+            enforce_impl_params_are_constrained(tcx, id.def_id);
+            enforce_impl_items_are_distinct(tcx, id.def_id);
+            if min_specialization {
+                check_min_specialization(tcx, id.def_id);
             }
         }
     }
@@ -82,11 +71,7 @@ pub fn provide(providers: &mut Providers) {
     *providers = Providers { check_mod_impl_wf, ..*providers };
 }
 
-fn enforce_impl_params_are_constrained(
-    tcx: TyCtxt<'_>,
-    impl_def_id: LocalDefId,
-    impl_item_refs: &[hir::ImplItemRef],
-) {
+fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
     // Every lifetime used in an associated type must be constrained.
     let impl_self_ty = tcx.type_of(impl_def_id);
     if impl_self_ty.references_error() {
@@ -114,9 +99,9 @@ fn enforce_impl_params_are_constrained(
     );
 
     // Disallow unconstrained lifetimes, but only if they appear in assoc types.
-    let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs
+    let lifetimes_in_associated_types: FxHashSet<_> = tcx
+        .associated_item_def_ids(impl_def_id)
         .iter()
-        .map(|item_ref| item_ref.id.def_id)
         .flat_map(|def_id| {
             let item = tcx.associated_item(def_id);
             match item.kind {
@@ -216,33 +201,32 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: &str)
 }
 
 /// Enforce that we do not have two items in an impl with the same name.
-fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef]) {
+fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
     let mut seen_type_items = FxHashMap::default();
     let mut seen_value_items = FxHashMap::default();
-    for impl_item_ref in impl_item_refs {
-        let impl_item = tcx.hir().impl_item(impl_item_ref.id);
+    for &impl_item_ref in tcx.associated_item_def_ids(impl_def_id) {
+        let impl_item = tcx.associated_item(impl_item_ref);
         let seen_items = match impl_item.kind {
-            hir::ImplItemKind::TyAlias(_) => &mut seen_type_items,
+            ty::AssocKind::Type => &mut seen_type_items,
             _ => &mut seen_value_items,
         };
-        match seen_items.entry(impl_item.ident.normalize_to_macros_2_0()) {
+        let span = tcx.def_span(impl_item_ref);
+        let ident = impl_item.ident(tcx);
+        match seen_items.entry(ident.normalize_to_macros_2_0()) {
             Occupied(entry) => {
                 let mut err = struct_span_err!(
                     tcx.sess,
-                    impl_item.span,
+                    span,
                     E0201,
                     "duplicate definitions with name `{}`:",
-                    impl_item.ident
-                );
-                err.span_label(
-                    *entry.get(),
-                    format!("previous definition of `{}` here", impl_item.ident),
+                    ident
                 );
-                err.span_label(impl_item.span, "duplicate definition");
+                err.span_label(*entry.get(), format!("previous definition of `{}` here", ident));
+                err.span_label(span, "duplicate definition");
                 err.emit();
             }
             Vacant(entry) => {
-                entry.insert(impl_item.span);
+                entry.insert(span);
             }
         }
     }
diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
index 0ecc28e6054..f07396ce74f 100644
--- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
@@ -79,19 +79,19 @@ use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
 use rustc_span::Span;
 use rustc_trait_selection::traits::{self, translate_substs, wf};
 
-pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: DefId, span: Span) {
+pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
     if let Some(node) = parent_specialization_node(tcx, impl_def_id) {
         tcx.infer_ctxt().enter(|infcx| {
-            check_always_applicable(&infcx, impl_def_id, node, span);
+            check_always_applicable(&infcx, impl_def_id, node);
         });
     }
 }
 
-fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: DefId) -> Option<Node> {
+fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Option<Node> {
     let trait_ref = tcx.impl_trait_ref(impl1_def_id)?;
     let trait_def = tcx.trait_def(trait_ref.def_id);
 
-    let impl2_node = trait_def.ancestors(tcx, impl1_def_id).ok()?.nth(1)?;
+    let impl2_node = trait_def.ancestors(tcx, impl1_def_id.to_def_id()).ok()?.nth(1)?;
 
     let always_applicable_trait =
         matches!(trait_def.specialization_kind, TraitSpecializationKind::AlwaysApplicable);
@@ -103,15 +103,8 @@ fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: DefId) -> Option<No
 }
 
 /// Check that `impl1` is a sound specialization
-fn check_always_applicable(
-    infcx: &InferCtxt<'_, '_>,
-    impl1_def_id: DefId,
-    impl2_node: Node,
-    span: Span,
-) {
-    if let Some((impl1_substs, impl2_substs)) =
-        get_impl_substs(infcx, impl1_def_id, impl2_node, span)
-    {
+fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId, impl2_node: Node) {
+    if let Some((impl1_substs, impl2_substs)) = get_impl_substs(infcx, impl1_def_id, impl2_node) {
         let impl2_def_id = impl2_node.def_id();
         debug!(
             "check_always_applicable(\nimpl1_def_id={:?},\nimpl2_def_id={:?},\nimpl2_substs={:?}\n)",
@@ -126,17 +119,10 @@ fn check_always_applicable(
             unconstrained_parent_impl_substs(tcx, impl2_def_id, impl2_substs)
         };
 
+        let span = tcx.def_span(impl1_def_id);
         check_static_lifetimes(tcx, &parent_substs, span);
         check_duplicate_params(tcx, impl1_substs, &parent_substs, span);
-
-        check_predicates(
-            infcx,
-            impl1_def_id.expect_local(),
-            impl1_substs,
-            impl2_node,
-            impl2_substs,
-            span,
-        );
+        check_predicates(infcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span);
     }
 }
 
@@ -152,20 +138,21 @@ fn check_always_applicable(
 /// Would return `S1 = [C]` and `S2 = [Vec<C>, C]`.
 fn get_impl_substs<'tcx>(
     infcx: &InferCtxt<'_, 'tcx>,
-    impl1_def_id: DefId,
+    impl1_def_id: LocalDefId,
     impl2_node: Node,
-    span: Span,
 ) -> Option<(SubstsRef<'tcx>, SubstsRef<'tcx>)> {
     let tcx = infcx.tcx;
     let param_env = tcx.param_env(impl1_def_id);
 
-    let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id);
-    let impl2_substs = translate_substs(infcx, param_env, impl1_def_id, impl1_substs, impl2_node);
+    let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id());
+    let impl2_substs =
+        translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node);
 
     // Conservatively use an empty `ParamEnv`.
     let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());
-    infcx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
+    infcx.resolve_regions_and_report_errors(impl1_def_id.to_def_id(), &outlives_env);
     let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
+        let span = tcx.def_span(impl1_def_id);
         tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
         return None;
     };
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index d613edf0ab0..b6d4f5fcda6 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -509,11 +509,21 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
     }
 
     tcx.sess.track_errors(|| {
-        tcx.sess.time("impl_wf_inference", || impl_wf_check::impl_wf_check(tcx));
+        tcx.sess.time("impl_wf_inference", || {
+            tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module))
+        });
     })?;
 
     tcx.sess.track_errors(|| {
-        tcx.sess.time("coherence_checking", || coherence::check_coherence(tcx));
+        tcx.sess.time("coherence_checking", || {
+            for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
+                tcx.ensure().coherent_trait(trait_def_id);
+            }
+
+            // these queries are executed for side-effects (error reporting):
+            tcx.ensure().crate_inherent_impls(());
+            tcx.ensure().crate_inherent_impls_overlap_check(());
+        });
     })?;
 
     if tcx.features().rustc_attrs {
@@ -523,7 +533,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
     }
 
     tcx.sess.track_errors(|| {
-        tcx.sess.time("wf_checking", || check::check_wf_new(tcx));
+        tcx.sess.time("wf_checking", || {
+            tcx.hir().par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
+        });
     })?;
 
     // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs
index 807c035fdbd..203e5dff0c7 100644
--- a/library/alloc/src/boxed/thin.rs
+++ b/library/alloc/src/boxed/thin.rs
@@ -33,6 +33,14 @@ pub struct ThinBox<T: ?Sized> {
     _marker: PhantomData<T>,
 }
 
+/// `ThinBox<T>` is `Send` if `T` is `Send` because the data is owned.
+#[unstable(feature = "thin_box", issue = "92791")]
+unsafe impl<T: ?Sized + Send> Send for ThinBox<T> {}
+
+/// `ThinBox<T>` is `Sync` if `T` is `Sync` because the data is owned.
+#[unstable(feature = "thin_box", issue = "92791")]
+unsafe impl<T: ?Sized + Sync> Sync for ThinBox<T> {}
+
 #[unstable(feature = "thin_box", issue = "92791")]
 impl<T> ThinBox<T> {
     /// Moves a type to the heap with its `Metadata` stored in the heap allocation instead of on
diff --git a/library/alloc/tests/fmt.rs b/library/alloc/tests/fmt.rs
index 67e12c612db..5ee6db43fda 100644
--- a/library/alloc/tests/fmt.rs
+++ b/library/alloc/tests/fmt.rs
@@ -207,7 +207,7 @@ fn test_format_macro_interface() {
     {
         let val = usize::MAX;
         let exp = format!("{val:#x}");
-        t!(format!("{:p}", val as *const isize), exp);
+        t!(format!("{:p}", std::ptr::invalid::<isize>(val)), exp);
     }
 
     // Escaping
diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs
index 53e48500e3b..60eb3a6da3a 100644
--- a/library/core/src/iter/adapters/chain.rs
+++ b/library/core/src/iter/adapters/chain.rs
@@ -37,33 +37,6 @@ impl<A, B> Chain<A, B> {
     }
 }
 
-/// Fuse the iterator if the expression is `None`.
-macro_rules! fuse {
-    ($self:ident . $iter:ident . $($call:tt)+) => {
-        match $self.$iter {
-            Some(ref mut iter) => match iter.$($call)+ {
-                None => {
-                    $self.$iter = None;
-                    None
-                }
-                item => item,
-            },
-            None => None,
-        }
-    };
-}
-
-/// Try an iterator method without fusing,
-/// like an inline `.as_mut().and_then(...)`
-macro_rules! maybe {
-    ($self:ident . $iter:ident . $($call:tt)+) => {
-        match $self.$iter {
-            Some(ref mut iter) => iter.$($call)+,
-            None => None,
-        }
-    };
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B> Iterator for Chain<A, B>
 where
@@ -74,10 +47,7 @@ where
 
     #[inline]
     fn next(&mut self) -> Option<A::Item> {
-        match fuse!(self.a.next()) {
-            None => maybe!(self.b.next()),
-            item => item,
-        }
+        and_then_or_clear(&mut self.a, Iterator::next).or_else(|| self.b.as_mut()?.next())
     }
 
     #[inline]
@@ -161,7 +131,7 @@ where
             self.a = None;
         }
 
-        maybe!(self.b.nth(n))
+        self.b.as_mut()?.nth(n)
     }
 
     #[inline]
@@ -169,23 +139,15 @@ where
     where
         P: FnMut(&Self::Item) -> bool,
     {
-        match fuse!(self.a.find(&mut predicate)) {
-            None => maybe!(self.b.find(predicate)),
-            item => item,
-        }
+        and_then_or_clear(&mut self.a, |a| a.find(&mut predicate))
+            .or_else(|| self.b.as_mut()?.find(predicate))
     }
 
     #[inline]
     fn last(self) -> Option<A::Item> {
         // Must exhaust a before b.
-        let a_last = match self.a {
-            Some(a) => a.last(),
-            None => None,
-        };
-        let b_last = match self.b {
-            Some(b) => b.last(),
-            None => None,
-        };
+        let a_last = self.a.and_then(Iterator::last);
+        let b_last = self.b.and_then(Iterator::last);
         b_last.or(a_last)
     }
 
@@ -220,10 +182,7 @@ where
 {
     #[inline]
     fn next_back(&mut self) -> Option<A::Item> {
-        match fuse!(self.b.next_back()) {
-            None => maybe!(self.a.next_back()),
-            item => item,
-        }
+        and_then_or_clear(&mut self.b, |b| b.next_back()).or_else(|| self.a.as_mut()?.next_back())
     }
 
     #[inline]
@@ -263,7 +222,7 @@ where
             self.b = None;
         }
 
-        maybe!(self.a.nth_back(n))
+        self.a.as_mut()?.nth_back(n)
     }
 
     #[inline]
@@ -271,10 +230,8 @@ where
     where
         P: FnMut(&Self::Item) -> bool,
     {
-        match fuse!(self.b.rfind(&mut predicate)) {
-            None => maybe!(self.a.rfind(predicate)),
-            item => item,
-        }
+        and_then_or_clear(&mut self.b, |b| b.rfind(&mut predicate))
+            .or_else(|| self.a.as_mut()?.rfind(predicate))
     }
 
     fn try_rfold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
@@ -324,3 +281,12 @@ where
     B: TrustedLen<Item = A::Item>,
 {
 }
+
+#[inline]
+fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> {
+    let x = f(opt.as_mut()?);
+    if x.is_none() {
+        *opt = None;
+    }
+    x
+}
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 351fd569d8a..15a120e35a2 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -290,20 +290,11 @@ where
     #[inline]
     fn next(&mut self) -> Option<U::Item> {
         loop {
-            if let Some(ref mut inner) = self.frontiter {
-                match inner.next() {
-                    None => self.frontiter = None,
-                    elt @ Some(_) => return elt,
-                }
+            if let elt @ Some(_) = and_then_or_clear(&mut self.frontiter, Iterator::next) {
+                return elt;
             }
             match self.iter.next() {
-                None => match self.backiter.as_mut()?.next() {
-                    None => {
-                        self.backiter = None;
-                        return None;
-                    }
-                    elt @ Some(_) => return elt,
-                },
+                None => return and_then_or_clear(&mut self.backiter, Iterator::next),
                 Some(inner) => self.frontiter = Some(inner.into_iter()),
             }
         }
@@ -436,21 +427,12 @@ where
     #[inline]
     fn next_back(&mut self) -> Option<U::Item> {
         loop {
-            if let Some(ref mut inner) = self.backiter {
-                match inner.next_back() {
-                    None => self.backiter = None,
-                    elt @ Some(_) => return elt,
-                }
+            if let elt @ Some(_) = and_then_or_clear(&mut self.backiter, |b| b.next_back()) {
+                return elt;
             }
             match self.iter.next_back() {
-                None => match self.frontiter.as_mut()?.next_back() {
-                    None => {
-                        self.frontiter = None;
-                        return None;
-                    }
-                    elt @ Some(_) => return elt,
-                },
-                next => self.backiter = next.map(IntoIterator::into_iter),
+                None => return and_then_or_clear(&mut self.frontiter, |f| f.next_back()),
+                Some(inner) => self.backiter = Some(inner.into_iter()),
             }
         }
     }
@@ -606,3 +588,12 @@ unsafe impl<T, const N: usize> TrustedConstSize for [T; N] {}
 unsafe impl<T, const N: usize> TrustedConstSize for &'_ [T; N] {}
 #[unstable(feature = "std_internals", issue = "none")]
 unsafe impl<T, const N: usize> TrustedConstSize for &'_ mut [T; N] {}
+
+#[inline]
+fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> {
+    let x = f(opt.as_mut()?);
+    if x.is_none() {
+        *opt = None;
+    }
+    x
+}
diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs
index 8adb53c6714..c9314454203 100644
--- a/library/core/src/iter/adapters/fuse.rs
+++ b/library/core/src/iter/adapters/fuse.rs
@@ -29,33 +29,6 @@ impl<I> Fuse<I> {
 #[stable(feature = "fused", since = "1.26.0")]
 impl<I> FusedIterator for Fuse<I> where I: Iterator {}
 
-/// Fuse the iterator if the expression is `None`.
-macro_rules! fuse {
-    ($self:ident . iter . $($call:tt)+) => {
-        match $self.iter {
-            Some(ref mut iter) => match iter.$($call)+ {
-                None => {
-                    $self.iter = None;
-                    None
-                }
-                item => item,
-            },
-            None => None,
-        }
-    };
-}
-
-/// Specialized macro that doesn't check if the expression is `None`.
-/// (We trust that a `FusedIterator` will fuse itself.)
-macro_rules! spec {
-    ($self:ident . iter . $($call:tt)+) => {
-        match $self.iter {
-            Some(ref mut iter) => iter.$($call)+,
-            None => None,
-        }
-    };
-}
-
 // Any specialized implementation here is made internal
 // to avoid exposing default fns outside this trait.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -281,12 +254,12 @@ where
 
     #[inline]
     default fn next(&mut self) -> Option<<I as Iterator>::Item> {
-        fuse!(self.iter.next())
+        and_then_or_clear(&mut self.iter, Iterator::next)
     }
 
     #[inline]
     default fn nth(&mut self, n: usize) -> Option<I::Item> {
-        fuse!(self.iter.nth(n))
+        and_then_or_clear(&mut self.iter, |iter| iter.nth(n))
     }
 
     #[inline]
@@ -308,7 +281,7 @@ where
     where
         P: FnMut(&Self::Item) -> bool,
     {
-        fuse!(self.iter.find(predicate))
+        and_then_or_clear(&mut self.iter, |iter| iter.find(predicate))
     }
 
     #[inline]
@@ -316,7 +289,7 @@ where
     where
         I: DoubleEndedIterator,
     {
-        fuse!(self.iter.next_back())
+        and_then_or_clear(&mut self.iter, |iter| iter.next_back())
     }
 
     #[inline]
@@ -324,7 +297,7 @@ where
     where
         I: DoubleEndedIterator,
     {
-        fuse!(self.iter.nth_back(n))
+        and_then_or_clear(&mut self.iter, |iter| iter.nth_back(n))
     }
 
     #[inline]
@@ -348,7 +321,7 @@ where
         P: FnMut(&Self::Item) -> bool,
         I: DoubleEndedIterator,
     {
-        fuse!(self.iter.rfind(predicate))
+        and_then_or_clear(&mut self.iter, |iter| iter.rfind(predicate))
     }
 }
 
@@ -361,12 +334,12 @@ where
 {
     #[inline]
     fn next(&mut self) -> Option<<I as Iterator>::Item> {
-        spec!(self.iter.next())
+        self.iter.as_mut()?.next()
     }
 
     #[inline]
     fn nth(&mut self, n: usize) -> Option<I::Item> {
-        spec!(self.iter.nth(n))
+        self.iter.as_mut()?.nth(n)
     }
 
     #[inline]
@@ -387,7 +360,7 @@ where
     where
         P: FnMut(&Self::Item) -> bool,
     {
-        spec!(self.iter.find(predicate))
+        self.iter.as_mut()?.find(predicate)
     }
 
     #[inline]
@@ -395,7 +368,7 @@ where
     where
         I: DoubleEndedIterator,
     {
-        spec!(self.iter.next_back())
+        self.iter.as_mut()?.next_back()
     }
 
     #[inline]
@@ -403,7 +376,7 @@ where
     where
         I: DoubleEndedIterator,
     {
-        spec!(self.iter.nth_back(n))
+        self.iter.as_mut()?.nth_back(n)
     }
 
     #[inline]
@@ -426,6 +399,15 @@ where
         P: FnMut(&Self::Item) -> bool,
         I: DoubleEndedIterator,
     {
-        spec!(self.iter.rfind(predicate))
+        self.iter.as_mut()?.rfind(predicate)
+    }
+}
+
+#[inline]
+fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> {
+    let x = f(opt.as_mut()?);
+    if x.is_none() {
+        *opt = None;
     }
+    x
 }
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index e570d831cc6..92d03b724b4 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -213,7 +213,7 @@ macro_rules! nonzero_leading_trailing_zeros {
                               without modifying the original"]
                 #[inline]
                 pub const fn leading_zeros(self) -> u32 {
-                    // SAFETY: since `self` can not be zero it is safe to call ctlz_nonzero
+                    // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`.
                     unsafe { intrinsics::ctlz_nonzero(self.0 as $Uint) as u32 }
                 }
 
@@ -237,7 +237,7 @@ macro_rules! nonzero_leading_trailing_zeros {
                               without modifying the original"]
                 #[inline]
                 pub const fn trailing_zeros(self) -> u32 {
-                    // SAFETY: since `self` can not be zero it is safe to call cttz_nonzero
+                    // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`.
                     unsafe { intrinsics::cttz_nonzero(self.0 as $Uint) as u32 }
                 }
 
diff --git a/library/core/tests/alloc.rs b/library/core/tests/alloc.rs
index 6762c0319e5..8a5a06b3440 100644
--- a/library/core/tests/alloc.rs
+++ b/library/core/tests/alloc.rs
@@ -1,5 +1,5 @@
 use core::alloc::Layout;
-use core::ptr::NonNull;
+use core::ptr::{self, NonNull};
 
 #[test]
 fn const_unchecked_layout() {
@@ -9,7 +9,7 @@ fn const_unchecked_layout() {
     const DANGLING: NonNull<u8> = LAYOUT.dangling();
     assert_eq!(LAYOUT.size(), SIZE);
     assert_eq!(LAYOUT.align(), ALIGN);
-    assert_eq!(Some(DANGLING), NonNull::new(ALIGN as *mut u8));
+    assert_eq!(Some(DANGLING), NonNull::new(ptr::invalid_mut(ALIGN)));
 }
 
 #[test]
diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs
index 5bc6aac1778..f7934d062a3 100644
--- a/library/core/tests/hash/mod.rs
+++ b/library/core/tests/hash/mod.rs
@@ -2,6 +2,7 @@ mod sip;
 
 use std::default::Default;
 use std::hash::{BuildHasher, Hash, Hasher};
+use std::ptr;
 use std::rc::Rc;
 
 struct MyHasher {
@@ -69,10 +70,10 @@ fn test_writer_hasher() {
     let cs: Rc<[u8]> = Rc::new([1, 2, 3]);
     assert_eq!(hash(&cs), 9);
 
-    let ptr = 5_usize as *const i32;
+    let ptr = ptr::invalid::<i32>(5_usize);
     assert_eq!(hash(&ptr), 5);
 
-    let ptr = 5_usize as *mut i32;
+    let ptr = ptr::invalid_mut::<i32>(5_usize);
     assert_eq!(hash(&ptr), 5);
 
     if cfg!(miri) {
diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
index 3e2956eac87..187a7db7fcb 100644
--- a/library/core/tests/ptr.rs
+++ b/library/core/tests/ptr.rs
@@ -353,9 +353,9 @@ fn align_offset_zst() {
     // all, because no amount of elements will align the pointer.
     let mut p = 1;
     while p < 1024 {
-        assert_eq!((p as *const ()).align_offset(p), 0);
+        assert_eq!(ptr::invalid::<()>(p).align_offset(p), 0);
         if p != 1 {
-            assert_eq!(((p + 1) as *const ()).align_offset(p), !0);
+            assert_eq!(ptr::invalid::<()>(p + 1).align_offset(p), !0);
         }
         p = (p + 1).next_power_of_two();
     }
@@ -371,7 +371,7 @@ fn align_offset_stride1() {
             let expected = ptr % align;
             let offset = if expected == 0 { 0 } else { align - expected };
             assert_eq!(
-                (ptr as *const u8).align_offset(align),
+                ptr::invalid::<u8>(ptr).align_offset(align),
                 offset,
                 "ptr = {}, align = {}, size = 1",
                 ptr,
@@ -434,14 +434,14 @@ fn align_offset_weird_strides() {
     while align < limit {
         for ptr in 1usize..4 * align {
             unsafe {
-                x |= test_weird_stride::<A3>(ptr as *const A3, align);
-                x |= test_weird_stride::<A4>(ptr as *const A4, align);
-                x |= test_weird_stride::<A5>(ptr as *const A5, align);
-                x |= test_weird_stride::<A6>(ptr as *const A6, align);
-                x |= test_weird_stride::<A7>(ptr as *const A7, align);
-                x |= test_weird_stride::<A8>(ptr as *const A8, align);
-                x |= test_weird_stride::<A9>(ptr as *const A9, align);
-                x |= test_weird_stride::<A10>(ptr as *const A10, align);
+                x |= test_weird_stride::<A3>(ptr::invalid::<A3>(ptr), align);
+                x |= test_weird_stride::<A4>(ptr::invalid::<A4>(ptr), align);
+                x |= test_weird_stride::<A5>(ptr::invalid::<A5>(ptr), align);
+                x |= test_weird_stride::<A6>(ptr::invalid::<A6>(ptr), align);
+                x |= test_weird_stride::<A7>(ptr::invalid::<A7>(ptr), align);
+                x |= test_weird_stride::<A8>(ptr::invalid::<A8>(ptr), align);
+                x |= test_weird_stride::<A9>(ptr::invalid::<A9>(ptr), align);
+                x |= test_weird_stride::<A10>(ptr::invalid::<A10>(ptr), align);
             }
         }
         align = (align + 1).next_power_of_two();
@@ -479,8 +479,8 @@ fn ptr_metadata() {
     let () = metadata(&[4, 7]);
     let () = metadata(&(4, String::new()));
     let () = metadata(&Pair(4, String::new()));
-    let () = metadata(0 as *const Extern);
-    let () = metadata(0 as *const <&u32 as std::ops::Deref>::Target);
+    let () = metadata(ptr::null::<()>() as *const Extern);
+    let () = metadata(ptr::null::<()>() as *const <&u32 as std::ops::Deref>::Target);
 
     assert_eq!(metadata("foo"), 3_usize);
     assert_eq!(metadata(&[4, 7][..]), 2_usize);
diff --git a/library/core/tests/waker.rs b/library/core/tests/waker.rs
index 6602ab36ba7..38a3a0adad9 100644
--- a/library/core/tests/waker.rs
+++ b/library/core/tests/waker.rs
@@ -3,7 +3,7 @@ use std::task::{RawWaker, RawWakerVTable, Waker};
 
 #[test]
 fn test_waker_getters() {
-    let raw_waker = RawWaker::new(42usize as *mut (), &WAKER_VTABLE);
+    let raw_waker = RawWaker::new(ptr::invalid_mut(42usize), &WAKER_VTABLE);
     assert_eq!(raw_waker.data() as usize, 42);
     assert!(ptr::eq(raw_waker.vtable(), &WAKER_VTABLE));
 
@@ -15,7 +15,7 @@ fn test_waker_getters() {
 }
 
 static WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
-    |data| RawWaker::new((data as usize + 1) as *mut (), &WAKER_VTABLE),
+    |data| RawWaker::new(ptr::invalid_mut(data as usize + 1), &WAKER_VTABLE),
     |_| {},
     |_| {},
     |_| {},
diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs
index 0ce6ae00ee2..f3fbfc44789 100644
--- a/library/std/src/io/cursor.rs
+++ b/library/std/src/io/cursor.rs
@@ -396,38 +396,99 @@ fn slice_write_vectored(
     Ok(nwritten)
 }
 
-// Resizing write implementation
-fn vec_write<A>(pos_mut: &mut u64, vec: &mut Vec<u8, A>, buf: &[u8]) -> io::Result<usize>
-where
-    A: Allocator,
-{
+/// Reserves the required space, and pads the vec with 0s if necessary.
+fn reserve_and_pad<A: Allocator>(
+    pos_mut: &mut u64,
+    vec: &mut Vec<u8, A>,
+    buf_len: usize,
+) -> io::Result<usize> {
     let pos: usize = (*pos_mut).try_into().map_err(|_| {
         io::const_io_error!(
             ErrorKind::InvalidInput,
             "cursor position exceeds maximum possible vector length",
         )
     })?;
-    // Make sure the internal buffer is as least as big as where we
-    // currently are
-    let len = vec.len();
-    if len < pos {
-        // use `resize` so that the zero filling is as efficient as possible
-        vec.resize(pos, 0);
-    }
-    // Figure out what bytes will be used to overwrite what's currently
-    // there (left), and what will be appended on the end (right)
-    {
-        let space = vec.len() - pos;
-        let (left, right) = buf.split_at(cmp::min(space, buf.len()));
-        vec[pos..pos + left.len()].copy_from_slice(left);
-        vec.extend_from_slice(right);
+
+    // For safety reasons, we don't want these numbers to overflow
+    // otherwise our allocation won't be enough
+    let desired_cap = pos.saturating_add(buf_len);
+    if desired_cap > vec.capacity() {
+        // We want our vec's total capacity
+        // to have room for (pos+buf_len) bytes. Reserve allocates
+        // based on additional elements from the length, so we need to
+        // reserve the difference
+        vec.reserve(desired_cap - vec.len());
+    }
+    // Pad if pos is above the current len.
+    if pos > vec.len() {
+        let diff = pos - vec.len();
+        // Unfortunately, `resize()` would suffice but the optimiser does not
+        // realise the `reserve` it does can be eliminated. So we do it manually
+        // to eliminate that extra branch
+        let spare = vec.spare_capacity_mut();
+        debug_assert!(spare.len() >= diff);
+        // Safety: we have allocated enough capacity for this.
+        // And we are only writing, not reading
+        unsafe {
+            spare.get_unchecked_mut(..diff).fill(core::mem::MaybeUninit::new(0));
+            vec.set_len(pos);
+        }
     }
 
+    Ok(pos)
+}
+
+/// Writes the slice to the vec without allocating
+/// # Safety: vec must have buf.len() spare capacity
+unsafe fn vec_write_unchecked<A>(pos: usize, vec: &mut Vec<u8, A>, buf: &[u8]) -> usize
+where
+    A: Allocator,
+{
+    debug_assert!(vec.capacity() >= pos + buf.len());
+    vec.as_mut_ptr().add(pos).copy_from(buf.as_ptr(), buf.len());
+    pos + buf.len()
+}
+
+/// Resizing write implementation for [`Cursor`]
+///
+/// Cursor is allowed to have a pre-allocated and initialised
+/// vector body, but with a position of 0. This means the [`Write`]
+/// will overwrite the contents of the vec.
+///
+/// This also allows for the vec body to be empty, but with a position of N.
+/// This means that [`Write`] will pad the vec with 0 initially,
+/// before writing anything from that point
+fn vec_write<A>(pos_mut: &mut u64, vec: &mut Vec<u8, A>, buf: &[u8]) -> io::Result<usize>
+where
+    A: Allocator,
+{
+    let buf_len = buf.len();
+    let mut pos = reserve_and_pad(pos_mut, vec, buf_len)?;
+
+    // Write the buf then progress the vec forward if necessary
+    // Safety: we have ensured that the capacity is available
+    // and that all bytes get written up to pos
+    unsafe {
+        pos = vec_write_unchecked(pos, vec, buf);
+        if pos > vec.len() {
+            vec.set_len(pos);
+        }
+    };
+
     // Bump us forward
-    *pos_mut = (pos + buf.len()) as u64;
-    Ok(buf.len())
+    *pos_mut += buf_len as u64;
+    Ok(buf_len)
 }
 
+/// Resizing write_vectored implementation for [`Cursor`]
+///
+/// Cursor is allowed to have a pre-allocated and initialised
+/// vector body, but with a position of 0. This means the [`Write`]
+/// will overwrite the contents of the vec.
+///
+/// This also allows for the vec body to be empty, but with a position of N.
+/// This means that [`Write`] will pad the vec with 0 initially,
+/// before writing anything from that point
 fn vec_write_vectored<A>(
     pos_mut: &mut u64,
     vec: &mut Vec<u8, A>,
@@ -436,11 +497,26 @@ fn vec_write_vectored<A>(
 where
     A: Allocator,
 {
-    let mut nwritten = 0;
-    for buf in bufs {
-        nwritten += vec_write(pos_mut, vec, buf)?;
+    // For safety reasons, we don't want this sum to overflow ever.
+    // If this saturates, the reserve should panic to avoid any unsound writing.
+    let buf_len = bufs.iter().fold(0usize, |a, b| a.saturating_add(b.len()));
+    let mut pos = reserve_and_pad(pos_mut, vec, buf_len)?;
+
+    // Write the buf then progress the vec forward if necessary
+    // Safety: we have ensured that the capacity is available
+    // and that all bytes get written up to the last pos
+    unsafe {
+        for buf in bufs {
+            pos = vec_write_unchecked(pos, vec, buf);
+        }
+        if pos > vec.len() {
+            vec.set_len(pos);
+        }
     }
-    Ok(nwritten)
+
+    // Bump us forward
+    *pos_mut += buf_len as u64;
+    Ok(buf_len)
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/io/cursor/tests.rs b/library/std/src/io/cursor/tests.rs
index f1ee177b7f3..d7c203c297f 100644
--- a/library/std/src/io/cursor/tests.rs
+++ b/library/std/src/io/cursor/tests.rs
@@ -20,6 +20,7 @@ fn test_vec_writer() {
 #[test]
 fn test_mem_writer() {
     let mut writer = Cursor::new(Vec::new());
+    writer.set_position(10);
     assert_eq!(writer.write(&[0]).unwrap(), 1);
     assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
     assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
@@ -30,6 +31,17 @@ fn test_mem_writer() {
         3
     );
     let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(&writer.get_ref()[..10], &[0; 10]);
+    assert_eq!(&writer.get_ref()[10..], b);
+}
+
+#[test]
+fn test_mem_writer_preallocated() {
+    let mut writer = Cursor::new(vec![0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 10]);
+    assert_eq!(writer.write(&[0]).unwrap(), 1);
+    assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+    assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
+    let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
     assert_eq!(&writer.get_ref()[..], b);
 }
 
@@ -517,3 +529,39 @@ fn const_cursor() {
     const _: &&[u8] = CURSOR.get_ref();
     const _: u64 = CURSOR.position();
 }
+
+#[bench]
+fn bench_write_vec(b: &mut test::Bencher) {
+    let slice = &[1; 128];
+
+    b.iter(|| {
+        let mut buf = b"some random data to overwrite".to_vec();
+        let mut cursor = Cursor::new(&mut buf);
+
+        let _ = cursor.write_all(slice);
+        test::black_box(&cursor);
+    })
+}
+
+#[bench]
+fn bench_write_vec_vectored(b: &mut test::Bencher) {
+    let slices = [
+        IoSlice::new(&[1; 128]),
+        IoSlice::new(&[2; 256]),
+        IoSlice::new(&[3; 512]),
+        IoSlice::new(&[4; 1024]),
+        IoSlice::new(&[5; 2048]),
+        IoSlice::new(&[6; 4096]),
+        IoSlice::new(&[7; 8192]),
+        IoSlice::new(&[8; 8192 * 2]),
+    ];
+
+    b.iter(|| {
+        let mut buf = b"some random data to overwrite".to_vec();
+        let mut cursor = Cursor::new(&mut buf);
+
+        let mut slices = slices;
+        let _ = cursor.write_all_vectored(&mut slices);
+        test::black_box(&cursor);
+    })
+}
diff --git a/library/std/src/sys/hermit/condvar.rs b/library/std/src/sys/hermit/condvar.rs
index 3f00160e55a..22059ca0dbe 100644
--- a/library/std/src/sys/hermit/condvar.rs
+++ b/library/std/src/sys/hermit/condvar.rs
@@ -3,6 +3,7 @@ use crate::ptr;
 use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
 use crate::sys::hermit::abi;
 use crate::sys::locks::Mutex;
+use crate::sys_common::lazy_box::{LazyBox, LazyInit};
 use crate::time::Duration;
 
 // The implementation is inspired by Andrew D. Birrell's paper
@@ -14,14 +15,26 @@ pub struct Condvar {
     sem2: *const c_void,
 }
 
-pub type MovableCondvar = Condvar;
+pub(crate) type MovableCondvar = LazyBox<Condvar>;
+
+impl LazyInit for Condvar {
+    fn init() -> Box<Self> {
+        Box::new(Self::new())
+    }
+}
 
 unsafe impl Send for Condvar {}
 unsafe impl Sync for Condvar {}
 
 impl Condvar {
-    pub const fn new() -> Condvar {
-        Condvar { counter: AtomicUsize::new(0), sem1: ptr::null(), sem2: ptr::null() }
+    pub fn new() -> Self {
+        let mut condvar =
+            Self { counter: AtomicUsize::new(0), sem1: ptr::null(), sem2: ptr::null() };
+        unsafe {
+            let _ = abi::sem_init(&mut condvar.sem1, 0);
+            let _ = abi::sem_init(&mut condvar.sem2, 0);
+        }
+        condvar
     }
 
     pub unsafe fn notify_one(&self) {
diff --git a/library/std/src/sys/hermit/mutex.rs b/library/std/src/sys/hermit/mutex.rs
index ef44bf411fb..eb15a04ffcf 100644
--- a/library/std/src/sys/hermit/mutex.rs
+++ b/library/std/src/sys/hermit/mutex.rs
@@ -175,9 +175,7 @@ impl Mutex {
     }
 
     #[inline]
-    pub unsafe fn init(&mut self) {
-        self.inner = Spinlock::new(MutexInner::new());
-    }
+    pub unsafe fn init(&mut self) {}
 
     #[inline]
     pub unsafe fn lock(&self) {
diff --git a/library/std/src/sys/hermit/rwlock.rs b/library/std/src/sys/hermit/rwlock.rs
index d43fa08a171..9701bab1f66 100644
--- a/library/std/src/sys/hermit/rwlock.rs
+++ b/library/std/src/sys/hermit/rwlock.rs
@@ -1,9 +1,10 @@
 use crate::cell::UnsafeCell;
-use crate::sys::locks::{Condvar, Mutex};
+use crate::sys::locks::{MovableCondvar, Mutex};
+use crate::sys_common::lazy_box::{LazyBox, LazyInit};
 
 pub struct RwLock {
     lock: Mutex,
-    cond: Condvar,
+    cond: MovableCondvar,
     state: UnsafeCell<State>,
 }
 
@@ -28,7 +29,11 @@ unsafe impl Sync for RwLock {}
 
 impl RwLock {
     pub const fn new() -> RwLock {
-        RwLock { lock: Mutex::new(), cond: Condvar::new(), state: UnsafeCell::new(State::Unlocked) }
+        RwLock {
+            lock: Mutex::new(),
+            cond: MovableCondvar::new(),
+            state: UnsafeCell::new(State::Unlocked),
+        }
     }
 
     #[inline]
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index ea410849694..9cd8b6d1455 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -160,7 +160,7 @@ pub(crate) fn maybe_download_ci_llvm(builder: &Builder<'_>) {
         // files in the tarball are in the past, so it doesn't trigger a
         // rebuild.
         let now = filetime::FileTime::from_system_time(std::time::SystemTime::now());
-        let llvm_config = llvm_root.join("bin/llvm-config");
+        let llvm_config = llvm_root.join("bin").join(exe("llvm-config", builder.config.build));
         t!(filetime::set_file_times(&llvm_config, now, now));
 
         let llvm_lib = llvm_root.join("lib");
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index e59324331ae..6e3651665c8 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -6,6 +6,7 @@ use std::path::PathBuf;
 use std::str::FromStr;
 
 use rustc_data_structures::fx::FxHashMap;
+use rustc_driver::print_flag_list;
 use rustc_session::config::{
     self, parse_crate_types_from_list, parse_externs, parse_target_triple, CrateType,
 };
@@ -310,11 +311,15 @@ impl RenderOptions {
 impl Options {
     /// Parses the given command-line for options. If an error message or other early-return has
     /// been printed, returns `Err` with the exit code.
-    pub(crate) fn from_matches(matches: &getopts::Matches) -> Result<Options, i32> {
+    pub(crate) fn from_matches(
+        matches: &getopts::Matches,
+        args: Vec<String>,
+    ) -> Result<Options, i32> {
+        let args = &args[1..];
         // Check for unstable options.
         nightly_options::check_nightly_options(matches, &opts());
 
-        if matches.opt_present("h") || matches.opt_present("help") {
+        if args.is_empty() || matches.opt_present("h") || matches.opt_present("help") {
             crate::usage("rustdoc");
             return Err(0);
         } else if matches.opt_present("version") {
@@ -335,6 +340,21 @@ impl Options {
         // check for deprecated options
         check_deprecated_options(matches, &diag);
 
+        let z_flags = matches.opt_strs("Z");
+        if z_flags.iter().any(|x| *x == "help") {
+            print_flag_list("-Z", config::DB_OPTIONS);
+            return Err(0);
+        }
+        let c_flags = matches.opt_strs("C");
+        if c_flags.iter().any(|x| *x == "help") {
+            print_flag_list("-C", config::CG_OPTIONS);
+            return Err(0);
+        }
+        let w_flags = matches.opt_strs("W");
+        if w_flags.iter().any(|x| *x == "help") {
+            print_flag_list("-W", config::DB_OPTIONS);
+            return Err(0);
+        }
         if matches.opt_strs("passes") == ["list"] {
             println!("Available passes for running rustdoc:");
             for pass in passes::PASSES {
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index c627dcc30d6..428519dbc16 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -252,8 +252,11 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
             bounds: b.into_iter().map(|x| x.into_tcx(tcx)).collect(),
             default: None,
         },
-        // FIXME: do not map to Typedef but to a custom variant
-        AssocTypeItem(t, _) => ItemEnum::Typedef(t.into_tcx(tcx)),
+        AssocTypeItem(t, b) => ItemEnum::AssocType {
+            generics: t.generics.into_tcx(tcx),
+            bounds: b.into_iter().map(|x| x.into_tcx(tcx)).collect(),
+            default: t.item_type.map(|ty| ty.into_tcx(tcx)),
+        },
         // `convert_item` early returns `None` for striped items and keywords.
         StrippedItem(_) | KeywordItem(_) => unreachable!(),
         ExternCrateItem { ref src } => ItemEnum::ExternCrate {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 54b85166041..db4c3d10237 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -686,7 +686,7 @@ fn main_args(at_args: &[String]) -> MainResult {
 
     // Note that we discard any distinction between different non-zero exit
     // codes from `from_matches` here.
-    let options = match config::Options::from_matches(&matches) {
+    let options = match config::Options::from_matches(&matches, args) {
         Ok(opts) => opts,
         Err(code) => {
             return if code == 0 {
diff --git a/src/llvm-project b/src/llvm-project
-Subproject c9e2e89ed3aa5a3be77143aa0c86906b4138374
+Subproject d1ddc34c4b23468f6d2bf553084834b104e16dd
diff --git a/src/test/run-make/issue-88756-default-output/Makefile b/src/test/run-make/issue-88756-default-output/Makefile
new file mode 100644
index 00000000000..cacbcbf3933
--- /dev/null
+++ b/src/test/run-make/issue-88756-default-output/Makefile
@@ -0,0 +1,4 @@
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(BARE_RUSTDOC) 2>&1 | sed -E 's@/nightly/|/beta/|/stable/|/1\.[0-9]+\.[0-9]+/@/$$CHANNEL/@g' | diff - output-default.stdout
diff --git a/src/test/run-make/issue-88756-default-output/README.md b/src/test/run-make/issue-88756-default-output/README.md
new file mode 100644
index 00000000000..8cbfac4f7d2
--- /dev/null
+++ b/src/test/run-make/issue-88756-default-output/README.md
@@ -0,0 +1 @@
+This is a test to verify that the default behavior of `rustdoc` is printing out help output instead of erroring out (#88756).
diff --git a/src/test/run-make/issue-88756-default-output/output-default.stdout b/src/test/run-make/issue-88756-default-output/output-default.stdout
new file mode 100644
index 00000000000..6d16fe5673b
--- /dev/null
+++ b/src/test/run-make/issue-88756-default-output/output-default.stdout
@@ -0,0 +1,193 @@
+rustdoc [options] <input>
+
+Options:
+    -h, --help          show this help message
+    -V, --version       print rustdoc's version
+    -v, --verbose       use verbose output
+    -w, --output-format [html]
+                        the output type to write
+        --output PATH   Which directory to place the output. This option is
+                        deprecated, use --out-dir instead.
+    -o, --out-dir PATH  which directory to place the output
+        --crate-name NAME
+                        specify the name of this crate
+        --crate-type [bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]
+                        Comma separated list of types of crates
+                        for the compiler to emit
+    -L, --library-path DIR
+                        directory to add to crate search path
+        --cfg           pass a --cfg to rustc
+        --check-cfg     pass a --check-cfg to rustc
+        --extern NAME[=PATH]
+                        pass an --extern to rustc
+        --extern-html-root-url NAME=URL
+                        base URL to use for dependencies; for example,
+                        "std=/doc" links std::vec::Vec to
+                        /doc/std/vec/struct.Vec.html
+        --extern-html-root-takes-precedence 
+                        give precedence to `--extern-html-root-url`, not
+                        `html_root_url`
+    -C, --codegen OPT[=VALUE]
+                        pass a codegen option to rustc
+        --document-private-items 
+                        document private items
+        --document-hidden-items 
+                        document items that have doc(hidden)
+        --test          run code examples as tests
+        --test-args ARGS
+                        arguments to pass to the test runner
+        --test-run-directory PATH
+                        The working directory in which to run tests
+        --target TRIPLE target triple to document
+        --markdown-css FILES
+                        CSS files to include via <link> in a rendered Markdown
+                        file
+        --html-in-header FILES
+                        files to include inline in the <head> section of a
+                        rendered Markdown file or generated documentation
+        --html-before-content FILES
+                        files to include inline between <body> and the content
+                        of a rendered Markdown file or generated documentation
+        --html-after-content FILES
+                        files to include inline between the content and
+                        </body> of a rendered Markdown file or generated
+                        documentation
+        --markdown-before-content FILES
+                        files to include inline between <body> and the content
+                        of a rendered Markdown file or generated documentation
+        --markdown-after-content FILES
+                        files to include inline between the content and
+                        </body> of a rendered Markdown file or generated
+                        documentation
+        --markdown-playground-url URL
+                        URL to send code snippets to
+        --markdown-no-toc 
+                        don't include table of contents
+    -e, --extend-css PATH
+                        To add some CSS rules with a given file to generate
+                        doc with your own theme. However, your theme might
+                        break if the rustdoc's generated HTML changes, so be
+                        careful!
+    -Z FLAG             internal and debugging options (only on nightly build)
+        --sysroot PATH  Override the system root
+        --playground-url URL
+                        URL to send code snippets to, may be reset by
+                        --markdown-playground-url or
+                        `#![doc(html_playground_url=...)]`
+        --display-doctest-warnings 
+                        show warnings that originate in doctests
+        --crate-version VERSION
+                        crate version to print into documentation
+        --sort-modules-by-appearance 
+                        sort modules by where they appear in the program,
+                        rather than alphabetically
+        --default-theme THEME
+                        Set the default theme. THEME should be the theme name,
+                        generally lowercase. If an unknown default theme is
+                        specified, the builtin default is used. The set of
+                        themes, and the rustdoc built-in default, are not
+                        stable.
+        --default-setting SETTING[=VALUE]
+                        Default value for a rustdoc setting (used when
+                        "rustdoc-SETTING" is absent from web browser Local
+                        Storage). If VALUE is not supplied, "true" is used.
+                        Supported SETTINGs and VALUEs are not documented and
+                        not stable.
+        --theme FILES   additional themes which will be added to the generated
+                        docs
+        --check-theme FILES
+                        check if given theme is valid
+        --resource-suffix PATH
+                        suffix to add to CSS and JavaScript files, e.g.,
+                        "light.css" will become "light-suffix.css"
+        --edition EDITION
+                        edition to use when compiling rust code (default:
+                        2015)
+        --color auto|always|never
+                        Configure coloring of output:
+                        auto = colorize, if output goes to a tty (default);
+                        always = always colorize output;
+                        never = never colorize output
+        --error-format human|json|short
+                        How errors and other messages are produced
+        --json CONFIG   Configure the structure of JSON diagnostics
+        --disable-minification 
+                        Disable minification applied on JS files
+    -A, --allow LINT    Set lint allowed
+    -W, --warn LINT     Set lint warnings
+        --force-warn LINT
+                        Set lint force-warn
+    -D, --deny LINT     Set lint denied
+    -F, --forbid LINT   Set lint forbidden
+        --cap-lints LEVEL
+                        Set the most restrictive lint level. More restrictive
+                        lints are capped at this level. By default, it is at
+                        `forbid` level.
+        --index-page PATH
+                        Markdown file to be used as index page
+        --enable-index-page 
+                        To enable generation of the index page
+        --static-root-path PATH
+                        Path string to force loading static files from in
+                        output pages. If not set, uses combinations of '../'
+                        to reach the documentation root.
+        --disable-per-crate-search 
+                        disables generating the crate selector on the search
+                        box
+        --persist-doctests PATH
+                        Directory to persist doctest executables into
+        --show-coverage 
+                        calculate percentage of public items with
+                        documentation
+        --enable-per-target-ignores 
+                        parse ignore-foo for ignoring doctests on a per-target
+                        basis
+        --runtool The tool to run tests with when building for a different target than host
+                        
+        --runtool-arg One (of possibly many) arguments to pass to the runtool
+                        
+        --test-builder PATH
+                        The rustc-like binary to use as the test builder
+        --check         Run rustdoc checks
+        --generate-redirect-map 
+                        Generate JSON file at the top level instead of
+                        generating HTML redirection files
+        --emit [unversioned-shared-resources,toolchain-shared-resources,invocation-specific]
+                        Comma separated list of types of output for rustdoc to
+                        emit
+        --no-run        Compile doctests without running them
+        --show-type-layout 
+                        Include the memory layout of types in the docs
+        --nocapture     Don't capture stdout and stderr of tests
+        --generate-link-to-definition 
+                        Make the identifiers in the HTML source code pages
+                        navigable
+        --scrape-examples-output-path collect function call information and output at the given path
+                        
+        --scrape-examples-target-crate collect function call information for functions from the target crate
+                        
+        --scrape-tests  Include test code when scraping examples
+        --with-examples path to function call information (for displaying examples in the documentation)
+                        
+        --plugin-path DIR
+                        removed, see issue #44136
+                        <https://github.com/rust-lang/rust/issues/44136> for
+                        more information
+        --passes PASSES removed, see issue #44136
+                        <https://github.com/rust-lang/rust/issues/44136> for
+                        more information
+        --plugins PLUGINS
+                        removed, see issue #44136
+                        <https://github.com/rust-lang/rust/issues/44136> for
+                        more information
+        --no-defaults   removed, see issue #44136
+                        <https://github.com/rust-lang/rust/issues/44136> for
+                        more information
+    -r, --input-format [rust]
+                        removed, see issue #44136
+                        <https://github.com/rust-lang/rust/issues/44136> for
+                        more information
+
+    @path               Read newline separated options from `path`
+
+More information available at https://doc.rust-lang.org/$CHANNEL/rustdoc/what-is-rustdoc.html
diff --git a/src/test/run-make/issue-88756-default-output/x.rs b/src/test/run-make/issue-88756-default-output/x.rs
new file mode 100644
index 00000000000..5df7576133a
--- /dev/null
+++ b/src/test/run-make/issue-88756-default-output/x.rs
@@ -0,0 +1 @@
+// nothing to see here
diff --git a/src/test/run-make/issue-88756-opt-help/Makefile b/src/test/run-make/issue-88756-opt-help/Makefile
new file mode 100644
index 00000000000..8ababbf5b4e
--- /dev/null
+++ b/src/test/run-make/issue-88756-opt-help/Makefile
@@ -0,0 +1,4 @@
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTDOC) -W help 2>&1 | diff - output-default.stdout
diff --git a/src/test/run-make/issue-88756-opt-help/README.md b/src/test/run-make/issue-88756-opt-help/README.md
new file mode 100644
index 00000000000..9b742753f25
--- /dev/null
+++ b/src/test/run-make/issue-88756-opt-help/README.md
@@ -0,0 +1 @@
+This is a test to verify that `rustdoc` behaves the same as rustc and prints out help output for its options like -W (#88756).
diff --git a/src/test/run-make/issue-88756-opt-help/output-default.stdout b/src/test/run-make/issue-88756-opt-help/output-default.stdout
new file mode 100644
index 00000000000..5cb7ecb649a
--- /dev/null
+++ b/src/test/run-make/issue-88756-opt-help/output-default.stdout
@@ -0,0 +1,193 @@
+    -W                          allow-features=val -- only allow the listed language features to be enabled in code (space separated)
+    -W                       always-encode-mir=val -- encode MIR of all functions into the crate metadata (default: no)
+    -W               assume-incomplete-release=val -- make cfg(version) treat the current version as incomplete (default: no)
+    -W                            asm-comments=val -- generate comments into the assembly (may change behavior) (default: no)
+    -W                       assert-incr-state=val -- assert that the incremental cache is in given state: either `loaded` or `not-loaded`.
+    -W                      binary-dep-depinfo=val -- include artifacts (sysroot, crate dependencies) used during compilation in dep-info (default: no)
+    -W                       branch-protection=val -- set options for branch target identification and pointer authentication on AArch64
+    -W                           cf-protection=val -- instrument control-flow architecture protection
+    -W               cgu-partitioning-strategy=val -- the codegen unit partitioning strategy to use
+    -W                                   chalk=val -- enable the experimental Chalk-based trait solving engine
+    -W                         codegen-backend=val -- the backend to use
+    -W                             combine-cgu=val -- combine CGUs into a single one
+    -W                              crate-attr=val -- inject the given attribute in the crate
+    -W                debug-info-for-profiling=val -- emit discriminators and other data necessary for AutoFDO
+    -W                            debug-macros=val -- emit line numbers debug info inside macros (default: no)
+    -W                 deduplicate-diagnostics=val -- deduplicate identical diagnostics (default: yes)
+    -W                  dep-info-omit-d-target=val -- in dep-info output, omit targets for tracking dependencies of the dep-info files themselves (default: no)
+    -W                               dep-tasks=val -- print tasks that execute and the color their dep node gets (requires debug build) (default: no)
+    -W                                 dlltool=val -- import library generation tool (windows-gnu only)
+    -W                 dont-buffer-diagnostics=val -- emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) (default: no)
+    -W                           drop-tracking=val -- enables drop tracking in generators (default: no)
+    -W                        dual-proc-macros=val -- load proc macros for both target and host, but only link to the target (default: no)
+    -W                          dump-dep-graph=val -- dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv) (default: no)
+    -W                                dump-mir=val -- dump MIR state to file.
+        `val` is used to select which passes and functions to dump. For example:
+        `all` matches all passes and functions,
+        `foo` matches all passes for functions whose name contains 'foo',
+        `foo & ConstProp` only the 'ConstProp' pass for function names containing 'foo',
+        `foo | bar` all passes for function names containing 'foo' or 'bar'.
+    -W                       dump-mir-dataflow=val -- in addition to `.mir` files, create graphviz `.dot` files with dataflow results (default: no)
+    -W                            dump-mir-dir=val -- the directory the MIR is dumped into (default: `mir_dump`)
+    -W            dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no)
+    -W                       dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no)
+    -W                       dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans.
+    -W                        emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
+    -W                             fewer-names=val -- reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) (default: no)
+    -W              force-unstable-if-unmarked=val -- force all crates to be `rustc_private` unstable (default: no)
+    -W                                    fuel=val -- set the optimization fuel quota for a crate
+    -W                       function-sections=val -- whether each function should go in its own section
+    -W                    future-incompat-test=val -- forces all lints to be future incompatible, used for internal testing (default: no)
+    -W                                  gcc-ld=val -- implementation of ld used by cc
+    -W                      graphviz-dark-mode=val -- use dark-themed colors in graphviz output (default: no)
+    -W                           graphviz-font=val -- use the given `fontname` in graphviz output; can be overridden by setting environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)
+    -W                               hir-stats=val -- print some statistics about AST and HIR (default: no)
+    -W                human-readable-cgu-names=val -- generate human-readable, predictable names for codegen units (default: no)
+    -W                        identify-regions=val -- display unnamed regions as `'<id>`, using a non-ident unique id (default: no)
+    -W                incremental-ignore-spans=val -- ignore spans during ICH computation -- used for testing (default: no)
+    -W                        incremental-info=val -- print high-level information about incremental reuse (or the lack thereof) (default: no)
+    -W              incremental-relative-spans=val -- hash spans relative to their parent item for incr. comp. (default: no)
+    -W                  incremental-verify-ich=val -- verify incr. comp. hashes of green query instances (default: no)
+    -W                              inline-mir=val -- enable MIR inlining (default: no)
+    -W                    inline-mir-threshold=val -- a default MIR inlining threshold (default: 50)
+    -W               inline-mir-hint-threshold=val -- inlining threshold for functions with inline hint (default: 100)
+    -W                      inline-in-all-cgus=val -- control whether `#[inline]` functions are in all CGUs
+    -W                             input-stats=val -- gather statistics about the input (default: no)
+    -W                     instrument-coverage=val -- instrument the generated code to support LLVM source-based code coverage reports (note, the compiler build config must include `profiler = true`); implies `-C symbol-mangling-version=v0`. Optional values are:
+        `=all` (implicit value)
+        `=except-unused-generics`
+        `=except-unused-functions`
+        `=off` (default)
+    -W                       instrument-mcount=val -- insert function instrument code for mcount-based tracing (default: no)
+    -W                       keep-hygiene-data=val -- keep hygiene data after analysis (default: no)
+    -W                   link-native-libraries=val -- link native libraries in the linker invocation (default: yes)
+    -W                               link-only=val -- link the `.rlink` file generated by `-Z no-link` (default: no)
+    -W                            llvm-plugins=val -- a list LLVM plugins to enable (space separated)
+    -W                         llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no)
+    -W                         location-detail=val -- comma separated list of location details to be tracked when using caller_location valid options are `file`, `line`, and `column` (default: all)
+    -W                                      ls=val -- list the symbols defined by a library crate (default: no)
+    -W                         macro-backtrace=val -- show macro backtraces (default: no)
+    -W                         merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name
+    -W                              meta-stats=val -- gather metadata statistics (default: no)
+    -W                          mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no)
+    -W                       mir-enable-passes=val -- use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be enabled, overriding all other checks. Passes that are not specified are enabled or disabled by other flags as usual.
+    -W                           mir-opt-level=val -- MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)
+    -W                         move-size-limit=val -- the size at which the `large_assignments` lint starts to be emitted
+    -W                         mutable-noalias=val -- emit noalias metadata for mutable references (default: yes)
+    -W                   new-llvm-pass-manager=val -- use new LLVM pass manager (default: no)
+    -W                               nll-facts=val -- dump facts from NLL analysis into side files (default: no)
+    -W                           nll-facts-dir=val -- the directory the NLL facts are dumped into (default: `nll-facts`)
+    -W                             no-analysis=val -- parse and expand the source, but run no analysis
+    -W                              no-codegen=val -- run all passes except codegen; no output
+    -W              no-generate-arange-section=val -- omit DWARF address ranges that give faster lookups
+    -W                     no-interleave-lints=val -- execute lints separately; allows benchmarking individual lints
+    -W                           no-leak-check=val -- disable the 'leak check' for subtyping; unsound, but useful for tests
+    -W                                 no-link=val -- compile without linking
+    -W                        no-parallel-llvm=val -- run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)
+    -W                 no-unique-section-names=val -- do not use unique names for text and data sections when -Z function-sections is used
+    -W                     no-profiler-runtime=val -- prevent automatic injection of the profiler_builtins crate
+    -W                          normalize-docs=val -- normalize associated items in rustdoc when generating documentation
+    -W                                     oom=val -- panic strategy for out-of-memory handling
+    -W                  osx-rpath-install-name=val -- pass `-install_name @rpath/...` to the macOS linker (default: no)
+    -W                       panic-abort-tests=val -- support compiling tests with panic=abort (default: no)
+    -W                           panic-in-drop=val -- panic strategy for panics in drops
+    -W                              parse-only=val -- parse only; do not compile, assemble, or link (default: no)
+    -W                              perf-stats=val -- print some performance-related statistics (default: no)
+    -W pick-stable-methods-before-any-unstable=val -- try to pick stable methods first before picking any unstable methods (default: yes)
+    -W                                     plt=val -- whether to use the PLT when calling into shared libraries;
+        only has effect for PIC code on systems with ELF binaries
+        (default: PLT is disabled if full relro is enabled)
+    -W                                polonius=val -- enable polonius-based borrow-checker (default: no)
+    -W                            polymorphize=val -- perform polymorphization analysis
+    -W                            pre-link-arg=val -- a single extra argument to prepend the linker invocation (can be used several times)
+    -W                           pre-link-args=val -- extra arguments to prepend to the linker invocation (space separated)
+    -W           precise-enum-drop-elaboration=val -- use a more precise version of drop elaboration for matches on enums (default: yes). This results in better codegen, but has caused miscompilations on some tier 2 platforms. See #77382 and #74551.
+    -W                              print-fuel=val -- make rustc print the total optimization fuel used by a crate
+    -W                       print-llvm-passes=val -- print the LLVM optimization passes being run (default: no)
+    -W                        print-mono-items=val -- print the result of the monomorphization collection pass
+    -W                        print-type-sizes=val -- print layout information for each type encountered (default: no)
+    -W                    proc-macro-backtrace=val -- show backtraces for panics during proc-macro execution (default: no)
+    -W                                 profile=val -- insert profiling code (default: no)
+    -W                        profile-closures=val -- profile size of closures
+    -W                            profile-emit=val -- file path to emit profiling data at runtime when using 'profile' (default based on relative source path)
+    -W                        profiler-runtime=val -- name of the profiler runtime crate to automatically inject (default: `profiler_builtins`)
+    -W                      profile-sample-use=val -- use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)
+    -W                         query-dep-graph=val -- enable queries of the dependency graph for regression testing (default: no)
+    -W                        randomize-layout=val -- randomize the layout of types (default: no)
+    -W                             layout-seed=val -- seed layout randomization
+    -W                   relax-elf-relocations=val -- whether ELF relocations can be relaxed
+    -W                             relro-level=val -- choose which RELRO level to use
+    -W                        remap-cwd-prefix=val -- remap paths under the current working directory to this path prefix
+    -W         simulate-remapped-rust-src-base=val -- simulate the effect of remap-debuginfo = true at bootstrapping by remapping path to rust's source base directory. only meant for testing purposes
+    -W                     report-delayed-bugs=val -- immediately print bugs registered with `delay_span_bug` (default: no)
+    -W                               sanitizer=val -- use a sanitizer
+    -W          sanitizer-memory-track-origins=val -- enable origins tracking in MemorySanitizer
+    -W                       sanitizer-recover=val -- enable recovery for selected sanitizers
+    -W                  saturating-float-casts=val -- make float->int casts UB-free: numbers outside the integer type's range are clipped to the max/min integer respectively, and NaN is mapped to 0 (default: yes)
+    -W                           save-analysis=val -- write syntax and type analysis (in JSON format) information, in addition to normal output (default: no)
+    -W                            self-profile=val -- run the self profiler and output the raw event data
+    -W                     self-profile-events=val -- specify the events recorded by the self profiler;
+        for example: `-Z self-profile-events=default,query-keys`
+        all options: none, all, default, generic-activity, query-provider, query-cache-hit
+                     query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes
+    -W                    self-profile-counter=val -- counter used by the self profiler (default: `wall-time`), one of:
+        `wall-time` (monotonic clock, i.e. `std::time::Instant`)
+        `instructions:u` (retired instructions, userspace-only)
+        `instructions-minus-irqs:u` (subtracting hardware interrupt counts for extra accuracy)
+    -W                          share-generics=val -- make the current crate share its generic instantiations
+    -W                               show-span=val -- show spans for compiler debugging (expr|pat|ty)
+    -W                              span-debug=val -- forward proc_macro::Span's `Debug` impl to `Span`
+    -W                       span-free-formats=val -- exclude spans when debug-printing compiler state (default: no)
+    -W                      src-hash-algorithm=val -- hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)
+    -W                         stack-protector=val -- control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)
+    -W                      strict-init-checks=val -- control if mem::uninitialized and mem::zeroed panic on more UB
+    -W                                   strip=val -- tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)
+    -W                        split-dwarf-kind=val -- split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform)
+        (default: `split`)
+
+        `split`: sections which do not require relocation are written into a DWARF object (`.dwo`)
+                 file which is ignored by the linker
+        `single`: sections which do not require relocation are written into object file but ignored
+                  by the linker
+    -W                    split-dwarf-inlining=val -- provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF
+    -W                 symbol-mangling-version=val -- which mangling version to use for symbol names ('legacy' (default) or 'v0')
+    -W                                   teach=val -- show extended diagnostic help (default: no)
+    -W                               temps-dir=val -- the directory the intermediate files are written to
+    -W                          terminal-width=val -- set the current terminal width
+    -W                          translate-lang=val -- language identifier for diagnostic output
+    -W                translate-additional-ftl=val -- additional fluent translation to preferentially use (for testing translation)
+    -W        translate-directionality-markers=val -- emit directionality isolation markers in translated diagnostics
+    -W                                tune-cpu=val -- select processor to schedule for (`rustc --print target-cpus` for details)
+    -W                                 thinlto=val -- enable ThinLTO when possible
+    -W                           thir-unsafeck=val -- use the THIR unsafety checker (default: no)
+    -W                                 threads=val -- use a thread pool with N threads
+    -W                                    time=val -- measure time of rustc processes (default: no)
+    -W                        time-llvm-passes=val -- measure time of each LLVM pass (default: no)
+    -W                             time-passes=val -- measure time of each rustc pass (default: no)
+    -W                               tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details)
+    -W                            trace-macros=val -- for every macro invocation, print its name and arguments (default: no)
+    -W   translate-remapped-path-to-local-path=val -- translate remapped paths into local paths when possible (default: yes)
+    -W                        trap-unreachable=val -- generate trap instructions for unreachable intrinsics (default: use target setting, usually yes)
+    -W                        treat-err-as-bug=val -- treat error number `val` that occurs as bug
+    -W                   trim-diagnostic-paths=val -- in diagnostics, use heuristics to shorten paths referring to items
+    -W                              ui-testing=val -- emit compiler diagnostics in a form suitable for UI testing (default: no)
+    -W            uninit-const-chunk-threshold=val -- allow generating const initializers with mixed init/uninit chunks, and set the maximum number of chunks for which this is allowed (default: 16)
+    -W          unleash-the-miri-inside-of-you=val -- take the brakes off const evaluation. NOTE: this is unsound (default: no)
+    -W                                unpretty=val -- present the input source, unstable (and less-pretty) variants;
+        `normal`, `identified`,
+        `expanded`, `expanded,identified`,
+        `expanded,hygiene` (with internal representations),
+        `ast-tree` (raw AST before expansion),
+        `ast-tree,expanded` (raw AST after expansion),
+        `hir` (the HIR), `hir,identified`,
+        `hir,typed` (HIR with types for each node),
+        `hir-tree` (dump the raw HIR),
+        `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)
+    -W                        unsound-mir-opts=val -- enable unsound and buggy MIR optimizations (default: no)
+    -W                        unstable-options=val -- adds unstable command line options to rustc interface (default: no)
+    -W                       use-ctors-section=val -- use legacy .ctors section for initializers rather than .init_array
+    -W                            validate-mir=val -- validate MIR after each transformation
+    -W                                 verbose=val -- in general, enable more debug printouts (default: no)
+    -W                          verify-llvm-ir=val -- verify LLVM IR (default: no)
+    -W            virtual-function-elimination=val -- enables dead virtual function elimination optimization. Requires `-Clto[=[fat,yes]]`
+    -W                         wasi-exec-model=val -- whether to build a wasi command or reactor
diff --git a/src/test/run-make/issue-88756-opt-help/x.rs b/src/test/run-make/issue-88756-opt-help/x.rs
new file mode 100644
index 00000000000..5df7576133a
--- /dev/null
+++ b/src/test/run-make/issue-88756-opt-help/x.rs
@@ -0,0 +1 @@
+// nothing to see here
diff --git a/src/test/rustdoc-json/assoc_items.rs b/src/test/rustdoc-json/assoc_items.rs
new file mode 100644
index 00000000000..2ee64c9f6eb
--- /dev/null
+++ b/src/test/rustdoc-json/assoc_items.rs
@@ -0,0 +1,29 @@
+#![no_std]
+
+// @has assoc_items.json
+
+pub struct Simple;
+
+impl Simple {
+    // @has - "$.index[*][?(@.name=='CONSTANT')].kind" \"assoc_const\"
+    pub const CONSTANT: usize = 0;
+}
+
+pub trait EasyToImpl {
+    // @has - "$.index[*][?(@.name=='ToDeclare')].kind" \"assoc_type\"
+    // @has - "$.index[*][?(@.name=='ToDeclare')].inner.default" null
+    type ToDeclare;
+    // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].kind" \"assoc_const\"
+    // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.default" null
+    const AN_ATTRIBUTE: usize;
+}
+
+impl EasyToImpl for Simple {
+    // @has - "$.index[*][?(@.name=='ToDeclare')].inner.default.kind" \"primitive\"
+    // @has - "$.index[*][?(@.name=='ToDeclare')].inner.default.inner" \"usize\"
+    type ToDeclare = usize;
+    // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.type.kind" \"primitive\"
+    // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.type.inner" \"usize\"
+    // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.default" \"12\"
+    const AN_ATTRIBUTE: usize = 12;
+}
diff --git a/src/test/rustdoc-ui/issue-83883-describe-lints.stdout b/src/test/rustdoc-ui/issue-83883-describe-lints.stdout
index 651faf5761f..5cb7ecb649a 100644
--- a/src/test/rustdoc-ui/issue-83883-describe-lints.stdout
+++ b/src/test/rustdoc-ui/issue-83883-describe-lints.stdout
@@ -1,25 +1,193 @@
+    -W                          allow-features=val -- only allow the listed language features to be enabled in code (space separated)
+    -W                       always-encode-mir=val -- encode MIR of all functions into the crate metadata (default: no)
+    -W               assume-incomplete-release=val -- make cfg(version) treat the current version as incomplete (default: no)
+    -W                            asm-comments=val -- generate comments into the assembly (may change behavior) (default: no)
+    -W                       assert-incr-state=val -- assert that the incremental cache is in given state: either `loaded` or `not-loaded`.
+    -W                      binary-dep-depinfo=val -- include artifacts (sysroot, crate dependencies) used during compilation in dep-info (default: no)
+    -W                       branch-protection=val -- set options for branch target identification and pointer authentication on AArch64
+    -W                           cf-protection=val -- instrument control-flow architecture protection
+    -W               cgu-partitioning-strategy=val -- the codegen unit partitioning strategy to use
+    -W                                   chalk=val -- enable the experimental Chalk-based trait solving engine
+    -W                         codegen-backend=val -- the backend to use
+    -W                             combine-cgu=val -- combine CGUs into a single one
+    -W                              crate-attr=val -- inject the given attribute in the crate
+    -W                debug-info-for-profiling=val -- emit discriminators and other data necessary for AutoFDO
+    -W                            debug-macros=val -- emit line numbers debug info inside macros (default: no)
+    -W                 deduplicate-diagnostics=val -- deduplicate identical diagnostics (default: yes)
+    -W                  dep-info-omit-d-target=val -- in dep-info output, omit targets for tracking dependencies of the dep-info files themselves (default: no)
+    -W                               dep-tasks=val -- print tasks that execute and the color their dep node gets (requires debug build) (default: no)
+    -W                                 dlltool=val -- import library generation tool (windows-gnu only)
+    -W                 dont-buffer-diagnostics=val -- emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) (default: no)
+    -W                           drop-tracking=val -- enables drop tracking in generators (default: no)
+    -W                        dual-proc-macros=val -- load proc macros for both target and host, but only link to the target (default: no)
+    -W                          dump-dep-graph=val -- dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv) (default: no)
+    -W                                dump-mir=val -- dump MIR state to file.
+        `val` is used to select which passes and functions to dump. For example:
+        `all` matches all passes and functions,
+        `foo` matches all passes for functions whose name contains 'foo',
+        `foo & ConstProp` only the 'ConstProp' pass for function names containing 'foo',
+        `foo | bar` all passes for function names containing 'foo' or 'bar'.
+    -W                       dump-mir-dataflow=val -- in addition to `.mir` files, create graphviz `.dot` files with dataflow results (default: no)
+    -W                            dump-mir-dir=val -- the directory the MIR is dumped into (default: `mir_dump`)
+    -W            dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no)
+    -W                       dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no)
+    -W                       dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans.
+    -W                        emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
+    -W                             fewer-names=val -- reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) (default: no)
+    -W              force-unstable-if-unmarked=val -- force all crates to be `rustc_private` unstable (default: no)
+    -W                                    fuel=val -- set the optimization fuel quota for a crate
+    -W                       function-sections=val -- whether each function should go in its own section
+    -W                    future-incompat-test=val -- forces all lints to be future incompatible, used for internal testing (default: no)
+    -W                                  gcc-ld=val -- implementation of ld used by cc
+    -W                      graphviz-dark-mode=val -- use dark-themed colors in graphviz output (default: no)
+    -W                           graphviz-font=val -- use the given `fontname` in graphviz output; can be overridden by setting environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)
+    -W                               hir-stats=val -- print some statistics about AST and HIR (default: no)
+    -W                human-readable-cgu-names=val -- generate human-readable, predictable names for codegen units (default: no)
+    -W                        identify-regions=val -- display unnamed regions as `'<id>`, using a non-ident unique id (default: no)
+    -W                incremental-ignore-spans=val -- ignore spans during ICH computation -- used for testing (default: no)
+    -W                        incremental-info=val -- print high-level information about incremental reuse (or the lack thereof) (default: no)
+    -W              incremental-relative-spans=val -- hash spans relative to their parent item for incr. comp. (default: no)
+    -W                  incremental-verify-ich=val -- verify incr. comp. hashes of green query instances (default: no)
+    -W                              inline-mir=val -- enable MIR inlining (default: no)
+    -W                    inline-mir-threshold=val -- a default MIR inlining threshold (default: 50)
+    -W               inline-mir-hint-threshold=val -- inlining threshold for functions with inline hint (default: 100)
+    -W                      inline-in-all-cgus=val -- control whether `#[inline]` functions are in all CGUs
+    -W                             input-stats=val -- gather statistics about the input (default: no)
+    -W                     instrument-coverage=val -- instrument the generated code to support LLVM source-based code coverage reports (note, the compiler build config must include `profiler = true`); implies `-C symbol-mangling-version=v0`. Optional values are:
+        `=all` (implicit value)
+        `=except-unused-generics`
+        `=except-unused-functions`
+        `=off` (default)
+    -W                       instrument-mcount=val -- insert function instrument code for mcount-based tracing (default: no)
+    -W                       keep-hygiene-data=val -- keep hygiene data after analysis (default: no)
+    -W                   link-native-libraries=val -- link native libraries in the linker invocation (default: yes)
+    -W                               link-only=val -- link the `.rlink` file generated by `-Z no-link` (default: no)
+    -W                            llvm-plugins=val -- a list LLVM plugins to enable (space separated)
+    -W                         llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no)
+    -W                         location-detail=val -- comma separated list of location details to be tracked when using caller_location valid options are `file`, `line`, and `column` (default: all)
+    -W                                      ls=val -- list the symbols defined by a library crate (default: no)
+    -W                         macro-backtrace=val -- show macro backtraces (default: no)
+    -W                         merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name
+    -W                              meta-stats=val -- gather metadata statistics (default: no)
+    -W                          mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no)
+    -W                       mir-enable-passes=val -- use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be enabled, overriding all other checks. Passes that are not specified are enabled or disabled by other flags as usual.
+    -W                           mir-opt-level=val -- MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)
+    -W                         move-size-limit=val -- the size at which the `large_assignments` lint starts to be emitted
+    -W                         mutable-noalias=val -- emit noalias metadata for mutable references (default: yes)
+    -W                   new-llvm-pass-manager=val -- use new LLVM pass manager (default: no)
+    -W                               nll-facts=val -- dump facts from NLL analysis into side files (default: no)
+    -W                           nll-facts-dir=val -- the directory the NLL facts are dumped into (default: `nll-facts`)
+    -W                             no-analysis=val -- parse and expand the source, but run no analysis
+    -W                              no-codegen=val -- run all passes except codegen; no output
+    -W              no-generate-arange-section=val -- omit DWARF address ranges that give faster lookups
+    -W                     no-interleave-lints=val -- execute lints separately; allows benchmarking individual lints
+    -W                           no-leak-check=val -- disable the 'leak check' for subtyping; unsound, but useful for tests
+    -W                                 no-link=val -- compile without linking
+    -W                        no-parallel-llvm=val -- run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)
+    -W                 no-unique-section-names=val -- do not use unique names for text and data sections when -Z function-sections is used
+    -W                     no-profiler-runtime=val -- prevent automatic injection of the profiler_builtins crate
+    -W                          normalize-docs=val -- normalize associated items in rustdoc when generating documentation
+    -W                                     oom=val -- panic strategy for out-of-memory handling
+    -W                  osx-rpath-install-name=val -- pass `-install_name @rpath/...` to the macOS linker (default: no)
+    -W                       panic-abort-tests=val -- support compiling tests with panic=abort (default: no)
+    -W                           panic-in-drop=val -- panic strategy for panics in drops
+    -W                              parse-only=val -- parse only; do not compile, assemble, or link (default: no)
+    -W                              perf-stats=val -- print some performance-related statistics (default: no)
+    -W pick-stable-methods-before-any-unstable=val -- try to pick stable methods first before picking any unstable methods (default: yes)
+    -W                                     plt=val -- whether to use the PLT when calling into shared libraries;
+        only has effect for PIC code on systems with ELF binaries
+        (default: PLT is disabled if full relro is enabled)
+    -W                                polonius=val -- enable polonius-based borrow-checker (default: no)
+    -W                            polymorphize=val -- perform polymorphization analysis
+    -W                            pre-link-arg=val -- a single extra argument to prepend the linker invocation (can be used several times)
+    -W                           pre-link-args=val -- extra arguments to prepend to the linker invocation (space separated)
+    -W           precise-enum-drop-elaboration=val -- use a more precise version of drop elaboration for matches on enums (default: yes). This results in better codegen, but has caused miscompilations on some tier 2 platforms. See #77382 and #74551.
+    -W                              print-fuel=val -- make rustc print the total optimization fuel used by a crate
+    -W                       print-llvm-passes=val -- print the LLVM optimization passes being run (default: no)
+    -W                        print-mono-items=val -- print the result of the monomorphization collection pass
+    -W                        print-type-sizes=val -- print layout information for each type encountered (default: no)
+    -W                    proc-macro-backtrace=val -- show backtraces for panics during proc-macro execution (default: no)
+    -W                                 profile=val -- insert profiling code (default: no)
+    -W                        profile-closures=val -- profile size of closures
+    -W                            profile-emit=val -- file path to emit profiling data at runtime when using 'profile' (default based on relative source path)
+    -W                        profiler-runtime=val -- name of the profiler runtime crate to automatically inject (default: `profiler_builtins`)
+    -W                      profile-sample-use=val -- use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)
+    -W                         query-dep-graph=val -- enable queries of the dependency graph for regression testing (default: no)
+    -W                        randomize-layout=val -- randomize the layout of types (default: no)
+    -W                             layout-seed=val -- seed layout randomization
+    -W                   relax-elf-relocations=val -- whether ELF relocations can be relaxed
+    -W                             relro-level=val -- choose which RELRO level to use
+    -W                        remap-cwd-prefix=val -- remap paths under the current working directory to this path prefix
+    -W         simulate-remapped-rust-src-base=val -- simulate the effect of remap-debuginfo = true at bootstrapping by remapping path to rust's source base directory. only meant for testing purposes
+    -W                     report-delayed-bugs=val -- immediately print bugs registered with `delay_span_bug` (default: no)
+    -W                               sanitizer=val -- use a sanitizer
+    -W          sanitizer-memory-track-origins=val -- enable origins tracking in MemorySanitizer
+    -W                       sanitizer-recover=val -- enable recovery for selected sanitizers
+    -W                  saturating-float-casts=val -- make float->int casts UB-free: numbers outside the integer type's range are clipped to the max/min integer respectively, and NaN is mapped to 0 (default: yes)
+    -W                           save-analysis=val -- write syntax and type analysis (in JSON format) information, in addition to normal output (default: no)
+    -W                            self-profile=val -- run the self profiler and output the raw event data
+    -W                     self-profile-events=val -- specify the events recorded by the self profiler;
+        for example: `-Z self-profile-events=default,query-keys`
+        all options: none, all, default, generic-activity, query-provider, query-cache-hit
+                     query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes
+    -W                    self-profile-counter=val -- counter used by the self profiler (default: `wall-time`), one of:
+        `wall-time` (monotonic clock, i.e. `std::time::Instant`)
+        `instructions:u` (retired instructions, userspace-only)
+        `instructions-minus-irqs:u` (subtracting hardware interrupt counts for extra accuracy)
+    -W                          share-generics=val -- make the current crate share its generic instantiations
+    -W                               show-span=val -- show spans for compiler debugging (expr|pat|ty)
+    -W                              span-debug=val -- forward proc_macro::Span's `Debug` impl to `Span`
+    -W                       span-free-formats=val -- exclude spans when debug-printing compiler state (default: no)
+    -W                      src-hash-algorithm=val -- hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)
+    -W                         stack-protector=val -- control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)
+    -W                      strict-init-checks=val -- control if mem::uninitialized and mem::zeroed panic on more UB
+    -W                                   strip=val -- tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)
+    -W                        split-dwarf-kind=val -- split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform)
+        (default: `split`)
 
-Available lint options:
-    -W <foo>           Warn about <foo>
-    -A <foo>           Allow <foo>
-    -D <foo>           Deny <foo>
-    -F <foo>           Forbid <foo> (deny <foo> and all attempts to override)
-
-
-Lint checks provided by rustc:
-
-    $NAMES  $LEVELS  $MEANINGS
-
-Lint groups provided by rustc:
-
-    $NAMES  $SUB_LINTS
-
-Lint checks provided by plugins loaded by this crate:
-
-    $NAMES  $LEVELS  $MEANINGS
-
-Lint groups provided by plugins loaded by this crate:
-
-    rustdoc::all  $GROUPS
-
-
+        `split`: sections which do not require relocation are written into a DWARF object (`.dwo`)
+                 file which is ignored by the linker
+        `single`: sections which do not require relocation are written into object file but ignored
+                  by the linker
+    -W                    split-dwarf-inlining=val -- provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF
+    -W                 symbol-mangling-version=val -- which mangling version to use for symbol names ('legacy' (default) or 'v0')
+    -W                                   teach=val -- show extended diagnostic help (default: no)
+    -W                               temps-dir=val -- the directory the intermediate files are written to
+    -W                          terminal-width=val -- set the current terminal width
+    -W                          translate-lang=val -- language identifier for diagnostic output
+    -W                translate-additional-ftl=val -- additional fluent translation to preferentially use (for testing translation)
+    -W        translate-directionality-markers=val -- emit directionality isolation markers in translated diagnostics
+    -W                                tune-cpu=val -- select processor to schedule for (`rustc --print target-cpus` for details)
+    -W                                 thinlto=val -- enable ThinLTO when possible
+    -W                           thir-unsafeck=val -- use the THIR unsafety checker (default: no)
+    -W                                 threads=val -- use a thread pool with N threads
+    -W                                    time=val -- measure time of rustc processes (default: no)
+    -W                        time-llvm-passes=val -- measure time of each LLVM pass (default: no)
+    -W                             time-passes=val -- measure time of each rustc pass (default: no)
+    -W                               tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details)
+    -W                            trace-macros=val -- for every macro invocation, print its name and arguments (default: no)
+    -W   translate-remapped-path-to-local-path=val -- translate remapped paths into local paths when possible (default: yes)
+    -W                        trap-unreachable=val -- generate trap instructions for unreachable intrinsics (default: use target setting, usually yes)
+    -W                        treat-err-as-bug=val -- treat error number `val` that occurs as bug
+    -W                   trim-diagnostic-paths=val -- in diagnostics, use heuristics to shorten paths referring to items
+    -W                              ui-testing=val -- emit compiler diagnostics in a form suitable for UI testing (default: no)
+    -W            uninit-const-chunk-threshold=val -- allow generating const initializers with mixed init/uninit chunks, and set the maximum number of chunks for which this is allowed (default: 16)
+    -W          unleash-the-miri-inside-of-you=val -- take the brakes off const evaluation. NOTE: this is unsound (default: no)
+    -W                                unpretty=val -- present the input source, unstable (and less-pretty) variants;
+        `normal`, `identified`,
+        `expanded`, `expanded,identified`,
+        `expanded,hygiene` (with internal representations),
+        `ast-tree` (raw AST before expansion),
+        `ast-tree,expanded` (raw AST after expansion),
+        `hir` (the HIR), `hir,identified`,
+        `hir,typed` (HIR with types for each node),
+        `hir-tree` (dump the raw HIR),
+        `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)
+    -W                        unsound-mir-opts=val -- enable unsound and buggy MIR optimizations (default: no)
+    -W                        unstable-options=val -- adds unstable command line options to rustc interface (default: no)
+    -W                       use-ctors-section=val -- use legacy .ctors section for initializers rather than .init_array
+    -W                            validate-mir=val -- validate MIR after each transformation
+    -W                                 verbose=val -- in general, enable more debug printouts (default: no)
+    -W                          verify-llvm-ir=val -- verify LLVM IR (default: no)
+    -W            virtual-function-elimination=val -- enables dead virtual function elimination optimization. Requires `-Clto[=[fat,yes]]`
+    -W                         wasi-exec-model=val -- whether to build a wasi command or reactor
diff --git a/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr b/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr
index ea475ffc554..ad21b38d07e 100644
--- a/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr
+++ b/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr
@@ -4,7 +4,7 @@ error[E0201]: duplicate definitions with name `bar`:
 LL |     const bar: bool = true;
    |     ----------------------- previous definition of `bar` here
 LL |     fn bar() {}
-   |     ^^^^^^^^^^^ duplicate definition
+   |     ^^^^^^^^ duplicate definition
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr
index 9ae25a8c222..5487af1a835 100644
--- a/src/test/ui/associated-item/issue-48027.stderr
+++ b/src/test/ui/associated-item/issue-48027.stderr
@@ -1,15 +1,3 @@
-error[E0283]: type annotations needed
-  --> $DIR/issue-48027.rs:3:32
-   |
-LL |     fn return_n(&self) -> [u8; Bar::X];
-   |                                ^^^^^^
-   |                                |
-   |                                cannot infer type
-   |                                help: use the fully qualified path to an implementation: `<Type as Bar>::X`
-   |
-   = note: cannot satisfy `_: Bar`
-   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
-
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/issue-48027.rs:6:6
    |
@@ -25,6 +13,18 @@ LL |     const X: usize;
    |           ^ ...because it contains this associated `const`
    = help: consider moving `X` to another trait
 
+error[E0283]: type annotations needed
+  --> $DIR/issue-48027.rs:3:32
+   |
+LL |     fn return_n(&self) -> [u8; Bar::X];
+   |                                ^^^^^^
+   |                                |
+   |                                cannot infer type
+   |                                help: use the fully qualified path to an implementation: `<Type as Bar>::X`
+   |
+   = note: cannot satisfy `_: Bar`
+   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0038, E0283.
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
index da79c7ac77f..bd3ee2abd2c 100644
--- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
+++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
@@ -1,3 +1,9 @@
+error[E0277]: the trait bound `(T, U): Get` is not satisfied
+  --> $DIR/associated-types-no-suitable-supertrait.rs:22:40
+   |
+LL |     fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
+
 error[E0277]: the trait bound `Self: Get` is not satisfied
   --> $DIR/associated-types-no-suitable-supertrait.rs:17:40
    |
@@ -9,12 +15,6 @@ help: consider further restricting `Self`
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Get {}
    |                                                              +++++++++++++++
 
-error[E0277]: the trait bound `(T, U): Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait.rs:22:40
-   |
-LL |     fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
-   |                                        ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
-
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/hr-associated-type-bound-2.rs b/src/test/ui/associated-types/hr-associated-type-bound-2.rs
index 2eb956c8dbb..a89f61a81a5 100644
--- a/src/test/ui/associated-types/hr-associated-type-bound-2.rs
+++ b/src/test/ui/associated-types/hr-associated-type-bound-2.rs
@@ -12,7 +12,7 @@ impl X<'_> for u32 //~ overflow evaluating the requirement `for<'b> u32: X<'b>`
 where
     for<'b> <Self as X<'b>>::U: Clone,
 {
-    type U = str; //~ overflow evaluating the requirement `for<'b> u32: X<'b>`
+    type U = str;
 }
 
 fn main() {
diff --git a/src/test/ui/associated-types/hr-associated-type-bound-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr
index fe9b4d630b9..1d3b7097da6 100644
--- a/src/test/ui/associated-types/hr-associated-type-bound-2.stderr
+++ b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr
@@ -18,21 +18,6 @@ LL | impl X<'_> for u32
    = note: 128 redundant requirements hidden
    = note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32`
 
-error[E0275]: overflow evaluating the requirement `for<'b> u32: X<'b>`
-  --> $DIR/hr-associated-type-bound-2.rs:15:5
-   |
-LL |     type U = str;
-   |     ^^^^^^^^^^^^^
-   |
-   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`hr_associated_type_bound_2`)
-note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32`
-  --> $DIR/hr-associated-type-bound-2.rs:11:6
-   |
-LL | impl X<'_> for u32
-   |      ^^^^^     ^^^
-   = note: 128 redundant requirements hidden
-   = note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr
index 5809c407a5f..52294f8c94a 100644
--- a/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr
+++ b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr
@@ -15,10 +15,10 @@ LL |     for<'b> <T as Z<'b, u16>>::W: Clone,
    |                                   ^^^^^ required by this bound in `Z`
 
 error[E0277]: the trait bound `str: Clone` is not satisfied
-  --> $DIR/hr-associated-type-bound-param-2.rs:3:8
+  --> $DIR/hr-associated-type-bound-param-2.rs:15:14
    |
-LL |     T: Z<'a, u16>,
-   |        ^^^^^^^^^^ the trait `Clone` is not implemented for `str`
+LL |     type W = str;
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
    = help: the trait `Clone` is implemented for `String`
 note: required by a bound in `Z`
@@ -31,10 +31,10 @@ LL |     for<'b> <T as Z<'b, u16>>::W: Clone,
    |                                   ^^^^^ required by this bound in `Z`
 
 error[E0277]: the trait bound `str: Clone` is not satisfied
-  --> $DIR/hr-associated-type-bound-param-2.rs:15:14
+  --> $DIR/hr-associated-type-bound-param-2.rs:3:8
    |
-LL |     type W = str;
-   |              ^^^ the trait `Clone` is not implemented for `str`
+LL |     T: Z<'a, u16>,
+   |        ^^^^^^^^^^ the trait `Clone` is not implemented for `str`
    |
    = help: the trait `Clone` is implemented for `String`
 note: required by a bound in `Z`
diff --git a/src/test/ui/associated-types/impl-wf-cycle-1.rs b/src/test/ui/associated-types/impl-wf-cycle-1.rs
index ba074210a2b..365eddaed13 100644
--- a/src/test/ui/associated-types/impl-wf-cycle-1.rs
+++ b/src/test/ui/associated-types/impl-wf-cycle-1.rs
@@ -13,16 +13,14 @@ trait Grault {
 }
 
 impl<T: Grault> Grault for (T,)
+//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
 where
     Self::A: Baz,
     Self::B: Fiz,
 {
     type A = ();
-    //~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
     type B = bool;
-    //~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
 }
-//~^^^^^^^^^^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
 
 fn main() {
     let x: <(_,) as Grault>::A = ();
diff --git a/src/test/ui/associated-types/impl-wf-cycle-1.stderr b/src/test/ui/associated-types/impl-wf-cycle-1.stderr
index 73167d08311..6f60128b8ef 100644
--- a/src/test/ui/associated-types/impl-wf-cycle-1.stderr
+++ b/src/test/ui/associated-types/impl-wf-cycle-1.stderr
@@ -2,11 +2,11 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
   --> $DIR/impl-wf-cycle-1.rs:15:1
    |
 LL | / impl<T: Grault> Grault for (T,)
+LL | |
 LL | | where
 LL | |     Self::A: Baz,
-LL | |     Self::B: Fiz,
 ...  |
-LL | |
+LL | |     type B = bool;
 LL | | }
    | |_^
    |
@@ -18,34 +18,6 @@ LL | impl<T: Grault> Grault for (T,)
    = note: 1 redundant requirement hidden
    = note: required because of the requirements on the impl of `Grault` for `(T,)`
 
-error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
-  --> $DIR/impl-wf-cycle-1.rs:20:5
-   |
-LL |     type A = ();
-   |     ^^^^^^^^^^^^
-   |
-note: required because of the requirements on the impl of `Grault` for `(T,)`
-  --> $DIR/impl-wf-cycle-1.rs:15:17
-   |
-LL | impl<T: Grault> Grault for (T,)
-   |                 ^^^^^^     ^^^^
-   = note: 1 redundant requirement hidden
-   = note: required because of the requirements on the impl of `Grault` for `(T,)`
-
-error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
-  --> $DIR/impl-wf-cycle-1.rs:22:5
-   |
-LL |     type B = bool;
-   |     ^^^^^^^^^^^^^^
-   |
-note: required because of the requirements on the impl of `Grault` for `(T,)`
-  --> $DIR/impl-wf-cycle-1.rs:15:17
-   |
-LL | impl<T: Grault> Grault for (T,)
-   |                 ^^^^^^     ^^^^
-   = note: 1 redundant requirement hidden
-   = note: required because of the requirements on the impl of `Grault` for `(T,)`
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/associated-types/impl-wf-cycle-2.rs b/src/test/ui/associated-types/impl-wf-cycle-2.rs
index 6fccc54f229..f2f3072e344 100644
--- a/src/test/ui/associated-types/impl-wf-cycle-2.rs
+++ b/src/test/ui/associated-types/impl-wf-cycle-2.rs
@@ -5,12 +5,11 @@ trait Grault {
 }
 
 impl<T: Grault> Grault for (T,)
+//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
 where
     Self::A: Copy,
 {
     type A = ();
-    //~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
 }
-//~^^^^^^^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
 
 fn main() {}
diff --git a/src/test/ui/associated-types/impl-wf-cycle-2.stderr b/src/test/ui/associated-types/impl-wf-cycle-2.stderr
index a17e63f28fe..ba14ffefae5 100644
--- a/src/test/ui/associated-types/impl-wf-cycle-2.stderr
+++ b/src/test/ui/associated-types/impl-wf-cycle-2.stderr
@@ -2,11 +2,11 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
   --> $DIR/impl-wf-cycle-2.rs:7:1
    |
 LL | / impl<T: Grault> Grault for (T,)
+LL | |
 LL | | where
 LL | |     Self::A: Copy,
 LL | | {
 LL | |     type A = ();
-LL | |
 LL | | }
    | |_^
    |
@@ -16,18 +16,6 @@ note: required because of the requirements on the impl of `Grault` for `(T,)`
 LL | impl<T: Grault> Grault for (T,)
    |                 ^^^^^^     ^^^^
 
-error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
-  --> $DIR/impl-wf-cycle-2.rs:11:5
-   |
-LL |     type A = ();
-   |     ^^^^^^^^^^^^
-   |
-note: required because of the requirements on the impl of `Grault` for `(T,)`
-  --> $DIR/impl-wf-cycle-2.rs:7:17
-   |
-LL | impl<T: Grault> Grault for (T,)
-   |                 ^^^^^^     ^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/associated-types/issue-59324.stderr b/src/test/ui/associated-types/issue-59324.stderr
index 45d2dfb5375..5cd781d9a0c 100644
--- a/src/test/ui/associated-types/issue-59324.stderr
+++ b/src/test/ui/associated-types/issue-59324.stderr
@@ -46,6 +46,12 @@ help: consider further restricting this bound
 LL | pub trait ThriftService<Bug: NotFoo + Foo>:
    |                                     +++++
 
+error[E0277]: the trait bound `(): Foo` is not satisfied
+  --> $DIR/issue-59324.rs:23:29
+   |
+LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
+   |                             ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
+
 error[E0277]: the trait bound `Bug: Foo` is not satisfied
   --> $DIR/issue-59324.rs:19:10
    |
@@ -57,12 +63,6 @@ help: consider further restricting this bound
 LL | pub trait ThriftService<Bug: NotFoo + Foo>:
    |                                     +++++
 
-error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/issue-59324.rs:23:29
-   |
-LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
-   |                             ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
-
 error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/chalkify/bugs/async.rs b/src/test/ui/chalkify/bugs/async.rs
index 58fc93064ed..ae5224dbd6f 100644
--- a/src/test/ui/chalkify/bugs/async.rs
+++ b/src/test/ui/chalkify/bugs/async.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: unknown
 // compile-flags: -Z chalk --edition=2021
 
 fn main() -> () {}
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
index 91289148079..c364c707ff9 100644
--- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
+++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
@@ -1,3 +1,15 @@
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
+   |
+LL | impl !Marker1 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
+
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1
+   |
+LL | impl !Marker2 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
+
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:23:1
    |
@@ -21,18 +33,6 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i
 LL | impl !Send for dyn Object + Marker2 {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
 
-error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
-  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
-   |
-LL | impl !Marker1 for dyn Object + Marker2 { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
-
-error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
-  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1
-   |
-LL | impl !Marker2 for dyn Object + Marker2 { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
-
 error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0117, E0321, E0371.
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
index 056198374a4..b80429794f9 100644
--- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
+++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
@@ -1,3 +1,15 @@
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
+   |
+LL | impl Marker1 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
+
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1
+   |
+LL | impl Marker2 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
+
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:23:1
    |
@@ -21,18 +33,6 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i
 LL | unsafe impl Send for dyn Object + Marker2 {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
 
-error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
-  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
-   |
-LL | impl Marker1 for dyn Object + Marker2 { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
-
-error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
-  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1
-   |
-LL | impl Marker2 for dyn Object + Marker2 { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
-
 error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0117, E0321, E0371.
diff --git a/src/test/ui/coherence/coherence-impls-copy.stderr b/src/test/ui/coherence/coherence-impls-copy.stderr
index b3ca354c633..86356af2564 100644
--- a/src/test/ui/coherence/coherence-impls-copy.stderr
+++ b/src/test/ui/coherence/coherence-impls-copy.stderr
@@ -9,49 +9,49 @@ LL | impl Copy for i32 {}
    |
    = note: define and implement a trait or new type instead
 
+error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync`
+  --> $DIR/coherence-impls-copy.rs:28:1
+   |
+LL | impl Copy for &'static NotSync {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> Copy for &T
+             where T: ?Sized;
+
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-copy.rs:25:1
+  --> $DIR/coherence-impls-copy.rs:33:1
    |
-LL | impl Copy for (MyType, MyType) {}
-   | ^^^^^^^^^^^^^^----------------
+LL | impl Copy for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^------------------
    | |             |
-   | |             this is not defined in the current crate because tuples are always foreign
+   | |             this is not defined in the current crate because slices are always foreign
    | impl doesn't use only types from inside the current crate
    |
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-copy.rs:30:1
+  --> $DIR/coherence-impls-copy.rs:25:1
    |
-LL | impl Copy for [MyType] {}
-   | ^^^^^^^^^^^^^^--------
+LL | impl Copy for (MyType, MyType) {}
+   | ^^^^^^^^^^^^^^----------------
    | |             |
-   | |             this is not defined in the current crate because slices are always foreign
+   | |             this is not defined in the current crate because tuples are always foreign
    | impl doesn't use only types from inside the current crate
    |
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-copy.rs:33:1
+  --> $DIR/coherence-impls-copy.rs:30:1
    |
-LL | impl Copy for &'static [NotSync] {}
-   | ^^^^^^^^^^^^^^------------------
+LL | impl Copy for [MyType] {}
+   | ^^^^^^^^^^^^^^--------
    | |             |
    | |             this is not defined in the current crate because slices are always foreign
    | impl doesn't use only types from inside the current crate
    |
    = note: define and implement a trait or new type instead
 
-error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync`
-  --> $DIR/coherence-impls-copy.rs:28:1
-   |
-LL | impl Copy for &'static NotSync {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `core`:
-           - impl<T> Copy for &T
-             where T: ?Sized;
-
 error[E0206]: the trait `Copy` may not be implemented for this type
   --> $DIR/coherence-impls-copy.rs:21:15
    |
diff --git a/src/test/ui/coherence/coherence-impls-send.stderr b/src/test/ui/coherence/coherence-impls-send.stderr
index dd1fd1b0dce..e1071846e14 100644
--- a/src/test/ui/coherence/coherence-impls-send.stderr
+++ b/src/test/ui/coherence/coherence-impls-send.stderr
@@ -1,4 +1,15 @@
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-send.rs:25:1
+   |
+LL | unsafe impl Send for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^^^^^^^------------------
+   | |                    |
+   | |                    this is not defined in the current crate because slices are always foreign
+   | impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/coherence-impls-send.rs:16:1
    |
 LL | unsafe impl Send for (MyType, MyType) {}
@@ -26,17 +37,6 @@ LL | unsafe impl Send for [MyType] {}
    |
    = note: define and implement a trait or new type instead
 
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-send.rs:25:1
-   |
-LL | unsafe impl Send for &'static [NotSync] {}
-   | ^^^^^^^^^^^^^^^^^^^^^------------------
-   | |                    |
-   | |                    this is not defined in the current crate because slices are always foreign
-   | impl doesn't use only types from inside the current crate
-   |
-   = note: define and implement a trait or new type instead
-
 error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0117, E0321.
diff --git a/src/test/ui/coherence/coherence-impls-sized.stderr b/src/test/ui/coherence/coherence-impls-sized.stderr
index e1e4acd4cd8..17a7544521d 100644
--- a/src/test/ui/coherence/coherence-impls-sized.stderr
+++ b/src/test/ui/coherence/coherence-impls-sized.stderr
@@ -1,36 +1,3 @@
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-sized.rs:20:1
-   |
-LL | impl Sized for (MyType, MyType) {}
-   | ^^^^^^^^^^^^^^^----------------
-   | |              |
-   | |              this is not defined in the current crate because tuples are always foreign
-   | impl doesn't use only types from inside the current crate
-   |
-   = note: define and implement a trait or new type instead
-
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-sized.rs:27:1
-   |
-LL | impl Sized for [MyType] {}
-   | ^^^^^^^^^^^^^^^--------
-   | |              |
-   | |              this is not defined in the current crate because slices are always foreign
-   | impl doesn't use only types from inside the current crate
-   |
-   = note: define and implement a trait or new type instead
-
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-sized.rs:31:1
-   |
-LL | impl Sized for &'static [NotSync] {}
-   | ^^^^^^^^^^^^^^^------------------
-   | |              |
-   | |              this is not defined in the current crate because slices are always foreign
-   | impl doesn't use only types from inside the current crate
-   |
-   = note: define and implement a trait or new type instead
-
 error[E0322]: explicit impls for the `Sized` trait are not permitted
   --> $DIR/coherence-impls-sized.rs:14:1
    |
@@ -49,6 +16,17 @@ error[E0322]: explicit impls for the `Sized` trait are not permitted
 LL | impl Sized for (MyType, MyType) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed
 
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:20:1
+   |
+LL | impl Sized for (MyType, MyType) {}
+   | ^^^^^^^^^^^^^^^----------------
+   | |              |
+   | |              this is not defined in the current crate because tuples are always foreign
+   | impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
 error[E0322]: explicit impls for the `Sized` trait are not permitted
   --> $DIR/coherence-impls-sized.rs:24:1
    |
@@ -61,12 +39,34 @@ error[E0322]: explicit impls for the `Sized` trait are not permitted
 LL | impl Sized for [MyType] {}
    | ^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed
 
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:27:1
+   |
+LL | impl Sized for [MyType] {}
+   | ^^^^^^^^^^^^^^^--------
+   | |              |
+   | |              this is not defined in the current crate because slices are always foreign
+   | impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
 error[E0322]: explicit impls for the `Sized` trait are not permitted
   --> $DIR/coherence-impls-sized.rs:31:1
    |
 LL | impl Sized for &'static [NotSync] {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed
 
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:31:1
+   |
+LL | impl Sized for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^------------------
+   | |              |
+   | |              this is not defined in the current crate because slices are always foreign
+   | impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
 error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0117, E0322.
diff --git a/src/test/ui/coherence/coherence-with-closure.stderr b/src/test/ui/coherence/coherence-with-closure.stderr
index 20b986cee69..d2ca63fa146 100644
--- a/src/test/ui/coherence/coherence-with-closure.stderr
+++ b/src/test/ui/coherence/coherence-with-closure.stderr
@@ -1,3 +1,12 @@
+error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
+  --> $DIR/coherence-with-closure.rs:12:1
+   |
+LL | impl Trait for Wrapper<OpaqueClosure> {}
+   | ------------------------------------- first implementation here
+LL |
+LL | impl<T: Sync> Trait for Wrapper<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueClosure>`
+
 error: cannot implement trait on type alias impl trait
   --> $DIR/coherence-with-closure.rs:10:24
    |
@@ -10,15 +19,6 @@ note: type alias impl trait defined here
 LL | type OpaqueClosure = impl Sized;
    |                      ^^^^^^^^^^
 
-error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
-  --> $DIR/coherence-with-closure.rs:12:1
-   |
-LL | impl Trait for Wrapper<OpaqueClosure> {}
-   | ------------------------------------- first implementation here
-LL |
-LL | impl<T: Sync> Trait for Wrapper<T> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueClosure>`
-
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-with-generator.stderr b/src/test/ui/coherence/coherence-with-generator.stderr
index 249ad3cb9ec..804bc1c3a6d 100644
--- a/src/test/ui/coherence/coherence-with-generator.stderr
+++ b/src/test/ui/coherence/coherence-with-generator.stderr
@@ -1,3 +1,12 @@
+error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
+  --> $DIR/coherence-with-generator.rs:16:1
+   |
+LL | impl Trait for Wrapper<OpaqueGenerator> {}
+   | --------------------------------------- first implementation here
+LL |
+LL | impl<T: Sync> Trait for Wrapper<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueGenerator>`
+
 error: cannot implement trait on type alias impl trait
   --> $DIR/coherence-with-generator.rs:14:24
    |
@@ -10,15 +19,6 @@ note: type alias impl trait defined here
 LL | type OpaqueGenerator = impl Sized;
    |                        ^^^^^^^^^^
 
-error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
-  --> $DIR/coherence-with-generator.rs:16:1
-   |
-LL | impl Trait for Wrapper<OpaqueGenerator> {}
-   | --------------------------------------- first implementation here
-LL |
-LL | impl<T: Sync> Trait for Wrapper<T> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueGenerator>`
-
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr b/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr
index 48d85e7ff64..4bba42c7782 100644
--- a/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr
+++ b/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr
@@ -47,15 +47,6 @@ LL | impl<const N: &u8> A<N> {
    = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
-  --> $DIR/const-param-elided-lifetime.rs:17:21
-   |
-LL |     fn foo<const M: &u8>(&self) {}
-   |                     ^^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(adt_const_params)]`
-
-error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:22:15
    |
 LL | impl<const N: &u8> B for A<N> {}
@@ -73,6 +64,15 @@ LL | fn bar<const N: &u8>() {}
    = note: the only supported types are integers, `bool` and `char`
    = help: more complex types are supported with `#![feature(adt_const_params)]`
 
+error: `&'static u8` is forbidden as the type of a const generic parameter
+  --> $DIR/const-param-elided-lifetime.rs:17:21
+   |
+LL |     fn foo<const M: &u8>(&self) {}
+   |                     ^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
+
 error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/error-codes/E0201.stderr b/src/test/ui/error-codes/E0201.stderr
index 89cfd402423..af029603fa1 100644
--- a/src/test/ui/error-codes/E0201.stderr
+++ b/src/test/ui/error-codes/E0201.stderr
@@ -2,17 +2,17 @@ error[E0201]: duplicate definitions with name `bar`:
   --> $DIR/E0201.rs:5:5
    |
 LL |     fn bar(&self) -> bool { self.0 > 5 }
-   |     ------------------------------------ previous definition of `bar` here
+   |     --------------------- previous definition of `bar` here
 LL |     fn bar() {}
-   |     ^^^^^^^^^^^ duplicate definition
+   |     ^^^^^^^^ duplicate definition
 
 error[E0201]: duplicate definitions with name `baz`:
   --> $DIR/E0201.rs:17:5
    |
 LL |     fn baz(&self) -> bool { true }
-   |     ------------------------------ previous definition of `baz` here
+   |     --------------------- previous definition of `baz` here
 LL |     fn baz(&self) -> bool { self.0 > 5 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
+   |     ^^^^^^^^^^^^^^^^^^^^^ duplicate definition
 
 error[E0201]: duplicate definitions with name `Quux`:
   --> $DIR/E0201.rs:18:5
diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
index a06c4b2b483..a1c69a5afb6 100644
--- a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
+++ b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
@@ -1,13 +1,3 @@
-error[E0658]: `Ptr<Self>` cannot be used as the type of `self` without the `arbitrary_self_types` feature
-  --> $DIR/feature-gate-arbitrary-self-types.rs:16:18
-   |
-LL |     fn foo(self: Ptr<Self>);
-   |                  ^^^^^^^^^
-   |
-   = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
-   = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
-
 error[E0658]: `Ptr<Bar>` cannot be used as the type of `self` without the `arbitrary_self_types` feature
   --> $DIR/feature-gate-arbitrary-self-types.rs:22:18
    |
@@ -28,6 +18,16 @@ LL |     fn bar(self: Box<Ptr<Self>>) {}
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
+error[E0658]: `Ptr<Self>` cannot be used as the type of `self` without the `arbitrary_self_types` feature
+  --> $DIR/feature-gate-arbitrary-self-types.rs:16:18
+   |
+LL |     fn foo(self: Ptr<Self>);
+   |                  ^^^^^^^^^
+   |
+   = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
+   = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
index f9c53a66c4b..a9f611b8745 100644
--- a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
+++ b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
@@ -8,20 +8,20 @@ LL |     fn foo(self: *const Self) {}
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
-error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature
-  --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18
+error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types` feature
+  --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18
    |
-LL |     fn bar(self: *const Self);
+LL |     fn bar(self: *const Self) {}
    |                  ^^^^^^^^^^^
    |
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
-error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types` feature
-  --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18
+error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature
+  --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18
    |
-LL |     fn bar(self: *const Self) {}
+LL |     fn bar(self: *const Self);
    |                  ^^^^^^^^^^^
    |
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.rs b/src/test/ui/generic-associated-types/bugs/issue-80626.rs
index a637da6cf6f..14f27aff1cc 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-80626.rs
+++ b/src/test/ui/generic-associated-types/bugs/issue-80626.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: #80626
 
 // This should pass, but it requires `Sized` to be coinductive.
 
diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr
index 8b0cc78e999..487b83dfa3f 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr
+++ b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr
@@ -4,16 +4,11 @@ error[E0275]: overflow evaluating the requirement `LinkedList<A>: Sized`
 LL |     Next(A::Allocated<Self>)
    |          ^^^^^^^^^^^^^^^^^^
    |
-   = note: no field of an enum variant may have a dynamically sized type
-   = help: change the field's type to have a statically known size
-help: borrowed types always have a statically known size
+note: required by a bound in `Allocator::Allocated`
+  --> $DIR/issue-80626.rs:9:20
    |
-LL |     Next(&A::Allocated<Self>)
-   |          +
-help: the `Box` type always has a statically known size and allocates its contents in the heap
-   |
-LL |     Next(Box<A::Allocated<Self>>)
-   |          ++++                  +
+LL |     type Allocated<T>;
+   |                    ^ required by this bound in `Allocator::Allocated`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.rs b/src/test/ui/generic-associated-types/bugs/issue-86218.rs
index 68cd0fd7efc..fb62c10a9e3 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-86218.rs
+++ b/src/test/ui/generic-associated-types/bugs/issue-86218.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: #86218
 
 // This should pass, but seems to run into a TAIT issue.
 
diff --git a/src/test/ui/generic-associated-types/bugs/issue-87735.rs b/src/test/ui/generic-associated-types/bugs/issue-87735.rs
index 53e3ad7fe69..0844d84c34f 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-87735.rs
+++ b/src/test/ui/generic-associated-types/bugs/issue-87735.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: #87735, #88526
 
 // This should pass, but we need an extension of implied bounds (probably).
 
diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.rs b/src/test/ui/generic-associated-types/bugs/issue-87748.rs
index 6e7cd45bdb1..a3d00ee03b1 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-87748.rs
+++ b/src/test/ui/generic-associated-types/bugs/issue-87748.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: #87748
 
 // This should pass, but unnormalized input args aren't treated as implied.
 
diff --git a/src/test/ui/generic-associated-types/bugs/issue-87755.rs b/src/test/ui/generic-associated-types/bugs/issue-87755.rs
index 31cea12a3e2..efa487d624f 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-87755.rs
+++ b/src/test/ui/generic-associated-types/bugs/issue-87755.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: #87755
 
 // This should pass.
 
diff --git a/src/test/ui/generic-associated-types/bugs/issue-87803.rs b/src/test/ui/generic-associated-types/bugs/issue-87803.rs
index 57a4b028d93..a8a111c99ef 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-87803.rs
+++ b/src/test/ui/generic-associated-types/bugs/issue-87803.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: #87803
 
 // This should pass, but using a type alias vs a reference directly
 // changes late-bound -> early-bound.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.rs b/src/test/ui/generic-associated-types/bugs/issue-88382.rs
index c9f34240527..5493b9b9391 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-88382.rs
+++ b/src/test/ui/generic-associated-types/bugs/issue-88382.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: #88382
 
 // This should pass, but has a missed normalization due to HRTB.
 
diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.rs b/src/test/ui/generic-associated-types/bugs/issue-88460.rs
index b31d012d2fc..f1c3b226915 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-88460.rs
+++ b/src/test/ui/generic-associated-types/bugs/issue-88460.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: #88460
 
 // This should pass, but has a missed normalization due to HRTB.
 
diff --git a/src/test/ui/generic-associated-types/bugs/issue-88526.rs b/src/test/ui/generic-associated-types/bugs/issue-88526.rs
index c72a450b926..15363ad04bf 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-88526.rs
+++ b/src/test/ui/generic-associated-types/bugs/issue-88526.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: #88526
 
 // This should pass, but requires more logic.
 
diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.rs b/src/test/ui/generic-associated-types/bugs/issue-89008.rs
index 1581b7105a8..79c28b0d221 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-89008.rs
+++ b/src/test/ui/generic-associated-types/bugs/issue-89008.rs
@@ -1,6 +1,6 @@
 // check-fail
 // edition:2021
-// known-bug
+// known-bug: #88908
 
 // This should pass, but seems to run into a TAIT bug.
 
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr
index 7f45fb83cef..a6858154dfb 100644
--- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr
@@ -19,44 +19,44 @@ LL |     Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>,
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext`
 
 error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
-  --> $DIR/issue-89118.rs:22:20
+  --> $DIR/issue-89118.rs:29:9
    |
-LL |     type Handler = Ctx<C::Dispatcher>;
-   |                    ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
+LL | impl<C> EthernetWorker<C> {}
+   |         ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
    |
 note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>`
   --> $DIR/issue-89118.rs:5:23
    |
 LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {}
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^     ^
-note: required by a bound in `StackContext`
-  --> $DIR/issue-89118.rs:9:14
+note: required by a bound in `EthernetWorker`
+  --> $DIR/issue-89118.rs:28:14
    |
-LL | trait StackContext
-   |       ------------ required by a bound in this
+LL | struct EthernetWorker<C>(C)
+   |        -------------- required by a bound in this
 LL | where
-LL |     Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>,
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext`
+LL |     Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>;
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EthernetWorker`
 
 error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
-  --> $DIR/issue-89118.rs:29:9
+  --> $DIR/issue-89118.rs:22:20
    |
-LL | impl<C> EthernetWorker<C> {}
-   |         ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
+LL |     type Handler = Ctx<C::Dispatcher>;
+   |                    ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
    |
 note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>`
   --> $DIR/issue-89118.rs:5:23
    |
 LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {}
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^     ^
-note: required by a bound in `EthernetWorker`
-  --> $DIR/issue-89118.rs:28:14
+note: required by a bound in `StackContext`
+  --> $DIR/issue-89118.rs:9:14
    |
-LL | struct EthernetWorker<C>(C)
-   |        -------------- required by a bound in this
+LL | trait StackContext
+   |       ------------ required by a bound in this
 LL | where
-LL |     Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>;
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EthernetWorker`
+LL |     Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>,
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/hrtb/issue-95034.rs b/src/test/ui/hrtb/issue-95034.rs
index aee6fe61ba8..d8edbe7e56b 100644
--- a/src/test/ui/hrtb/issue-95034.rs
+++ b/src/test/ui/hrtb/issue-95034.rs
@@ -1,4 +1,4 @@
-// known-bug
+// known-bug: #95034
 // failure-status: 101
 // compile-flags: --edition=2021 --crate-type=lib
 // rustc-env:RUST_BACKTRACE=0
diff --git a/src/test/ui/impl-duplicate-methods.stderr b/src/test/ui/impl-duplicate-methods.stderr
index b6dc4882fc8..c19702a5bf0 100644
--- a/src/test/ui/impl-duplicate-methods.stderr
+++ b/src/test/ui/impl-duplicate-methods.stderr
@@ -2,9 +2,9 @@ error[E0201]: duplicate definitions with name `orange`:
   --> $DIR/impl-duplicate-methods.rs:5:5
    |
 LL |     fn orange(&self) {}
-   |     ------------------- previous definition of `orange` here
+   |     ---------------- previous definition of `orange` here
 LL |     fn orange(&self) {}
-   |     ^^^^^^^^^^^^^^^^^^^ duplicate definition
+   |     ^^^^^^^^^^^^^^^^ duplicate definition
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/auto-trait.stderr b/src/test/ui/impl-trait/auto-trait.stderr
index 3b360f492b7..5e10272b0db 100644
--- a/src/test/ui/impl-trait/auto-trait.stderr
+++ b/src/test/ui/impl-trait/auto-trait.stderr
@@ -1,3 +1,12 @@
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+  --> $DIR/auto-trait.rs:21:1
+   |
+LL | impl<T: Send> AnotherTrait for T {}
+   | -------------------------------- first implementation here
+...
+LL | impl AnotherTrait for D<OpaqueType> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
+
 error: cannot implement trait on type alias impl trait
   --> $DIR/auto-trait.rs:21:25
    |
@@ -10,15 +19,6 @@ note: type alias impl trait defined here
 LL | type OpaqueType = impl OpaqueTrait;
    |                   ^^^^^^^^^^^^^^^^
 
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
-  --> $DIR/auto-trait.rs:21:1
-   |
-LL | impl<T: Send> AnotherTrait for T {}
-   | -------------------------------- first implementation here
-...
-LL | impl AnotherTrait for D<OpaqueType> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
-
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/impl-trait/negative-reasoning.stderr b/src/test/ui/impl-trait/negative-reasoning.stderr
index 98f9fbd8fef..479b451855d 100644
--- a/src/test/ui/impl-trait/negative-reasoning.stderr
+++ b/src/test/ui/impl-trait/negative-reasoning.stderr
@@ -1,3 +1,14 @@
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+  --> $DIR/negative-reasoning.rs:19:1
+   |
+LL | impl<T: std::fmt::Debug> AnotherTrait for T {}
+   | ------------------------------------------- first implementation here
+...
+LL | impl AnotherTrait for D<OpaqueType> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
+   |
+   = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions
+
 error: cannot implement trait on type alias impl trait
   --> $DIR/negative-reasoning.rs:19:25
    |
@@ -10,17 +21,6 @@ note: type alias impl trait defined here
 LL | type OpaqueType = impl OpaqueTrait;
    |                   ^^^^^^^^^^^^^^^^
 
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
-  --> $DIR/negative-reasoning.rs:19:1
-   |
-LL | impl<T: std::fmt::Debug> AnotherTrait for T {}
-   | ------------------------------------------- first implementation here
-...
-LL | impl AnotherTrait for D<OpaqueType> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
-   |
-   = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions
-
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/impl-trait/nested-return-type2.rs b/src/test/ui/impl-trait/nested-return-type2.rs
index 39928d543e1..279641a46c3 100644
--- a/src/test/ui/impl-trait/nested-return-type2.rs
+++ b/src/test/ui/impl-trait/nested-return-type2.rs
@@ -1,5 +1,3 @@
-// check-pass
-
 trait Duh {}
 
 impl Duh for i32 {}
@@ -20,11 +18,9 @@ impl<R: Duh, F: FnMut() -> R> Trait for F {
 // the hidden type. We already have obligations registered on the inference
 // var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque
 // type does not implement `Duh`, even if its hidden type does.
-// Lazy TAIT would error out, but we inserted a hack to make it work again,
-// keeping backwards compatibility.
 fn foo() -> impl Trait<Assoc = impl Send> {
+    //~^ ERROR `impl Send: Duh` is not satisfied
     || 42
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/impl-trait/nested-return-type2.stderr b/src/test/ui/impl-trait/nested-return-type2.stderr
new file mode 100644
index 00000000000..f996e99de07
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type2.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `impl Send: Duh` is not satisfied
+  --> $DIR/nested-return-type2.rs:21:13
+   |
+LL | fn foo() -> impl Trait<Assoc = impl Send> {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Duh` is not implemented for `impl Send`
+   |
+   = help: the trait `Duh` is implemented for `i32`
+note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2.rs:23:5: 23:10]`
+  --> $DIR/nested-return-type2.rs:12:31
+   |
+LL | impl<R: Duh, F: FnMut() -> R> Trait for F {
+   |                               ^^^^^     ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-20413.rs b/src/test/ui/issues/issue-20413.rs
index a4345ccdfbe..138a235e675 100644
--- a/src/test/ui/issues/issue-20413.rs
+++ b/src/test/ui/issues/issue-20413.rs
@@ -1,5 +1,5 @@
 trait Foo {
-  fn answer(self);
+    fn answer(self);
 }
 
 struct NoData<T>;
@@ -7,18 +7,17 @@ struct NoData<T>;
 
 impl<T> Foo for T where NoData<T>: Foo {
   //~^ ERROR: overflow evaluating the requirement
-  //~| ERROR: overflow evaluating the requirement
   fn answer(self) {
     let val: NoData<T> = NoData;
   }
 }
 
 trait Bar {
-  fn answer(self);
+    fn answer(self);
 }
 
 trait Baz {
-  fn answer(self);
+    fn answer(self);
 }
 
 struct AlmostNoData<T>(Option<T>);
@@ -27,7 +26,6 @@ struct EvenLessData<T>(Option<T>);
 
 impl<T> Bar for T where EvenLessData<T>: Baz {
 //~^ ERROR: overflow evaluating the requirement
-//~| ERROR: overflow evaluating the requirement
   fn answer(self) {
     let val: EvenLessData<T> = EvenLessData(None);
   }
@@ -35,7 +33,6 @@ impl<T> Bar for T where EvenLessData<T>: Baz {
 
 impl<T> Baz for T where AlmostNoData<T>: Bar {
 //~^ ERROR: overflow evaluating the requirement
-//~| ERROR: overflow evaluating the requirement
   fn answer(self) {
     let val: NoData<T> = AlmostNoData(None);
   }
diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr
index 29352141404..ea493c58a33 100644
--- a/src/test/ui/issues/issue-20413.stderr
+++ b/src/test/ui/issues/issue-20413.stderr
@@ -22,102 +22,47 @@ LL | impl<T> Foo for T where NoData<T>: Foo {
    = note: 127 redundant requirements hidden
    = note: required because of the requirements on the impl of `Foo` for `NoData<T>`
 
-error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
-  --> $DIR/issue-20413.rs:8:36
-   |
-LL | impl<T> Foo for T where NoData<T>: Foo {
-   |                                    ^^^
-   |
-   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-20413.rs:8:9
-   |
-LL | impl<T> Foo for T where NoData<T>: Foo {
-   |         ^^^     ^
-   = note: 127 redundant requirements hidden
-   = note: required because of the requirements on the impl of `Foo` for `NoData<T>`
-
 error[E0275]: overflow evaluating the requirement `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Baz`
-  --> $DIR/issue-20413.rs:28:42
+  --> $DIR/issue-20413.rs:27:42
    |
 LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |                                          ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
 note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-20413.rs:28:9
+  --> $DIR/issue-20413.rs:27:9
    |
 LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |         ^^^     ^
 note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-20413.rs:36:9
+  --> $DIR/issue-20413.rs:34:9
    |
 LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |         ^^^     ^
    = note: 126 redundant requirements hidden
    = note: required because of the requirements on the impl of `Baz` for `EvenLessData<T>`
 
-error[E0275]: overflow evaluating the requirement `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Baz`
-  --> $DIR/issue-20413.rs:28:42
-   |
-LL | impl<T> Bar for T where EvenLessData<T>: Baz {
-   |                                          ^^^
-   |
-   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-20413.rs:28:9
-   |
-LL | impl<T> Bar for T where EvenLessData<T>: Baz {
-   |         ^^^     ^
-note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-20413.rs:36:9
-   |
-LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
-   |         ^^^     ^
-   = note: 126 redundant requirements hidden
-   = note: required because of the requirements on the impl of `Baz` for `EvenLessData<T>`
-
-error[E0275]: overflow evaluating the requirement `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Bar`
-  --> $DIR/issue-20413.rs:36:42
-   |
-LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
-   |                                          ^^^
-   |
-   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-20413.rs:36:9
-   |
-LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
-   |         ^^^     ^
-note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-20413.rs:28:9
-   |
-LL | impl<T> Bar for T where EvenLessData<T>: Baz {
-   |         ^^^     ^
-   = note: 126 redundant requirements hidden
-   = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<T>`
-
 error[E0275]: overflow evaluating the requirement `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Bar`
-  --> $DIR/issue-20413.rs:36:42
+  --> $DIR/issue-20413.rs:34:42
    |
 LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |                                          ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
 note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-20413.rs:36:9
+  --> $DIR/issue-20413.rs:34:9
    |
 LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |         ^^^     ^
 note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-20413.rs:28:9
+  --> $DIR/issue-20413.rs:27:9
    |
 LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |         ^^^     ^
    = note: 126 redundant requirements hidden
    = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<T>`
 
-error: aborting due to 7 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0275, E0392.
 For more information about an error, try `rustc --explain E0275`.
diff --git a/src/test/ui/issues/issue-4265.stderr b/src/test/ui/issues/issue-4265.stderr
index acdf963ed3b..27e83d49574 100644
--- a/src/test/ui/issues/issue-4265.stderr
+++ b/src/test/ui/issues/issue-4265.stderr
@@ -1,14 +1,11 @@
 error[E0201]: duplicate definitions with name `bar`:
   --> $DIR/issue-4265.rs:10:5
    |
-LL | /     fn bar() {
-LL | |         Foo { baz: 0 }.bar();
-LL | |     }
-   | |_____- previous definition of `bar` here
-LL |
-LL | /     fn bar() {
-LL | |     }
-   | |_____^ duplicate definition
+LL |     fn bar() {
+   |     -------- previous definition of `bar` here
+...
+LL |     fn bar() {
+   |     ^^^^^^^^ duplicate definition
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-47511.rs b/src/test/ui/issues/issue-47511.rs
index 98c141b6c6a..eb4860e75d7 100644
--- a/src/test/ui/issues/issue-47511.rs
+++ b/src/test/ui/issues/issue-47511.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: #47511
 
 // Regression test for #47511: anonymous lifetimes can appear
 // unconstrained in a return type, but only if they appear just once
diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
index 33f6c498b6f..affb4e8d044 100644
--- a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
+++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
@@ -10,6 +10,28 @@ LL | struct Foo<T: 'static> {
    |             +++++++++
 
 error[E0309]: the parameter type `K` may not live long enough
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33
+   |
+LL |     fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
+   |                                 ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL | impl<K: 'a> Nested<K> {
+   |       ++++
+
+error[E0309]: the parameter type `M` may not live long enough
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36
+   |
+LL |     fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
+   |                                    ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL |     fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b + 'a>() {
+   |                                                            ++++
+
+error[E0309]: the parameter type `K` may not live long enough
   --> $DIR/lifetime-doesnt-live-long-enough.rs:24:19
    |
 LL |     fn foo<'a, L: X<&'a Nested<K>>>();
@@ -40,28 +62,6 @@ help: consider adding an explicit lifetime bound...
 LL |     fn baz<'a, L: 'a, M: X<&'a Nested<L>>>() {
    |                 ++++
 
-error[E0309]: the parameter type `K` may not live long enough
-  --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33
-   |
-LL |     fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
-   |                                 ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
-   |
-help: consider adding an explicit lifetime bound...
-   |
-LL | impl<K: 'a> Nested<K> {
-   |       ++++
-
-error[E0309]: the parameter type `M` may not live long enough
-  --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36
-   |
-LL |     fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
-   |                                    ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
-   |
-help: consider adding an explicit lifetime bound...
-   |
-LL |     fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b + 'a>() {
-   |                                                            ++++
-
 error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0309, E0310.
diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs
index c79c1daf774..0e0d604ae04 100644
--- a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs
+++ b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs
@@ -20,43 +20,43 @@ fn main() {
 
     // AcqRel is always forbidden as a failure ordering
     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Relaxed, Ordering::AcqRel);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::AcqRel);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::AcqRel);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::AcqRel);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::SeqCst, Ordering::AcqRel);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`
 
     // Release is always forbidden as a failure ordering
     let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Release);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Release);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Release, Ordering::Release);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Release);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Release);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`
 
     // Release success order forbids failure order of Acquire or SeqCst
     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::Acquire);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be stronger
+    //~^ ERROR `compare_exchange_weak`'s success ordering must be at least as strong as
     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::SeqCst);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be stronger
+    //~^ ERROR `compare_exchange_weak`'s success ordering must be at least as strong as
 
     // Relaxed success order also forbids failure order of Acquire or SeqCst
     let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::SeqCst);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be stronger
+    //~^ ERROR `compare_exchange_weak`'s success ordering must be at least as strong as
     let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Acquire);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be stronger
+    //~^ ERROR `compare_exchange_weak`'s success ordering must be at least as strong as
 
     // Acquire/AcqRel forbids failure order of SeqCst
     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::SeqCst);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be stronger
+    //~^ ERROR `compare_exchange_weak`'s success ordering must be at least as strong as
     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::SeqCst);
-    //~^ ERROR compare_exchange_weak's failure ordering may not be stronger
+    //~^ ERROR `compare_exchange_weak`'s success ordering must be at least as strong as
 }
diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr
index 13350ab0b9c..d5e53418b6f 100644
--- a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr
+++ b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr
@@ -1,131 +1,137 @@
-error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:22:67
    |
 LL |     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Relaxed, Ordering::AcqRel);
-   |                                                                   ^^^^^^^^^^^^^^^^
+   |                                                                   ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
    = note: `#[deny(invalid_atomic_ordering)]` on by default
-   = help: consider using ordering mode `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:24:67
    |
 LL |     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::AcqRel);
-   |                                                                   ^^^^^^^^^^^^^^^^
+   |                                                                   ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:26:67
    |
 LL |     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::AcqRel);
-   |                                                                   ^^^^^^^^^^^^^^^^
+   |                                                                   ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering mode `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:28:66
    |
 LL |     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::AcqRel);
-   |                                                                  ^^^^^^^^^^^^^^^^
+   |                                                                  ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:30:66
    |
 LL |     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::SeqCst, Ordering::AcqRel);
-   |                                                                  ^^^^^^^^^^^^^^^^
+   |                                                                  ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:34:67
    |
 LL |     let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Release);
-   |                                                                   ^^^^^^^^^^^^^^^^^
+   |                                                                   ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering mode `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:36:67
    |
 LL |     let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Release);
-   |                                                                   ^^^^^^^^^^^^^^^^^
+   |                                                                   ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:38:67
    |
 LL |     let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Release, Ordering::Release);
-   |                                                                   ^^^^^^^^^^^^^^^^^
+   |                                                                   ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering mode `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:40:66
    |
 LL |     let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Release);
-   |                                                                  ^^^^^^^^^^^^^^^^^
+   |                                                                  ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:42:66
    |
 LL |     let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Release);
-   |                                                                  ^^^^^^^^^^^^^^^^^
+   |                                                                  ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange_weak's failure ordering may not be stronger than the success ordering of `Release`
-  --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:46:67
+error: `compare_exchange_weak`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:46:48
    |
 LL |     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::Acquire);
-   |                                                                   ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering mode `Relaxed` instead
+   |                                                ^^^^^^^^^^^^^^^^^  ----------------- `Acquire` failure ordering
+   |                                                |
+   |                                                `Release` success ordering
+   |                                                help: consider using `AcqRel` success ordering instead
 
-error: compare_exchange_weak's failure ordering may not be stronger than the success ordering of `Release`
-  --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:48:67
+error: `compare_exchange_weak`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:48:48
    |
 LL |     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::SeqCst);
-   |                                                                   ^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering mode `Relaxed` instead
+   |                                                ^^^^^^^^^^^^^^^^^  ---------------- `SeqCst` failure ordering
+   |                                                |
+   |                                                `Release` success ordering
+   |                                                help: consider using `SeqCst` success ordering instead
 
-error: compare_exchange_weak's failure ordering may not be stronger than the success ordering of `Relaxed`
-  --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:52:67
+error: `compare_exchange_weak`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:52:48
    |
 LL |     let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::SeqCst);
-   |                                                                   ^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering mode `Relaxed` instead
+   |                                                ^^^^^^^^^^^^^^^^^  ---------------- `SeqCst` failure ordering
+   |                                                |
+   |                                                `Relaxed` success ordering
+   |                                                help: consider using `SeqCst` success ordering instead
 
-error: compare_exchange_weak's failure ordering may not be stronger than the success ordering of `Relaxed`
-  --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:54:67
+error: `compare_exchange_weak`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:54:48
    |
 LL |     let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Acquire);
-   |                                                                   ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering mode `Relaxed` instead
+   |                                                ^^^^^^^^^^^^^^^^^  ----------------- `Acquire` failure ordering
+   |                                                |
+   |                                                `Relaxed` success ordering
+   |                                                help: consider using `Acquire` success ordering instead
 
-error: compare_exchange_weak's failure ordering may not be stronger than the success ordering of `Acquire`
-  --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:58:67
+error: `compare_exchange_weak`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:58:48
    |
 LL |     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::SeqCst);
-   |                                                                   ^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   |                                                ^^^^^^^^^^^^^^^^^  ---------------- `SeqCst` failure ordering
+   |                                                |
+   |                                                `Acquire` success ordering
+   |                                                help: consider using `SeqCst` success ordering instead
 
-error: compare_exchange_weak's failure ordering may not be stronger than the success ordering of `AcqRel`
-  --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:60:66
+error: `compare_exchange_weak`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:60:48
    |
 LL |     let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::SeqCst);
-   |                                                                  ^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   |                                                ^^^^^^^^^^^^^^^^  ---------------- `SeqCst` failure ordering
+   |                                                |
+   |                                                `AcqRel` success ordering
+   |                                                help: consider using `SeqCst` success ordering instead
 
 error: aborting due to 16 previous errors
 
diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.rs b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.rs
index 8ef3a400cf0..da98d854262 100644
--- a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.rs
+++ b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.rs
@@ -18,43 +18,43 @@ fn main() {
 
     // AcqRel is always forbidden as a failure ordering
     let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::AcqRel);
-    //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::AcqRel);
-    //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::AcqRel);
-    //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::AcqRel);
-    //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::AcqRel);
-    //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`
 
     // Release is always forbidden as a failure ordering
     let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Release);
-    //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Release);
-    //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Release);
-    //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Release);
-    //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Release);
-    //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`
 
     // Release success order forbids failure order of Acquire or SeqCst
     let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Acquire);
-    //~^ ERROR compare_exchange's failure ordering may not be stronger
+    //~^ ERROR `compare_exchange`'s success ordering must be at least as strong as
     let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::SeqCst);
-    //~^ ERROR compare_exchange's failure ordering may not be stronger
+    //~^ ERROR `compare_exchange`'s success ordering must be at least as strong as
 
     // Relaxed success order also forbids failure order of Acquire or SeqCst
     let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::SeqCst);
-    //~^ ERROR compare_exchange's failure ordering may not be stronger
+    //~^ ERROR `compare_exchange`'s success ordering must be at least as strong as
     let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Acquire);
-    //~^ ERROR compare_exchange's failure ordering may not be stronger
+    //~^ ERROR `compare_exchange`'s success ordering must be at least as strong as
 
     // Acquire/AcqRel forbids failure order of SeqCst
     let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::SeqCst);
-    //~^ ERROR compare_exchange's failure ordering may not be stronger
+    //~^ ERROR `compare_exchange`'s success ordering must be at least as strong as
     let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::SeqCst);
-    //~^ ERROR compare_exchange's failure ordering may not be stronger
+    //~^ ERROR `compare_exchange`'s success ordering must be at least as strong as
 }
diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.stderr b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.stderr
index daedfec7430..41121a20dee 100644
--- a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.stderr
+++ b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.stderr
@@ -1,131 +1,137 @@
-error: compare_exchange's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange.rs:20:57
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::AcqRel);
-   |                                                         ^^^^^^^^^^^^^^^^
+   |                                                         ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
    = note: `#[deny(invalid_atomic_ordering)]` on by default
-   = help: consider using ordering mode `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange.rs:22:57
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::AcqRel);
-   |                                                         ^^^^^^^^^^^^^^^^
+   |                                                         ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange.rs:24:57
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::AcqRel);
-   |                                                         ^^^^^^^^^^^^^^^^
+   |                                                         ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering mode `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange.rs:26:56
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::AcqRel);
-   |                                                        ^^^^^^^^^^^^^^^^
+   |                                                        ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange.rs:28:56
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::AcqRel);
-   |                                                        ^^^^^^^^^^^^^^^^
+   |                                                        ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange.rs:32:57
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Release);
-   |                                                         ^^^^^^^^^^^^^^^^^
+   |                                                         ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering mode `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange.rs:34:57
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Release);
-   |                                                         ^^^^^^^^^^^^^^^^^
+   |                                                         ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange.rs:36:57
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Release);
-   |                                                         ^^^^^^^^^^^^^^^^^
+   |                                                         ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering mode `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange.rs:38:56
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Release);
-   |                                                        ^^^^^^^^^^^^^^^^^
+   |                                                        ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange's failure ordering may not be `Release` or `AcqRel`
+error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-exchange.rs:40:56
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Release);
-   |                                                        ^^^^^^^^^^^^^^^^^
+   |                                                        ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: compare_exchange's failure ordering may not be stronger than the success ordering of `Release`
-  --> $DIR/lint-invalid-atomic-ordering-exchange.rs:44:57
+error: `compare_exchange`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-exchange.rs:44:38
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Acquire);
-   |                                                         ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering mode `Relaxed` instead
+   |                                      ^^^^^^^^^^^^^^^^^  ----------------- `Acquire` failure ordering
+   |                                      |
+   |                                      `Release` success ordering
+   |                                      help: consider using `AcqRel` success ordering instead
 
-error: compare_exchange's failure ordering may not be stronger than the success ordering of `Release`
-  --> $DIR/lint-invalid-atomic-ordering-exchange.rs:46:57
+error: `compare_exchange`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-exchange.rs:46:38
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::SeqCst);
-   |                                                         ^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering mode `Relaxed` instead
+   |                                      ^^^^^^^^^^^^^^^^^  ---------------- `SeqCst` failure ordering
+   |                                      |
+   |                                      `Release` success ordering
+   |                                      help: consider using `SeqCst` success ordering instead
 
-error: compare_exchange's failure ordering may not be stronger than the success ordering of `Relaxed`
-  --> $DIR/lint-invalid-atomic-ordering-exchange.rs:50:57
+error: `compare_exchange`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-exchange.rs:50:38
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::SeqCst);
-   |                                                         ^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering mode `Relaxed` instead
+   |                                      ^^^^^^^^^^^^^^^^^  ---------------- `SeqCst` failure ordering
+   |                                      |
+   |                                      `Relaxed` success ordering
+   |                                      help: consider using `SeqCst` success ordering instead
 
-error: compare_exchange's failure ordering may not be stronger than the success ordering of `Relaxed`
-  --> $DIR/lint-invalid-atomic-ordering-exchange.rs:52:57
+error: `compare_exchange`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-exchange.rs:52:38
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Acquire);
-   |                                                         ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering mode `Relaxed` instead
+   |                                      ^^^^^^^^^^^^^^^^^  ----------------- `Acquire` failure ordering
+   |                                      |
+   |                                      `Relaxed` success ordering
+   |                                      help: consider using `Acquire` success ordering instead
 
-error: compare_exchange's failure ordering may not be stronger than the success ordering of `Acquire`
-  --> $DIR/lint-invalid-atomic-ordering-exchange.rs:56:57
+error: `compare_exchange`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-exchange.rs:56:38
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::SeqCst);
-   |                                                         ^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   |                                      ^^^^^^^^^^^^^^^^^  ---------------- `SeqCst` failure ordering
+   |                                      |
+   |                                      `Acquire` success ordering
+   |                                      help: consider using `SeqCst` success ordering instead
 
-error: compare_exchange's failure ordering may not be stronger than the success ordering of `AcqRel`
-  --> $DIR/lint-invalid-atomic-ordering-exchange.rs:58:56
+error: `compare_exchange`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-exchange.rs:58:38
    |
 LL |     let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::SeqCst);
-   |                                                        ^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   |                                      ^^^^^^^^^^^^^^^^  ---------------- `SeqCst` failure ordering
+   |                                      |
+   |                                      `AcqRel` success ordering
+   |                                      help: consider using `SeqCst` success ordering instead
 
 error: aborting due to 16 previous errors
 
diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs b/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs
index 938ca0359f8..73eda182aa8 100644
--- a/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs
+++ b/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs
@@ -18,43 +18,43 @@ fn main() {
 
     // AcqRel is always forbidden as a failure ordering
     let _ = x.fetch_update(Ordering::Relaxed, Ordering::AcqRel, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.fetch_update(Ordering::Acquire, Ordering::AcqRel, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.fetch_update(Ordering::Release, Ordering::AcqRel, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.fetch_update(Ordering::AcqRel, Ordering::AcqRel, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.fetch_update(Ordering::SeqCst, Ordering::AcqRel, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel`
 
     // Release is always forbidden as a failure ordering
     let _ = x.fetch_update(Ordering::Relaxed, Ordering::Release, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.fetch_update(Ordering::Acquire, Ordering::Release, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.fetch_update(Ordering::Release, Ordering::Release, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.fetch_update(Ordering::AcqRel, Ordering::Release, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel`
     let _ = x.fetch_update(Ordering::SeqCst, Ordering::Release, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel`
+    //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel`
 
     // Release success order forbids failure order of Acquire or SeqCst
     let _ = x.fetch_update(Ordering::Release, Ordering::Acquire, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be stronger
+    //~^ ERROR `fetch_update`'s success ordering must be at least as strong as
     let _ = x.fetch_update(Ordering::Release, Ordering::SeqCst, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be stronger
+    //~^ ERROR `fetch_update`'s success ordering must be at least as strong as
 
     // Relaxed success order also forbids failure order of Acquire or SeqCst
     let _ = x.fetch_update(Ordering::Relaxed, Ordering::SeqCst, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be stronger
+    //~^ ERROR `fetch_update`'s success ordering must be at least as strong as
     let _ = x.fetch_update(Ordering::Relaxed, Ordering::Acquire, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be stronger
+    //~^ ERROR `fetch_update`'s success ordering must be at least as strong as
 
     // Acquire/AcqRel forbids failure order of SeqCst
     let _ = x.fetch_update(Ordering::Acquire, Ordering::SeqCst, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be stronger
+    //~^ ERROR `fetch_update`'s success ordering must be at least as strong as
     let _ = x.fetch_update(Ordering::AcqRel, Ordering::SeqCst, |old| Some(old + 1));
-    //~^ ERROR fetch_update's failure ordering may not be stronger
+    //~^ ERROR `fetch_update`'s success ordering must be at least as strong as
 }
diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr b/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr
index dabc1da7e55..7bea56d57fb 100644
--- a/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr
+++ b/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr
@@ -1,131 +1,137 @@
-error: fetch_update's failure ordering may not be `Release` or `AcqRel`
+error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:20:47
    |
 LL |     let _ = x.fetch_update(Ordering::Relaxed, Ordering::AcqRel, |old| Some(old + 1));
-   |                                               ^^^^^^^^^^^^^^^^
+   |                                               ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
    = note: `#[deny(invalid_atomic_ordering)]` on by default
-   = help: consider using ordering mode `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: fetch_update's failure ordering may not be `Release` or `AcqRel`
+error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:22:47
    |
 LL |     let _ = x.fetch_update(Ordering::Acquire, Ordering::AcqRel, |old| Some(old + 1));
-   |                                               ^^^^^^^^^^^^^^^^
+   |                                               ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: fetch_update's failure ordering may not be `Release` or `AcqRel`
+error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:24:47
    |
 LL |     let _ = x.fetch_update(Ordering::Release, Ordering::AcqRel, |old| Some(old + 1));
-   |                                               ^^^^^^^^^^^^^^^^
+   |                                               ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering mode `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: fetch_update's failure ordering may not be `Release` or `AcqRel`
+error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:26:46
    |
 LL |     let _ = x.fetch_update(Ordering::AcqRel, Ordering::AcqRel, |old| Some(old + 1));
-   |                                              ^^^^^^^^^^^^^^^^
+   |                                              ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: fetch_update's failure ordering may not be `Release` or `AcqRel`
+error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:28:46
    |
 LL |     let _ = x.fetch_update(Ordering::SeqCst, Ordering::AcqRel, |old| Some(old + 1));
-   |                                              ^^^^^^^^^^^^^^^^
+   |                                              ^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: fetch_update's failure ordering may not be `Release` or `AcqRel`
+error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:32:47
    |
 LL |     let _ = x.fetch_update(Ordering::Relaxed, Ordering::Release, |old| Some(old + 1));
-   |                                               ^^^^^^^^^^^^^^^^^
+   |                                               ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering mode `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: fetch_update's failure ordering may not be `Release` or `AcqRel`
+error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:34:47
    |
 LL |     let _ = x.fetch_update(Ordering::Acquire, Ordering::Release, |old| Some(old + 1));
-   |                                               ^^^^^^^^^^^^^^^^^
+   |                                               ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: fetch_update's failure ordering may not be `Release` or `AcqRel`
+error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:36:47
    |
 LL |     let _ = x.fetch_update(Ordering::Release, Ordering::Release, |old| Some(old + 1));
-   |                                               ^^^^^^^^^^^^^^^^^
+   |                                               ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering mode `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: fetch_update's failure ordering may not be `Release` or `AcqRel`
+error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:38:46
    |
 LL |     let _ = x.fetch_update(Ordering::AcqRel, Ordering::Release, |old| Some(old + 1));
-   |                                              ^^^^^^^^^^^^^^^^^
+   |                                              ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: fetch_update's failure ordering may not be `Release` or `AcqRel`
+error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write
   --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:40:46
    |
 LL |     let _ = x.fetch_update(Ordering::SeqCst, Ordering::Release, |old| Some(old + 1));
-   |                                              ^^^^^^^^^^^^^^^^^
+   |                                              ^^^^^^^^^^^^^^^^^ invalid failure ordering
    |
-   = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` instead
+   = help: consider using `Acquire` or `Relaxed` failure ordering instead
 
-error: fetch_update's failure ordering may not be stronger than the success ordering of `Release`
-  --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:44:47
+error: `fetch_update`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:44:28
    |
 LL |     let _ = x.fetch_update(Ordering::Release, Ordering::Acquire, |old| Some(old + 1));
-   |                                               ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering mode `Relaxed` instead
+   |                            ^^^^^^^^^^^^^^^^^  ----------------- `Acquire` failure ordering
+   |                            |
+   |                            `Release` success ordering
+   |                            help: consider using `AcqRel` success ordering instead
 
-error: fetch_update's failure ordering may not be stronger than the success ordering of `Release`
-  --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:46:47
+error: `fetch_update`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:46:28
    |
 LL |     let _ = x.fetch_update(Ordering::Release, Ordering::SeqCst, |old| Some(old + 1));
-   |                                               ^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering mode `Relaxed` instead
+   |                            ^^^^^^^^^^^^^^^^^  ---------------- `SeqCst` failure ordering
+   |                            |
+   |                            `Release` success ordering
+   |                            help: consider using `SeqCst` success ordering instead
 
-error: fetch_update's failure ordering may not be stronger than the success ordering of `Relaxed`
-  --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:50:47
+error: `fetch_update`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:50:28
    |
 LL |     let _ = x.fetch_update(Ordering::Relaxed, Ordering::SeqCst, |old| Some(old + 1));
-   |                                               ^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering mode `Relaxed` instead
+   |                            ^^^^^^^^^^^^^^^^^  ---------------- `SeqCst` failure ordering
+   |                            |
+   |                            `Relaxed` success ordering
+   |                            help: consider using `SeqCst` success ordering instead
 
-error: fetch_update's failure ordering may not be stronger than the success ordering of `Relaxed`
-  --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:52:47
+error: `fetch_update`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:52:28
    |
 LL |     let _ = x.fetch_update(Ordering::Relaxed, Ordering::Acquire, |old| Some(old + 1));
-   |                                               ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering mode `Relaxed` instead
+   |                            ^^^^^^^^^^^^^^^^^  ----------------- `Acquire` failure ordering
+   |                            |
+   |                            `Relaxed` success ordering
+   |                            help: consider using `Acquire` success ordering instead
 
-error: fetch_update's failure ordering may not be stronger than the success ordering of `Acquire`
-  --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:56:47
+error: `fetch_update`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:56:28
    |
 LL |     let _ = x.fetch_update(Ordering::Acquire, Ordering::SeqCst, |old| Some(old + 1));
-   |                                               ^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   |                            ^^^^^^^^^^^^^^^^^  ---------------- `SeqCst` failure ordering
+   |                            |
+   |                            `Acquire` success ordering
+   |                            help: consider using `SeqCst` success ordering instead
 
-error: fetch_update's failure ordering may not be stronger than the success ordering of `AcqRel`
-  --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:58:46
+error: `fetch_update`'s success ordering must be at least as strong as its failure ordering
+  --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:58:28
    |
 LL |     let _ = x.fetch_update(Ordering::AcqRel, Ordering::SeqCst, |old| Some(old + 1));
-   |                                              ^^^^^^^^^^^^^^^^
-   |
-   = help: consider using ordering modes `Acquire` or `Relaxed` instead
+   |                            ^^^^^^^^^^^^^^^^  ---------------- `SeqCst` failure ordering
+   |                            |
+   |                            `AcqRel` success ordering
+   |                            help: consider using `SeqCst` success ordering instead
 
 error: aborting due to 16 previous errors
 
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs
deleted file mode 100644
index 1db9d33c72a..00000000000
--- a/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// check-pass
-// compile-flags: -Z unpretty=expanded
-
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
-
-fn main() {
-    let elem = 1i32;
-    assert!(elem == 1);
-}
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout b/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout
deleted file mode 100644
index a590eb32232..00000000000
--- a/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout
+++ /dev/null
@@ -1,29 +0,0 @@
-#![feature(prelude_import)]
-#![no_std]
-// check-pass
-// compile-flags: -Z unpretty=expanded
-
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
-#[prelude_import]
-use ::std::prelude::rust_2015::*;
-#[macro_use]
-extern crate std;
-
-fn main() {
-    let elem = 1i32;
-    {
-        #[allow(unused_imports)]
-        use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
-        let mut __capture0 = ::core::asserting::Capture::new();
-        let __local_bind0 = &elem;
-        if !(*{
-                                (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
-                                __local_bind0
-                            } == 1) {
-                {
-                    ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem == 1\nWith captures:\n  elem = ",
-                                        "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
-                }
-            }
-    };
-}
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs
new file mode 100644
index 00000000000..5ec84b08ff8
--- /dev/null
+++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs
@@ -0,0 +1,32 @@
+// check-pass
+// compile-flags: -Z unpretty=expanded
+
+#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+
+fn arbitrary_consuming_method_for_demonstration_purposes() {
+    let elem = 1i32;
+    assert!(elem as usize);
+}
+
+fn addr_of() {
+    let elem = 1i32;
+    assert!(&elem);
+}
+
+fn binary() {
+    let elem = 1i32;
+    assert!(elem == 1);
+    assert!(elem >= 1);
+    assert!(elem > 0);
+    assert!(elem < 3);
+    assert!(elem <= 3);
+    assert!(elem != 3);
+}
+
+fn unary() {
+    let elem = &1i32;
+    assert!(*elem);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout b/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
new file mode 100644
index 00000000000..90f858f80e6
--- /dev/null
+++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
@@ -0,0 +1,147 @@
+#![feature(prelude_import)]
+#![no_std]
+// check-pass
+// compile-flags: -Z unpretty=expanded
+
+#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+
+fn arbitrary_consuming_method_for_demonstration_purposes() {
+    let elem = 1i32;
+    {
+        #[allow(unused_imports)]
+        use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+        let mut __capture0 = ::core::asserting::Capture::new();
+        let __local_bind0 = &elem;
+        if ::core::intrinsics::unlikely(!(*{
+                                    (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+                                    __local_bind0
+                                } as usize)) {
+
+
+
+
+                {
+                    ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem as usize\nWith captures:\n  elem = ",
+                                        "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+                }
+            }
+    };
+}
+fn addr_of() {
+    let elem = 1i32;
+    {
+        #[allow(unused_imports)]
+        use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+        let mut __capture0 = ::core::asserting::Capture::new();
+        let __local_bind0 = &elem;
+        if ::core::intrinsics::unlikely(!&*__local_bind0) {
+                (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+                {
+                    ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: &elem\nWith captures:\n  elem = ",
+                                        "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+                }
+            }
+    };
+}
+fn binary() {
+    let elem = 1i32;
+    {
+        #[allow(unused_imports)]
+        use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+        let mut __capture0 = ::core::asserting::Capture::new();
+        let __local_bind0 = &elem;
+        if ::core::intrinsics::unlikely(!(*__local_bind0 == 1)) {
+                (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+                {
+                    ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem == 1\nWith captures:\n  elem = ",
+                                        "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+                }
+            }
+    };
+    {
+        #[allow(unused_imports)]
+        use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+        let mut __capture0 = ::core::asserting::Capture::new();
+        let __local_bind0 = &elem;
+        if ::core::intrinsics::unlikely(!(*__local_bind0 >= 1)) {
+                (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+                {
+                    ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem >= 1\nWith captures:\n  elem = ",
+                                        "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+                }
+            }
+    };
+    {
+        #[allow(unused_imports)]
+        use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+        let mut __capture0 = ::core::asserting::Capture::new();
+        let __local_bind0 = &elem;
+        if ::core::intrinsics::unlikely(!(*__local_bind0 > 0)) {
+                (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+                {
+                    ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem > 0\nWith captures:\n  elem = ",
+                                        "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+                }
+            }
+    };
+    {
+        #[allow(unused_imports)]
+        use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+        let mut __capture0 = ::core::asserting::Capture::new();
+        let __local_bind0 = &elem;
+        if ::core::intrinsics::unlikely(!(*__local_bind0 < 3)) {
+                (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+                {
+                    ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem < 3\nWith captures:\n  elem = ",
+                                        "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+                }
+            }
+    };
+    {
+        #[allow(unused_imports)]
+        use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+        let mut __capture0 = ::core::asserting::Capture::new();
+        let __local_bind0 = &elem;
+        if ::core::intrinsics::unlikely(!(*__local_bind0 <= 3)) {
+                (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+                {
+                    ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem <= 3\nWith captures:\n  elem = ",
+                                        "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+                }
+            }
+    };
+    {
+        #[allow(unused_imports)]
+        use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+        let mut __capture0 = ::core::asserting::Capture::new();
+        let __local_bind0 = &elem;
+        if ::core::intrinsics::unlikely(!(*__local_bind0 != 3)) {
+                (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+                {
+                    ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem != 3\nWith captures:\n  elem = ",
+                                        "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+                }
+            }
+    };
+}
+fn unary() {
+    let elem = &1i32;
+    {
+        #[allow(unused_imports)]
+        use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+        let mut __capture0 = ::core::asserting::Capture::new();
+        let __local_bind0 = &elem;
+        if ::core::intrinsics::unlikely(!**__local_bind0) {
+                (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+                {
+                    ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: *elem\nWith captures:\n  elem = ",
+                                        "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+                }
+            }
+    };
+}
+fn main() {}
diff --git a/src/test/ui/methods/method-macro-backtrace.stderr b/src/test/ui/methods/method-macro-backtrace.stderr
index 7860365476a..7ae00835c96 100644
--- a/src/test/ui/methods/method-macro-backtrace.stderr
+++ b/src/test/ui/methods/method-macro-backtrace.stderr
@@ -2,9 +2,9 @@ error[E0201]: duplicate definitions with name `bar`:
   --> $DIR/method-macro-backtrace.rs:22:5
    |
 LL |     fn bar(&self) { }
-   |     ----------------- previous definition of `bar` here
+   |     ------------- previous definition of `bar` here
 LL |     fn bar(&self) { }
-   |     ^^^^^^^^^^^^^^^^^ duplicate definition
+   |     ^^^^^^^^^^^^^ duplicate definition
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr
index 40b4b42f742..b77c8c7fd5b 100644
--- a/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr
+++ b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr
@@ -1,3 +1,29 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/adt-param-with-implicit-sized-bound.rs:25:9
+   |
+LL | struct Struct5<T: ?Sized>{
+   |                - this type parameter needs to be `std::marker::Sized`
+LL |     _t: X<T>,
+   |         ^^^^ doesn't have a size known at compile-time
+   |
+note: required by a bound in `X`
+  --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10
+   |
+LL | struct X<T>(T);
+   |          ^ required by this bound in `X`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+  --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10
+   |
+LL | struct X<T>(T);
+   |          ^  - ...if indirection were used here: `Box<T>`
+   |          |
+   |          this could be changed to `T: ?Sized`...
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - struct Struct5<T: ?Sized>{
+LL + struct Struct5<T>{
+   |
+
 error[E0277]: the size for values of type `Self` cannot be known at compilation time
   --> $DIR/adt-param-with-implicit-sized-bound.rs:2:19
    |
@@ -81,32 +107,6 @@ help: consider relaxing the implicit `Sized` restriction
 LL | struct Struct4<T: ?Sized>{
    |                 ++++++++
 
-error[E0277]: the size for values of type `T` cannot be known at compilation time
-  --> $DIR/adt-param-with-implicit-sized-bound.rs:25:9
-   |
-LL | struct Struct5<T: ?Sized>{
-   |                - this type parameter needs to be `std::marker::Sized`
-LL |     _t: X<T>,
-   |         ^^^^ doesn't have a size known at compile-time
-   |
-note: required by a bound in `X`
-  --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10
-   |
-LL | struct X<T>(T);
-   |          ^ required by this bound in `X`
-help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
-  --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10
-   |
-LL | struct X<T>(T);
-   |          ^  - ...if indirection were used here: `Box<T>`
-   |          |
-   |          this could be changed to `T: ?Sized`...
-help: consider removing the `?Sized` bound to make the type parameter `Sized`
-   |
-LL - struct Struct5<T: ?Sized>{
-LL + struct Struct5<T>{
-   |
-
 error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/auxiliary/not-object-safe.rs b/src/test/ui/suggestions/auxiliary/not-object-safe.rs
new file mode 100644
index 00000000000..7c9829b823e
--- /dev/null
+++ b/src/test/ui/suggestions/auxiliary/not-object-safe.rs
@@ -0,0 +1,6 @@
+use std::sync::Arc;
+
+pub trait A {
+    fn f();
+    fn f2(self: &Arc<Self>);
+}
diff --git a/src/test/ui/suggestions/issue-98500.rs b/src/test/ui/suggestions/issue-98500.rs
new file mode 100644
index 00000000000..a2717fd9206
--- /dev/null
+++ b/src/test/ui/suggestions/issue-98500.rs
@@ -0,0 +1,14 @@
+// aux-build:not-object-safe.rs
+
+extern crate not_object_safe;
+
+pub trait B where
+    Self: not_object_safe::A,
+{
+    fn f2(&self);
+}
+
+struct S(Box<dyn B>);
+//~^ ERROR the trait `B` cannot be made into an object
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-98500.stderr b/src/test/ui/suggestions/issue-98500.stderr
new file mode 100644
index 00000000000..e7251d735e3
--- /dev/null
+++ b/src/test/ui/suggestions/issue-98500.stderr
@@ -0,0 +1,24 @@
+error[E0038]: the trait `B` cannot be made into an object
+  --> $DIR/issue-98500.rs:11:14
+   |
+LL | struct S(Box<dyn B>);
+   |              ^^^^^ `B` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/auxiliary/not-object-safe.rs:4:8
+   |
+LL |     fn f();
+   |        ^ ...because associated function `f` has no `self` parameter
+LL |     fn f2(self: &Arc<Self>);
+   |        ^^ ...because method `f2`'s `self` parameter cannot be dispatched on
+   |
+  ::: $DIR/issue-98500.rs:5:11
+   |
+LL | pub trait B where
+   |           - this trait cannot be made into an object...
+   = help: consider moving `f` to another trait
+   = help: consider moving `f2` to another trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed
index 73bb6725f5a..69487c565c9 100644
--- a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed
+++ b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed
@@ -2,7 +2,7 @@
 #![allow(unused_variables, dead_code)]
 
 trait Trait {
-    fn foo(&self) where Self: Other, Self: Sized, { }
+    fn foo(&self) where Self: Other, Self: Sized { }
     fn bar(self: &Self) {} //~ ERROR invalid `self` parameter type
 }
 
diff --git a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr
index 74237e6e6c6..c0dc71df06e 100644
--- a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr
+++ b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr
@@ -1,12 +1,3 @@
-error[E0307]: invalid `self` parameter type: ()
-  --> $DIR/object-unsafe-trait-should-use-where-sized.rs:6:18
-   |
-LL |     fn bar(self: ()) {}
-   |                  ^^
-   |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
-
 error[E0038]: the trait `Trait` cannot be made into an object
   --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:12
    |
@@ -28,13 +19,22 @@ LL |     fn foo(&self) where Self: Other, { }
    |            +++++
 help: alternatively, consider constraining `foo` so it does not apply to trait objects
    |
-LL |     fn foo() where Self: Other, Self: Sized, { }
-   |                               +++++++++++++
+LL |     fn foo() where Self: Other, Self: Sized { }
+   |                               ~~~~~~~~~~~~~
 help: consider changing method `bar`'s `self` parameter to be `&self`
    |
 LL |     fn bar(self: &Self) {}
    |                  ~~~~~
 
+error[E0307]: invalid `self` parameter type: ()
+  --> $DIR/object-unsafe-trait-should-use-where-sized.rs:6:18
+   |
+LL |     fn bar(self: ()) {}
+   |                  ^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0038, E0307.
diff --git a/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.rs b/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.rs
index 288b2098b4c..fd975aaaee4 100644
--- a/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.rs
+++ b/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.rs
@@ -1,4 +1,4 @@
-// known-bug
+// known-bug: #93008
 // build-fail
 // failure-status: 101
 // compile-flags:--crate-type=lib -Zmir-opt-level=3
diff --git a/src/test/ui/traits/alias/issue-83613.stderr b/src/test/ui/traits/alias/issue-83613.stderr
index bbc240b6aec..b9d93160192 100644
--- a/src/test/ui/traits/alias/issue-83613.stderr
+++ b/src/test/ui/traits/alias/issue-83613.stderr
@@ -1,3 +1,11 @@
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
+  --> $DIR/issue-83613.rs:10:1
+   |
+LL | impl<T: Send> AnotherTrait for T {}
+   | -------------------------------- first implementation here
+LL | impl AnotherTrait for OpaqueType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
+
 error: cannot implement trait on type alias impl trait
   --> $DIR/issue-83613.rs:10:23
    |
@@ -10,14 +18,6 @@ note: type alias impl trait defined here
 LL | type OpaqueType = impl OpaqueTrait;
    |                   ^^^^^^^^^^^^^^^^
 
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
-  --> $DIR/issue-83613.rs:10:1
-   |
-LL | impl<T: Send> AnotherTrait for T {}
-   | -------------------------------- first implementation here
-LL | impl AnotherTrait for OpaqueType {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
-
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/issue-78372.rs b/src/test/ui/traits/issue-78372.rs
index 77a8c92c81c..92f9f4b467a 100644
--- a/src/test/ui/traits/issue-78372.rs
+++ b/src/test/ui/traits/issue-78372.rs
@@ -4,7 +4,6 @@ impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} //~ ERROR cannot find type `U`
 //~^ ERROR cannot find type `MISC` in this scope
 //~| ERROR use of unstable library feature 'dispatch_from_dyn'
 //~| ERROR the trait `DispatchFromDyn` may only be implemented for a coercion between structures
-//~| ERROR type parameter `T` must be covered by another type when it appears before the first
 trait Foo: X<u32> {}
 trait X<T> {
     fn foo(self: Smaht<Self, T>);
diff --git a/src/test/ui/traits/issue-78372.stderr b/src/test/ui/traits/issue-78372.stderr
index 49a9f479368..7574c9107d9 100644
--- a/src/test/ui/traits/issue-78372.stderr
+++ b/src/test/ui/traits/issue-78372.stderr
@@ -50,22 +50,13 @@ LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
    |
    = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable
 
-error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Smaht<[type error], [type error]>`)
-  --> $DIR/issue-78372.rs:3:6
-   |
-LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
-   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Smaht<[type error], [type error]>`)
-   |
-   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
-   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
-
 error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
   --> $DIR/issue-78372.rs:3:1
    |
 LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0210, E0378, E0412, E0658.
-For more information about an error, try `rustc --explain E0210`.
+Some errors have detailed explanations: E0378, E0412, E0658.
+For more information about an error, try `rustc --explain E0378`.
diff --git a/src/test/ui/traits/issue-8153.stderr b/src/test/ui/traits/issue-8153.stderr
index 4389c3dc288..b76bbc0235f 100644
--- a/src/test/ui/traits/issue-8153.stderr
+++ b/src/test/ui/traits/issue-8153.stderr
@@ -2,9 +2,9 @@ error[E0201]: duplicate definitions with name `bar`:
   --> $DIR/issue-8153.rs:11:5
    |
 LL |     fn bar(&self) -> isize {1}
-   |     -------------------------- previous definition of `bar` here
+   |     ---------------------- previous definition of `bar` here
 LL |     fn bar(&self) -> isize {2}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
+   |     ^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs
index 179f525de52..328096d44b4 100644
--- a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs
+++ b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs
@@ -1,4 +1,4 @@
-// known-bug
+// known-bug: #96572
 // compile-flags: --edition=2021 --crate-type=lib
 // rustc-env:RUST_BACKTRACE=0
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
index 9c4e6c5496f..067ed7ea1e5 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
@@ -1,7 +1,7 @@
 // Regression test for issue #57611
 // Ensures that we don't ICE
 // FIXME: This should compile, but it currently doesn't
-// known-bug
+// known-bug: unknown
 
 #![feature(trait_alias)]
 #![feature(type_alias_impl_trait)]
diff --git a/src/test/ui/union/issue-81199.stderr b/src/test/ui/union/issue-81199.stderr
index f26bfe3a0b0..5bb98675361 100644
--- a/src/test/ui/union/issue-81199.stderr
+++ b/src/test/ui/union/issue-81199.stderr
@@ -1,28 +1,18 @@
-error[E0277]: the trait bound `T: Pointee` is not satisfied in `PtrComponents<T>`
+error[E0277]: the trait bound `T: Pointee` is not satisfied
   --> $DIR/issue-81199.rs:5:17
    |
 LL |     components: PtrComponents<T>,
-   |                 ^^^^^^^^^^^^^^^^ within `PtrComponents<T>`, the trait `Pointee` is not implemented for `T`
+   |                 ^^^^^^^^^^^^^^^^ the trait `Pointee` is not implemented for `T`
    |
-note: required because it appears within the type `PtrComponents<T>`
-  --> $DIR/issue-81199.rs:10:8
+note: required by a bound in `PtrComponents`
+  --> $DIR/issue-81199.rs:10:25
    |
 LL | struct PtrComponents<T: Pointee + ?Sized> {
-   |        ^^^^^^^^^^^^^
-   = note: no field of a union may have a dynamically sized type
-   = help: change the field's type to have a statically known size
+   |                         ^^^^^^^ required by this bound in `PtrComponents`
 help: consider further restricting this bound
    |
 LL | union PtrRepr<T: ?Sized + Pointee> {
    |                         +++++++++
-help: borrowed types always have a statically known size
-   |
-LL |     components: &PtrComponents<T>,
-   |                 +
-help: the `Box` type always has a statically known size and allocates its contents in the heap
-   |
-LL |     components: Box<PtrComponents<T>>,
-   |                 ++++                +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/issue-96810.rs b/src/test/ui/wf/issue-96810.rs
new file mode 100644
index 00000000000..c2948086b20
--- /dev/null
+++ b/src/test/ui/wf/issue-96810.rs
@@ -0,0 +1,12 @@
+struct S<T: Tr>(T::Assoc);
+
+trait Tr {
+    type Assoc;
+}
+
+struct Hoge<K> {
+    s: S<K>, //~ ERROR the trait bound `K: Tr` is not satisfied
+    a: u32,
+}
+
+fn main() {}
diff --git a/src/test/ui/wf/issue-96810.stderr b/src/test/ui/wf/issue-96810.stderr
new file mode 100644
index 00000000000..1407e62b1e1
--- /dev/null
+++ b/src/test/ui/wf/issue-96810.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `K: Tr` is not satisfied
+  --> $DIR/issue-96810.rs:8:8
+   |
+LL |     s: S<K>,
+   |        ^^^^ the trait `Tr` is not implemented for `K`
+   |
+note: required by a bound in `S`
+  --> $DIR/issue-96810.rs:1:13
+   |
+LL | struct S<T: Tr>(T::Assoc);
+   |             ^^ required by this bound in `S`
+help: consider restricting type parameter `K`
+   |
+LL | struct Hoge<K: Tr> {
+   |              ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
index f447940ea3b..8ae84dbb3dc 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg_for_edges;
+use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_trait_method;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
@@ -14,17 +14,14 @@ use super::MAP_FLATTEN;
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, map_arg: &Expr<'_>, map_span: Span) {
     if let Some((caller_ty_name, method_to_use)) = try_get_caller_ty_name_and_method_name(cx, expr, recv, map_arg) {
         let mut applicability = Applicability::MachineApplicable;
-        let help_msgs = [
-            &format!("try replacing `map` with `{}`", method_to_use),
-            "and remove the `.flatten()`",
-        ];
+        
         let closure_snippet = snippet_with_applicability(cx, map_arg.span, "..", &mut applicability);
-        span_lint_and_sugg_for_edges(
+        span_lint_and_sugg(
             cx,
             MAP_FLATTEN,
             expr.span.with_lo(map_span.lo()),
             &format!("called `map(..).flatten()` on `{}`", caller_ty_name),
-            &help_msgs,
+            &format!("try replacing `map` with `{}` and remove the `.flatten()`", method_to_use),
             format!("{}({})", method_to_use, closure_snippet),
             applicability,
         );
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
index 448dc4e6147..3d1208824fa 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
@@ -4,7 +4,6 @@ use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_mac
 use clippy_utils::ty::{implements_trait, match_type};
 use clippy_utils::{contains_return, is_trait_item, last_path_segment, paths};
 use if_chain::if_chain;
-use rustc_errors::emitter::MAX_SUGGESTION_HIGHLIGHT_LINES;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -33,7 +32,6 @@ pub(super) fn check<'tcx>(
         arg: &hir::Expr<'_>,
         or_has_args: bool,
         span: Span,
-        method_span: Span,
     ) -> bool {
         let is_default_default = || is_trait_item(cx, fun, sym::Default);
 
@@ -56,19 +54,14 @@ pub(super) fn check<'tcx>(
             then {
                 let mut applicability = Applicability::MachineApplicable;
                 let hint = "unwrap_or_default()";
-                let mut sugg_span = span;
+                let sugg_span = span;
 
-                let mut sugg: String = format!(
+                let sugg: String = format!(
                     "{}.{}",
                     snippet_with_applicability(cx, self_expr.span, "..", &mut applicability),
                     hint
                 );
 
-                if sugg.lines().count() > MAX_SUGGESTION_HIGHLIGHT_LINES {
-                    sugg_span = method_span.with_hi(span.hi());
-                    sugg = hint.to_string();
-                }
-
                 span_lint_and_sugg(
                     cx,
                     OR_FUN_CALL,
@@ -178,7 +171,7 @@ pub(super) fn check<'tcx>(
         match inner_arg.kind {
             hir::ExprKind::Call(fun, or_args) => {
                 let or_has_args = !or_args.is_empty();
-                if !check_unwrap_or_default(cx, name, fun, self_arg, arg, or_has_args, expr.span, method_span) {
+                if !check_unwrap_or_default(cx, name, fun, self_arg, arg, or_has_args, expr.span) {
                     let fun_span = if or_has_args { None } else { Some(fun.span) };
                     check_general_case(cx, name, method_span, self_arg, arg, expr.span, fun_span);
                 }
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 99e9e3275ab..2564099f4db 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -112,7 +112,6 @@ const LINT_EMISSION_FUNCTIONS: [&[&str]; 8] = [
     &["clippy_utils", "diagnostics", "span_lint_and_sugg"],
     &["clippy_utils", "diagnostics", "span_lint_and_then"],
     &["clippy_utils", "diagnostics", "span_lint_hir_and_then"],
-    &["clippy_utils", "diagnostics", "span_lint_and_sugg_for_edges"],
 ];
 const SUGGESTION_DIAGNOSTIC_BUILDER_METHODS: [(&str, bool); 9] = [
     ("span_suggestion", false),
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index 39595f589c7..7f55db3b31f 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -8,7 +8,7 @@
 //! Thank you!
 //! ~The `INTERNAL_METADATA_COLLECTOR` lint
 
-use rustc_errors::{emitter::MAX_SUGGESTION_HIGHLIGHT_LINES, Applicability, Diagnostic, MultiSpan};
+use rustc_errors::{Applicability, Diagnostic, MultiSpan};
 use rustc_hir::HirId;
 use rustc_lint::{LateContext, Lint, LintContext};
 use rustc_span::source_map::Span;
@@ -219,95 +219,6 @@ pub fn span_lint_and_sugg<'a, T: LintContext>(
     });
 }
 
-/// Like [`span_lint_and_sugg`] with a focus on the edges. The output will either
-/// emit single span or multispan suggestion depending on the number of its lines.
-///
-/// If the given suggestion string has more lines than the maximum display length defined by
-/// [`MAX_SUGGESTION_HIGHLIGHT_LINES`][`rustc_errors::emitter::MAX_SUGGESTION_HIGHLIGHT_LINES`],
-/// this function will split the suggestion and span to showcase the change for the top and
-/// bottom edge of the code. For normal suggestions, in one display window, the help message
-/// will be combined with a colon.
-///
-/// Multipart suggestions like the one being created here currently cannot be
-/// applied by rustfix (See [rustfix#141](https://github.com/rust-lang/rustfix/issues/141)).
-/// Testing rustfix with this lint emission function might require a file with
-/// suggestions that can be fixed and those that can't. See
-/// [clippy#8520](https://github.com/rust-lang/rust-clippy/pull/8520/files) for
-/// an example and of this.
-///
-/// # Example for a long suggestion
-///
-/// ```text
-/// error: called `map(..).flatten()` on `Option`
-///   --> $DIR/map_flatten.rs:8:10
-///    |
-/// LL |           .map(|x| {
-///    |  __________^
-/// LL | |             if x <= 5 {
-/// LL | |                 Some(x)
-/// LL | |             } else {
-/// ...  |
-/// LL | |         })
-/// LL | |         .flatten();
-///    | |__________________^
-///    |
-///   = note: `-D clippy::map-flatten` implied by `-D warnings`
-/// help: try replacing `map` with `and_then`
-///    |
-/// LL ~         .and_then(|x| {
-/// LL +             if x <= 5 {
-/// LL +                 Some(x)
-///    |
-/// help: and remove the `.flatten()`
-///    |
-/// LL +                 None
-/// LL +             }
-/// LL ~         });
-///    |
-/// ```
-pub fn span_lint_and_sugg_for_edges(
-    cx: &LateContext<'_>,
-    lint: &'static Lint,
-    sp: Span,
-    msg: &str,
-    helps: &[&str; 2],
-    sugg: String,
-    applicability: Applicability,
-) {
-    span_lint_and_then(cx, lint, sp, msg, |diag| {
-        let sugg_lines_count = sugg.lines().count();
-        if sugg_lines_count > MAX_SUGGESTION_HIGHLIGHT_LINES {
-            let sm = cx.sess().source_map();
-            if let (Ok(line_upper), Ok(line_bottom)) =
-                (sm.lookup_line(sp.lo()), sm.lookup_line(sp.hi()))
-            {
-                let split_idx = MAX_SUGGESTION_HIGHLIGHT_LINES / 2;
-                let span_upper = sm.span_until_char(
-                    sp.with_hi(line_upper.sf.lines(|lines| lines[line_upper.line + split_idx])),
-                    '\n',
-                );
-                let span_bottom = sp.with_lo(line_bottom.sf.lines(|lines| lines[line_bottom.line - split_idx]));
-
-                let sugg_lines_vec = sugg.lines().collect::<Vec<&str>>();
-                let sugg_upper = sugg_lines_vec[..split_idx].join("\n");
-                let sugg_bottom = sugg_lines_vec[sugg_lines_count - split_idx..].join("\n");
-
-                diag.span_suggestion(span_upper, helps[0], sugg_upper, applicability);
-                diag.span_suggestion(span_bottom, helps[1], sugg_bottom, applicability);
-
-                return;
-            }
-        }
-        diag.span_suggestion_with_style(
-            sp,
-            &helps.join(", "),
-            sugg,
-            applicability,
-            rustc_errors::SuggestionStyle::ShowAlways,
-        );
-    });
-}
-
 /// Create a suggestion made from several `span → replacement`.
 ///
 /// Note: in the JSON format (used by `compiletest_rs`), the help message will
diff --git a/src/tools/clippy/tests/ui/map_flatten.stderr b/src/tools/clippy/tests/ui/map_flatten.stderr
index c9c60df838f..4b2630d6858 100644
--- a/src/tools/clippy/tests/ui/map_flatten.stderr
+++ b/src/tools/clippy/tests/ui/map_flatten.stderr
@@ -12,14 +12,12 @@ LL | |         .flatten();
    | |__________________^
    |
    = note: `-D clippy::map-flatten` implied by `-D warnings`
-help: try replacing `map` with `and_then`
+help: try replacing `map` with `and_then` and remove the `.flatten()`
    |
 LL ~         .and_then(|x| {
 LL +             if x <= 5 {
 LL +                 Some(x)
-   |
-help: and remove the `.flatten()`
-   |
+LL +             } else {
 LL +                 None
 LL +             }
 LL ~         });
@@ -38,14 +36,12 @@ LL | |         })
 LL | |         .flatten();
    | |__________________^
    |
-help: try replacing `map` with `and_then`
+help: try replacing `map` with `and_then` and remove the `.flatten()`
    |
 LL ~         .and_then(|x| {
 LL +             if x == 1 {
 LL +                 Ok(x)
-   |
-help: and remove the `.flatten()`
-   |
+LL +             } else {
 LL +                 Err(0)
 LL +             }
 LL ~         });
@@ -64,14 +60,13 @@ LL | |         })
 LL | |         .flatten();
    | |__________________^
    |
-help: try replacing `map` with `and_then`
+help: try replacing `map` with `and_then` and remove the `.flatten()`
    |
 LL ~         .and_then(|res| {
 LL +             if res > 0 {
 LL +                 do_something();
-   |
-help: and remove the `.flatten()`
-   |
+LL +                 Ok(res)
+LL +             } else {
 LL +                 Err(0)
 LL +             }
 LL ~         });
@@ -90,14 +85,12 @@ LL | |         })
 LL | |         .flatten()
    | |__________________^
    |
-help: try replacing `map` with `filter_map`
+help: try replacing `map` with `filter_map` and remove the `.flatten()`
    |
 LL ~         .filter_map(|some_value| {
 LL +             if some_value > 3 {
 LL +                 Some(some_value)
-   |
-help: and remove the `.flatten()`
-   |
+LL +             } else {
 LL +                 None
 LL +             }
 LL +         })
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
index 928e5bd509c..e9b41354c58 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
@@ -59,8 +59,6 @@ fn issue8878() {
         .and_then(|_| {
 // we need some newlines
 // so that the span is big enough
-// we need some newlines
-// so that the span is big enough
 // for a splitted output of the diagnostic
             Some("")
  // whitespace beforehand is important as well
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
index 828e24acaad..f3b82ad08d0 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
@@ -2,79 +2,45 @@ error: called `map(..).flatten()` on `Iterator`
   --> $DIR/map_flatten_fixable.rs:18:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect();
-   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id)`
    |
    = note: `-D clippy::map-flatten` implied by `-D warnings`
-help: try replacing `map` with `filter_map`, and remove the `.flatten()`
-   |
-LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id).collect();
-   |                                               ~~~~~~~~~~~~~~~~~~~~~
 
 error: called `map(..).flatten()` on `Iterator`
   --> $DIR/map_flatten_fixable.rs:19:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect();
-   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: try replacing `map` with `filter_map`, and remove the `.flatten()`
-   |
-LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id_ref).collect();
-   |                                               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_ref)`
 
 error: called `map(..).flatten()` on `Iterator`
   --> $DIR/map_flatten_fixable.rs:20:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect();
-   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: try replacing `map` with `filter_map`, and remove the `.flatten()`
-   |
-LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id_closure).collect();
-   |                                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_closure)`
 
 error: called `map(..).flatten()` on `Iterator`
   --> $DIR/map_flatten_fixable.rs:21:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect();
-   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: try replacing `map` with `filter_map`, and remove the `.flatten()`
-   |
-LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(|x| x.checked_add(1)).collect();
-   |                                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|x| x.checked_add(1))`
 
 error: called `map(..).flatten()` on `Iterator`
   --> $DIR/map_flatten_fixable.rs:24:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
-   |                                               ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: try replacing `map` with `flat_map`, and remove the `.flatten()`
-   |
-LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().flat_map(|x| 0..x).collect();
-   |                                               ~~~~~~~~~~~~~~~~~~
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|x| 0..x)`
 
 error: called `map(..).flatten()` on `Option`
   --> $DIR/map_flatten_fixable.rs:27:40
    |
 LL |     let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
-   |                                        ^^^^^^^^^^^^^^^^^^^^
-   |
-help: try replacing `map` with `and_then`, and remove the `.flatten()`
-   |
-LL |     let _: Option<_> = (Some(Some(1))).and_then(|x| x);
-   |                                        ~~~~~~~~~~~~~~~
+   |                                        ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
 
 error: called `map(..).flatten()` on `Result`
   --> $DIR/map_flatten_fixable.rs:30:42
    |
 LL |     let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten();
-   |                                          ^^^^^^^^^^^^^^^^^^^^
-   |
-help: try replacing `map` with `and_then`, and remove the `.flatten()`
-   |
-LL |     let _: Result<_, &str> = (Ok(Ok(1))).and_then(|x| x);
-   |                                          ~~~~~~~~~~~~~~~
+   |                                          ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
 
 error: called `map(..).flatten()` on `Option`
   --> $DIR/map_flatten_fixable.rs:59:10
@@ -89,14 +55,12 @@ LL | |         })
 LL | |         .flatten();
    | |__________________^
    |
-help: try replacing `map` with `and_then`
+help: try replacing `map` with `and_then` and remove the `.flatten()`
    |
 LL ~         .and_then(|_| {
 LL + // we need some newlines
 LL + // so that the span is big enough
-   |
-help: and remove the `.flatten()`
-   |
+LL + // for a splitted output of the diagnostic
 LL +             Some("")
 LL +  // whitespace beforehand is important as well
 LL ~         });
diff --git a/src/tools/clippy/tests/ui/or_fun_call.fixed b/src/tools/clippy/tests/ui/or_fun_call.fixed
index 3208048e0d5..123aed40251 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.fixed
+++ b/src/tools/clippy/tests/ui/or_fun_call.fixed
@@ -185,8 +185,7 @@ mod issue8239 {
             .reduce(|mut acc, f| {
                 acc.push_str(&f);
                 acc
-            })
-            .unwrap_or_default();
+            }).unwrap_or_default();
     }
 
     fn more_to_max_suggestion_highest_lines_1() {
@@ -198,8 +197,7 @@ mod issue8239 {
                 let _ = "";
                 acc.push_str(&f);
                 acc
-            })
-            .unwrap_or_default();
+            }).unwrap_or_default();
     }
 
     fn equal_to_max_suggestion_highest_lines() {
diff --git a/src/tools/clippy/tests/ui/or_fun_call.stderr b/src/tools/clippy/tests/ui/or_fun_call.stderr
index 549b00ae3c4..dfe15654bc3 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.stderr
+++ b/src/tools/clippy/tests/ui/or_fun_call.stderr
@@ -109,16 +109,50 @@ LL |         None.unwrap_or( unsafe { ptr_to_ref(s) }    );
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })`
 
 error: use of `unwrap_or` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:189:14
+  --> $DIR/or_fun_call.rs:182:9
+   |
+LL | /         frames
+LL | |             .iter()
+LL | |             .map(|f: &String| f.to_lowercase())
+LL | |             .reduce(|mut acc, f| {
+...  |
+LL | |             })
+LL | |             .unwrap_or(String::new());
+   | |_____________________________________^
+   |
+help: try this
+   |
+LL ~         frames
+LL +             .iter()
+LL +             .map(|f: &String| f.to_lowercase())
+LL +             .reduce(|mut acc, f| {
+LL +                 acc.push_str(&f);
+LL +                 acc
+LL ~             }).unwrap_or_default();
    |
-LL |             .unwrap_or(String::new());
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:202:14
+  --> $DIR/or_fun_call.rs:195:9
+   |
+LL | /         iter.map(|f: &String| f.to_lowercase())
+LL | |             .reduce(|mut acc, f| {
+LL | |                 let _ = "";
+LL | |                 let _ = "";
+...  |
+LL | |             })
+LL | |             .unwrap_or(String::new());
+   | |_____________________________________^
+   |
+help: try this
+   |
+LL ~         iter.map(|f: &String| f.to_lowercase())
+LL +             .reduce(|mut acc, f| {
+LL +                 let _ = "";
+LL +                 let _ = "";
+LL +                 acc.push_str(&f);
+LL +                 acc
+LL ~             }).unwrap_or_default();
    |
-LL |             .unwrap_or(String::new());
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a call to `new`
   --> $DIR/or_fun_call.rs:208:9
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 5352f7c6fe0..31e979a574b 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -395,7 +395,29 @@ impl TestProps {
                 );
                 config.set_name_directive(ln, STDERR_PER_BITWIDTH, &mut self.stderr_per_bitwidth);
                 config.set_name_directive(ln, INCREMENTAL, &mut self.incremental);
-                config.set_name_directive(ln, KNOWN_BUG, &mut self.known_bug);
+
+                // Unlike the other `name_value_directive`s this needs to be handled manually,
+                // because it sets a `bool` flag.
+                if let Some(known_bug) = config.parse_name_value_directive(ln, KNOWN_BUG) {
+                    let known_bug = known_bug.trim();
+                    if known_bug == "unknown"
+                        || known_bug.split(',').all(|issue_ref| {
+                            issue_ref
+                                .trim()
+                                .split_once('#')
+                                .filter(|(_, number)| {
+                                    number.chars().all(|digit| digit.is_numeric())
+                                })
+                                .is_some()
+                        })
+                    {
+                        self.known_bug = true;
+                    } else {
+                        panic!(
+                            "Invalid known-bug value: {known_bug}\nIt requires comma-separated issue references (`#000` or `chalk#000`) or `unknown`."
+                        );
+                    }
+                }
                 config.set_name_value_directive(ln, MIR_UNIT_TEST, &mut self.mir_unit_test, |s| {
                     s.trim().to_string()
                 });
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 04a1d257bc0..fe5195738c1 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -30,7 +30,7 @@ except ImportError:
 # These should be collaborators of the rust-lang/rust repository (with at least
 # read privileges on it). CI will fail otherwise.
 MAINTAINERS = {
-    'miri': {'oli-obk', 'RalfJung', 'eddyb'},
+    'miri': {'oli-obk', 'RalfJung'},
     'rls': {'Xanewok'},
     'rustfmt': {'topecongiro', 'calebcartwright'},
     'book': {'carols10cents', 'steveklabnik'},
diff --git a/triagebot.toml b/triagebot.toml
index cef78cc3b33..8aefb1f620b 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -215,3 +215,108 @@ changelog-path = "RELEASES.md"
 changelog-branch = "master"
 
 [shortcut]
+
+
+[mentions."compiler/rustc_apfloat"]
+message = """
+Changes rustc_apfloat. rustc_apfloat is currently in limbo and you almost
+certainly don't want to change it (see #55993).
+"""
+cc = ["@eddyb"]
+
+[mentions."compiler/rustc_codegen_cranelift"]
+cc = ["@bjorn3"]
+
+[mentions."compiler/rustc_codegen_gcc"]
+cc = ["@antoyo"]
+
+[mentions."compiler/rustc_const_eval/src/interpret"]
+message = "Some changes occurred to the CTFE / Miri engine"
+cc = ["@rust-lang/miri"]
+
+[mentions."compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs"]
+message = "Some changes occurred in need_type_info.rs"
+cc = ["@lcnr"]
+
+[mentions."compiler/rustc_middle/src/mir/interpret"]
+message = "Some changes occurred to the CTFE / Miri engine"
+cc = ["@rust-lang/miri"]
+
+[mentions."compiler/rustc_mir_transform/src/"]
+message = "Some changes occurred to MIR optimizations"
+cc = ["@rust-lang/mir-opt"]
+
+[mentions."compiler/rustc_trait_selection/src/traits/const_evaluatable.rs"]
+message = "Some changes occurred in const_evaluatable.rs"
+cc = ["@lcnr"]
+
+[mentions."compiler/rustc_error_codes/src/error_codes.rs"]
+message = "Some changes occurred in diagnostic error codes"
+cc = ["@GuillaumeGomez"]
+
+[mentions."library"]
+message = """
+Hey! It looks like you've submitted a new PR for the library teams!
+
+If this PR contains changes to any `rust-lang/rust` public library APIs then
+please comment with `@rustbot label +T-libs-api -T-libs` to tag it
+appropriately. If this PR contains changes to any unstable APIs please edit
+the PR description to add a link to the relevant [API Change
+Proposal](https://std-dev-guide.rust-lang.org/feature-lifecycle/api-change-proposals.html)
+or [create one](https://github.com/rust-lang/libs-team/issues/new?assignees=&labels=api-change-proposal%2C+T-libs-api&template=api-change-proposal.md&title=%28My+API+Change+Proposal%29)
+if you haven't already. If you're unsure where your change falls no worries,
+just leave it as is and the reviewer will take a look and make a decision to
+forward on if necessary.
+
+Examples of `T-libs-api` changes:
+
+* Stabilizing library features
+* Introducing insta-stable changes such as new implementations of existing
+  stable traits on existing stable types
+* Introducing new or changing existing unstable library APIs (excluding
+  permanently unstable features / features without a tracking issue)
+* Changing public documentation in ways that create new stability guarantees
+* Changing observable runtime behavior of library APIs
+"""
+
+[mentions."src/librustdoc/clean/types.rs"]
+cc = ["@camelid"]
+
+[mentions."src/librustdoc/html/static"]
+message = "Some changes occurred in HTML/CSS/JS."
+cc = [
+    "@GuillaumeGomez",
+    "@Folyd",
+    "@jsha",
+]
+
+[mentions."src/librustdoc/html/static/css/themes"]
+message = "Some changes occurred in HTML/CSS themes."
+cc = ["@GuillaumeGomez"]
+
+[mentions."src/librustdoc/html/static/css/themes/ayu.css"]
+message = "A change occurred in the Ayu theme."
+cc = ["@Cldfire"]
+
+[mentions."src/rustdoc-json-types"]
+message = """
+rustdoc-json-types is a **public** (although nightly-only) API.
+If possible, consider changing `src/librustdoc/json/conversions.rs`;
+otherwise, make sure you bump the `FORMAT_VERSION` constant.
+"""
+cc = [
+    "@CraftSpider",
+    "@aDotInTheVoid",
+]
+
+[mentions."src/tools/cargo"]
+cc = ["@ehuss"]
+
+[mentions."src/tools/clippy"]
+cc = ["@rust-lang/clippy"]
+
+[mentions."src/tools/miri"]
+cc = ["@rust-lang/miri"]
+
+[mentions."src/tools/rustfmt"]
+cc = ["@rust-lang/rustfmt"]