about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock4
-rw-r--r--compiler/rustc_borrowck/src/borrowck_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/derive.rs14
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs111
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml32
-rw-r--r--compiler/rustc_codegen_gcc/.gitignore2
-rw-r--r--compiler/rustc_codegen_gcc/Cargo.lock4
-rw-r--r--compiler/rustc_codegen_gcc/Readme.md17
-rw-r--r--compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml1
-rwxr-xr-xcompiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh8
-rw-r--r--compiler/rustc_codegen_gcc/example/mini_core.rs20
-rw-r--r--compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs3
-rw-r--r--compiler/rustc_codegen_gcc/example/std_example.rs1
-rw-r--r--compiler/rustc_codegen_gcc/failing-ui-tests.txt6
-rw-r--r--compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch49
-rw-r--r--compiler/rustc_codegen_gcc/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs1
-rw-r--r--compiler/rustc_codegen_gcc/src/attributes.rs39
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs72
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs5
-rw-r--r--compiler/rustc_codegen_gcc/src/declare.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/archs.rs46
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs7
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs159
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs18
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs6
-rwxr-xr-xcompiler/rustc_codegen_gcc/test.sh8
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs212
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs12
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs5
-rw-r--r--compiler/rustc_hir/src/hir.rs23
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/bounds.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs34
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/mod.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs16
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs19
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs3
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs1
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs13
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs2
-rw-r--r--compiler/rustc_infer/src/traits/util.rs24
-rw-r--r--compiler/rustc_interface/src/interface.rs6
-rw-r--r--compiler/rustc_interface/src/queries.rs6
-rw-r--r--compiler/rustc_lint/src/builtin.rs8
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs4
-rw-r--r--compiler/rustc_lint/src/unused.rs5
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs3
-rw-r--r--compiler/rustc_macros/src/diagnostics/error.rs10
-rw-r--r--compiler/rustc_macros/src/diagnostics/subdiagnostic.rs2
-rw-r--r--compiler/rustc_macros/src/diagnostics/utils.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs10
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs20
-rw-r--r--compiler/rustc_middle/src/query/mod.rs6
-rw-r--r--compiler/rustc_middle/src/query/on_disk_cache.rs2
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs17
-rw-r--r--compiler/rustc_middle/src/ty/context.rs35
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs8
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs36
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs1
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs6
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs14
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs2
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs137
-rw-r--r--compiler/rustc_privacy/src/lib.rs68
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs92
-rw-r--r--compiler/rustc_resolve/src/ident.rs13
-rw-r--r--compiler/rustc_resolve/src/imports.rs32
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs1
-rw-r--r--compiler/rustc_resolve/src/lib.rs3
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--compiler/rustc_session/src/session.rs10
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_tvos.rs4
-rw-r--r--compiler/rustc_target/src/spec/apple/tests.rs5
-rw-r--r--compiler/rustc_target/src/spec/apple_base.rs18
-rw-r--r--compiler/rustc_target/src/spec/mod.rs8
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_tvos.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_linux_android.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_solaris.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_sun_solaris.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs1
-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.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_none.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_redox.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs10
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs17
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs28
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs44
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs41
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs11
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs6
-rw-r--r--compiler/rustc_traits/src/evaluate_obligation.rs9
-rw-r--r--compiler/rustc_traits/src/type_op.rs14
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs2
-rw-r--r--compiler/rustc_ty_utils/src/errors.rs2
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs35
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs188
-rw-r--r--library/core/src/ffi/mod.rs23
-rw-r--r--library/core/src/slice/raw.rs24
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/build.rs2
-rw-r--r--library/std/src/fs/tests.rs28
-rw-r--r--library/std/src/os/ios/fs.rs2
-rw-r--r--library/std/src/os/mod.rs3
-rw-r--r--library/std/src/os/unix/mod.rs3
-rw-r--r--library/std/src/os/unix/net/stream.rs3
-rw-r--r--library/std/src/os/unix/ucred.rs4
-rw-r--r--library/std/src/os/unix/ucred/tests.rs9
-rw-r--r--library/std/src/personality/gcc.rs2
-rw-r--r--library/std/src/sync/mpsc/mod.rs4
-rw-r--r--library/std/src/sys/unix/args.rs4
-rw-r--r--library/std/src/sys/unix/env.rs11
-rw-r--r--library/std/src/sys/unix/fd.rs6
-rw-r--r--library/std/src/sys/unix/fs.rs38
-rw-r--r--library/std/src/sys/unix/locks/pthread_condvar.rs3
-rw-r--r--library/std/src/sys/unix/mod.rs3
-rw-r--r--library/std/src/sys/unix/os.rs12
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs51
-rw-r--r--library/std/src/sys/unix/rand.rs3
-rw-r--r--library/std/src/sys/unix/thread.rs11
-rw-r--r--library/std/src/sys/unix/thread_parking/pthread.rs3
-rw-r--r--library/std/src/sys/unix/time.rs6
-rw-r--r--library/std/src/sys/unix/weak.rs4
-rw-r--r--library/std/src/sys_common/net.rs2
-rw-r--r--library/std/src/thread/tests.rs1
-rw-r--r--library/unwind/src/libunwind.rs2
-rw-r--r--src/bootstrap/download.rs22
-rw-r--r--src/bootstrap/lib.rs14
-rw-r--r--src/bootstrap/run.rs11
-rw-r--r--src/bootstrap/test.rs38
-rw-r--r--src/bootstrap/tool.rs2
-rw-r--r--src/bootstrap/util.rs2
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/platform-support.md4
-rw-r--r--src/doc/rustc/src/platform-support/apple-tvos.md85
-rw-r--r--src/doc/style-guide/src/README.md63
-rw-r--r--src/doc/style-guide/src/SUMMARY.md8
-rw-r--r--src/doc/style-guide/src/advice.md6
-rw-r--r--src/doc/style-guide/src/cargo.md21
-rw-r--r--src/doc/style-guide/src/expressions.md2
-rw-r--r--src/doc/style-guide/src/items.md30
-rw-r--r--src/doc/style-guide/src/principles.md32
-rw-r--r--src/doc/style-guide/src/statements.md12
-rwxr-xr-xsrc/etc/htmldocck.py54
-rw-r--r--src/librustdoc/clean/mod.rs21
-rw-r--r--src/librustdoc/clean/utils.rs3
-rw-r--r--src/librustdoc/html/format.rs17
-rw-r--r--src/librustdoc/html/layout.rs2
-rw-r--r--src/librustdoc/html/render/mod.rs7
-rw-r--r--src/librustdoc/html/static/js/main.js8
-rw-r--r--src/librustdoc/html/templates/page.html1
-rw-r--r--src/tools/build_helper/src/util.rs20
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs14
-rw-r--r--src/tools/rustdoc-gui-test/src/main.rs9
-rw-r--r--tests/codegen/naked-nocoverage.rs2
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs14
-rw-r--r--tests/codegen/stack-protector.rs36
-rw-r--r--tests/run-make/target-specs/Makefile1
-rw-r--r--tests/run-make/target-specs/endianness-mismatch.json11
-rw-r--r--tests/rustdoc-gui/help-page.goml4
-rw-r--r--tests/rustdoc-gui/search-result-color.goml5
-rw-r--r--tests/rustdoc-gui/settings.goml60
-rw-r--r--tests/rustdoc/files-creation-hidden.rs1
-rw-r--r--tests/rustdoc/files-creation-private.rs4
-rw-r--r--tests/rustdoc/generic-associated-types/gats.rs4
-rw-r--r--tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs6
-rw-r--r--tests/rustdoc/issue-111249-file-creation.rs6
-rw-r--r--tests/rustdoc/where.SWhere_Echo_impl.html2
-rw-r--r--tests/rustdoc/where.SWhere_Simd_item-decl.html2
-rw-r--r--tests/rustdoc/where.alpha_trait_decl.html3
-rw-r--r--tests/rustdoc/where.bravo_trait_decl.html5
-rw-r--r--tests/rustdoc/where.charlie_fn_decl.html2
-rw-r--r--tests/rustdoc/where.golf_type_alias_decl.html2
-rw-r--r--tests/rustdoc/where.rs5
-rw-r--r--tests/ui/asm/aarch64/may_unwind.rs1
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.current.stderr (renamed from tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr)12
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.next.stderr48
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs2
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/basic.current_with.stderr11
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/basic.current_without.stderr29
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/basic.next_with.stderr11
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/basic.next_without.stderr29
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/basic.rs14
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/equality.current.stderr (renamed from tests/ui/associated-type-bounds/return-type-notation/equality.stderr)4
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/equality.next.stderr17
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/equality.rs2
-rw-r--r--tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr31
-rw-r--r--tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr31
-rw-r--r--tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr16
-rw-r--r--tests/ui/async-await/issue-70935-complex-spans.rs17
-rw-r--r--tests/ui/async-await/return-type-notation/issue-110963-early.current.stderr (renamed from tests/ui/async-await/return-type-notation/issue-110963-early.stderr)10
-rw-r--r--tests/ui/async-await/return-type-notation/issue-110963-early.next.stderr37
-rw-r--r--tests/ui/async-await/return-type-notation/issue-110963-early.rs2
-rw-r--r--tests/ui/async-await/return-type-notation/issue-110963-late.current.stderr (renamed from tests/ui/async-await/return-type-notation/issue-110963-late.stderr)2
-rw-r--r--tests/ui/async-await/return-type-notation/issue-110963-late.next.stderr11
-rw-r--r--tests/ui/async-await/return-type-notation/issue-110963-late.rs2
-rw-r--r--tests/ui/async-await/return-type-notation/super-method-bound.current.stderr (renamed from tests/ui/async-await/return-type-notation/super-method-bound.stderr)2
-rw-r--r--tests/ui/async-await/return-type-notation/super-method-bound.next.stderr11
-rw-r--r--tests/ui/async-await/return-type-notation/super-method-bound.rs2
-rw-r--r--tests/ui/async-await/return-type-notation/supertrait-bound.current.stderr (renamed from tests/ui/async-await/return-type-notation/supertrait-bound.stderr)2
-rw-r--r--tests/ui/async-await/return-type-notation/supertrait-bound.next.stderr11
-rw-r--r--tests/ui/async-await/return-type-notation/supertrait-bound.rs2
-rw-r--r--tests/ui/async-await/return-type-notation/ty-or-ct-params.current.stderr (renamed from tests/ui/async-await/return-type-notation/ty-or-ct-params.stderr)6
-rw-r--r--tests/ui/async-await/return-type-notation/ty-or-ct-params.next.stderr29
-rw-r--r--tests/ui/async-await/return-type-notation/ty-or-ct-params.rs2
-rw-r--r--tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.rs40
-rw-r--r--tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr17
-rw-r--r--tests/ui/cfg/diagnostics-reexport.rs24
-rw-r--r--tests/ui/cfg/diagnostics-reexport.stderr38
-rw-r--r--tests/ui/closures/cannot-call-unsized-via-ptr-2.rs11
-rw-r--r--tests/ui/closures/cannot-call-unsized-via-ptr-2.stderr21
-rw-r--r--tests/ui/closures/cannot-call-unsized-via-ptr.rs10
-rw-r--r--tests/ui/closures/cannot-call-unsized-via-ptr.stderr12
-rw-r--r--tests/ui/closures/closure-move-sync.rs6
-rw-r--r--tests/ui/closures/closure-move-sync.stderr20
-rw-r--r--tests/ui/const-generics/issue-112505-overflow.stderr4
-rw-r--r--tests/ui/const-generics/transmute-fail.stderr4
-rw-r--r--tests/ui/consts/timeout.rs25
-rw-r--r--tests/ui/consts/timeout.stderr15
-rw-r--r--tests/ui/error-codes/E0283.stderr4
-rw-r--r--tests/ui/error-codes/E0790.stderr4
-rw-r--r--tests/ui/extern/extern-crate-visibility.stderr8
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr27
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr27
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.no_current.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.no_next.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.rs24
-rw-r--r--tests/ui/for/issue-20605.next.stderr2
-rw-r--r--tests/ui/for/issue-20605.rs2
-rw-r--r--tests/ui/generic-associated-types/issue-88595.rs1
-rw-r--r--tests/ui/generic-associated-types/issue-88595.stderr26
-rw-r--r--tests/ui/impl-trait/in-assoc-type-unconstrained.stderr4
-rw-r--r--tests/ui/impl-trait/in-assoc-type.stderr4
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr9
-rw-r--r--tests/ui/issues/issue-11680.stderr8
-rw-r--r--tests/ui/issues/issue-5883.rs2
-rw-r--r--tests/ui/issues/issue-5883.stderr18
-rw-r--r--tests/ui/layout/cannot-transmute-unnormalizable-type.rs22
-rw-r--r--tests/ui/layout/cannot-transmute-unnormalizable-type.stderr19
-rw-r--r--tests/ui/macros/issue-88228.stderr4
-rw-r--r--tests/ui/nll/ty-outlives/impl-trait-captures.stderr4
-rw-r--r--tests/ui/privacy/export-tag-variant.stderr4
-rw-r--r--tests/ui/privacy/privacy-in-paths.stderr12
-rw-r--r--tests/ui/privacy/privacy-ufcs.stderr4
-rw-r--r--tests/ui/privacy/privacy1.stderr28
-rw-r--r--tests/ui/privacy/sealed-traits/private-trait-non-local.rs4
-rw-r--r--tests/ui/privacy/sealed-traits/private-trait-non-local.stderr12
-rw-r--r--tests/ui/privacy/sealed-traits/private-trait.rs10
-rw-r--r--tests/ui/privacy/sealed-traits/private-trait.stderr17
-rw-r--r--tests/ui/privacy/sealed-traits/re-exported-trait.fixed13
-rw-r--r--tests/ui/privacy/sealed-traits/re-exported-trait.rs13
-rw-r--r--tests/ui/privacy/sealed-traits/re-exported-trait.stderr19
-rw-r--r--tests/ui/privacy/sealed-traits/sealed-trait-local.rs19
-rw-r--r--tests/ui/privacy/sealed-traits/sealed-trait-local.stderr16
-rw-r--r--tests/ui/proc-macro/derive-helper-shadowing.stderr4
-rw-r--r--tests/ui/reachable/unreachable-variant.stderr2
-rw-r--r--tests/ui/resolve/privacy-enum-ctor.stderr8
-rw-r--r--tests/ui/stability-attribute/stability-in-private-module.stderr4
-rw-r--r--tests/ui/stdlib-unit-tests/not-sync.rs2
-rw-r--r--tests/ui/stdlib-unit-tests/not-sync.stderr15
-rw-r--r--tests/ui/structs/struct-variant-privacy-xc.stderr4
-rw-r--r--tests/ui/structs/struct-variant-privacy.stderr4
-rw-r--r--tests/ui/test-attrs/test-panic-abort-disabled.rs1
-rw-r--r--tests/ui/test-attrs/test-type.rs3
-rw-r--r--tests/ui/traits/new-solver/alias-bound-unsound.rs2
-rw-r--r--tests/ui/traits/new-solver/alias-bound-unsound.stderr14
-rw-r--r--tests/ui/traits/new-solver/member-constraints-in-root-universe.rs17
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs28
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr20
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_behind_struct_field.rs30
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs26
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params3.rs35
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.rs28
-rw-r--r--tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr20
-rw-r--r--tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/multi-error.rs23
-rw-r--r--tests/ui/type-alias-impl-trait/multi-error.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/non-defining-method.rs21
-rw-r--r--tests/ui/type-alias-impl-trait/non-defining-method.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr55
-rw-r--r--tests/ui/type-alias-impl-trait/normalize-hidden-types.rs60
-rw-r--r--tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.rs33
-rw-r--r--tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr22
-rw-r--r--tests/ui/type-alias-impl-trait/unnameable_type.stderr5
-rw-r--r--tests/ui/use/use-keyword.rs2
-rw-r--r--tests/ui/xcrate/xcrate-private-by-default.stderr20
327 files changed, 3322 insertions, 1427 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3d0f9e8844e..28db4063996 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -697,9 +697,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.92"
+version = "0.1.93"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64518f1ae689f74db058bbfb3238dfe6eb53f59f4ae712f1ff4348628522e190"
+checksum = "76630810d973ecea3dbf611e1b7aecfb1012751ef1ff8de3998f89014a166781"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index acca1a1477f..a4e0e773a81 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -278,7 +278,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         move_from_span: Span,
         move_from_desc: &str,
     ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
-        struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc,)
+        struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc)
     }
 
     /// Signal an error due to an attempt to move out of the interior
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 7119510849a..5c365e98f0b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -705,7 +705,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx
                 .explicit_item_bounds(def_id)
                 .subst_iter_copied(tcx, substs)
-                .find_map(find_fn_kind_from_did),
+                .find_map(|(clause, span)| find_fn_kind_from_did((clause.as_predicate(), span))),
             ty::Closure(_, substs) => match substs.as_closure().kind() {
                 ty::ClosureKind::Fn => Some(hir::Mutability::Not),
                 ty::ClosureKind::FnMut => Some(hir::Mutability::Mut),
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 0a897272d35..e164e98539b 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -50,7 +50,6 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::MoveData;
 use rustc_mir_dataflow::ResultsCursor;
 
-use crate::renumber::RegionCtxt;
 use crate::session_diagnostics::MoveUnsized;
 use crate::{
     borrow_set::BorrowSet,
@@ -1040,9 +1039,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             .collect();
 
         let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| {
-            self.infcx.next_nll_region_var(
+            self.infcx.next_nll_region_var_in_universe(
                 NllRegionVariableOrigin::Existential { from_forall: false },
-                || RegionCtxt::Unknown,
+                ty::UniverseIndex::ROOT,
             )
         });
 
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index fe4483104ee..140853db695 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -8,7 +8,7 @@ use rustc_feature::AttributeTemplate;
 use rustc_parse::validate_attr;
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Ident};
-use rustc_span::Span;
+use rustc_span::{ErrorGuaranteed, Span};
 
 pub(crate) struct Expander(pub bool);
 
@@ -22,7 +22,7 @@ impl MultiItemModifier for Expander {
         _: bool,
     ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
         let sess = ecx.sess;
-        if report_bad_target(sess, &item, span) {
+        if report_bad_target(sess, &item, span).is_err() {
             // We don't want to pass inappropriate targets to derive macros to avoid
             // follow up errors, all other errors below are recoverable.
             return ExpandResult::Ready(vec![item]);
@@ -103,7 +103,11 @@ fn dummy_annotatable() -> Annotatable {
     })
 }
 
-fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
+fn report_bad_target(
+    sess: &Session,
+    item: &Annotatable,
+    span: Span,
+) -> Result<(), ErrorGuaranteed> {
     let item_kind = match item {
         Annotatable::Item(item) => Some(&item.kind),
         Annotatable::Stmt(stmt) => match &stmt.kind {
@@ -116,9 +120,9 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
     let bad_target =
         !matches!(item_kind, Some(ItemKind::Struct(..) | ItemKind::Enum(..) | ItemKind::Union(..)));
     if bad_target {
-        sess.emit_err(errors::BadDeriveTarget { span, item: item.span() });
+        return Err(sess.emit_err(errors::BadDeriveTarget { span, item: item.span() }));
     }
-    bad_target
+    Ok(())
 }
 
 fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) {
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index fcc68010a34..d7a92dac50f 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -8,7 +8,7 @@ use rustc_ast_pretty::pprust;
 use rustc_errors::Applicability;
 use rustc_expand::base::*;
 use rustc_span::symbol::{sym, Ident, Symbol};
-use rustc_span::{FileNameDisplayPreference, Span};
+use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span};
 use std::iter;
 use thin_vec::{thin_vec, ThinVec};
 
@@ -128,12 +128,15 @@ pub fn expand_test_or_bench(
         };
     };
 
-    // has_*_signature will report any errors in the type so compilation
+    // check_*_signature will report any errors in the type so compilation
     // will fail. We shouldn't try to expand in this case because the errors
     // would be spurious.
-    if (!is_bench && !has_test_signature(cx, &item))
-        || (is_bench && !has_bench_signature(cx, &item))
-    {
+    let check_result = if is_bench {
+        check_bench_signature(cx, &item, &fn_)
+    } else {
+        check_test_signature(cx, &item, &fn_)
+    };
+    if check_result.is_err() {
         return if is_stmt {
             vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))]
         } else {
@@ -523,72 +526,62 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType {
     }
 }
 
-fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
+fn check_test_signature(
+    cx: &ExtCtxt<'_>,
+    i: &ast::Item,
+    f: &ast::Fn,
+) -> Result<(), ErrorGuaranteed> {
     let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic);
     let sd = &cx.sess.parse_sess.span_diagnostic;
-    match &i.kind {
-        ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => {
-            if let ast::Unsafe::Yes(span) = sig.header.unsafety {
-                sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" });
-                return false;
-            }
-            if let ast::Async::Yes { span, .. } = sig.header.asyncness {
-                sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" });
-                return false;
-            }
 
-            // If the termination trait is active, the compiler will check that the output
-            // type implements the `Termination` trait as `libtest` enforces that.
-            let has_output = match &sig.decl.output {
-                ast::FnRetTy::Default(..) => false,
-                ast::FnRetTy::Ty(t) if t.kind.is_unit() => false,
-                _ => true,
-            };
-
-            if !sig.decl.inputs.is_empty() {
-                sd.span_err(i.span, "functions used as tests can not have any arguments");
-                return false;
-            }
+    if let ast::Unsafe::Yes(span) = f.sig.header.unsafety {
+        return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" }));
+    }
 
-            if has_should_panic_attr && has_output {
-                sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
-                return false;
-            }
+    if let ast::Async::Yes { span, .. } = f.sig.header.asyncness {
+        return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" }));
+    }
 
-            if generics.params.iter().any(|param| !matches!(param.kind, GenericParamKind::Lifetime))
-            {
-                sd.span_err(
-                    i.span,
-                    "functions used as tests can not have any non-lifetime generic parameters",
-                );
-                return false;
-            }
+    // If the termination trait is active, the compiler will check that the output
+    // type implements the `Termination` trait as `libtest` enforces that.
+    let has_output = match &f.sig.decl.output {
+        ast::FnRetTy::Default(..) => false,
+        ast::FnRetTy::Ty(t) if t.kind.is_unit() => false,
+        _ => true,
+    };
 
-            true
-        }
-        _ => {
-            // should be unreachable because `is_test_fn_item` should catch all non-fn items
-            debug_assert!(false);
-            false
-        }
+    if !f.sig.decl.inputs.is_empty() {
+        return Err(sd.span_err(i.span, "functions used as tests can not have any arguments"));
     }
-}
 
-fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
-    let has_sig = match &i.kind {
-        // N.B., inadequate check, but we're running
-        // well before resolve, can't get too deep.
-        ast::ItemKind::Fn(box ast::Fn { sig, .. }) => sig.decl.inputs.len() == 1,
-        _ => false,
-    };
+    if has_should_panic_attr && has_output {
+        return Err(sd.span_err(i.span, "functions using `#[should_panic]` must return `()`"));
+    }
+
+    if f.generics.params.iter().any(|param| !matches!(param.kind, GenericParamKind::Lifetime)) {
+        return Err(sd.span_err(
+            i.span,
+            "functions used as tests can not have any non-lifetime generic parameters",
+        ));
+    }
+
+    Ok(())
+}
 
-    if !has_sig {
-        cx.sess.parse_sess.span_diagnostic.span_err(
+fn check_bench_signature(
+    cx: &ExtCtxt<'_>,
+    i: &ast::Item,
+    f: &ast::Fn,
+) -> Result<(), ErrorGuaranteed> {
+    // N.B., inadequate check, but we're running
+    // well before resolve, can't get too deep.
+    if f.sig.decl.inputs.len() != 1 {
+        return Err(cx.sess.parse_sess.span_diagnostic.span_err(
             i.span,
             "functions used as benches must have \
             signature `fn(&mut Bencher) -> impl Termination`",
-        );
+        ));
     }
 
-    has_sig
+    Ok(())
 }
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
index 42fb35e738f..556c6444833 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
@@ -20,9 +20,9 @@ jobs:
       matrix:
         libgccjit_version:
           - { gcc: "libgccjit.so", artifacts_branch: "master" }
-        commands: [
-          "--test-successful-rustc --nb-parts 2 --current-part 0",
-          "--test-successful-rustc --nb-parts 2 --current-part 1",
+        cargo_runner: [
+          "sde -future -rtm_mode full --",
+          "",
         ]
 
     steps:
@@ -36,6 +36,20 @@ jobs:
     - name: Install packages
       run: sudo apt-get install ninja-build ripgrep
 
+    - name: Install Intel Software Development Emulator
+      if: ${{ matrix.cargo_runner }}
+      run: |
+          mkdir intel-sde
+          cd intel-sde
+          dir=sde-external-9.14.0-2022-10-25-lin
+          file=$dir.tar.xz
+          wget https://downloadmirror.intel.com/751535/$file
+          tar xvf $file
+          sudo mkdir /usr/share/intel-sde
+          sudo cp -r $dir/* /usr/share/intel-sde
+          sudo ln -s /usr/share/intel-sde/sde /usr/bin/sde
+          sudo ln -s /usr/share/intel-sde/sde64 /usr/bin/sde64
+
     - name: Download artifact
       uses: dawidd6/action-download-artifact@v2
       with:
@@ -91,6 +105,10 @@ jobs:
         ./prepare_build.sh
         ./build.sh --release --release-sysroot
         cargo test
+
+    - name: Clean
+      if: ${{ !matrix.cargo_runner }}
+      run: |
         ./clean_all.sh
 
     - name: Prepare dependencies
@@ -107,10 +125,18 @@ jobs:
         args: --release
 
     - name: Run tests
+      if: ${{ !matrix.cargo_runner }}
       run: |
         ./test.sh --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore
 
     - name: Run stdarch tests
+      if: ${{ !matrix.cargo_runner }}
       run: |
         cd build_sysroot/sysroot_src/library/stdarch/
         CHANNEL=release TARGET=x86_64-unknown-linux-gnu ../../../../cargo.sh test
+
+    - name: Run stdarch tests
+      if: ${{ matrix.cargo_runner }}
+      run: |
+        cd build_sysroot/sysroot_src/library/stdarch/
+        STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu ../../../../cargo.sh test -- --skip rtm --skip tbm --skip sse4a
diff --git a/compiler/rustc_codegen_gcc/.gitignore b/compiler/rustc_codegen_gcc/.gitignore
index 12ed5667563..c5ed7de200c 100644
--- a/compiler/rustc_codegen_gcc/.gitignore
+++ b/compiler/rustc_codegen_gcc/.gitignore
@@ -23,3 +23,5 @@ benchmarks
 tools/llvm-project
 tools/llvmint
 tools/llvmint-2
+# The `llvm` folder is generated by the `tools/generate_intrinsics.py` script to update intrinsics.
+llvm
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index 0f2e152f8ce..1c8754bf675 100644
--- a/compiler/rustc_codegen_gcc/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/Cargo.lock
@@ -35,7 +35,7 @@ dependencies = [
 [[package]]
 name = "gccjit"
 version = "1.0.0"
-source = "git+https://github.com/antoyo/gccjit.rs#fe242b7eb26980e6c78859d51c8d4cc1e43381a3"
+source = "git+https://github.com/antoyo/gccjit.rs#d6e52626cfc6f487094a5d5ac66302baf3439984"
 dependencies = [
  "gccjit_sys",
 ]
@@ -43,7 +43,7 @@ dependencies = [
 [[package]]
 name = "gccjit_sys"
 version = "0.0.1"
-source = "git+https://github.com/antoyo/gccjit.rs#fe242b7eb26980e6c78859d51c8d4cc1e43381a3"
+source = "git+https://github.com/antoyo/gccjit.rs#d6e52626cfc6f487094a5d5ac66302baf3439984"
 dependencies = [
  "libc",
 ]
diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md
index bb741943892..a93637d9038 100644
--- a/compiler/rustc_codegen_gcc/Readme.md
+++ b/compiler/rustc_codegen_gcc/Readme.md
@@ -193,7 +193,7 @@ Using git-subtree with `rustc` requires a patched git to make it work.
 The PR that is needed is [here](https://github.com/gitgitgadget/git/pull/493).
 Use the following instructions to install it:
 
-```
+```bash
 git clone git@github.com:tqc/git.git
 cd git
 git checkout tqc/subtree
@@ -204,6 +204,21 @@ make
 cp git-subtree ~/bin
 ```
 
+Then, do a sync with this command:
+
+```bash
+PATH="$HOME/bin:$PATH" ~/bin/git-subtree push -P compiler/rustc_codegen_gcc/ ../rustc_codegen_gcc/ sync_branch_name
+cd ../rustc_codegen_gcc
+git checkout master
+git pull
+git checkout sync_branch_name
+git merge master
+```
+
+TODO: write a script that does the above.
+
+https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.20madness/near/258877725
+
 ### How to use [mem-trace](https://github.com/antoyo/mem-trace)
 
 `rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't a chance to intercept the calls to `malloc`.
diff --git a/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml b/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml
index cfadf47cc3f..a84f86a8218 100644
--- a/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml
@@ -9,6 +9,7 @@ compiler_builtins = "0.1"
 alloc = { path = "./sysroot_src/library/alloc" }
 std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
 test = { path = "./sysroot_src/library/test" }
+proc_macro = { path = "./sysroot_src/library/proc_macro" }
 
 [patch.crates-io]
 rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" }
diff --git a/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh b/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh
index 56768bbf1d0..71b3876bac2 100755
--- a/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh
+++ b/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh
@@ -29,10 +29,10 @@ git config user.name || git config user.name "None"
 
 git commit -m "Initial commit" -q
 for file in $(ls ../../patches/ | grep -v patcha); do
-echo "[GIT] apply" $file
-git apply ../../patches/$file
-git add -A
-git commit --no-gpg-sign -m "Patch $file"
+    echo "[GIT] apply" $file
+    git apply ../../patches/$file
+    git add -A
+    git commit --no-gpg-sign -m "Patch $file"
 done
 popd
 
diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs
index c27b610f2ab..0cd7e6047c2 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core.rs
@@ -451,6 +451,9 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
     drop_in_place(to_drop);
 }
 
+#[lang = "unpin"]
+pub auto trait Unpin {}
+
 #[lang = "deref"]
 pub trait Deref {
     type Target: ?Sized;
@@ -488,10 +491,23 @@ pub struct Box<T: ?Sized, A: Allocator = Global>(Unique<T>, A);
 
 impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {}
 
+impl<T> Box<T> {
+    pub fn new(val: T) -> Box<T> {
+        unsafe {
+            let size = intrinsics::size_of::<T>();
+            let ptr = libc::malloc(size);
+            intrinsics::copy(&val as *const T as *const u8, ptr, size);
+            Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, Global)
+        }
+    }
+}
+
 impl<T: ?Sized, A: Allocator> Drop for Box<T, A> {
     fn drop(&mut self) {
-        // inner value is dropped by compiler
-        libc::free(self.pointer.0 as *mut u8);
+        // inner value is dropped by compiler.
+        unsafe {
+            libc::free(self.0.pointer.0 as *mut u8);
+        }
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
index cff26077740..b93d6859706 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
@@ -168,6 +168,9 @@ fn main() {
         world as Box<dyn SomeTrait>;
 
         assert_eq!(intrinsics::bitreverse(0b10101000u8), 0b00010101u8);
+        assert_eq!(intrinsics::bitreverse(0xddccu16), 0x33bbu16);
+        assert_eq!(intrinsics::bitreverse(0xffee_ddccu32), 0x33bb77ffu32);
+        assert_eq!(intrinsics::bitreverse(0x1234_5678_ffee_ddccu64), 0x33bb77ff1e6a2c48u64);
 
         assert_eq!(intrinsics::bswap(0xabu8), 0xabu8);
         assert_eq!(intrinsics::bswap(0xddccu16), 0xccddu16);
diff --git a/compiler/rustc_codegen_gcc/example/std_example.rs b/compiler/rustc_codegen_gcc/example/std_example.rs
index 5c171c49fd1..18f2ddcde12 100644
--- a/compiler/rustc_codegen_gcc/example/std_example.rs
+++ b/compiler/rustc_codegen_gcc/example/std_example.rs
@@ -58,6 +58,7 @@ fn main() {
 
     assert_eq!(0b0000000000000000000000000010000010000000000000000000000000000000_0000000000100000000000000000000000001000000000000100000000000000u128.leading_zeros(), 26);
     assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7);
+    assert_eq!(0x1234_5678_ffee_ddcc_1234_5678_ffee_ddccu128.reverse_bits(), 0x33bb77ff1e6a2c4833bb77ff1e6a2c48u128);
 
     let _d = 0i128.checked_div(2i128);
     let _d = 0u128.checked_div(2u128);
diff --git a/compiler/rustc_codegen_gcc/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/failing-ui-tests.txt
index 8539e27ea6a..801464daae9 100644
--- a/compiler/rustc_codegen_gcc/failing-ui-tests.txt
+++ b/compiler/rustc_codegen_gcc/failing-ui-tests.txt
@@ -54,8 +54,8 @@ tests/ui/issues/issue-40883.rs
 tests/ui/issues/issue-43853.rs
 tests/ui/issues/issue-47364.rs
 tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
-tests/ui/rfc-2091-track-caller/std-panic-locations.rs
-tests/ui/rfcs/rfc1857-drop-order.rs
+tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs
+tests/ui/rfcs/rfc-1857-stabilize-drop-order/drop-order.rs
 tests/ui/simd/issue-17170.rs
 tests/ui/simd/issue-39720.rs
 tests/ui/simd/issue-89193.rs
@@ -66,3 +66,5 @@ tests/ui/generator/panic-safe.rs
 tests/ui/issues/issue-14875.rs
 tests/ui/issues/issue-29948.rs
 tests/ui/panic-while-printing.rs
+tests/ui/enum-discriminant/get_discr.rs
+tests/ui/panics/nested_panic_caught.rs
diff --git a/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch b/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch
deleted file mode 100644
index ee5ba449fb8..00000000000
--- a/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From dd82e95c9de212524e14fc60155de1ae40156dfc Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Sun, 24 Nov 2019 15:34:06 +0100
-Subject: [PATCH] [core] Ignore failing tests
-
----
- library/core/tests/iter.rs       |  4 ++++
- library/core/tests/num/bignum.rs | 10 ++++++++++
- library/core/tests/num/mod.rs    |  5 +++--
- library/core/tests/time.rs       |  1 +
- 4 files changed, 18 insertions(+), 2 deletions(-)
-
-diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
-index 4bc44e9..8e3c7a4 100644
---- a/library/core/tests/array.rs
-+++ b/library/core/tests/array.rs
-@@ -242,6 +242,7 @@ fn iterator_drops() {
-     assert_eq!(i.get(), 5);
- }
- 
-+/*
- // This test does not work on targets without panic=unwind support.
- // To work around this problem, test is marked is should_panic, so it will
- // be automagically skipped on unsuitable targets, such as
-@@ -283,6 +284,7 @@ fn array_default_impl_avoids_leaks_on_panic() {
-     assert_eq!(COUNTER.load(Relaxed), 0);
-     panic!("test succeeded")
- }
-+*/
- 
- #[test]
- fn empty_array_is_always_default() {
-@@ -304,6 +304,7 @@ fn array_map() {
-     assert_eq!(b, [1, 2, 3]);
- }
- 
-+/*
- // See note on above test for why `should_panic` is used.
- #[test]
- #[should_panic(expected = "test succeeded")]
-@@ -332,6 +333,7 @@ fn array_map_drop_safety() {
-     assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create);
-     panic!("test succeeded")
- }
-+*/
- 
- #[test]
- fn cell_allows_array_cycle() {
--- 2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain
index 933ecd45baa..ebb04d0069c 100644
--- a/compiler/rustc_codegen_gcc/rust-toolchain
+++ b/compiler/rustc_codegen_gcc/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-03-02"
+channel = "nightly-2023-06-19"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index 250aa79f8d6..4c3b7f5036c 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -518,7 +518,6 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                 OperandValue::Immediate(op.tmp_var.to_rvalue()).store(self, place);
             }
         }
-
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs
index db841b1b524..eb0cce19b85 100644
--- a/compiler/rustc_codegen_gcc/src/attributes.rs
+++ b/compiler/rustc_codegen_gcc/src/attributes.rs
@@ -2,9 +2,13 @@
 use gccjit::FnAttribute;
 use gccjit::Function;
 use rustc_attr::InstructionSetAttr;
+#[cfg(feature="master")]
+use rustc_attr::InlineAttr;
 use rustc_codegen_ssa::target_features::tied_target_features;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::ty;
+#[cfg(feature="master")]
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_session::Session;
 use rustc_span::symbol::sym;
 use smallvec::{smallvec, SmallVec};
@@ -67,6 +71,24 @@ fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> {
     }
 }
 
+/// Get GCC attribute for the provided inline heuristic.
+#[cfg(feature="master")]
+#[inline]
+fn inline_attr<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, inline: InlineAttr) -> Option<FnAttribute<'gcc>> {
+    match inline {
+        InlineAttr::Hint => Some(FnAttribute::Inline),
+        InlineAttr::Always => Some(FnAttribute::AlwaysInline),
+        InlineAttr::Never => {
+            if cx.sess().target.arch != "amdgpu" {
+                Some(FnAttribute::NoInline)
+            } else {
+                None
+            }
+        }
+        InlineAttr::None => None,
+    }
+}
+
 /// Composite function which sets GCC attributes for function depending on its AST (`#[attribute]`)
 /// attributes.
 pub fn from_fn_attrs<'gcc, 'tcx>(
@@ -77,6 +99,23 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
 ) {
     let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
 
+    #[cfg(feature="master")]
+    {
+        let inline =
+            if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
+                InlineAttr::Never
+            }
+            else if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) {
+                InlineAttr::Hint
+            }
+            else {
+                codegen_fn_attrs.inline
+            };
+        if let Some(attr) = inline_attr(cx, inline) {
+            func.add_attribute(attr);
+        }
+    }
+
     let function_features =
         codegen_fn_attrs.target_features.iter().map(|features| features.as_str()).collect::<Vec<&str>>();
 
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index f9ea0f00456..43d0aafbd50 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -181,6 +181,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             })
             .collect();
 
+        debug_assert_eq!(casted_args.len(), args.len());
+
         Cow::Owned(casted_args)
     }
 
@@ -207,7 +209,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
         let func_name = format!("{:?}", func_ptr);
 
-        let casted_args: Vec<_> = param_types
+        let mut casted_args: Vec<_> = param_types
             .into_iter()
             .zip(args.iter())
             .enumerate()
@@ -237,6 +239,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             })
             .collect();
 
+        // NOTE: to take into account variadic functions.
+        for i in casted_args.len()..args.len() {
+            casted_args.push(args[i]);
+        }
+
         Cow::Owned(casted_args)
     }
 
@@ -280,8 +287,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         }
     }
 
-    fn function_ptr_call(&mut self, func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
-        let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr");
+    fn function_ptr_call(&mut self, typ: Type<'gcc>, mut func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
+        let gcc_func =
+            match func_ptr.get_type().dyncast_function_ptr_type() {
+                Some(func) => func,
+                None => {
+                    // NOTE: due to opaque pointers now being used, we need to cast here.
+                    let new_func_type = typ.dyncast_function_ptr_type().expect("function ptr");
+                    func_ptr = self.context.new_cast(None, func_ptr, typ);
+                    new_func_type
+                },
+            };
         let func_name = format!("{:?}", func_ptr);
         let previous_arg_count = args.len();
         let orig_args = args;
@@ -424,16 +440,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         self.llbb().end_with_void_return(None)
     }
 
-    fn ret(&mut self, value: RValue<'gcc>) {
-        let value =
-            if self.structs_as_pointer.borrow().contains(&value) {
-                // NOTE: hack to workaround a limitation of the rustc API: see comment on
-                // CodegenCx.structs_as_pointer
-                value.dereference(None).to_rvalue()
-            }
-            else {
-                value
-            };
+    fn ret(&mut self, mut value: RValue<'gcc>) {
+        if self.structs_as_pointer.borrow().contains(&value) {
+            // NOTE: hack to workaround a limitation of the rustc API: see comment on
+            // CodegenCx.structs_as_pointer
+            value = value.dereference(None).to_rvalue();
+        }
+        let expected_return_type = self.current_func().get_return_type();
+        if !expected_return_type.is_compatible_with(value.get_type()) {
+            // NOTE: due to opaque pointers now being used, we need to cast here.
+            value = self.context.new_cast(None, value, expected_return_type);
+        }
         self.llbb().end_with_return(None, value);
     }
 
@@ -719,17 +736,25 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         unimplemented!();
     }
 
-    fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
+    fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
         let block = self.llbb();
         let function = block.get_function();
         // NOTE: instead of returning the dereference here, we have to assign it to a variable in
         // the current basic block. Otherwise, it could be used in another basic block, causing a
         // dereference after a drop, for instance.
-        // TODO(antoyo): handle align of the load instruction.
-        let ptr = self.context.new_cast(None, ptr, pointee_ty.make_pointer());
+        // FIXME(antoyo): this check that we don't call get_aligned() a second time on a type.
+        // Ideally, we shouldn't need to do this check.
+        let aligned_type =
+            if pointee_ty == self.cx.u128_type || pointee_ty == self.cx.i128_type {
+                pointee_ty
+            }
+            else {
+                pointee_ty.get_aligned(align.bytes())
+            };
+        let ptr = self.context.new_cast(None, ptr, aligned_type.make_pointer());
         let deref = ptr.dereference(None).to_rvalue();
         unsafe { RETURN_VALUE_COUNT += 1 };
-        let loaded_value = function.new_local(None, pointee_ty, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT }));
+        let loaded_value = function.new_local(None, aligned_type, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT }));
         block.add_assignment(None, loaded_value, deref);
         loaded_value.to_rvalue()
     }
@@ -909,7 +934,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         self.context.new_bitcast(None, result, ptr_type)
     }
 
-    fn inbounds_gep(&mut self, _typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> {
+    fn inbounds_gep(&mut self, typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> {
+        // NOTE: due to opaque pointers now being used, we need to cast here.
+        let ptr = self.context.new_cast(None, ptr, typ.make_pointer());
         // NOTE: array indexing is always considered in bounds in GCC (TODO(antoyo): to be verified).
         let mut indices = indices.into_iter();
         let index = indices.next().expect("first index in inbounds_gep");
@@ -938,6 +965,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
             element.get_address(None)
         }
         else if let Some(struct_type) = value_type.is_struct() {
+            // NOTE: due to opaque pointers now being used, we need to bitcast here.
+            let ptr = self.bitcast_if_needed(ptr, value_type.make_pointer());
             ptr.dereference_field(None, struct_type.get_field(idx as i32)).get_address(None)
         }
         else {
@@ -1356,7 +1385,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
 
     fn call(
         &mut self,
-        _typ: Type<'gcc>,
+        typ: Type<'gcc>,
         _fn_attrs: Option<&CodegenFnAttrs>,
         fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
         func: RValue<'gcc>,
@@ -1370,7 +1399,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         }
         else {
             // If it's a not function that was defined, it's a function pointer.
-            self.function_ptr_call(func, args, funclet)
+            self.function_ptr_call(typ, func, args, funclet)
         };
         if let Some(_fn_abi) = fn_abi {
             // TODO(bjorn3): Apply function attributes
@@ -1843,7 +1872,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
         #[cfg(feature="master")]
         let (cond, element_type) = {
-            let then_val_vector_type = then_val.get_type().dyncast_vector().expect("vector type");
+            // TODO(antoyo): dyncast_vector should not require a call to unqualified.
+            let then_val_vector_type = then_val.get_type().unqualified().dyncast_vector().expect("vector type");
             let then_val_element_type = then_val_vector_type.get_element_type();
             let then_val_element_size = then_val_element_type.get_size();
 
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 33e3b0baa92..d8a1fd315c0 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -1,5 +1,5 @@
 #[cfg(feature = "master")]
-use gccjit::FnAttribute;
+use gccjit::{FnAttribute, VarAttribute, Visibility};
 use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue};
 use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, StaticMethods};
 use rustc_middle::span_bug;
@@ -234,7 +234,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             );
 
             if !self.tcx.is_reachable_non_generic(def_id) {
-                // TODO(antoyo): set visibility.
+                #[cfg(feature = "master")]
+                global.add_attribute(VarAttribute::Visibility(Visibility::Hidden));
             }
 
             global
diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs
index 4748e7e4be2..493626c3cf5 100644
--- a/compiler/rustc_codegen_gcc/src/declare.rs
+++ b/compiler/rustc_codegen_gcc/src/declare.rs
@@ -132,7 +132,7 @@ fn declare_raw_fn<'gcc>(cx: &CodegenCx<'gcc, '_>, name: &str, _callconv: () /*ll
 pub fn mangle_name(name: &str) -> String {
     name.replace(|char: char| {
         if !char.is_alphanumeric() && char != '_' {
-            debug_assert!("$.".contains(char), "Unsupported char in function name: {}", char);
+            debug_assert!("$.*".contains(char), "Unsupported char in function name {}: {}", name, char);
             true
         }
         else {
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
index 8a4559355ea..438eab78943 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
@@ -2967,10 +2967,6 @@ match name {
     "llvm.nvvm.clz.ll" => "__nvvm_clz_ll",
     "llvm.nvvm.cos.approx.f" => "__nvvm_cos_approx_f",
     "llvm.nvvm.cos.approx.ftz.f" => "__nvvm_cos_approx_ftz_f",
-    "llvm.nvvm.cp.async.ca.shared.global.16" => "__nvvm_cp_async_ca_shared_global_16",
-    "llvm.nvvm.cp.async.ca.shared.global.4" => "__nvvm_cp_async_ca_shared_global_4",
-    "llvm.nvvm.cp.async.ca.shared.global.8" => "__nvvm_cp_async_ca_shared_global_8",
-    "llvm.nvvm.cp.async.cg.shared.global.16" => "__nvvm_cp_async_cg_shared_global_16",
     "llvm.nvvm.cp.async.commit.group" => "__nvvm_cp_async_commit_group",
     "llvm.nvvm.cp.async.mbarrier.arrive" => "__nvvm_cp_async_mbarrier_arrive",
     "llvm.nvvm.cp.async.mbarrier.arrive.noinc" => "__nvvm_cp_async_mbarrier_arrive_noinc",
@@ -3086,18 +3082,8 @@ match name {
     "llvm.nvvm.fma.rn.f16" => "__nvvm_fma_rn_f16",
     "llvm.nvvm.fma.rn.f16x2" => "__nvvm_fma_rn_f16x2",
     "llvm.nvvm.fma.rn.ftz.f" => "__nvvm_fma_rn_ftz_f",
-    "llvm.nvvm.fma.rn.ftz.f16" => "__nvvm_fma_rn_ftz_f16",
-    "llvm.nvvm.fma.rn.ftz.f16x2" => "__nvvm_fma_rn_ftz_f16x2",
-    "llvm.nvvm.fma.rn.ftz.relu.f16" => "__nvvm_fma_rn_ftz_relu_f16",
-    "llvm.nvvm.fma.rn.ftz.relu.f16x2" => "__nvvm_fma_rn_ftz_relu_f16x2",
-    "llvm.nvvm.fma.rn.ftz.sat.f16" => "__nvvm_fma_rn_ftz_sat_f16",
-    "llvm.nvvm.fma.rn.ftz.sat.f16x2" => "__nvvm_fma_rn_ftz_sat_f16x2",
     "llvm.nvvm.fma.rn.relu.bf16" => "__nvvm_fma_rn_relu_bf16",
     "llvm.nvvm.fma.rn.relu.bf16x2" => "__nvvm_fma_rn_relu_bf16x2",
-    "llvm.nvvm.fma.rn.relu.f16" => "__nvvm_fma_rn_relu_f16",
-    "llvm.nvvm.fma.rn.relu.f16x2" => "__nvvm_fma_rn_relu_f16x2",
-    "llvm.nvvm.fma.rn.sat.f16" => "__nvvm_fma_rn_sat_f16",
-    "llvm.nvvm.fma.rn.sat.f16x2" => "__nvvm_fma_rn_sat_f16x2",
     "llvm.nvvm.fma.rp.d" => "__nvvm_fma_rp_d",
     "llvm.nvvm.fma.rp.f" => "__nvvm_fma_rp_f",
     "llvm.nvvm.fma.rp.ftz.f" => "__nvvm_fma_rp_ftz_f",
@@ -3111,32 +3097,18 @@ match name {
     "llvm.nvvm.fmax.f16" => "__nvvm_fmax_f16",
     "llvm.nvvm.fmax.f16x2" => "__nvvm_fmax_f16x2",
     "llvm.nvvm.fmax.ftz.f" => "__nvvm_fmax_ftz_f",
-    "llvm.nvvm.fmax.ftz.f16" => "__nvvm_fmax_ftz_f16",
-    "llvm.nvvm.fmax.ftz.f16x2" => "__nvvm_fmax_ftz_f16x2",
     "llvm.nvvm.fmax.ftz.nan.f" => "__nvvm_fmax_ftz_nan_f",
-    "llvm.nvvm.fmax.ftz.nan.f16" => "__nvvm_fmax_ftz_nan_f16",
-    "llvm.nvvm.fmax.ftz.nan.f16x2" => "__nvvm_fmax_ftz_nan_f16x2",
     "llvm.nvvm.fmax.ftz.nan.xorsign.abs.f" => "__nvvm_fmax_ftz_nan_xorsign_abs_f",
-    "llvm.nvvm.fmax.ftz.nan.xorsign.abs.f16" => "__nvvm_fmax_ftz_nan_xorsign_abs_f16",
-    "llvm.nvvm.fmax.ftz.nan.xorsign.abs.f16x2" => "__nvvm_fmax_ftz_nan_xorsign_abs_f16x2",
     "llvm.nvvm.fmax.ftz.xorsign.abs.f" => "__nvvm_fmax_ftz_xorsign_abs_f",
-    "llvm.nvvm.fmax.ftz.xorsign.abs.f16" => "__nvvm_fmax_ftz_xorsign_abs_f16",
-    "llvm.nvvm.fmax.ftz.xorsign.abs.f16x2" => "__nvvm_fmax_ftz_xorsign_abs_f16x2",
     "llvm.nvvm.fmax.nan.bf16" => "__nvvm_fmax_nan_bf16",
     "llvm.nvvm.fmax.nan.bf16x2" => "__nvvm_fmax_nan_bf16x2",
     "llvm.nvvm.fmax.nan.f" => "__nvvm_fmax_nan_f",
-    "llvm.nvvm.fmax.nan.f16" => "__nvvm_fmax_nan_f16",
-    "llvm.nvvm.fmax.nan.f16x2" => "__nvvm_fmax_nan_f16x2",
     "llvm.nvvm.fmax.nan.xorsign.abs.bf16" => "__nvvm_fmax_nan_xorsign_abs_bf16",
     "llvm.nvvm.fmax.nan.xorsign.abs.bf16x2" => "__nvvm_fmax_nan_xorsign_abs_bf16x2",
     "llvm.nvvm.fmax.nan.xorsign.abs.f" => "__nvvm_fmax_nan_xorsign_abs_f",
-    "llvm.nvvm.fmax.nan.xorsign.abs.f16" => "__nvvm_fmax_nan_xorsign_abs_f16",
-    "llvm.nvvm.fmax.nan.xorsign.abs.f16x2" => "__nvvm_fmax_nan_xorsign_abs_f16x2",
     "llvm.nvvm.fmax.xorsign.abs.bf16" => "__nvvm_fmax_xorsign_abs_bf16",
     "llvm.nvvm.fmax.xorsign.abs.bf16x2" => "__nvvm_fmax_xorsign_abs_bf16x2",
     "llvm.nvvm.fmax.xorsign.abs.f" => "__nvvm_fmax_xorsign_abs_f",
-    "llvm.nvvm.fmax.xorsign.abs.f16" => "__nvvm_fmax_xorsign_abs_f16",
-    "llvm.nvvm.fmax.xorsign.abs.f16x2" => "__nvvm_fmax_xorsign_abs_f16x2",
     "llvm.nvvm.fmin.bf16" => "__nvvm_fmin_bf16",
     "llvm.nvvm.fmin.bf16x2" => "__nvvm_fmin_bf16x2",
     "llvm.nvvm.fmin.d" => "__nvvm_fmin_d",
@@ -3144,32 +3116,18 @@ match name {
     "llvm.nvvm.fmin.f16" => "__nvvm_fmin_f16",
     "llvm.nvvm.fmin.f16x2" => "__nvvm_fmin_f16x2",
     "llvm.nvvm.fmin.ftz.f" => "__nvvm_fmin_ftz_f",
-    "llvm.nvvm.fmin.ftz.f16" => "__nvvm_fmin_ftz_f16",
-    "llvm.nvvm.fmin.ftz.f16x2" => "__nvvm_fmin_ftz_f16x2",
     "llvm.nvvm.fmin.ftz.nan.f" => "__nvvm_fmin_ftz_nan_f",
-    "llvm.nvvm.fmin.ftz.nan.f16" => "__nvvm_fmin_ftz_nan_f16",
-    "llvm.nvvm.fmin.ftz.nan.f16x2" => "__nvvm_fmin_ftz_nan_f16x2",
     "llvm.nvvm.fmin.ftz.nan.xorsign.abs.f" => "__nvvm_fmin_ftz_nan_xorsign_abs_f",
-    "llvm.nvvm.fmin.ftz.nan.xorsign.abs.f16" => "__nvvm_fmin_ftz_nan_xorsign_abs_f16",
-    "llvm.nvvm.fmin.ftz.nan.xorsign.abs.f16x2" => "__nvvm_fmin_ftz_nan_xorsign_abs_f16x2",
     "llvm.nvvm.fmin.ftz.xorsign.abs.f" => "__nvvm_fmin_ftz_xorsign_abs_f",
-    "llvm.nvvm.fmin.ftz.xorsign.abs.f16" => "__nvvm_fmin_ftz_xorsign_abs_f16",
-    "llvm.nvvm.fmin.ftz.xorsign.abs.f16x2" => "__nvvm_fmin_ftz_xorsign_abs_f16x2",
     "llvm.nvvm.fmin.nan.bf16" => "__nvvm_fmin_nan_bf16",
     "llvm.nvvm.fmin.nan.bf16x2" => "__nvvm_fmin_nan_bf16x2",
     "llvm.nvvm.fmin.nan.f" => "__nvvm_fmin_nan_f",
-    "llvm.nvvm.fmin.nan.f16" => "__nvvm_fmin_nan_f16",
-    "llvm.nvvm.fmin.nan.f16x2" => "__nvvm_fmin_nan_f16x2",
     "llvm.nvvm.fmin.nan.xorsign.abs.bf16" => "__nvvm_fmin_nan_xorsign_abs_bf16",
     "llvm.nvvm.fmin.nan.xorsign.abs.bf16x2" => "__nvvm_fmin_nan_xorsign_abs_bf16x2",
     "llvm.nvvm.fmin.nan.xorsign.abs.f" => "__nvvm_fmin_nan_xorsign_abs_f",
-    "llvm.nvvm.fmin.nan.xorsign.abs.f16" => "__nvvm_fmin_nan_xorsign_abs_f16",
-    "llvm.nvvm.fmin.nan.xorsign.abs.f16x2" => "__nvvm_fmin_nan_xorsign_abs_f16x2",
     "llvm.nvvm.fmin.xorsign.abs.bf16" => "__nvvm_fmin_xorsign_abs_bf16",
     "llvm.nvvm.fmin.xorsign.abs.bf16x2" => "__nvvm_fmin_xorsign_abs_bf16x2",
     "llvm.nvvm.fmin.xorsign.abs.f" => "__nvvm_fmin_xorsign_abs_f",
-    "llvm.nvvm.fmin.xorsign.abs.f16" => "__nvvm_fmin_xorsign_abs_f16",
-    "llvm.nvvm.fmin.xorsign.abs.f16x2" => "__nvvm_fmin_xorsign_abs_f16x2",
     "llvm.nvvm.fns" => "__nvvm_fns",
     "llvm.nvvm.h2f" => "__nvvm_h2f",
     "llvm.nvvm.i2d.rm" => "__nvvm_i2d_rm",
@@ -7895,6 +7853,10 @@ match name {
     "llvm.x86.subborrow.u64" => "__builtin_ia32_subborrow_u64",
     "llvm.x86.tbm.bextri.u32" => "__builtin_ia32_bextri_u32",
     "llvm.x86.tbm.bextri.u64" => "__builtin_ia32_bextri_u64",
+    "llvm.x86.tcmmimfp16ps" => "__builtin_ia32_tcmmimfp16ps",
+    "llvm.x86.tcmmimfp16ps.internal" => "__builtin_ia32_tcmmimfp16ps_internal",
+    "llvm.x86.tcmmrlfp16ps" => "__builtin_ia32_tcmmrlfp16ps",
+    "llvm.x86.tcmmrlfp16ps.internal" => "__builtin_ia32_tcmmrlfp16ps_internal",
     "llvm.x86.tdpbf16ps" => "__builtin_ia32_tdpbf16ps",
     "llvm.x86.tdpbf16ps.internal" => "__builtin_ia32_tdpbf16ps_internal",
     "llvm.x86.tdpbssd" => "__builtin_ia32_tdpbssd",
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
index 0edec566be3..f28348380d7 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
@@ -313,6 +313,13 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc
                 let new_args = args.to_vec();
                 args = vec![new_args[1], new_args[0], new_args[2], new_args[3], new_args[4]].into();
             },
+            "__builtin_ia32_vpshrdv_v8di" | "__builtin_ia32_vpshrdv_v4di" | "__builtin_ia32_vpshrdv_v2di" |
+                "__builtin_ia32_vpshrdv_v16si" | "__builtin_ia32_vpshrdv_v8si" | "__builtin_ia32_vpshrdv_v4si" |
+                "__builtin_ia32_vpshrdv_v32hi" | "__builtin_ia32_vpshrdv_v16hi" | "__builtin_ia32_vpshrdv_v8hi" => {
+                // The first two arguments are reversed, compared to LLVM.
+                let new_args = args.to_vec();
+                args = vec![new_args[1], new_args[0], new_args[2]].into();
+            },
             _ => (),
         }
     }
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 60176874747..a31fee39918 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -551,141 +551,52 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let context = &self.cx.context;
         let result =
             match width {
-                8 => {
-                    // First step.
-                    let left = self.and(value, context.new_rvalue_from_int(typ, 0xF0));
-                    let left = self.lshr(left, context.new_rvalue_from_int(typ, 4));
-                    let right = self.and(value, context.new_rvalue_from_int(typ, 0x0F));
-                    let right = self.shl(right, context.new_rvalue_from_int(typ, 4));
-                    let step1 = self.or(left, right);
-
-                    // Second step.
-                    let left = self.and(step1, context.new_rvalue_from_int(typ, 0xCC));
-                    let left = self.lshr(left, context.new_rvalue_from_int(typ, 2));
-                    let right = self.and(step1, context.new_rvalue_from_int(typ, 0x33));
-                    let right = self.shl(right, context.new_rvalue_from_int(typ, 2));
-                    let step2 = self.or(left, right);
-
-                    // Third step.
-                    let left = self.and(step2, context.new_rvalue_from_int(typ, 0xAA));
-                    let left = self.lshr(left, context.new_rvalue_from_int(typ, 1));
-                    let right = self.and(step2, context.new_rvalue_from_int(typ, 0x55));
-                    let right = self.shl(right, context.new_rvalue_from_int(typ, 1));
-                    let step3 = self.or(left, right);
-
-                    step3
-                },
-                16 => {
-                    // First step.
-                    let left = self.and(value, context.new_rvalue_from_int(typ, 0x5555));
-                    let left = self.shl(left, context.new_rvalue_from_int(typ, 1));
-                    let right = self.and(value, context.new_rvalue_from_int(typ, 0xAAAA));
-                    let right = self.lshr(right, context.new_rvalue_from_int(typ, 1));
-                    let step1 = self.or(left, right);
-
-                    // Second step.
-                    let left = self.and(step1, context.new_rvalue_from_int(typ, 0x3333));
-                    let left = self.shl(left, context.new_rvalue_from_int(typ, 2));
-                    let right = self.and(step1, context.new_rvalue_from_int(typ, 0xCCCC));
-                    let right = self.lshr(right, context.new_rvalue_from_int(typ, 2));
-                    let step2 = self.or(left, right);
-
-                    // Third step.
-                    let left = self.and(step2, context.new_rvalue_from_int(typ, 0x0F0F));
-                    let left = self.shl(left, context.new_rvalue_from_int(typ, 4));
-                    let right = self.and(step2, context.new_rvalue_from_int(typ, 0xF0F0));
-                    let right = self.lshr(right, context.new_rvalue_from_int(typ, 4));
-                    let step3 = self.or(left, right);
-
-                    // Fourth step.
-                    let left = self.and(step3, context.new_rvalue_from_int(typ, 0x00FF));
-                    let left = self.shl(left, context.new_rvalue_from_int(typ, 8));
-                    let right = self.and(step3, context.new_rvalue_from_int(typ, 0xFF00));
-                    let right = self.lshr(right, context.new_rvalue_from_int(typ, 8));
-                    let step4 = self.or(left, right);
+                8 | 16 | 32 | 64 => {
+                    let mask = ((1u128 << width) - 1) as u64;
+                    let (m0, m1, m2) = if width > 16 {
+                        (
+                            context.new_rvalue_from_long(typ, (0x5555555555555555u64 & mask) as i64),
+                            context.new_rvalue_from_long(typ, (0x3333333333333333u64 & mask) as i64),
+                            context.new_rvalue_from_long(typ, (0x0f0f0f0f0f0f0f0fu64 & mask) as i64),
+                        )
+                    } else {
+                        (
+                            context.new_rvalue_from_int(typ, (0x5555u64 & mask) as i32),
+                            context.new_rvalue_from_int(typ, (0x3333u64 & mask) as i32),
+                            context.new_rvalue_from_int(typ, (0x0f0fu64 & mask) as i32),
+                        )
+                    };
+                    let one = context.new_rvalue_from_int(typ, 1);
+                    let two = context.new_rvalue_from_int(typ, 2);
+                    let four = context.new_rvalue_from_int(typ, 4);
 
-                    step4
-                },
-                32 => {
-                    // TODO(antoyo): Refactor with other implementations.
                     // First step.
-                    let left = self.and(value, context.new_rvalue_from_long(typ, 0x55555555));
-                    let left = self.shl(left, context.new_rvalue_from_long(typ, 1));
-                    let right = self.and(value, context.new_rvalue_from_long(typ, 0xAAAAAAAA));
-                    let right = self.lshr(right, context.new_rvalue_from_long(typ, 1));
+                    let left = self.lshr(value, one);
+                    let left = self.and(left, m0);
+                    let right = self.and(value, m0);
+                    let right = self.shl(right, one);
                     let step1 = self.or(left, right);
 
                     // Second step.
-                    let left = self.and(step1, context.new_rvalue_from_long(typ, 0x33333333));
-                    let left = self.shl(left, context.new_rvalue_from_long(typ, 2));
-                    let right = self.and(step1, context.new_rvalue_from_long(typ, 0xCCCCCCCC));
-                    let right = self.lshr(right, context.new_rvalue_from_long(typ, 2));
+                    let left = self.lshr(step1, two);
+                    let left = self.and(left, m1);
+                    let right = self.and(step1, m1);
+                    let right = self.shl(right, two);
                     let step2 = self.or(left, right);
 
                     // Third step.
-                    let left = self.and(step2, context.new_rvalue_from_long(typ, 0x0F0F0F0F));
-                    let left = self.shl(left, context.new_rvalue_from_long(typ, 4));
-                    let right = self.and(step2, context.new_rvalue_from_long(typ, 0xF0F0F0F0));
-                    let right = self.lshr(right, context.new_rvalue_from_long(typ, 4));
+                    let left = self.lshr(step2, four);
+                    let left = self.and(left, m2);
+                    let right = self.and(step2, m2);
+                    let right = self.shl(right, four);
                     let step3 = self.or(left, right);
 
                     // Fourth step.
-                    let left = self.and(step3, context.new_rvalue_from_long(typ, 0x00FF00FF));
-                    let left = self.shl(left, context.new_rvalue_from_long(typ, 8));
-                    let right = self.and(step3, context.new_rvalue_from_long(typ, 0xFF00FF00));
-                    let right = self.lshr(right, context.new_rvalue_from_long(typ, 8));
-                    let step4 = self.or(left, right);
-
-                    // Fifth step.
-                    let left = self.and(step4, context.new_rvalue_from_long(typ, 0x0000FFFF));
-                    let left = self.shl(left, context.new_rvalue_from_long(typ, 16));
-                    let right = self.and(step4, context.new_rvalue_from_long(typ, 0xFFFF0000));
-                    let right = self.lshr(right, context.new_rvalue_from_long(typ, 16));
-                    let step5 = self.or(left, right);
-
-                    step5
-                },
-                64 => {
-                    // First step.
-                    let left = self.shl(value, context.new_rvalue_from_long(typ, 32));
-                    let right = self.lshr(value, context.new_rvalue_from_long(typ, 32));
-                    let step1 = self.or(left, right);
-
-                    // Second step.
-                    let left = self.and(step1, context.new_rvalue_from_long(typ, 0x0001FFFF0001FFFF));
-                    let left = self.shl(left, context.new_rvalue_from_long(typ, 15));
-                    let right = self.and(step1, context.new_rvalue_from_long(typ, 0xFFFE0000FFFE0000u64 as i64)); // TODO(antoyo): transmute the number instead?
-                    let right = self.lshr(right, context.new_rvalue_from_long(typ, 17));
-                    let step2 = self.or(left, right);
-
-                    // Third step.
-                    let left = self.lshr(step2, context.new_rvalue_from_long(typ, 10));
-                    let left = self.xor(step2, left);
-                    let temp = self.and(left, context.new_rvalue_from_long(typ, 0x003F801F003F801F));
-
-                    let left = self.shl(temp, context.new_rvalue_from_long(typ, 10));
-                    let left = self.or(temp, left);
-                    let step3 = self.xor(left, step2);
-
-                    // Fourth step.
-                    let left = self.lshr(step3, context.new_rvalue_from_long(typ, 4));
-                    let left = self.xor(step3, left);
-                    let temp = self.and(left, context.new_rvalue_from_long(typ, 0x0E0384210E038421));
-
-                    let left = self.shl(temp, context.new_rvalue_from_long(typ, 4));
-                    let left = self.or(temp, left);
-                    let step4 = self.xor(left, step3);
-
-                    // Fifth step.
-                    let left = self.lshr(step4, context.new_rvalue_from_long(typ, 2));
-                    let left = self.xor(step4, left);
-                    let temp = self.and(left, context.new_rvalue_from_long(typ, 0x2248884222488842));
-
-                    let left = self.shl(temp, context.new_rvalue_from_long(typ, 2));
-                    let left = self.or(temp, left);
-                    let step5 = self.xor(left, step4);
-
-                    step5
+                    if width == 8 {
+                        step3
+                    } else {
+                        self.gcc_bswap(step3, width)
+                    }
                 },
                 128 => {
                     // TODO(antoyo): find a more efficient implementation?
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index b59c3a64f57..9115cf97119 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -165,10 +165,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
             InvalidMonomorphizationReturnIntegerType { span, name, ret_ty, out_ty }
         );
 
+        let arg1 = args[0].immediate();
+        // NOTE: we get different vector types for the same vector type and libgccjit doesn't
+        // compare them as equal, so bitcast.
+        // FIXME(antoyo): allow comparing vector types as equal in libgccjit.
+        let arg2 = bx.context.new_bitcast(None, args[1].immediate(), arg1.get_type());
         return Ok(compare_simd_types(
             bx,
-            args[0].immediate(),
-            args[1].immediate(),
+            arg1,
+            arg2,
             in_elem,
             llret_ty,
             cmp_op,
@@ -341,7 +346,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         // endian and MSB-first for big endian.
 
         let vector = args[0].immediate();
-        let vector_type = vector.get_type().dyncast_vector().expect("vector type");
+        // TODO(antoyo): dyncast_vector should not require a call to unqualified.
+        let vector_type = vector.get_type().unqualified().dyncast_vector().expect("vector type");
         let elem_type = vector_type.get_element_type();
 
         let expected_int_bits = in_len.max(8);
@@ -848,7 +854,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                 (true, true) => {
                     // Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition
                     // TODO(antoyo): improve using conditional operators if possible.
-                    let arg_type = lhs.get_type();
+                    // TODO(antoyo): dyncast_vector should not require a call to unqualified.
+                    let arg_type = lhs.get_type().unqualified();
                     // TODO(antoyo): convert lhs and rhs to unsigned.
                     let sum = lhs + rhs;
                     let vector_type = arg_type.dyncast_vector().expect("vector type");
@@ -878,7 +885,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                     res & cmp
                 },
                 (true, false) => {
-                    let arg_type = lhs.get_type();
+                    // TODO(antoyo): dyncast_vector should not require a call to unqualified.
+                    let arg_type = lhs.get_type().unqualified();
                     // TODO(antoyo): this uses the same algorithm from saturating add, but add the
                     // negative of the right operand. Find a proper subtraction algorithm.
                     let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs);
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index ea013c4428c..2a6b642782d 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -111,6 +111,8 @@ impl CodegenBackend for GccCodegenBackend {
     }
 
     fn init(&self, sess: &Session) {
+        #[cfg(feature="master")]
+        gccjit::set_global_personality_function_name(b"rust_eh_personality\0");
         if sess.lto() != Lto::No {
             sess.emit_warning(LTONotSupported {});
         }
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index 30a3fe67b85..74f016cf90a 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -383,8 +383,8 @@ impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         unimplemented!();
     }
 
-    fn fn_decl_backend_type(&self, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
-        // FIXME(antoyo): return correct type.
-        self.type_void()
+    fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
+        let (return_type, param_types, variadic, _) = fn_abi.gcc_type(self);
+        self.context.new_function_pointer_type(None, return_type, &param_types, variadic)
     }
 }
diff --git a/compiler/rustc_codegen_gcc/test.sh b/compiler/rustc_codegen_gcc/test.sh
index 6139892aefc..592997b8ab9 100755
--- a/compiler/rustc_codegen_gcc/test.sh
+++ b/compiler/rustc_codegen_gcc/test.sh
@@ -214,12 +214,14 @@ function setup_rustc() {
     rm config.toml || true
 
     cat > config.toml <<EOF
+changelog-seen = 2
+
 [rust]
 codegen-backends = []
 deny-warnings = false
 
 [build]
-cargo = "$(which cargo)"
+cargo = "$(rustup which cargo)"
 local-rebuild = true
 rustc = "$HOME/.rustup/toolchains/$rust_toolchain-$TARGET_TRIPLE/bin/rustc"
 
@@ -237,7 +239,7 @@ EOF
 function asm_tests() {
     setup_rustc
 
-    echo "[TEST] rustc test suite"
+    echo "[TEST] rustc asm test suite"
     RUSTC_ARGS="-Zpanic-abort-tests -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort"
     COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 tests/assembly/asm --rustc-args "$RUSTC_ARGS"
 }
@@ -338,6 +340,8 @@ function test_rustc() {
     for test in $(rg -i --files-with-matches "//(\[\w+\])?~|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" tests/ui); do
       rm $test
     done
+    rm tests/ui/consts/const_cmp_type_id.rs
+    rm tests/ui/consts/issue-73976-monomorphic.rs
 
     git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
 
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 4ccef98afc3..51ac441a7a4 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -320,7 +320,6 @@ pub type ExportedSymbols = FxHashMap<CrateNum, Arc<Vec<(String, SymbolExportInfo
 #[derive(Clone)]
 pub struct CodegenContext<B: WriteBackendMethods> {
     // Resources needed when running LTO
-    pub backend: B,
     pub prof: SelfProfilerRef,
     pub lto: Lto,
     pub save_temps: bool,
@@ -338,14 +337,10 @@ pub struct CodegenContext<B: WriteBackendMethods> {
     pub msvc_imps_needed: bool,
     pub is_pe_coff: bool,
     pub target_can_use_split_dwarf: bool,
-    pub target_pointer_width: u32,
     pub target_arch: String,
-    pub debuginfo: config::DebugInfo,
     pub split_debuginfo: rustc_target::spec::SplitDebuginfo,
     pub split_dwarf_kind: rustc_session::config::SplitDwarfKind,
 
-    /// Number of cgus excluding the allocator/metadata modules
-    pub total_cgus: usize,
     /// Handler to use for diagnostics produced during codegen.
     pub diag_emitter: SharedEmitter,
     /// LLVM optimizations for which we want to print remarks.
@@ -441,7 +436,6 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
     target_cpu: String,
     metadata: EncodedMetadata,
     metadata_module: Option<CompiledModule>,
-    total_cgus: usize,
 ) -> OngoingCodegen<B> {
     let (coordinator_send, coordinator_receive) = channel();
     let sess = tcx.sess;
@@ -469,7 +463,6 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
         shared_emitter,
         codegen_worker_send,
         coordinator_receive,
-        total_cgus,
         sess.jobserver.clone(),
         Arc::new(regular_config),
         Arc::new(metadata_config),
@@ -685,7 +678,7 @@ fn produce_final_output_artifacts(
     // These are used in linking steps and will be cleaned up afterward.
 }
 
-pub enum WorkItem<B: WriteBackendMethods> {
+pub(crate) enum WorkItem<B: WriteBackendMethods> {
     /// Optimize a newly codegened, totally unoptimized module.
     Optimize(ModuleCodegen<B::Module>),
     /// Copy the post-LTO artifacts from the incremental cache to the output
@@ -731,7 +724,8 @@ impl<B: WriteBackendMethods> WorkItem<B> {
     }
 }
 
-enum WorkItemResult<B: WriteBackendMethods> {
+/// A result produced by the backend.
+pub(crate) enum WorkItemResult<B: WriteBackendMethods> {
     Compiled(CompiledModule),
     NeedsLink(ModuleCodegen<B::Module>),
     NeedsFatLTO(FatLTOInput<B>),
@@ -923,38 +917,41 @@ fn finish_intra_module_work<B: ExtraBackendMethods>(
     }
 }
 
-pub enum Message<B: WriteBackendMethods> {
+/// Messages sent to the coordinator.
+pub(crate) enum Message<B: WriteBackendMethods> {
+    /// A jobserver token has become available. Sent from the jobserver helper
+    /// thread.
     Token(io::Result<Acquired>),
-    NeedsFatLTO {
-        result: FatLTOInput<B>,
-        worker_id: usize,
-    },
-    NeedsThinLTO {
-        name: String,
-        thin_buffer: B::ThinBuffer,
-        worker_id: usize,
-    },
-    NeedsLink {
-        module: ModuleCodegen<B::Module>,
-        worker_id: usize,
-    },
-    Done {
-        result: Result<CompiledModule, Option<WorkerFatalError>>,
-        worker_id: usize,
-    },
-    CodegenDone {
-        llvm_work_item: WorkItem<B>,
-        cost: u64,
-    },
+
+    /// The backend has finished processing a work item for a codegen unit.
+    /// Sent from a backend worker thread.
+    WorkItem { result: Result<WorkItemResult<B>, Option<WorkerFatalError>>, worker_id: usize },
+
+    /// The frontend has finished generating something (backend IR or a
+    /// post-LTO artifact) for a codegen unit, and it should be passed to the
+    /// backend. Sent from the main thread.
+    CodegenDone { llvm_work_item: WorkItem<B>, cost: u64 },
+
+    /// Similar to `CodegenDone`, but for reusing a pre-LTO artifact
+    /// Sent from the main thread.
     AddImportOnlyModule {
         module_data: SerializedModule<B::ModuleBuffer>,
         work_product: WorkProduct,
     },
+
+    /// The frontend has finished generating everything for all codegen units.
+    /// Sent from the main thread.
     CodegenComplete,
-    CodegenItem,
+
+    /// Some normal-ish compiler error occurred, and codegen should be wound
+    /// down. Sent from the main thread.
     CodegenAborted,
 }
 
+/// A message sent from the coordinator thread to the main thread telling it to
+/// process another codegen unit.
+pub struct CguMessage;
+
 type DiagnosticArgName<'source> = Cow<'source, str>;
 
 struct Diagnostic {
@@ -976,9 +973,8 @@ fn start_executing_work<B: ExtraBackendMethods>(
     tcx: TyCtxt<'_>,
     crate_info: &CrateInfo,
     shared_emitter: SharedEmitter,
-    codegen_worker_send: Sender<Message<B>>,
+    codegen_worker_send: Sender<CguMessage>,
     coordinator_receive: Receiver<Box<dyn Any + Send>>,
-    total_cgus: usize,
     jobserver: Client,
     regular_config: Arc<ModuleConfig>,
     metadata_config: Arc<ModuleConfig>,
@@ -1046,7 +1042,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
         };
     let backend_features = tcx.global_backend_features(());
     let cgcx = CodegenContext::<B> {
-        backend: backend.clone(),
         crate_types: sess.crate_types().to_vec(),
         each_linked_rlib_for_lto,
         lto: sess.lto(),
@@ -1067,13 +1062,10 @@ fn start_executing_work<B: ExtraBackendMethods>(
         metadata_module_config: metadata_config,
         allocator_module_config: allocator_config,
         tm_factory: backend.target_machine_factory(tcx.sess, ol, backend_features),
-        total_cgus,
         msvc_imps_needed: msvc_imps_needed(tcx),
         is_pe_coff: tcx.sess.target.is_like_windows,
         target_can_use_split_dwarf: tcx.sess.target_can_use_split_dwarf(),
-        target_pointer_width: tcx.sess.target.pointer_width,
         target_arch: tcx.sess.target.arch.to_string(),
-        debuginfo: tcx.sess.opts.debuginfo,
         split_debuginfo: tcx.sess.split_debuginfo(),
         split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind,
     };
@@ -1235,10 +1227,19 @@ fn start_executing_work<B: ExtraBackendMethods>(
         let mut needs_thin_lto = Vec::new();
         let mut lto_import_only_modules = Vec::new();
         let mut started_lto = false;
-        let mut codegen_aborted = false;
 
-        // This flag tracks whether all items have gone through codegens
-        let mut codegen_done = false;
+        /// Possible state transitions:
+        /// - Ongoing -> Completed
+        /// - Ongoing -> Aborted
+        /// - Completed -> Aborted
+        #[derive(Debug, PartialEq)]
+        enum CodegenState {
+            Ongoing,
+            Completed,
+            Aborted,
+        }
+        use CodegenState::*;
+        let mut codegen_state = Ongoing;
 
         // This is the queue of LLVM work items that still need processing.
         let mut work_items = Vec::<(WorkItem<B>, u64)>::new();
@@ -1258,10 +1259,10 @@ fn start_executing_work<B: ExtraBackendMethods>(
         // wait for all existing work to finish, so many of the conditions here
         // only apply if codegen hasn't been aborted as they represent pending
         // work to be done.
-        while !codegen_done
+        while codegen_state == Ongoing
             || running > 0
             || main_thread_worker_state == MainThreadWorkerState::LLVMing
-            || (!codegen_aborted
+            || (codegen_state == Completed
                 && !(work_items.is_empty()
                     && needs_fat_lto.is_empty()
                     && needs_thin_lto.is_empty()
@@ -1271,7 +1272,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
             // While there are still CGUs to be codegened, the coordinator has
             // to decide how to utilize the compiler processes implicit Token:
             // For codegenning more CGU or for running them through LLVM.
-            if !codegen_done {
+            if codegen_state == Ongoing {
                 if main_thread_worker_state == MainThreadWorkerState::Idle {
                     // Compute the number of workers that will be running once we've taken as many
                     // items from the work queue as we can, plus one for the main thread. It's not
@@ -1284,9 +1285,9 @@ fn start_executing_work<B: ExtraBackendMethods>(
                     let anticipated_running = running + additional_running + 1;
 
                     if !queue_full_enough(work_items.len(), anticipated_running) {
-                        // The queue is not full enough, codegen more items:
-                        if codegen_worker_send.send(Message::CodegenItem).is_err() {
-                            panic!("Could not send Message::CodegenItem to main thread")
+                        // The queue is not full enough, process more codegen units:
+                        if codegen_worker_send.send(CguMessage).is_err() {
+                            panic!("Could not send CguMessage to main thread")
                         }
                         main_thread_worker_state = MainThreadWorkerState::Codegenning;
                     } else {
@@ -1308,10 +1309,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
                         spawn_work(cgcx, item);
                     }
                 }
-            } else if codegen_aborted {
-                // don't queue up any more work if codegen was aborted, we're
-                // just waiting for our existing children to finish
-            } else {
+            } else if codegen_state == Completed {
                 // If we've finished everything related to normal codegen
                 // then it must be the case that we've got some LTO work to do.
                 // Perform the serial work here of figuring out what we're
@@ -1378,11 +1376,15 @@ fn start_executing_work<B: ExtraBackendMethods>(
                         // Already making good use of that token
                     }
                 }
+            } else {
+                // Don't queue up any more work if codegen was aborted, we're
+                // just waiting for our existing children to finish.
+                assert!(codegen_state == Aborted);
             }
 
             // Spin up what work we can, only doing this while we've got available
             // parallelism slots and work left to spawn.
-            while !codegen_aborted && !work_items.is_empty() && running < tokens.len() {
+            while codegen_state != Aborted && !work_items.is_empty() && running < tokens.len() {
                 let (item, _) = work_items.pop().unwrap();
 
                 maybe_start_llvm_timer(prof, cgcx.config(item.module_kind()), &mut llvm_start_time);
@@ -1434,8 +1436,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
                         Err(e) => {
                             let msg = &format!("failed to acquire jobserver token: {}", e);
                             shared_emitter.fatal(msg);
-                            codegen_done = true;
-                            codegen_aborted = true;
+                            codegen_state = Aborted;
                         }
                     }
                 }
@@ -1463,7 +1464,9 @@ fn start_executing_work<B: ExtraBackendMethods>(
                 }
 
                 Message::CodegenComplete => {
-                    codegen_done = true;
+                    if codegen_state != Aborted {
+                        codegen_state = Completed;
+                    }
                     assert_eq!(main_thread_worker_state, MainThreadWorkerState::Codegenning);
                     main_thread_worker_state = MainThreadWorkerState::Idle;
                 }
@@ -1475,58 +1478,59 @@ fn start_executing_work<B: ExtraBackendMethods>(
                 // then conditions above will ensure no more work is spawned but
                 // we'll keep executing this loop until `running` hits 0.
                 Message::CodegenAborted => {
-                    codegen_done = true;
-                    codegen_aborted = true;
+                    codegen_state = Aborted;
                 }
-                Message::Done { result: Ok(compiled_module), worker_id } => {
+
+                Message::WorkItem { result, worker_id } => {
                     free_worker(worker_id);
-                    match compiled_module.kind {
-                        ModuleKind::Regular => {
-                            compiled_modules.push(compiled_module);
+
+                    match result {
+                        Ok(WorkItemResult::Compiled(compiled_module)) => {
+                            match compiled_module.kind {
+                                ModuleKind::Regular => {
+                                    compiled_modules.push(compiled_module);
+                                }
+                                ModuleKind::Allocator => {
+                                    assert!(compiled_allocator_module.is_none());
+                                    compiled_allocator_module = Some(compiled_module);
+                                }
+                                ModuleKind::Metadata => bug!("Should be handled separately"),
+                            }
                         }
-                        ModuleKind::Allocator => {
-                            assert!(compiled_allocator_module.is_none());
-                            compiled_allocator_module = Some(compiled_module);
+                        Ok(WorkItemResult::NeedsLink(module)) => {
+                            needs_link.push(module);
+                        }
+                        Ok(WorkItemResult::NeedsFatLTO(fat_lto_input)) => {
+                            assert!(!started_lto);
+                            needs_fat_lto.push(fat_lto_input);
+                        }
+                        Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer)) => {
+                            assert!(!started_lto);
+                            needs_thin_lto.push((name, thin_buffer));
+                        }
+                        Err(Some(WorkerFatalError)) => {
+                            // Like `CodegenAborted`, wait for remaining work to finish.
+                            codegen_state = Aborted;
+                        }
+                        Err(None) => {
+                            // If the thread failed that means it panicked, so
+                            // we abort immediately.
+                            bug!("worker thread panicked");
                         }
-                        ModuleKind::Metadata => bug!("Should be handled separately"),
                     }
                 }
-                Message::NeedsLink { module, worker_id } => {
-                    free_worker(worker_id);
-                    needs_link.push(module);
-                }
-                Message::NeedsFatLTO { result, worker_id } => {
-                    assert!(!started_lto);
-                    free_worker(worker_id);
-                    needs_fat_lto.push(result);
-                }
-                Message::NeedsThinLTO { name, thin_buffer, worker_id } => {
-                    assert!(!started_lto);
-                    free_worker(worker_id);
-                    needs_thin_lto.push((name, thin_buffer));
-                }
+
                 Message::AddImportOnlyModule { module_data, work_product } => {
                     assert!(!started_lto);
-                    assert!(!codegen_done);
+                    assert_eq!(codegen_state, Ongoing);
                     assert_eq!(main_thread_worker_state, MainThreadWorkerState::Codegenning);
                     lto_import_only_modules.push((module_data, work_product));
                     main_thread_worker_state = MainThreadWorkerState::Idle;
                 }
-                // If the thread failed that means it panicked, so we abort immediately.
-                Message::Done { result: Err(None), worker_id: _ } => {
-                    bug!("worker thread panicked");
-                }
-                Message::Done { result: Err(Some(WorkerFatalError)), worker_id } => {
-                    // Similar to CodegenAborted, wait for remaining work to finish.
-                    free_worker(worker_id);
-                    codegen_done = true;
-                    codegen_aborted = true;
-                }
-                Message::CodegenItem => bug!("the coordinator should not receive codegen requests"),
             }
         }
 
-        if codegen_aborted {
+        if codegen_state == Aborted {
             return Err(());
         }
 
@@ -1641,22 +1645,11 @@ fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B>
             fn drop(&mut self) {
                 let worker_id = self.worker_id;
                 let msg = match self.result.take() {
-                    Some(Ok(WorkItemResult::Compiled(m))) => {
-                        Message::Done::<B> { result: Ok(m), worker_id }
-                    }
-                    Some(Ok(WorkItemResult::NeedsLink(m))) => {
-                        Message::NeedsLink::<B> { module: m, worker_id }
-                    }
-                    Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
-                        Message::NeedsFatLTO::<B> { result: m, worker_id }
-                    }
-                    Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
-                        Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
-                    }
+                    Some(Ok(result)) => Message::WorkItem::<B> { result: Ok(result), worker_id },
                     Some(Err(FatalError)) => {
-                        Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
+                        Message::WorkItem::<B> { result: Err(Some(WorkerFatalError)), worker_id }
                     }
-                    None => Message::Done::<B> { result: Err(None), worker_id },
+                    None => Message::WorkItem::<B> { result: Err(None), worker_id },
                 };
                 drop(self.coordinator_send.send(Box::new(msg)));
             }
@@ -1879,7 +1872,7 @@ pub struct OngoingCodegen<B: ExtraBackendMethods> {
     pub metadata: EncodedMetadata,
     pub metadata_module: Option<CompiledModule>,
     pub crate_info: CrateInfo,
-    pub codegen_worker_receive: Receiver<Message<B>>,
+    pub codegen_worker_receive: Receiver<CguMessage>,
     pub shared_emitter_main: SharedEmitterMain,
     pub output_filenames: Arc<OutputFilenames>,
     pub coordinator: Coordinator<B>,
@@ -1953,10 +1946,9 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
 
     pub fn wait_for_signal_to_codegen_item(&self) {
         match self.codegen_worker_receive.recv() {
-            Ok(Message::CodegenItem) => {
-                // Nothing to do
+            Ok(CguMessage) => {
+                // Ok to proceed.
             }
-            Ok(_) => panic!("unexpected message"),
             Err(_) => {
                 // One of the LLVM threads must have panicked, fall through so
                 // error handling can be reached.
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 6abc56d5975..28f3c23364c 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -580,7 +580,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
 ) -> OngoingCodegen<B> {
     // Skip crate items and just output metadata in -Z no-codegen mode.
     if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
-        let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, metadata, None, 1);
+        let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, metadata, None);
 
         ongoing_codegen.codegen_finished(tcx);
 
@@ -631,14 +631,8 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
         })
     });
 
-    let ongoing_codegen = start_async_codegen(
-        backend.clone(),
-        tcx,
-        target_cpu,
-        metadata,
-        metadata_module,
-        codegen_units.len(),
-    );
+    let ongoing_codegen =
+        start_async_codegen(backend.clone(), tcx, target_cpu, metadata, metadata_module);
 
     // Codegen an allocator shim, if necessary.
     if let Some(kind) = allocator_kind_for_codegen(tcx) {
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 0db96d4e735..984cc1557a4 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -97,6 +97,7 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[
     rustc_codegen_ssa::DEFAULT_LOCALE_RESOURCE,
     rustc_const_eval::DEFAULT_LOCALE_RESOURCE,
     rustc_error_messages::DEFAULT_LOCALE_RESOURCE,
+    rustc_errors::DEFAULT_LOCALE_RESOURCE,
     rustc_expand::DEFAULT_LOCALE_RESOURCE,
     rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE,
     rustc_hir_typeck::DEFAULT_LOCALE_RESOURCE,
@@ -329,7 +330,7 @@ fn run_compiler(
                         return;
                     }
                     let should_stop =
-                        print_crate_info(&***compiler.codegen_backend(), compiler.session(), false);
+                        print_crate_info(&**compiler.codegen_backend(), compiler.session(), false);
 
                     if should_stop == Compilation::Stop {
                         return;
@@ -351,7 +352,7 @@ fn run_compiler(
 
     interface::run_compiler(config, |compiler| {
         let sess = compiler.session();
-        let should_stop = print_crate_info(&***compiler.codegen_backend(), sess, true)
+        let should_stop = print_crate_info(&**compiler.codegen_backend(), sess, true)
             .and_then(|| list_metadata(sess, &*compiler.codegen_backend().metadata_loader()))
             .and_then(|| try_process_rlink(sess, compiler));
 
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 70fc66947df..5e5001bc8b4 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3743,6 +3743,29 @@ impl<'hir> Node<'hir> {
         }
     }
 
+    /// Get the type for constants, assoc types, type aliases and statics.
+    pub fn ty(self) -> Option<&'hir Ty<'hir>> {
+        match self {
+            Node::Item(it) => match it.kind {
+                ItemKind::TyAlias(ty, _) | ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => {
+                    Some(ty)
+                }
+                _ => None,
+            },
+            Node::TraitItem(it) => match it.kind {
+                TraitItemKind::Const(ty, _) => Some(ty),
+                TraitItemKind::Type(_, ty) => ty,
+                _ => None,
+            },
+            Node::ImplItem(it) => match it.kind {
+                ImplItemKind::Const(ty, _) => Some(ty),
+                ImplItemKind::Type(ty) => Some(ty),
+                _ => None,
+            },
+            _ => None,
+        }
+    }
+
     pub fn alias_ty(self) -> Option<&'hir Ty<'hir>> {
         match self {
             Node::Item(Item { kind: ItemKind::TyAlias(ty, ..), .. }) => Some(ty),
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
index e4eb0e6abd4..d29601e9008 100644
--- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -412,7 +412,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
             // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait).
             let output = tcx.fn_sig(assoc_item.def_id).skip_binder().output();
             let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
-                && tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder
+                && tcx.is_impl_trait_in_trait(alias_ty.def_id)
             {
                 alias_ty
             } else {
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index 7f060af2245..dc17ef7048d 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -122,9 +122,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         let all_candidate_names: Vec<_> = all_candidates()
             .flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
-            .filter_map(
-                |item| if item.kind == ty::AssocKind::Type { Some(item.name) } else { None },
-            )
+            .filter_map(|item| {
+                if item.opt_rpitit_info.is_none() && item.kind == ty::AssocKind::Type {
+                    Some(item.name)
+                } else {
+                    None
+                }
+            })
             .collect();
 
         if let (Some(suggested_name), true) = (
@@ -159,9 +163,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             .flat_map(|trait_def_id| {
                 self.tcx().associated_items(*trait_def_id).in_definition_order()
             })
-            .filter_map(
-                |item| if item.kind == ty::AssocKind::Type { Some(item.name) } else { None },
-            )
+            .filter_map(|item| {
+                if item.opt_rpitit_info.is_none() && item.kind == ty::AssocKind::Type {
+                    Some(item.name)
+                } else {
+                    None
+                }
+            })
             .collect();
 
         if let (Some(suggested_name), true) = (
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 22aa3c7ff08..a7e81f41c69 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -563,8 +563,8 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
             check_union(tcx, id.owner_id.def_id);
         }
         DefKind::OpaqueTy => {
-            let opaque = tcx.hir().expect_item(id.owner_id.def_id).expect_opaque_ty();
-            if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin
+            let origin = tcx.opaque_type_origin(id.owner_id.def_id);
+            if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin
                 && let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id)
                 && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
             {
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 1dfe053b215..596c5518086 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -409,9 +409,7 @@ fn fn_sig_suggestion<'tcx>(
         output = if let ty::Alias(_, alias_ty) = *output.kind() {
             tcx.explicit_item_bounds(alias_ty.def_id)
                 .subst_iter_copied(tcx, alias_ty.substs)
-                .find_map(|(bound, _)| {
-                    bound.to_opt_poly_projection_pred()?.no_bound_vars()?.term.ty()
-                })
+                .find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty())
                 .unwrap_or_else(|| {
                     span_bug!(
                         ident.span,
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 51e9b4c4501..744eb036933 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1086,7 +1086,7 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
             wfcx.infcx,
             wfcx.param_env,
             wfcx.body_def_id,
-            normalized_bound,
+            normalized_bound.as_predicate(),
             bound_span,
         )
     });
@@ -1543,8 +1543,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
         if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
             && self.seen.insert(unshifted_opaque_ty.def_id)
             && let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
-            && let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
-            && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
+            && let origin = tcx.opaque_type_origin(opaque_def_id)
+            && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = origin
             && source == self.fn_def_id
         {
             let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| {
@@ -1562,7 +1562,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
                     self.wfcx.infcx,
                     self.wfcx.param_env,
                     self.wfcx.body_def_id,
-                    bound,
+                    bound.as_predicate(),
                     bound_span,
                 ));
                 // Set the debruijn index back to innermost here, since we already eagerly
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 5f35678d95d..958313fee6f 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -19,7 +19,7 @@ fn associated_type_bounds<'tcx>(
     assoc_item_def_id: LocalDefId,
     ast_bounds: &'tcx [hir::GenericBound<'tcx>],
     span: Span,
-) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
+) -> &'tcx [(ty::Clause<'tcx>, Span)] {
     let item_ty = tcx.mk_projection(
         assoc_item_def_id.to_def_id(),
         InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
@@ -33,8 +33,11 @@ fn associated_type_bounds<'tcx>(
     let trait_def_id = tcx.local_parent(assoc_item_def_id);
     let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id);
 
-    let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| {
-        match pred.kind().skip_binder() {
+    let bounds_from_parent = trait_predicates
+        .predicates
+        .iter()
+        .copied()
+        .filter(|(pred, _)| match pred.kind().skip_binder() {
             ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => tr.self_ty() == item_ty,
             ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => {
                 proj.projection_ty.self_ty() == item_ty
@@ -43,15 +46,10 @@ fn associated_type_bounds<'tcx>(
                 outlives.0 == item_ty
             }
             _ => false,
-        }
-    });
+        })
+        .map(|(pred, span)| (pred.expect_clause(), span));
 
-    let all_bounds = tcx.arena.alloc_from_iter(
-        bounds
-            .clauses()
-            .map(|(clause, span)| (clause.as_predicate(), span))
-            .chain(bounds_from_parent),
-    );
+    let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent));
     debug!(
         "associated_type_bounds({}) = {:?}",
         tcx.def_path_str(assoc_item_def_id.to_def_id()),
@@ -71,7 +69,7 @@ fn opaque_type_bounds<'tcx>(
     ast_bounds: &'tcx [hir::GenericBound<'tcx>],
     item_ty: Ty<'tcx>,
     span: Span,
-) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
+) -> &'tcx [(ty::Clause<'tcx>, Span)] {
     ty::print::with_no_queries!({
         let icx = ItemCtxt::new(tcx, opaque_def_id);
         let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
@@ -79,15 +77,14 @@ fn opaque_type_bounds<'tcx>(
         icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
         debug!(?bounds);
 
-        tcx.arena
-            .alloc_from_iter(bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span)))
+        tcx.arena.alloc_from_iter(bounds.clauses())
     })
 }
 
 pub(super) fn explicit_item_bounds(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,
-) -> ty::EarlyBinder<&'_ [(ty::Predicate<'_>, Span)]> {
+) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
     match tcx.opt_rpitit_info(def_id.to_def_id()) {
         // RPITIT's bounds are the same as opaque type bounds, but with
         // a projection self type.
@@ -139,11 +136,8 @@ pub(super) fn explicit_item_bounds(
 pub(super) fn item_bounds(
     tcx: TyCtxt<'_>,
     def_id: DefId,
-) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> {
+) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
     tcx.explicit_item_bounds(def_id).map_bound(|bounds| {
-        tcx.mk_predicates_from_iter(util::elaborate(
-            tcx,
-            bounds.iter().map(|&(bound, _span)| bound),
-        ))
+        tcx.mk_clauses_from_iter(util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)))
     })
 }
diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
index 98f4a8e00ef..48624cefe4d 100644
--- a/compiler/rustc_hir_analysis/src/outlives/mod.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs
@@ -3,7 +3,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
+use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
@@ -17,7 +17,7 @@ pub fn provide(providers: &mut Providers) {
     *providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers };
 }
 
-fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::ClauseKind<'_>, Span)] {
+fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clause<'_>, Span)] {
     let id = tcx.hir().local_def_id_to_hir_id(item_def_id);
 
     if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst)
@@ -52,7 +52,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau
                 if tcx.has_attr(item_def_id, sym::rustc_outlives) {
                     let mut pred: Vec<String> = predicates
                         .iter()
-                        .map(|(out_pred, _)| match out_pred {
+                        .map(|(out_pred, _)| match out_pred.kind().skip_binder() {
                             ty::ClauseKind::RegionOutlives(p) => p.to_string(),
                             ty::ClauseKind::TypeOutlives(p) => p.to_string(),
                             err => bug!("unexpected clause {:?}", err),
@@ -104,13 +104,15 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
                     |(ty::OutlivesPredicate(kind1, region2), &span)| {
                         match kind1.unpack() {
                             GenericArgKind::Type(ty1) => Some((
-                                ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty1, *region2)),
+                                ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty1, *region2))
+                                    .to_predicate(tcx),
                                 span,
                             )),
                             GenericArgKind::Lifetime(region1) => Some((
                                 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
                                     region1, *region2,
-                                )),
+                                ))
+                                .to_predicate(tcx),
                                 span,
                             )),
                             GenericArgKind::Const(_) => {
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 8bb9ca2acf2..23d8da88a45 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -162,28 +162,25 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
         // which thus mentions `'a` and should thus accept hidden types that borrow 'a
         // instead of requiring an additional `+ 'a`.
         match pred.kind().skip_binder() {
-            ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
+            ty::ClauseKind::Trait(ty::TraitPredicate {
                 trait_ref: ty::TraitRef { def_id: _, substs, .. },
                 constness: _,
                 polarity: _,
-            })) => {
+            }) => {
                 for subst in &substs[1..] {
                     subst.visit_with(&mut collector);
                 }
             }
-            ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
+            ty::ClauseKind::Projection(ty::ProjectionPredicate {
                 projection_ty: ty::AliasTy { substs, .. },
                 term,
-            })) => {
+            }) => {
                 for subst in &substs[1..] {
                     subst.visit_with(&mut collector);
                 }
                 term.visit_with(&mut collector);
             }
-            ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
-                _,
-                region,
-            ))) => {
+            ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_, region)) => {
                 region.visit_with(&mut collector);
             }
             _ => {
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index a07580fe72d..c7fa27da1ac 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -536,33 +536,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
 
                 for ty in [first_ty, second_ty] {
-                    for (pred, _) in self
+                    for (clause, _) in self
                         .tcx
                         .explicit_item_bounds(rpit_def_id)
                         .subst_iter_copied(self.tcx, substs)
                     {
-                        let pred = pred.kind().rebind(match pred.kind().skip_binder() {
-                            ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
+                        let pred = clause.kind().rebind(match clause.kind().skip_binder() {
+                            ty::ClauseKind::Trait(trait_pred) => {
                                 // FIXME(rpitit): This will need to be fixed when we move to associated types
                                 assert!(matches!(
                                     *trait_pred.trait_ref.self_ty().kind(),
                                     ty::Alias(_, ty::AliasTy { def_id, substs: alias_substs, .. })
                                     if def_id == rpit_def_id && substs == alias_substs
                                 ));
-                                ty::PredicateKind::Clause(ty::ClauseKind::Trait(
-                                    trait_pred.with_self_ty(self.tcx, ty),
-                                ))
+                                ty::ClauseKind::Trait(trait_pred.with_self_ty(self.tcx, ty))
                             }
-                            ty::PredicateKind::Clause(ty::ClauseKind::Projection(
-                                mut proj_pred,
-                            )) => {
+                            ty::ClauseKind::Projection(mut proj_pred) => {
                                 assert!(matches!(
                                     *proj_pred.projection_ty.self_ty().kind(),
                                     ty::Alias(_, ty::AliasTy { def_id, substs: alias_substs, .. })
                                     if def_id == rpit_def_id && substs == alias_substs
                                 ));
                                 proj_pred = proj_pred.with_self_ty(self.tcx, ty);
-                                ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj_pred))
+                                ty::ClauseKind::Projection(proj_pred)
                             }
                             _ => continue,
                         });
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 69ccbf0b58f..0a1b639af51 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -92,10 +92,7 @@ pub(super) fn check_fn<'a, 'tcx>(
         fcx.check_pat_top(&param.pat, param_ty, ty_span, None);
 
         // Check that argument is Sized.
-        // The check for a non-trivial pattern is a hack to avoid duplicate warnings
-        // for simple cases like `fn foo(x: Trait)`,
-        // where we would error once on the parameter as a whole, and once on the binding `x`.
-        if param.pat.simple_ident().is_none() && !params_can_be_unsized {
+        if !params_can_be_unsized {
             fcx.require_type_is_sized(
                 param_ty,
                 param.pat.span,
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 94b37fb3450..c64b64e925a 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -174,7 +174,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
                 .deduce_closure_signature_from_predicates(
                     expected_ty,
-                    self.tcx.explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
+                    self.tcx
+                        .explicit_item_bounds(def_id)
+                        .subst_iter_copied(self.tcx, substs)
+                        .map(|(c, s)| (c.as_predicate(), s)),
                 ),
             ty::Dynamic(ref object_type, ..) => {
                 let sig = object_type.projection_bounds().find_map(|pb| {
@@ -717,13 +720,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .tcx
                 .explicit_item_bounds(def_id)
                 .subst_iter_copied(self.tcx, substs)
-                .find_map(|(p, s)| get_future_output(p, s))?,
+                .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
             ty::Error(_) => return None,
             ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self
                 .tcx
                 .explicit_item_bounds(proj.def_id)
                 .subst_iter_copied(self.tcx, proj.substs)
-                .find_map(|(p, s)| get_future_output(p, s))?,
+                .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
             _ => span_bug!(
                 self.tcx.def_span(expr_def_id),
                 "async fn generator return type not an inference variable: {ret_ty}"
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index dabe7749cb6..fdbb153ec7d 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -577,7 +577,7 @@ fn check_must_not_suspend_ty<'tcx>(
             let mut has_emitted = false;
             for &(predicate, _) in fcx.tcx.explicit_item_bounds(def).skip_binder() {
                 // We only look at the `DefId`, so it is safe to skip the binder here.
-                if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ref poly_trait_predicate)) =
+                if let ty::ClauseKind::Trait(ref poly_trait_predicate) =
                     predicate.kind().skip_binder()
                 {
                     let def_id = poly_trait_predicate.trait_ref.def_id;
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index e759fd6bc94..762176ecfc7 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -12,6 +12,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir_analysis::autoderef::{self, Autoderef};
 use rustc_infer::infer::canonical::OriginalQueryValues;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
+use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
 use rustc_middle::middle::stability;
@@ -448,15 +449,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     );
                 }
             } else {
-                // Encountered a real ambiguity, so abort the lookup. If `ty` is not
-                // an `Err`, report the right "type annotations needed" error pointing
-                // to it.
+                // Ended up encountering a type variable when doing autoderef,
+                // but it may not be a type variable after processing obligations
+                // in our local `FnCtxt`, so don't call `structurally_resolved_type`.
                 let ty = &bad_ty.ty;
                 let ty = self
                     .probe_instantiate_query_response(span, &orig_values, ty)
                     .unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty));
-                let ty = self.structurally_resolved_type(span, ty.value);
-                assert!(matches!(ty.kind(), ty::Error(_)));
+                let ty = self.resolve_vars_if_possible(ty.value);
+                let guar = match *ty.kind() {
+                    ty::Infer(ty::TyVar(_)) => self
+                        .err_ctxt()
+                        .emit_inference_failure_err(self.body_id, span, ty.into(), E0282, true)
+                        .emit(),
+                    ty::Error(guar) => guar,
+                    _ => bug!("unexpected bad final type in method autoderef"),
+                };
+                self.demand_eqtype(span, ty, self.tcx.ty_error(guar));
                 return Err(MethodError::NoMatch(NoMatchData {
                     static_candidates: Vec::new(),
                     unsatisfied_predicates: Vec::new(),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 63370eec10b..15213c4b023 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -408,9 +408,9 @@ impl<'tcx> InferCtxt<'tcx> {
                 predicate
                     .kind()
                     .map_bound(|kind| match kind {
-                        ty::PredicateKind::Clause(ty::ClauseKind::Projection(
-                            projection_predicate,
-                        )) if projection_predicate.projection_ty.def_id == item_def_id => {
+                        ty::ClauseKind::Projection(projection_predicate)
+                            if projection_predicate.projection_ty.def_id == item_def_id =>
+                        {
                             projection_predicate.term.ty()
                         }
                         _ => None,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index a723dc3f079..2a32f0b5047 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -260,7 +260,8 @@ impl<T> Trait<T> for X {
                     (ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if alias.def_id.is_local() && matches!(tcx.def_kind(body_owner_def_id), DefKind::AssocFn | DefKind::AssocConst) => {
                         if tcx.is_type_alias_impl_trait(alias.def_id) {
                             if !tcx.opaque_types_defined_by(body_owner_def_id.expect_local()).contains(&alias.def_id.expect_local()) {
-                                diag.span_note(tcx.def_span(body_owner_def_id), "\
+                                let sp = tcx.def_ident_span(body_owner_def_id).unwrap_or_else(|| tcx.def_span(body_owner_def_id));
+                                diag.span_note(sp, "\
                                     this item must have the opaque type in its signature \
                                     in order to be able to register hidden types");
                             }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 9526ed144c3..7dbc18908d5 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1474,6 +1474,7 @@ impl<'tcx> InferCtxt<'tcx> {
     /// universes. Updates `self.universe` to that new universe.
     pub fn create_next_universe(&self) -> ty::UniverseIndex {
         let u = self.universe.get().next_universe();
+        debug!("create_next_universe {u:?}");
         self.universe.set(u);
         u
     }
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 3cb1788dc19..3098b8bc2f9 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -378,7 +378,7 @@ impl<'tcx> InferCtxt<'tcx> {
             DefiningAnchor::Bind(bind) => bind,
         };
 
-        let origin = self.opaque_type_origin_unchecked(def_id);
+        let origin = self.tcx.opaque_type_origin(def_id);
         let in_definition_scope = match origin {
             // Async `impl Trait`
             hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id,
@@ -395,13 +395,6 @@ impl<'tcx> InferCtxt<'tcx> {
         };
         in_definition_scope.then_some(origin)
     }
-
-    /// Returns the origin of the opaque type `def_id` even if we are not in its
-    /// defining scope.
-    #[instrument(skip(self), level = "trace", ret)]
-    fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin {
-        self.tcx.hir().expect_item(def_id).expect_opaque_ty().origin
-    }
 }
 
 /// Visitor that requires that (almost) all regions in the type visited outlive
@@ -649,9 +642,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 ct_op: |ct| ct,
             });
 
-            if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection)) =
-                predicate.kind().skip_binder()
-            {
+            if let ty::ClauseKind::Projection(projection) = predicate.kind().skip_binder() {
                 if projection.term.references_error() {
                     // No point on adding any obligations since there's a type error involved.
                     obligations.clear();
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 59ae2ce6c60..871171f9447 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -296,7 +296,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         trace!("{:#?}", bounds.skip_binder());
         bounds
             .subst_iter(tcx, alias_ty.substs)
-            .filter_map(|p| p.to_opt_type_outlives())
+            .filter_map(|p| p.as_type_outlives_clause())
             .filter_map(|p| p.no_bound_vars())
             .map(|OutlivesPredicate(_, r)| r)
     }
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 00d4934b749..26919872952 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -167,13 +167,33 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) {
     }
 }
 
+impl<'tcx> Elaboratable<'tcx> for (ty::Clause<'tcx>, Span) {
+    fn predicate(&self) -> ty::Predicate<'tcx> {
+        self.0.as_predicate()
+    }
+
+    fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
+        (predicate.expect_clause(), self.1)
+    }
+
+    fn child_with_derived_cause(
+        &self,
+        predicate: ty::Predicate<'tcx>,
+        _span: Span,
+        _parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
+        _index: usize,
+    ) -> Self {
+        (predicate.expect_clause(), self.1)
+    }
+}
+
 impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> {
     fn predicate(&self) -> ty::Predicate<'tcx> {
         self.as_predicate()
     }
 
     fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
-        predicate.as_clause().unwrap()
+        predicate.expect_clause()
     }
 
     fn child_with_derived_cause(
@@ -183,7 +203,7 @@ impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> {
         _parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
         _index: usize,
     ) -> Self {
-        predicate.as_clause().unwrap()
+        predicate.expect_clause()
     }
 }
 
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 5e3ea71f0e7..54dabb75764 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -36,7 +36,7 @@ pub type Result<T> = result::Result<T, ErrorGuaranteed>;
 /// Created by passing [`Config`] to [`run_compiler`].
 pub struct Compiler {
     pub(crate) sess: Lrc<Session>,
-    codegen_backend: Lrc<Box<dyn CodegenBackend>>,
+    codegen_backend: Lrc<dyn CodegenBackend>,
     pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>,
     pub(crate) override_queries: Option<fn(&Session, &mut Providers, &mut ExternProviders)>,
 }
@@ -45,7 +45,7 @@ impl Compiler {
     pub fn session(&self) -> &Lrc<Session> {
         &self.sess
     }
-    pub fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> {
+    pub fn codegen_backend(&self) -> &Lrc<dyn CodegenBackend> {
         &self.codegen_backend
     }
     pub fn register_lints(&self) -> &Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>> {
@@ -318,7 +318,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
 
             let compiler = Compiler {
                 sess: Lrc::new(sess),
-                codegen_backend: Lrc::new(codegen_backend),
+                codegen_backend: Lrc::from(codegen_backend),
                 register_lints: config.register_lints,
                 override_queries: config.override_queries,
             };
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index d1ba748d7af..8c4cdc6696a 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -115,7 +115,7 @@ impl<'tcx> Queries<'tcx> {
     fn session(&self) -> &Lrc<Session> {
         &self.compiler.sess
     }
-    fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> {
+    fn codegen_backend(&self) -> &Lrc<dyn CodegenBackend> {
         self.compiler.codegen_backend()
     }
 
@@ -259,7 +259,7 @@ impl<'tcx> Queries<'tcx> {
             // Hook for UI tests.
             Self::check_for_rustc_errors_attr(tcx);
 
-            Ok(passes::start_codegen(&***self.codegen_backend(), tcx))
+            Ok(passes::start_codegen(&**self.codegen_backend(), tcx))
         })
     }
 
@@ -324,7 +324,7 @@ impl<'tcx> Queries<'tcx> {
 pub struct Linker {
     // compilation inputs
     sess: Lrc<Session>,
-    codegen_backend: Lrc<Box<dyn CodegenBackend>>,
+    codegen_backend: Lrc<dyn CodegenBackend>,
 
     // compilation outputs
     dep_graph: DepGraph,
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 9fb83bec993..5c5ec452850 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1984,12 +1984,12 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN
 
 impl ExplicitOutlivesRequirements {
     fn lifetimes_outliving_lifetime<'tcx>(
-        inferred_outlives: &'tcx [(ty::ClauseKind<'tcx>, Span)],
+        inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)],
         def_id: DefId,
     ) -> Vec<ty::Region<'tcx>> {
         inferred_outlives
             .iter()
-            .filter_map(|(clause, _)| match *clause {
+            .filter_map(|(clause, _)| match clause.kind().skip_binder() {
                 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a {
                     ty::ReEarlyBound(ebr) if ebr.def_id == def_id => Some(b),
                     _ => None,
@@ -2000,12 +2000,12 @@ impl ExplicitOutlivesRequirements {
     }
 
     fn lifetimes_outliving_type<'tcx>(
-        inferred_outlives: &'tcx [(ty::ClauseKind<'tcx>, Span)],
+        inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)],
         index: u32,
     ) -> Vec<ty::Region<'tcx>> {
         inferred_outlives
             .iter()
-            .filter_map(|(clause, _)| match *clause {
+            .filter_map(|(clause, _)| match clause.kind().skip_binder() {
                 ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
                     a.is_param(index).then_some(b)
                 }
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index 61c23b4c255..63a56806a45 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
             // Liberate bound regions in the predicate since we
             // don't actually care about lifetimes in this check.
             let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.kind());
-            let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) = predicate else {
+            let ty::ClauseKind::Projection(proj) = predicate else {
                 continue;
             };
             // Only check types, since those are the only things that may
@@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
                     let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) {
                         (
                             ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }),
-                            ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)),
+                            ty::ClauseKind::Trait(trait_pred),
                         ) => Some(AddBound {
                             suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(),
                             trait_ref: trait_pred.print_modifiers_and_trait_path(),
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index e0033c48edb..5015b751eee 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -289,9 +289,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                         .filter_only_self()
                         .find_map(|(pred, _span)| {
                             // We only look at the `DefId`, so it is safe to skip the binder here.
-                            if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
-                                ref poly_trait_predicate,
-                            )) = pred.kind().skip_binder()
+                            if let ty::ClauseKind::Trait(ref poly_trait_predicate) =
+                                pred.kind().skip_binder()
                             {
                                 let def_id = poly_trait_predicate.trait_ref.def_id;
 
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 53ece08ac3d..cbb4458d1d4 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3464,7 +3464,8 @@ declare_lint! {
     /// out an update in your own time.
     pub LONG_RUNNING_CONST_EVAL,
     Deny,
-    "detects long const eval operations"
+    "detects long const eval operations",
+    report_in_external_macro
 }
 
 declare_lint! {
diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs
index b37dc826d28..84b18a62028 100644
--- a/compiler/rustc_macros/src/diagnostics/error.rs
+++ b/compiler/rustc_macros/src/diagnostics/error.rs
@@ -54,7 +54,7 @@ fn path_to_string(path: &syn::Path) -> String {
 
 /// Returns an error diagnostic on span `span` with msg `msg`.
 #[must_use]
-pub(crate) fn span_err(span: impl MultiSpan, msg: &str) -> Diagnostic {
+pub(crate) fn span_err<T: Into<String>>(span: impl MultiSpan, msg: T) -> Diagnostic {
     Diagnostic::spanned(span, Level::Error, msg)
 }
 
@@ -77,11 +77,9 @@ pub(crate) fn invalid_attr(attr: &Attribute) -> Diagnostic {
     let span = attr.span().unwrap();
     let path = path_to_string(attr.path());
     match attr.meta {
-        Meta::Path(_) => span_err(span, &format!("`#[{path}]` is not a valid attribute")),
-        Meta::NameValue(_) => {
-            span_err(span, &format!("`#[{path} = ...]` is not a valid attribute"))
-        }
-        Meta::List(_) => span_err(span, &format!("`#[{path}(...)]` is not a valid attribute")),
+        Meta::Path(_) => span_err(span, format!("`#[{path}]` is not a valid attribute")),
+        Meta::NameValue(_) => span_err(span, format!("`#[{path} = ...]` is not a valid attribute")),
+        Meta::List(_) => span_err(span, format!("`#[{path}(...)]` is not a valid attribute")),
     }
 }
 
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index e3d9eb96574..e8dc986914e 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -200,7 +200,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
 
                 throw_span_err!(
                     attr.span().unwrap(),
-                    &format!(
+                    format!(
                         "diagnostic slug must be first argument of a `#[{name}(...)]` attribute"
                     )
                 );
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index 85dd9f6a3ce..12563292181 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -347,7 +347,7 @@ pub(crate) trait HasFieldMap {
                 None => {
                     span_err(
                         span.unwrap(),
-                        &format!("`{field}` doesn't refer to a field on this type"),
+                        format!("`{field}` doesn't refer to a field on this type"),
                     )
                     .emit();
                     quote! {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 21cbab54293..90014bd9267 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -25,7 +25,7 @@ use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc_middle::ty::codec::TyDecoder;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::GeneratorDiagnosticData;
-use rustc_middle::ty::{self, ParameterizedOverTcx, Predicate, Ty, TyCtxt, Visibility};
+use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility};
 use rustc_serialize::opaque::MemDecoder;
 use rustc_serialize::{Decodable, Decoder};
 use rustc_session::cstore::{
@@ -642,6 +642,12 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx
     }
 }
 
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] {
+    fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self {
+        ty::codec::RefDecodable::decode(d)
+    }
+}
+
 impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyValue<T> {
     fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
         decoder.read_lazy()
@@ -854,7 +860,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         self,
         index: DefIndex,
         tcx: TyCtxt<'tcx>,
-    ) -> ty::EarlyBinder<&'tcx [(Predicate<'tcx>, Span)]> {
+    ) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> {
         let lazy = self.root.tables.explicit_item_bounds.get(self, index);
         let output = if lazy.is_default() {
             &mut []
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 12f3a0fc2c2..eee29d2090a 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1138,8 +1138,8 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
         | DefKind::InlineConst => true,
 
         DefKind::OpaqueTy => {
-            let opaque = tcx.hir().expect_item(def_id).expect_opaque_ty();
-            if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin
+            let origin = tcx.opaque_type_origin(def_id);
+            if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin
                 && let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id)
                 && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
             {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index d11308196ea..9cffd96f4a3 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -375,8 +375,8 @@ define_tables! {
     is_type_alias_impl_trait: Table<DefIndex, bool>,
     attr_flags: Table<DefIndex, AttrFlags>,
     def_path_hashes: Table<DefIndex, DefPathHash>,
-    explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>,
-    inferred_outlives_of: Table<DefIndex, LazyArray<(ty::ClauseKind<'static>, Span)>>,
+    explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
+    inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
     inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
     associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>,
     opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>,
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 1511e255235..ca735d52314 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -231,7 +231,7 @@ pub struct CodegenUnit<'tcx> {
     /// as well as the crate name and disambiguator.
     name: Symbol,
     items: FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)>,
-    size_estimate: Option<usize>,
+    size_estimate: usize,
     primary: bool,
     /// True if this is CGU is used to hold code coverage information for dead code,
     /// false otherwise.
@@ -269,7 +269,7 @@ impl<'tcx> CodegenUnit<'tcx> {
         CodegenUnit {
             name,
             items: Default::default(),
-            size_estimate: None,
+            size_estimate: 0,
             primary: false,
             is_code_coverage_dead_code_cgu: false,
         }
@@ -320,23 +320,21 @@ impl<'tcx> CodegenUnit<'tcx> {
         base_n::encode(hash, base_n::CASE_INSENSITIVE)
     }
 
-    pub fn create_size_estimate(&mut self, tcx: TyCtxt<'tcx>) {
+    pub fn compute_size_estimate(&mut self, tcx: TyCtxt<'tcx>) {
         // Estimate the size of a codegen unit as (approximately) the number of MIR
         // statements it corresponds to.
-        self.size_estimate = Some(self.items.keys().map(|mi| mi.size_estimate(tcx)).sum());
+        self.size_estimate = self.items.keys().map(|mi| mi.size_estimate(tcx)).sum();
     }
 
     #[inline]
-    /// Should only be called if [`create_size_estimate`] has previously been called.
+    /// Should only be called if [`compute_size_estimate`] has previously been called.
     ///
-    /// [`create_size_estimate`]: Self::create_size_estimate
+    /// [`compute_size_estimate`]: Self::compute_size_estimate
     pub fn size_estimate(&self) -> usize {
+        // Items are never zero-sized, so if we have items the estimate must be
+        // non-zero, unless we forgot to call `compute_size_estimate` first.
+        assert!(self.items.is_empty() || self.size_estimate != 0);
         self.size_estimate
-            .expect("create_size_estimate must be called before getting a size_estimate")
-    }
-
-    pub fn modify_size_estimate(&mut self, delta: usize) {
-        *self.size_estimate.as_mut().unwrap() += delta;
     }
 
     pub fn contains_item(&self, item: &MonoItem<'tcx>) -> bool {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 440dede1700..5d6a477b9ad 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -346,7 +346,7 @@ rustc_queries! {
     /// `key` is the `DefId` of the associated type or opaque type.
     ///
     /// Bounds from the parent (e.g. with nested impl trait) are not included.
-    query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, Span)]> {
+    query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> {
         desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
@@ -373,7 +373,7 @@ rustc_queries! {
     /// ```
     ///
     /// Bounds from the parent (e.g. with nested impl trait) are not included.
-    query item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
+    query item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Clause<'tcx>>> {
         desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
     }
 
@@ -647,7 +647,7 @@ rustc_queries! {
 
     /// Returns the inferred outlives predicates (e.g., for `struct
     /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
-    query inferred_outlives_of(key: DefId) -> &'tcx [(ty::ClauseKind<'tcx>, Span)] {
+    query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Clause<'tcx>, Span)] {
         desc { |tcx| "computing inferred outlives predicates of `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index 105667ba1e6..220118ae5cc 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -798,7 +798,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>
     }
 }
 
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::ClauseKind<'tcx>, Span)] {
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] {
     #[inline]
     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
         RefDecodable::decode(d)
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index ff8cd904ef8..248251e1ef5 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -128,6 +128,12 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Predicate<'tcx>
     }
 }
 
+impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Clause<'tcx> {
+    fn encode(&self, e: &mut E) {
+        self.as_predicate().encode(e);
+    }
+}
+
 impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Region<'tcx> {
     fn encode(&self, e: &mut E) {
         self.kind().encode(e);
@@ -241,6 +247,13 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Predicate<'tcx>
     }
 }
 
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Clause<'tcx> {
+    fn decode(decoder: &mut D) -> ty::Clause<'tcx> {
+        let pred: ty::Predicate<'tcx> = Decodable::decode(decoder);
+        pred.expect_clause()
+    }
+}
+
 impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for SubstsRef<'tcx> {
     fn decode(decoder: &mut D) -> Self {
         let len = decoder.read_usize();
@@ -365,9 +378,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
     }
 }
 
-impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
-    for [(ty::ClauseKind<'tcx>, Span)]
-{
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] {
     fn decode(decoder: &mut D) -> &'tcx Self {
         decoder.interner().arena.alloc_from_iter(
             (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(),
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 2b4f69167bf..1f9cf2c6448 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -25,10 +25,10 @@ use crate::traits::solve::{
     ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData,
 };
 use crate::ty::{
-    self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid,
-    GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
-    PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions,
-    TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility,
+    self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, FloatTy, FloatVar,
+    FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst,
+    ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind,
+    ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility,
 };
 use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
 use rustc_ast::{self as ast, attr};
@@ -141,7 +141,9 @@ pub struct CtxtInterners<'tcx> {
     region: InternedSet<'tcx, RegionKind<'tcx>>,
     poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
     predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
+    // FIXME(clause): remove this when all usages are moved to predicate
     predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
+    clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
     projs: InternedSet<'tcx, List<ProjectionKind>>,
     place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
     const_: InternedSet<'tcx, ConstData<'tcx>>,
@@ -167,6 +169,7 @@ impl<'tcx> CtxtInterners<'tcx> {
             canonical_var_infos: Default::default(),
             predicate: Default::default(),
             predicates: Default::default(),
+            clauses: Default::default(),
             projs: Default::default(),
             place_elems: Default::default(),
             const_: Default::default(),
@@ -1189,6 +1192,12 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn local_visibility(self, def_id: LocalDefId) -> Visibility {
         self.visibility(def_id).expect_local()
     }
+
+    /// Returns the origin of the opaque type `def_id`.
+    #[instrument(skip(self), level = "trace", ret)]
+    pub fn opaque_type_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin {
+        self.hir().expect_item(def_id).expect_opaque_ty().origin
+    }
 }
 
 /// A trait implemented for all `X<'a>` types that can be safely and
@@ -1533,6 +1542,7 @@ slice_interners!(
     canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>),
     poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
     predicates: intern_predicates(Predicate<'tcx>),
+    clauses: intern_clauses(Clause<'tcx>),
     projs: pub mk_projs(ProjectionKind),
     place_elems: pub mk_place_elems(PlaceElem<'tcx>),
     bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
@@ -1564,7 +1574,7 @@ impl<'tcx> TyCtxt<'tcx> {
         let future_trait = self.require_lang_item(LangItem::Future, None);
 
         self.explicit_item_bounds(def_id).skip_binder().iter().any(|&(predicate, _)| {
-            let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() else {
+            let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else {
                 return false;
             };
             trait_predicate.trait_ref.def_id == future_trait
@@ -2084,6 +2094,13 @@ impl<'tcx> TyCtxt<'tcx> {
         self.intern_predicates(preds)
     }
 
+    pub fn mk_clauses(self, preds: &[Clause<'tcx>]) -> &'tcx List<Clause<'tcx>> {
+        // FIXME consider asking the input slice to be sorted to avoid
+        // re-interning permutations, in which case that would be asserted
+        // here.
+        self.intern_clauses(preds)
+    }
+
     pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
     where
         I: Iterator<Item = T>,
@@ -2135,6 +2152,14 @@ impl<'tcx> TyCtxt<'tcx> {
         T::collect_and_apply(iter, |xs| self.mk_predicates(xs))
     }
 
+    pub fn mk_clauses_from_iter<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<Clause<'tcx>, &'tcx List<Clause<'tcx>>>,
+    {
+        T::collect_and_apply(iter, |xs| self.mk_clauses(xs))
+    }
+
     pub fn mk_type_list_from_iter<I, T>(self, iter: I) -> T::Output
     where
         I: Iterator<Item = T>,
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index c5a306fdf1f..c1d6856d33c 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -318,7 +318,13 @@ impl<'tcx> SizeSkeleton<'tcx> {
             Ok(layout) => {
                 return Ok(SizeSkeleton::Known(layout.size));
             }
-            Err(err) => err,
+            Err(err @ LayoutError::Unknown(_)) => err,
+            // We can't extract SizeSkeleton info from other layout errors
+            Err(
+                e @ LayoutError::Cycle
+                | e @ LayoutError::SizeOverflow(_)
+                | e @ LayoutError::NormalizationFailure(..),
+            ) => return Err(e),
         };
 
         match *ty.kind() {
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index cd459130827..0e604fdf6f4 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -602,6 +602,24 @@ impl<'tcx> Clause<'tcx> {
             None
         }
     }
+
+    pub fn as_type_outlives_clause(self) -> Option<Binder<'tcx, TypeOutlivesPredicate<'tcx>>> {
+        let clause = self.kind();
+        if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() {
+            Some(clause.rebind(o))
+        } else {
+            None
+        }
+    }
+
+    pub fn as_region_outlives_clause(self) -> Option<Binder<'tcx, RegionOutlivesPredicate<'tcx>>> {
+        let clause = self.kind();
+        if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() {
+            Some(clause.rebind(o))
+        } else {
+            None
+        }
+    }
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
@@ -713,7 +731,7 @@ pub struct CratePredicatesMap<'tcx> {
     /// predicate of its outlive bounds. If an item has no outlives
     /// bounds, it will have no entry.
     // FIXME(clause): should this be a `Clause`?
-    pub predicates: FxHashMap<DefId, &'tcx [(ClauseKind<'tcx>, Span)]>,
+    pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
 }
 
 impl<'tcx> Predicate<'tcx> {
@@ -1243,7 +1261,21 @@ impl<'tcx> ToPredicate<'tcx> for ClauseKind<'tcx> {
 impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> {
     #[inline(always)]
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause)))
+        tcx.mk_predicate(self.map_bound(ty::PredicateKind::Clause))
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
+    #[inline(always)]
+    fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+        self.as_predicate()
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ClauseKind<'tcx> {
+    #[inline(always)]
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+        tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(self))).expect_clause()
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 97d13822adc..cc2b26a5e14 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -128,6 +128,7 @@ parameterized_over_tcx! {
     ty::TraitRef,
     ty::Const,
     ty::Predicate,
+    ty::Clause,
     ty::ClauseKind,
     ty::GeneratorDiagnosticData,
 }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index fdcc608bf8e..7afda73862d 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -928,7 +928,7 @@ pub trait PrettyPrinter<'tcx>:
             let bound_predicate = predicate.kind();
 
             match bound_predicate.skip_binder() {
-                ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
+                ty::ClauseKind::Trait(pred) => {
                     let trait_ref = bound_predicate.rebind(pred.trait_ref);
 
                     // Don't print + Sized, but rather + ?Sized if absent.
@@ -939,7 +939,7 @@ pub trait PrettyPrinter<'tcx>:
 
                     self.insert_trait_and_projection(trait_ref, None, &mut traits, &mut fn_traits);
                 }
-                ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
+                ty::ClauseKind::Projection(pred) => {
                     let proj_ref = bound_predicate.rebind(pred);
                     let trait_ref = proj_ref.required_poly_trait_ref(tcx);
 
@@ -953,7 +953,7 @@ pub trait PrettyPrinter<'tcx>:
                         &mut fn_traits,
                     );
                 }
-                ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => {
+                ty::ClauseKind::TypeOutlives(outlives) => {
                     lifetimes.push(outlives.1);
                 }
                 _ => {}
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index e53e1e0a54c..959bf032a83 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -666,10 +666,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
         self,
         folder: &mut F,
     ) -> Result<Self, F::Error> {
-        Ok(folder
-            .try_fold_predicate(self.as_predicate())?
-            .as_clause()
-            .expect("no sensible folder would do this"))
+        Ok(folder.try_fold_predicate(self.as_predicate())?.expect_clause())
     }
 }
 
@@ -713,6 +710,15 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Predicate<'tcx>> {
     }
 }
 
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Clause<'tcx>> {
+    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        ty::util::fold_list(self, folder, |tcx, v| tcx.mk_clauses(v))
+    }
+}
+
 impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
     fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
         self,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 3b63b08de5b..c0627ab5c01 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1584,7 +1584,7 @@ pub struct EarlyBoundRegion {
 
 impl fmt::Debug for EarlyBoundRegion {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}, {}", self.index, self.name)
+        write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name)
     }
 }
 
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 9f58cce2769..029fb2e9ba0 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1824,7 +1824,7 @@ fn check_must_not_suspend_ty<'tcx>(
             let mut has_emitted = false;
             for &(predicate, _) in tcx.explicit_item_bounds(def).skip_binder() {
                 // We only look at the `DefId`, so it is safe to skip the binder here.
-                if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ref poly_trait_predicate)) =
+                if let ty::ClauseKind::Trait(ref poly_trait_predicate) =
                     predicate.kind().skip_binder()
                 {
                     let def_id = poly_trait_predicate.trait_ref.def_id;
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 531644f0b84..97e3748b8b8 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -125,7 +125,7 @@ struct PartitioningCx<'a, 'tcx> {
     usage_map: &'a UsageMap<'tcx>,
 }
 
-struct PlacedRootMonoItems<'tcx> {
+struct PlacedMonoItems<'tcx> {
     /// The codegen units, sorted by name to make things deterministic.
     codegen_units: Vec<CodegenUnit<'tcx>>,
 
@@ -150,18 +150,13 @@ where
 
     let cx = &PartitioningCx { tcx, usage_map };
 
-    // In the first step, we place all regular monomorphizations into their
-    // respective 'home' codegen unit. Regular monomorphizations are all
-    // functions and statics defined in the local crate.
-    let PlacedRootMonoItems { mut codegen_units, internalization_candidates, unique_inlined_stats } = {
-        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
-        let mut placed = place_root_mono_items(cx, mono_items);
+    // Place all mono items into a codegen unit. `place_mono_items` is
+    // responsible for initializing the CGU size estimates.
+    let PlacedMonoItems { mut codegen_units, internalization_candidates, unique_inlined_stats } = {
+        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_items");
+        let placed = place_mono_items(cx, mono_items);
 
-        for cgu in &mut placed.codegen_units {
-            cgu.create_size_estimate(tcx);
-        }
-
-        debug_dump(tcx, "ROOTS", &placed.codegen_units, placed.unique_inlined_stats);
+        debug_dump(tcx, "PLACE", &placed.codegen_units, placed.unique_inlined_stats);
 
         placed
     };
@@ -175,23 +170,8 @@ where
         debug_dump(tcx, "MERGE", &codegen_units, unique_inlined_stats);
     }
 
-    // In the next step, we use the inlining map to determine which additional
-    // monomorphizations have to go into each codegen unit. These additional
-    // monomorphizations can be drop-glue, functions from external crates, and
-    // local functions the definition of which is marked with `#[inline]`.
-    {
-        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items");
-        place_inlined_mono_items(cx, &mut codegen_units);
-
-        for cgu in &mut codegen_units {
-            cgu.create_size_estimate(tcx);
-        }
-
-        debug_dump(tcx, "INLINE", &codegen_units, unique_inlined_stats);
-    }
-
-    // Next we try to make as many symbols "internal" as possible, so LLVM has
-    // more freedom to optimize.
+    // Make as many symbols "internal" as possible, so LLVM has more freedom to
+    // optimize.
     if !tcx.sess.link_dead_code() {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
         internalize_symbols(cx, &mut codegen_units, internalization_candidates);
@@ -212,10 +192,7 @@ where
     codegen_units
 }
 
-fn place_root_mono_items<'tcx, I>(
-    cx: &PartitioningCx<'_, 'tcx>,
-    mono_items: I,
-) -> PlacedRootMonoItems<'tcx>
+fn place_mono_items<'tcx, I>(cx: &PartitioningCx<'_, 'tcx>, mono_items: I) -> PlacedMonoItems<'tcx>
 where
     I: Iterator<Item = MonoItem<'tcx>>,
 {
@@ -236,6 +213,8 @@ where
     let mut num_unique_inlined_items = 0;
     let mut unique_inlined_items_size = 0;
     for mono_item in mono_items {
+        // Handle only root items directly here. Inlined items are handled at
+        // the bottom of the loop based on reachability.
         match mono_item.instantiation_mode(cx.tcx) {
             InstantiationMode::GloballyShared { .. } => {}
             InstantiationMode::LocalCopy => {
@@ -248,7 +227,7 @@ where
         let characteristic_def_id = characteristic_def_id_of_mono_item(cx.tcx, mono_item);
         let is_volatile = is_incremental_build && mono_item.is_generic_fn();
 
-        let codegen_unit_name = match characteristic_def_id {
+        let cgu_name = match characteristic_def_id {
             Some(def_id) => compute_codegen_unit_name(
                 cx.tcx,
                 cgu_name_builder,
@@ -259,9 +238,7 @@ where
             None => fallback_cgu_name(cgu_name_builder),
         };
 
-        let codegen_unit = codegen_units
-            .entry(codegen_unit_name)
-            .or_insert_with(|| CodegenUnit::new(codegen_unit_name));
+        let cgu = codegen_units.entry(cgu_name).or_insert_with(|| CodegenUnit::new(cgu_name));
 
         let mut can_be_internalized = true;
         let (linkage, visibility) = mono_item_linkage_and_visibility(
@@ -274,23 +251,56 @@ where
             internalization_candidates.insert(mono_item);
         }
 
-        codegen_unit.items_mut().insert(mono_item, (linkage, visibility));
+        cgu.items_mut().insert(mono_item, (linkage, visibility));
+
+        // Get all inlined items that are reachable from `mono_item` without
+        // going via another root item. This includes drop-glue, functions from
+        // external crates, and local functions the definition of which is
+        // marked with `#[inline]`.
+        let mut reachable_inlined_items = FxHashSet::default();
+        get_reachable_inlined_items(cx.tcx, mono_item, cx.usage_map, &mut reachable_inlined_items);
+
+        // Add those inlined items. It's possible an inlined item is reachable
+        // from multiple root items within a CGU, which is fine, it just means
+        // the `insert` will be a no-op.
+        for inlined_item in reachable_inlined_items {
+            // This is a CGU-private copy.
+            cgu.items_mut().insert(inlined_item, (Linkage::Internal, Visibility::Default));
+        }
     }
 
     // Always ensure we have at least one CGU; otherwise, if we have a
     // crate with just types (for example), we could wind up with no CGU.
     if codegen_units.is_empty() {
-        let codegen_unit_name = fallback_cgu_name(cgu_name_builder);
-        codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name));
+        let cgu_name = fallback_cgu_name(cgu_name_builder);
+        codegen_units.insert(cgu_name, CodegenUnit::new(cgu_name));
     }
 
     let mut codegen_units: Vec<_> = codegen_units.into_values().collect();
     codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
 
-    PlacedRootMonoItems {
+    for cgu in codegen_units.iter_mut() {
+        cgu.compute_size_estimate(cx.tcx);
+    }
+
+    return PlacedMonoItems {
         codegen_units,
         internalization_candidates,
         unique_inlined_stats: (num_unique_inlined_items, unique_inlined_items_size),
+    };
+
+    fn get_reachable_inlined_items<'tcx>(
+        tcx: TyCtxt<'tcx>,
+        item: MonoItem<'tcx>,
+        usage_map: &UsageMap<'tcx>,
+        visited: &mut FxHashSet<MonoItem<'tcx>>,
+    ) {
+        usage_map.for_each_inlined_used_item(tcx, item, |inlined_item| {
+            let is_new = visited.insert(inlined_item);
+            if is_new {
+                get_reachable_inlined_items(tcx, inlined_item, usage_map, visited);
+            }
+        });
     }
 }
 
@@ -314,7 +324,7 @@ fn merge_codegen_units<'tcx>(
     // worse generated code. So we don't allow CGUs smaller than this (unless
     // there is just one CGU, of course). Note that CGU sizes of 100,000+ are
     // common in larger programs, so this isn't all that large.
-    const NON_INCR_MIN_CGU_SIZE: usize = 1000;
+    const NON_INCR_MIN_CGU_SIZE: usize = 1800;
 
     // Repeatedly merge the two smallest codegen units as long as:
     // - we have more CGUs than the upper limit, or
@@ -338,9 +348,11 @@ fn merge_codegen_units<'tcx>(
         let mut smallest = codegen_units.pop().unwrap();
         let second_smallest = codegen_units.last_mut().unwrap();
 
-        // Move the mono-items from `smallest` to `second_smallest`
-        second_smallest.modify_size_estimate(smallest.size_estimate());
+        // Move the items from `smallest` to `second_smallest`. Some of them
+        // may be duplicate inlined items, in which case the destination CGU is
+        // unaffected. Recalculate size estimates afterwards.
         second_smallest.items_mut().extend(smallest.items_mut().drain());
+        second_smallest.compute_size_estimate(cx.tcx);
 
         // Record that `second_smallest` now contains all the stuff that was
         // in `smallest` before.
@@ -406,43 +418,6 @@ fn merge_codegen_units<'tcx>(
     codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
 }
 
-fn place_inlined_mono_items<'tcx>(
-    cx: &PartitioningCx<'_, 'tcx>,
-    codegen_units: &mut [CodegenUnit<'tcx>],
-) {
-    for cgu in codegen_units.iter_mut() {
-        // Collect all inlined items that need to be available in this codegen unit.
-        let mut reachable_inlined_items = FxHashSet::default();
-        for root in cgu.items().keys() {
-            // Get all inlined items that are reachable from it without going
-            // via another root item.
-            get_reachable_inlined_items(cx.tcx, *root, cx.usage_map, &mut reachable_inlined_items);
-        }
-
-        // Add all monomorphizations that are not already there.
-        for inlined_item in reachable_inlined_items {
-            assert!(!cgu.items().contains_key(&inlined_item));
-
-            // This is a CGU-private copy.
-            cgu.items_mut().insert(inlined_item, (Linkage::Internal, Visibility::Default));
-        }
-    }
-
-    fn get_reachable_inlined_items<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        item: MonoItem<'tcx>,
-        usage_map: &UsageMap<'tcx>,
-        visited: &mut FxHashSet<MonoItem<'tcx>>,
-    ) {
-        usage_map.for_each_inlined_used_item(tcx, item, |inlined_item| {
-            let is_new = visited.insert(inlined_item);
-            if is_new {
-                get_reachable_inlined_items(tcx, inlined_item, usage_map, visited);
-            }
-        });
-    }
-}
-
 fn internalize_symbols<'tcx>(
     cx: &PartitioningCx<'_, 'tcx>,
     codegen_units: &mut [CodegenUnit<'tcx>],
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index b897a6198e3..8a848e5db62 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -114,6 +114,12 @@ trait DefIdVisitor<'tcx> {
     ) -> ControlFlow<Self::BreakTy> {
         self.skeleton().visit_predicates(predicates)
     }
+    fn visit_clauses(
+        &mut self,
+        predicates: &[(ty::Clause<'tcx>, Span)],
+    ) -> ControlFlow<Self::BreakTy> {
+        self.skeleton().visit_clauses(predicates)
+    }
 }
 
 struct DefIdVisitorSkeleton<'v, 'tcx, V: ?Sized> {
@@ -159,42 +165,23 @@ where
         }
     }
 
-    fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<V::BreakTy> {
-        match predicate.kind().skip_binder() {
-            ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
-                trait_ref,
-                constness: _,
-                polarity: _,
-            })) => self.visit_trait(trait_ref),
-            ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
-                projection_ty,
-                term,
-            })) => {
+    fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> ControlFlow<V::BreakTy> {
+        match clause.kind().skip_binder() {
+            ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness: _, polarity: _ }) => {
+                self.visit_trait(trait_ref)
+            }
+            ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
                 term.visit_with(self)?;
                 self.visit_projection_ty(projection_ty)
             }
-            ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
-                ty,
-                _region,
-            ))) => ty.visit_with(self),
-            ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => {
-                ControlFlow::Continue(())
-            }
-            ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
+            ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self),
+            ty::ClauseKind::RegionOutlives(..) => ControlFlow::Continue(()),
+            ty::ClauseKind::ConstArgHasType(ct, ty) => {
                 ct.visit_with(self)?;
                 ty.visit_with(self)
             }
-            ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => ct.visit_with(self),
-            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => arg.visit_with(self),
-
-            ty::PredicateKind::ObjectSafe(_)
-            | ty::PredicateKind::ClosureKind(_, _, _)
-            | ty::PredicateKind::Subtype(_)
-            | ty::PredicateKind::Coerce(_)
-            | ty::PredicateKind::ConstEquate(_, _)
-            | ty::PredicateKind::TypeWellFormedFromEnv(_)
-            | ty::PredicateKind::Ambiguous
-            | ty::PredicateKind::AliasRelate(..) => bug!("unexpected predicate: {:?}", predicate),
+            ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self),
+            ty::ClauseKind::WellFormed(arg) => arg.visit_with(self),
         }
     }
 
@@ -203,7 +190,16 @@ where
         predicates: ty::GenericPredicates<'tcx>,
     ) -> ControlFlow<V::BreakTy> {
         let ty::GenericPredicates { parent: _, predicates } = predicates;
-        predicates.iter().try_for_each(|&(predicate, _span)| self.visit_predicate(predicate))
+        predicates.iter().try_for_each(|&(predicate, _span)| {
+            let clause = predicate
+                .as_clause()
+                .unwrap_or_else(|| bug!("unexpected predicate: {:?}", predicate));
+            self.visit_clause(clause)
+        })
+    }
+
+    fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> ControlFlow<V::BreakTy> {
+        clauses.iter().try_for_each(|&(clause, _span)| self.visit_clause(clause))
     }
 }
 
@@ -307,10 +303,7 @@ where
                     // through the trait list (default type visitor doesn't visit those traits).
                     // All traits in the list are considered the "primary" part of the type
                     // and are visited by shallow visitors.
-                    self.visit_predicates(ty::GenericPredicates {
-                        parent: None,
-                        predicates: tcx.explicit_item_bounds(def_id).skip_binder(),
-                    })?;
+                    self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder())?;
                 }
             }
             // These types don't have their own def-ids (but may have subcomponents
@@ -1814,10 +1807,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
 
     fn bounds(&mut self) -> &mut Self {
         self.in_primary_interface = false;
-        self.visit_predicates(ty::GenericPredicates {
-            parent: None,
-            predicates: self.tcx.explicit_item_bounds(self.item_def_id).skip_binder(),
-        });
+        self.visit_clauses(self.tcx.explicit_item_bounds(self.item_def_id).skip_binder());
         self
     }
 
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 539b4a1d5e7..d77fb922e84 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -103,6 +103,7 @@ pub(crate) struct ImportSuggestion {
     pub descr: &'static str,
     pub path: Path,
     pub accessible: bool,
+    pub via_import: bool,
     /// An extra note that should be issued if this item is suggested
     pub note: Option<String>,
 }
@@ -140,9 +141,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         let mut reported_spans = FxHashSet::default();
-        for error in &self.privacy_errors {
+        for error in std::mem::take(&mut self.privacy_errors) {
             if reported_spans.insert(error.dedup_span) {
-                self.report_privacy_error(error);
+                self.report_privacy_error(&error);
             }
         }
     }
@@ -1256,6 +1257,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                 path,
                                 accessible: child_accessible,
                                 note,
+                                via_import,
                             });
                         }
                     }
@@ -1609,8 +1611,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         None
     }
 
-    fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
-        let PrivacyError { ident, binding, .. } = *privacy_error;
+    fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'a>) {
+        let PrivacyError { ident, binding, outermost_res, parent_scope, dedup_span } =
+            *privacy_error;
 
         let res = binding.res();
         let ctor_fields_span = self.ctor_fields_span(binding);
@@ -1627,6 +1630,33 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident);
         err.span_label(ident.span, format!("private {}", descr));
 
+        if let Some((this_res, outer_ident)) = outermost_res {
+            let import_suggestions = self.lookup_import_candidates(
+                outer_ident,
+                this_res.ns().unwrap_or(Namespace::TypeNS),
+                &parent_scope,
+                &|res: Res| res == this_res,
+            );
+            let point_to_def = !show_candidates(
+                self.tcx,
+                &mut err,
+                Some(dedup_span.until(outer_ident.span.shrink_to_hi())),
+                &import_suggestions,
+                Instead::Yes,
+                FoundUse::Yes,
+                DiagnosticMode::Import,
+                vec![],
+                "",
+            );
+            // If we suggest importing a public re-export, don't point at the definition.
+            if point_to_def && ident.span != outer_ident.span {
+                err.span_label(
+                    outer_ident.span,
+                    format!("{} `{outer_ident}` is not publicly re-exported", this_res.descr()),
+                );
+            }
+        }
+
         let mut non_exhaustive = None;
         // If an ADT is foreign and marked as `non_exhaustive`, then that's
         // probably why we have the privacy error.
@@ -2455,7 +2485,8 @@ pub(crate) fn import_candidates(
 
 /// When an entity with a given name is not available in scope, we search for
 /// entities with that name in all crates. This method allows outputting the
-/// results of this search in a programmer-friendly way
+/// results of this search in a programmer-friendly way. If any entities are
+/// found and suggested, returns `true`, otherwise returns `false`.
 fn show_candidates(
     tcx: TyCtxt<'_>,
     err: &mut Diagnostic,
@@ -2467,19 +2498,19 @@ fn show_candidates(
     mode: DiagnosticMode,
     path: Vec<Segment>,
     append: &str,
-) {
+) -> bool {
     if candidates.is_empty() {
-        return;
+        return false;
     }
 
-    let mut accessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> =
+    let mut accessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>, bool)> =
         Vec::new();
-    let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> =
+    let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>, bool)> =
         Vec::new();
 
     candidates.iter().for_each(|c| {
         (if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings })
-            .push((path_names_to_string(&c.path), c.descr, c.did, &c.note))
+            .push((path_names_to_string(&c.path), c.descr, c.did, &c.note, c.via_import))
     });
 
     // we want consistent results across executions, but candidates are produced
@@ -2493,20 +2524,25 @@ fn show_candidates(
     }
 
     if !accessible_path_strings.is_empty() {
-        let (determiner, kind, name) = if accessible_path_strings.len() == 1 {
-            ("this", accessible_path_strings[0].1, format!(" `{}`", accessible_path_strings[0].0))
-        } else {
-            ("one of these", "items", String::new())
-        };
+        let (determiner, kind, name, through) =
+            if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] {
+                (
+                    "this",
+                    *descr,
+                    format!(" `{name}`"),
+                    if *via_import { " through its public re-export" } else { "" },
+                )
+            } else {
+                ("one of these", "items", String::new(), "")
+            };
 
         let instead = if let Instead::Yes = instead { " instead" } else { "" };
         let mut msg = if let DiagnosticMode::Pattern = mode {
             format!(
-                "if you meant to match on {}{}{}, use the full path in the pattern",
-                kind, instead, name
+                "if you meant to match on {kind}{instead}{name}, use the full path in the pattern",
             )
         } else {
-            format!("consider importing {} {}{}", determiner, kind, instead)
+            format!("consider importing {determiner} {kind}{through}{instead}")
         };
 
         for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
@@ -2522,7 +2558,7 @@ fn show_candidates(
                         accessible_path_strings.into_iter().map(|a| a.0),
                         Applicability::MaybeIncorrect,
                     );
-                    return;
+                    return true;
                 }
                 DiagnosticMode::Import => ("", ""),
                 DiagnosticMode::Normal => ("use ", ";\n"),
@@ -2563,6 +2599,7 @@ fn show_candidates(
 
             err.help(msg);
         }
+        true
     } else if !matches!(mode, DiagnosticMode::Import) {
         assert!(!inaccessible_path_strings.is_empty());
 
@@ -2571,13 +2608,9 @@ fn show_candidates(
         } else {
             ""
         };
-        if inaccessible_path_strings.len() == 1 {
-            let (name, descr, def_id, note) = &inaccessible_path_strings[0];
+        if let [(name, descr, def_id, note, _)] = &inaccessible_path_strings[..] {
             let msg = format!(
-                "{}{} `{}`{} exists but is inaccessible",
-                prefix,
-                descr,
-                name,
+                "{prefix}{descr} `{name}`{} exists but is inaccessible",
                 if let DiagnosticMode::Pattern = mode { ", which" } else { "" }
             );
 
@@ -2594,11 +2627,11 @@ fn show_candidates(
                 err.note(note.to_string());
             }
         } else {
-            let (_, descr_first, _, _) = &inaccessible_path_strings[0];
+            let (_, descr_first, _, _, _) = &inaccessible_path_strings[0];
             let descr = if inaccessible_path_strings
                 .iter()
                 .skip(1)
-                .all(|(_, descr, _, _)| descr == descr_first)
+                .all(|(_, descr, _, _, _)| descr == descr_first)
             {
                 descr_first
             } else {
@@ -2611,7 +2644,7 @@ fn show_candidates(
             let mut has_colon = false;
 
             let mut spans = Vec::new();
-            for (name, _, def_id, _) in &inaccessible_path_strings {
+            for (name, _, def_id, _, _) in &inaccessible_path_strings {
                 if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
                     let span = tcx.source_span(local_def_id);
                     let span = tcx.sess.source_map().guess_head_span(span);
@@ -2637,6 +2670,9 @@ fn show_candidates(
 
             err.span_note(multi_span, msg);
         }
+        true
+    } else {
+        false
     }
 }
 
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index e29a1626aed..e5fa062967f 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -893,6 +893,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         ident,
                         binding,
                         dedup_span: path_span,
+                        outermost_res: None,
+                        parent_scope: *parent_scope,
                     });
                 } else {
                     return Err((Determined, Weak::No));
@@ -1369,6 +1371,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let mut allow_super = true;
         let mut second_binding = None;
 
+        // We'll provide more context to the privacy errors later, up to `len`.
+        let privacy_errors_len = self.privacy_errors.len();
+
         for (segment_idx, &Segment { ident, id, .. }) in path.iter().enumerate() {
             debug!("resolve_path ident {} {:?} {:?}", segment_idx, ident, id);
             let record_segment_res = |this: &mut Self, res| {
@@ -1506,6 +1511,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         second_binding = Some(binding);
                     }
                     let res = binding.res();
+
+                    // Mark every privacy error in this path with the res to the last element. This allows us
+                    // to detect the item the user cares about and either find an alternative import, or tell
+                    // the user it is not accessible.
+                    for error in &mut self.privacy_errors[privacy_errors_len..] {
+                        error.outermost_res = Some((res, ident));
+                    }
+
                     let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res);
                     if let Some(next_module) = binding.module() {
                         module = Some(ModuleOrUniformRoot::Module(next_module));
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 47d8e5993fd..c458fc872aa 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -609,7 +609,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
     }
 
-    fn throw_unresolved_import_error(&self, errors: Vec<(&Import<'_>, UnresolvedImportError)>) {
+    fn throw_unresolved_import_error(&mut self, errors: Vec<(&Import<'_>, UnresolvedImportError)>) {
         if errors.is_empty() {
             return;
         }
@@ -679,6 +679,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     _ => {}
                 }
             }
+
+            match &import.kind {
+                ImportKind::Single { source, .. } => {
+                    if let Some(ModuleOrUniformRoot::Module(module)) = import.imported_module.get()
+                     && let Some(module) = module.opt_def_id()
+                    {
+                        self.find_cfg_stripped(&mut diag, &source.name, module)
+                    }
+                },
+                _ => {}
+            }
         }
 
         diag.emit();
@@ -792,6 +803,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         };
         let prev_ambiguity_errors_len = self.ambiguity_errors.len();
         let finalize = Finalize::with_root_span(import.root_id, import.span, import.root_span);
+
+        // We'll provide more context to the privacy errors later, up to `len`.
+        let privacy_errors_len = self.privacy_errors.len();
+
         let path_res = self.resolve_path(
             &import.module_path,
             None,
@@ -931,6 +946,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 _ => unreachable!(),
             };
 
+        if self.privacy_errors.len() != privacy_errors_len {
+            // Get the Res for the last element, so that we can point to alternative ways of
+            // importing it if available.
+            let mut path = import.module_path.clone();
+            path.push(Segment::from_ident(ident));
+            if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
+                self.resolve_path(&path, None, &import.parent_scope, Some(finalize), ignore_binding)
+            {
+                let res = module.res().map(|r| (r, ident));
+                for error in &mut self.privacy_errors[privacy_errors_len..] {
+                    error.outermost_res = res;
+                }
+            }
+        }
+
         let mut all_ns_err = true;
         self.per_ns(|this, ns| {
             if !type_ns_only || ns == TypeNS {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 7284b33f09d..475772734ff 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1831,6 +1831,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                                 path,
                                 accessible: true,
                                 note: None,
+                                via_import: false,
                             },
                         ));
                     } else {
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 82b333fee28..8c1cd2f1557 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -689,10 +689,13 @@ impl<'a> NameBindingKind<'a> {
     }
 }
 
+#[derive(Debug)]
 struct PrivacyError<'a> {
     ident: Ident,
     binding: &'a NameBinding<'a>,
     dedup_span: Span,
+    outermost_res: Option<(Res, Ident)>,
+    parent_scope: ParentScope<'a>,
 }
 
 #[derive(Debug)]
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index edf95949d32..270d8331602 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1613,7 +1613,7 @@ options! {
     plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "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)"),
+        (default: PLT is disabled if full relro is enabled on x86_64)"),
     polonius: bool = (false, parse_bool, [TRACKED],
         "enable polonius-based borrow-checker (default: no)"),
     polymorphize: bool = (false, parse_bool, [TRACKED],
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 5feea83edb6..ea5beb6f8be 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -1009,11 +1009,11 @@ impl Session {
         self.edition().rust_2024()
     }
 
-    /// Returns `true` if we cannot skip the PLT for shared library calls.
+    /// Returns `true` if we should use the PLT for shared library calls.
     pub fn needs_plt(&self) -> bool {
-        // Check if the current target usually needs PLT to be enabled.
+        // Check if the current target usually wants PLT to be enabled.
         // The user can use the command line flag to override it.
-        let needs_plt = self.target.needs_plt;
+        let want_plt = self.target.plt_by_default;
 
         let dbg_opts = &self.opts.unstable_opts;
 
@@ -1025,8 +1025,8 @@ impl Session {
         let full_relro = RelroLevel::Full == relro_level;
 
         // If user didn't explicitly forced us to use / skip the PLT,
-        // then try to skip it where possible.
-        dbg_opts.plt.unwrap_or(needs_plt || !full_relro)
+        // then use it unless the target doesn't want it by default or the full relro forces it on.
+        dbg_opts.plt.unwrap_or(want_plt || !full_relro)
     }
 
     /// Checks if LLVM lifetime markers should be emitted.
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
index bb7c39ff26b..f7cdfa71c4b 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
@@ -1,10 +1,10 @@
-use super::apple_base::{opts, Arch};
+use super::apple_base::{opts, tvos_llvm_target, Arch};
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub fn target() -> Target {
     let arch = Arch::Arm64;
     Target {
-        llvm_target: "arm64-apple-tvos".into(),
+        llvm_target: tvos_llvm_target(arch).into(),
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/apple/tests.rs b/compiler/rustc_target/src/spec/apple/tests.rs
index 3c90a5e7e93..3b23ddadcc4 100644
--- a/compiler/rustc_target/src/spec/apple/tests.rs
+++ b/compiler/rustc_target/src/spec/apple/tests.rs
@@ -30,6 +30,9 @@ fn macos_link_environment_unmodified() {
     for target in all_macos_targets {
         // macOS targets should only remove information for cross-compiling, but never
         // for the host.
-        assert_eq!(target.link_env_remove, crate::spec::cvs!["IPHONEOS_DEPLOYMENT_TARGET"]);
+        assert_eq!(
+            target.link_env_remove,
+            crate::spec::cvs!["IPHONEOS_DEPLOYMENT_TARGET", "TVOS_DEPLOYMENT_TARGET"],
+        );
     }
 }
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
index ff224631828..8a8d1ab95e8 100644
--- a/compiler/rustc_target/src/spec/apple_base.rs
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -240,7 +240,12 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]>
         // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which
         // may occur when we're linking a custom build script while targeting iOS for example.
         if let Ok(sdkroot) = env::var("SDKROOT") {
-            if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform")
+            if sdkroot.contains("iPhoneOS.platform")
+                || sdkroot.contains("iPhoneSimulator.platform")
+                || sdkroot.contains("AppleTVOS.platform")
+                || sdkroot.contains("AppleTVSimulator.platform")
+                || sdkroot.contains("WatchOS.platform")
+                || sdkroot.contains("WatchSimulator.platform")
             {
                 env_remove.push("SDKROOT".into())
             }
@@ -249,6 +254,7 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]>
         // "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld",
         // although this is apparently ignored when using the linker at "/usr/bin/ld".
         env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".into());
+        env_remove.push("TVOS_DEPLOYMENT_TARGET".into());
         env_remove.into()
     } else {
         // Otherwise if cross-compiling for a different OS/SDK, remove any part
@@ -299,6 +305,16 @@ fn tvos_lld_platform_version() -> String {
     format!("{major}.{minor}")
 }
 
+pub fn tvos_llvm_target(arch: Arch) -> String {
+    let (major, minor) = tvos_deployment_target();
+    format!("{}-apple-tvos{}.{}.0", arch.target_name(), major, minor)
+}
+
+pub fn tvos_sim_llvm_target(arch: Arch) -> String {
+    let (major, minor) = tvos_deployment_target();
+    format!("{}-apple-tvos{}.{}.0-simulator", arch.target_name(), major, minor)
+}
+
 fn watchos_deployment_target() -> (u32, u32) {
     // If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
     from_set_deployment_target("WATCHOS_DEPLOYMENT_TARGET").unwrap_or((5, 0))
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 0f26b703536..c15a330ee74 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1670,7 +1670,7 @@ pub struct TargetOptions {
     pub static_position_independent_executables: bool,
     /// Determines if the target always requires using the PLT for indirect
     /// library calls or not. This controls the default value of the `-Z plt` flag.
-    pub needs_plt: bool,
+    pub plt_by_default: bool,
     /// Either partial, full, or off. Full RELRO makes the dynamic linker
     /// resolve all symbols at startup and marks the GOT read-only before
     /// starting the program, preventing overwriting the GOT.
@@ -1992,7 +1992,7 @@ impl Default for TargetOptions {
             no_default_libraries: true,
             position_independent_executables: false,
             static_position_independent_executables: false,
-            needs_plt: false,
+            plt_by_default: true,
             relro_level: RelroLevel::None,
             pre_link_objects: Default::default(),
             post_link_objects: Default::default(),
@@ -2665,7 +2665,7 @@ impl Target {
         key!(no_default_libraries, bool);
         key!(position_independent_executables, bool);
         key!(static_position_independent_executables, bool);
-        key!(needs_plt, bool);
+        key!(plt_by_default, bool);
         key!(relro_level, RelroLevel)?;
         key!(archive_format);
         key!(allow_asm, bool);
@@ -2921,7 +2921,7 @@ impl ToJson for Target {
         target_option_val!(no_default_libraries);
         target_option_val!(position_independent_executables);
         target_option_val!(static_position_independent_executables);
-        target_option_val!(needs_plt);
+        target_option_val!(plt_by_default);
         target_option_val!(relro_level);
         target_option_val!(archive_format);
         target_option_val!(allow_asm);
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
index 76de7d20c4c..2ec4d9569e3 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
@@ -1,12 +1,13 @@
-use super::apple_base::{opts, Arch};
+use super::apple_base::{opts, tvos_sim_llvm_target, Arch};
 use crate::spec::{StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let arch = Arch::X86_64_sim;
     Target {
-        llvm_target: "x86_64-apple-tvos".into(),
+        llvm_target: tvos_sim_llvm_target(arch).into(),
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".into(),
+        data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .into(),
         arch: arch.target_arch(),
         options: TargetOptions {
             max_atomic_width: Some(128),
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 cba6fda19dc..a7ed74f4721 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
@@ -63,6 +63,7 @@ pub fn target() -> Target {
         linker: Some("rust-lld".into()),
         max_atomic_width: Some(64),
         cpu: "x86-64".into(),
+        plt_by_default: false,
         features: "+rdrnd,+rdseed,+lvi-cfi,+lvi-load-hardening".into(),
         llvm_args: cvs!["--x86-experimental-lvi-inline-asm-hardening"],
         position_independent_executables: true,
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 a3bdb5f5465..c110674fd87 100644
--- a/compiler/rustc_target/src/spec/x86_64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/x86_64_linux_android.rs
@@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, T
 pub fn target() -> Target {
     let mut base = super::android_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     // 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);
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs
index 6fb2dfd807a..8424757df07 100644
--- a/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs
+++ b/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
         arch: "x86_64".into(),
         options: TargetOptions {
             cpu: "x86-64".into(),
+            plt_by_default: false,
             max_atomic_width: Some(64),
             pre_link_args: TargetOptions::link_args(
                 LinkerFlavor::Gnu(Cc::Yes, Lld::No),
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 d2906d6c4ae..e2c59d2938e 100644
--- a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
+++ b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     let mut base = super::solaris_base::opts();
     base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]);
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.vendor = "pc".into();
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::X86;
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 37feaa9dbbf..1b8885c34da 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
@@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, Target};
 pub fn target() -> Target {
     let mut base = super::windows_gnu_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     // Use high-entropy 64 bit address space for ASLR
     base.add_pre_link_args(
         LinkerFlavor::Gnu(Cc::No, Lld::No),
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 039bc2bd2bb..8f5e398a0be 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,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, Target};
 pub fn target() -> Target {
     let mut base = super::windows_gnullvm_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-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_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs
index 081806aa698..6b897ca7070 100644
--- a/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs
@@ -3,6 +3,7 @@ use crate::spec::Target;
 pub fn target() -> Target {
     let mut base = super::windows_msvc_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
 
     Target {
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 0f31ea86b3f..650065f6330 100644
--- a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs
+++ b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     let mut base = super::solaris_base::opts();
     base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]);
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.vendor = "sun".into();
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::X86;
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 67ce3768db0..3b8e75977b5 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs
@@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
 pub fn target() -> Target {
     let mut base = super::dragonfly_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.stack_probes = StackProbeType::X86;
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 b41e5842aad..b2d91d09996 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
@@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target};
 pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.stack_probes = StackProbeType::X86;
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs
index a3231d19f4c..bee93541960 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs
@@ -3,6 +3,7 @@ use crate::spec::{SanitizerSet, StackProbeType, Target};
 pub fn target() -> Target {
     let mut base = super::fuchsia_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::X86;
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
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 9a7a3b501cf..16ed3150e6e 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs
@@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
 pub fn target() -> Target {
     let mut base = super::haiku_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.stack_probes = StackProbeType::X86;
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs
index fb1af33f80a..74ef2527c36 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs
@@ -3,6 +3,7 @@ use crate::spec::{StackProbeType, Target};
 pub fn target() -> Target {
     let mut base = super::hermit_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.features = "+rdrnd,+rdseed".into();
     base.stack_probes = StackProbeType::X86;
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 ca5b62e279c..9259cfe5f0e 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     let mut base = super::illumos_base::opts();
     base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64", "-std=c99"]);
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD;
 
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs
index 26da7e80011..912d289c47f 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs
@@ -3,6 +3,7 @@ use crate::spec::{PanicStrategy, Target};
 pub fn target() -> Target {
     let mut base = super::l4re_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.panic_strategy = PanicStrategy::Abort;
 
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 deb15c02c68..2f970f87cc6 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
@@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target};
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.stack_probes = StackProbeType::X86;
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 626d5b480c6..5469d02c592 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
@@ -10,7 +10,7 @@ pub fn target() -> Target {
     base.has_thread_local = false;
     // BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI
     // breaks code gen. See LLVM bug 36743
-    base.needs_plt = true;
+    base.plt_by_default = true;
 
     Target {
         llvm_target: "x86_64-unknown-linux-gnux32".into(),
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 bf4cf7d7bec..7154f5fa306 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
@@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target};
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.stack_probes = StackProbeType::X86;
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 74c434935ba..2e7bf34f7d2 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
@@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, T
 pub fn target() -> Target {
     let mut base = super::netbsd_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.stack_probes = StackProbeType::X86;
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
index 43c5ce78ce3..fe3b24f2d4a 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
@@ -10,6 +10,7 @@ use super::{RelroLevel, SanitizerSet, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     let opts = TargetOptions {
         cpu: "x86-64".into(),
+        plt_by_default: false,
         max_atomic_width: Some(64),
         stack_probes: StackProbeType::X86,
         position_independent_executables: true,
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 8e4d42a0aca..86fa9bf7ed2 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
@@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
 pub fn target() -> Target {
     let mut base = super::openbsd_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.stack_probes = StackProbeType::X86;
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 b47f15cf578..decc9736782 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs
@@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
 pub fn target() -> Target {
     let mut base = super::redox_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.stack_probes = StackProbeType::X86;
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs
index a7ae17839da..67664a74710 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs
@@ -10,6 +10,7 @@ use crate::spec::Target;
 pub fn target() -> Target {
     let mut base = super::uefi_msvc_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
 
     // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to
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 c3eaa6939bb..1a9d2a57182 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
@@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, Target};
 pub fn target() -> Target {
     let mut base = super::windows_uwp_gnu_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     // Use high-entropy 64 bit address space for ASLR
     base.add_pre_link_args(
         LinkerFlavor::Gnu(Cc::No, Lld::No),
diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs
index b2769350bf6..1ae403fa83f 100644
--- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs
@@ -3,6 +3,7 @@ use crate::spec::Target;
 pub fn target() -> Target {
     let mut base = super::windows_uwp_msvc_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     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 365ade6bcf9..a7c4aaecf91 100644
--- a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs
@@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
 pub fn target() -> Target {
     let mut base = super::vxworks_base::opts();
     base.cpu = "x86-64".into();
+    base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.stack_probes = StackProbeType::X86;
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index f2a39faf383..cde8a52cdec 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -522,13 +522,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
 
         for assumption in self.tcx().item_bounds(alias_ty.def_id).subst(self.tcx(), alias_ty.substs)
         {
-            if let Some(clause) = assumption.as_clause() {
-                match G::consider_alias_bound_candidate(self, goal, clause) {
-                    Ok(result) => {
-                        candidates.push(Candidate { source: CandidateSource::AliasBound, result })
-                    }
-                    Err(NoSolution) => (),
+            match G::consider_alias_bound_candidate(self, goal, assumption) {
+                Ok(result) => {
+                    candidates.push(Candidate { source: CandidateSource::AliasBound, result })
                 }
+                Err(NoSolution) => (),
             }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index 97b86a06c8c..439cf788ab4 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -353,7 +353,11 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
         // FIXME(associated_const_equality): Also add associated consts to
         // the requirements here.
         if item.kind == ty::AssocKind::Type {
-            requirements.extend(tcx.item_bounds(item.def_id).subst(tcx, trait_ref.substs));
+            requirements.extend(
+                tcx.item_bounds(item.def_id)
+                    .subst_iter(tcx, trait_ref.substs)
+                    .map(|clause| clause.as_predicate()),
+            );
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 75a92af714b..557341f7ac8 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1049,6 +1049,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     }
 
                     ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => {
+                        let ty = self.resolve_vars_if_possible(ty);
                         match self.tcx.sess.opts.unstable_opts.trait_solver {
                             TraitSolver::Classic => {
                                 // WF predicates cannot themselves make
@@ -2382,17 +2383,21 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             && let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next()
                         {
                             let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count();
-                            let message = if non_blanket_impl_count == 1 {
-                                "use the fully-qualified path to the only available implementation".to_string()
-                            } else {
+                            // If there is only one implementation of the trait, suggest using it.
+                            // Otherwise, use a placeholder comment for the implementation.
+                            let (message, impl_suggestion) = if non_blanket_impl_count == 1 {(
+                                "use the fully-qualified path to the only available implementation".to_string(),
+                                format!("<{} as ", self.tcx.type_of(impl_def_id).subst_identity())
+                            )} else {(
                                 format!(
                                     "use a fully-qualified path to a specific available implementation ({} found)",
                                     non_blanket_impl_count
-                                )
-                            };
+                                ),
+                                "</* self type */ as ".to_string()
+                            )};
                             let mut suggestions = vec![(
                                 path.span.shrink_to_lo(),
-                                format!("<{} as ", self.tcx.type_of(impl_def_id).subst_identity())
+                                impl_suggestion
                             )];
                             if let Some(generic_arg) = trait_path_segment.args {
                                 let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext);
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 966c4a7dcf3..71d2380f234 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1157,7 +1157,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
                 ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                     self.tcx.item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
-                        if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) = pred.kind().skip_binder()
+                        if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
                         && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                         // args tuple will always be substs[1]
                         && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
@@ -2724,6 +2724,32 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     let msg = format!("required by this bound in `{short_item_name}`");
                     multispan.push_span_label(span, msg);
                     err.span_note(multispan, descr);
+                    if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
+                        && let ty::ClauseKind::Trait(trait_pred) = clause
+                    {
+                        let def_id = trait_pred.def_id();
+                        let visible_item = if let Some(local) = def_id.as_local() {
+                            // Check for local traits being reachable.
+                            let vis = &self.tcx.resolutions(()).effective_visibilities;
+                            // Account for non-`pub` traits in the root of the local crate.
+                            let is_locally_reachable = self.tcx.parent(def_id).is_crate_root();
+                            vis.is_reachable(local) || is_locally_reachable
+                        } else {
+                            // Check for foreign traits being reachable.
+                            self.tcx.visible_parent_map(()).get(&def_id).is_some()
+                        };
+                        if let DefKind::Trait = tcx.def_kind(item_def_id) && !visible_item {
+                            // FIXME(estebank): extend this to search for all the types that do
+                            // implement this trait and list them.
+                            err.note(format!(
+                                "`{short_item_name}` is a \"sealed trait\", because to implement \
+                                 it you also need to implelement `{}`, which is not accessible; \
+                                 this is usually done to force you to use one of the provided \
+                                 types that already implement it",
+                                with_no_trimmed_paths!(tcx.def_path_str(def_id)),
+                            ));
+                        }
+                    }
                 } else {
                     err.span_note(tcx.def_span(item_def_id), descr);
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 15081d65682..a5481714e3e 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -65,12 +65,12 @@ pub use self::specialize::{
 pub use self::structural_match::search_for_structural_match_violation;
 pub use self::structural_normalize::StructurallyNormalizeExt;
 pub use self::util::elaborate;
-pub use self::util::{expand_trait_aliases, TraitAliasExpander};
-pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
 pub use self::util::{
-    supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item,
-    SupertraitDefIds,
+    check_substs_compatible, supertrait_def_ids, supertraits, transitive_bounds,
+    transitive_bounds_that_define_assoc_item, SupertraitDefIds,
 };
+pub use self::util::{expand_trait_aliases, TraitAliasExpander};
+pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
 
 pub use self::chalk_fulfill::FulfillmentContext as ChalkFulfillmentContext;
 
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 499745473a2..df93c4d45dc 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -271,7 +271,7 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span
         .in_definition_order()
         .filter(|item| item.kind == ty::AssocKind::Type)
         .flat_map(|item| tcx.explicit_item_bounds(item.def_id).subst_identity_iter_copied())
-        .filter_map(|pred_span| predicate_references_self(tcx, pred_span))
+        .filter_map(|(clause, span)| predicate_references_self(tcx, (clause.as_predicate(), span)))
         .collect()
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index de76587c7b9..2a78c5befa4 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1,5 +1,6 @@
 //! Code for projecting associated types out of trait references.
 
+use super::check_substs_compatible;
 use super::specialization_graph;
 use super::translate_substs;
 use super::util;
@@ -1584,7 +1585,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
         obligation,
         candidate_set,
         ProjectionCandidate::TraitDef,
-        bounds.iter(),
+        bounds.iter().map(|clause| clause.as_predicate()),
         true,
     );
 }
@@ -2378,47 +2379,6 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     }
 }
 
-// Verify that the trait item and its implementation have compatible substs lists
-fn check_substs_compatible<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    assoc_item: ty::AssocItem,
-    substs: ty::SubstsRef<'tcx>,
-) -> bool {
-    fn check_substs_compatible_inner<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        generics: &'tcx ty::Generics,
-        args: &'tcx [ty::GenericArg<'tcx>],
-    ) -> bool {
-        if generics.count() != args.len() {
-            return false;
-        }
-
-        let (parent_args, own_args) = args.split_at(generics.parent_count);
-
-        if let Some(parent) = generics.parent
-            && let parent_generics = tcx.generics_of(parent)
-            && !check_substs_compatible_inner(tcx, parent_generics, parent_args) {
-            return false;
-        }
-
-        for (param, arg) in std::iter::zip(&generics.params, own_args) {
-            match (&param.kind, arg.unpack()) {
-                (ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
-                | (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
-                | (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
-                _ => return false,
-            }
-        }
-
-        true
-    }
-
-    let generics = tcx.generics_of(assoc_item.def_id);
-    // Chop off any additional substs (RPITIT) substs
-    let substs = &substs[0..generics.count().min(substs.len())];
-    check_substs_compatible_inner(tcx, generics, substs)
-}
-
 fn confirm_impl_trait_in_trait_candidate<'tcx>(
     selcx: &mut SelectionContext<'_, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 3c356978d5c..a50af417a44 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -170,7 +170,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let candidate_predicate = tcx.item_bounds(def_id).map_bound(|i| i[idx]).subst(tcx, substs);
         let candidate = candidate_predicate
-            .to_opt_poly_trait_pred()
+            .as_trait_clause()
             .expect("projection candidate is not a trait predicate")
             .map_bound(|t| t.trait_ref);
         let mut obligations = Vec::new();
@@ -631,7 +631,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         let assoc_ty_substs = tcx.mk_substs(&substs);
                         let bound =
                             bound.map_bound(|b| b.kind().skip_binder()).subst(tcx, assoc_ty_substs);
-                        tcx.mk_predicate(ty::Binder::bind_with_vars(bound, bound_vars))
+                        ty::Binder::bind_with_vars(bound, bound_vars).to_predicate(tcx)
                     };
                 let normalized_bound = normalize_with_depth_to(
                     self,
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 0f0e3f1f16a..0a8b7b688e7 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1668,9 +1668,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             .enumerate()
             .filter_map(|(idx, bound)| {
                 let bound_predicate = bound.kind();
-                if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
-                    bound_predicate.skip_binder()
-                {
+                if let ty::ClauseKind::Trait(pred) = bound_predicate.skip_binder() {
                     let bound = bound_predicate.rebind(pred.trait_ref);
                     if self.infcx.probe(|_| {
                         match self.match_normalize_trait_ref(
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 906c357e8ca..05a7f3e3b02 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -302,3 +302,44 @@ pub enum TupleArgumentsFlag {
     Yes,
     No,
 }
+
+// Verify that the trait item and its implementation have compatible substs lists
+pub fn check_substs_compatible<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    assoc_item: ty::AssocItem,
+    substs: ty::SubstsRef<'tcx>,
+) -> bool {
+    fn check_substs_compatible_inner<'tcx>(
+        tcx: TyCtxt<'tcx>,
+        generics: &'tcx ty::Generics,
+        args: &'tcx [ty::GenericArg<'tcx>],
+    ) -> bool {
+        if generics.count() != args.len() {
+            return false;
+        }
+
+        let (parent_args, own_args) = args.split_at(generics.parent_count);
+
+        if let Some(parent) = generics.parent
+            && let parent_generics = tcx.generics_of(parent)
+            && !check_substs_compatible_inner(tcx, parent_generics, parent_args) {
+            return false;
+        }
+
+        for (param, arg) in std::iter::zip(&generics.params, own_args) {
+            match (&param.kind, arg.unpack()) {
+                (ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
+                | (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
+                | (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
+                _ => return false,
+            }
+        }
+
+        true
+    }
+
+    let generics = tcx.generics_of(assoc_item.def_id);
+    // Chop off any additional substs (RPITIT) substs
+    let substs = &substs[0..generics.count().min(substs.len())];
+    check_substs_compatible_inner(tcx, generics, substs)
+}
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index e80d413d976..e96e89ce73c 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -77,12 +77,19 @@ pub fn unnormalized_obligations<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     arg: GenericArg<'tcx>,
 ) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
+    debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg));
+
+    // However, if `arg` IS an unresolved inference variable, returns `None`,
+    // because we are not able to make any progress at all. This is to prevent
+    // "livelock" where we say "$0 is WF if $0 is WF".
+    if arg.is_non_region_infer() {
+        return None;
+    }
+
     if let ty::GenericArgKind::Lifetime(..) = arg.unpack() {
         return Some(vec![]);
     }
 
-    debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg));
-
     let mut wf = WfPredicates {
         infcx,
         param_env,
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index 38f94c38861..7e64cbdf54a 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -54,7 +54,9 @@ impl<'tcx> RustIrDatabase<'tcx> {
             .tcx
             .explicit_item_bounds(def_id)
             .subst_iter_copied(self.interner.tcx, &bound_vars)
-            .filter_map(|(bound, _)| LowerInto::<Option<_>>::lower_into(bound, self.interner))
+            .filter_map(|(bound, _)| {
+                LowerInto::<Option<_>>::lower_into(bound.as_predicate(), self.interner)
+            })
             .collect()
     }
 }
@@ -520,7 +522,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
                 .filter_map(|bound| {
                     LowerInto::<
                     Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>>
-                >::lower_into(bound, self.interner)
+                >::lower_into(bound.as_predicate(), self.interner)
                 })
                 .collect();
 
diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs
index 73756caf372..e8917d72483 100644
--- a/compiler/rustc_traits/src/evaluate_obligation.rs
+++ b/compiler/rustc_traits/src/evaluate_obligation.rs
@@ -1,6 +1,5 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
-use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 use rustc_span::source_map::DUMMY_SP;
 use rustc_trait_selection::traits::query::CanonicalPredicateGoal;
@@ -18,12 +17,8 @@ fn evaluate_obligation<'tcx>(
 ) -> Result<EvaluationResult, OverflowError> {
     assert!(!tcx.next_trait_solver_globally());
     debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal);
-    // HACK This bubble is required for this tests to pass:
-    // impl-trait/issue99642.rs
-    let (ref infcx, goal, _canonical_inference_vars) = tcx
-        .infer_ctxt()
-        .with_opaque_type_inference(DefiningAnchor::Bubble)
-        .build_with_canonical(DUMMY_SP, &canonical_goal);
+    let (ref infcx, goal, _canonical_inference_vars) =
+        tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal);
     debug!("evaluate_obligation: goal={:#?}", goal);
     let ParamEnvAnd { param_env, value: predicate } = goal;
 
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index 9904acb1c0d..98d814d54f2 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -2,7 +2,6 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::query::NoSolution;
-use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::{FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable};
 use rustc_middle::ty::{ParamEnvAnd, Predicate};
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
@@ -106,15 +105,10 @@ fn type_op_prove_predicate<'tcx>(
     tcx: TyCtxt<'tcx>,
     canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>,
 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
-    // HACK This bubble is required for this test to pass:
-    // impl-trait/issue-99642.rs
-    tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter_canonical_trait_query(
-        &canonicalized,
-        |ocx, key| {
-            type_op_prove_predicate_with_cause(ocx, key, ObligationCause::dummy());
-            Ok(())
-        },
-    )
+    tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| {
+        type_op_prove_predicate_with_cause(ocx, key, ObligationCause::dummy());
+        Ok(())
+    })
 }
 
 /// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors,
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 658ab03c0f4..5b731641e9d 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -259,7 +259,7 @@ fn associated_type_for_impl_trait_in_trait(
     opaque_ty_def_id: LocalDefId,
 ) -> LocalDefId {
     let (hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id)) =
-        tcx.hir().expect_item(opaque_ty_def_id).expect_opaque_ty().origin
+        tcx.opaque_type_origin(opaque_ty_def_id)
     else {
         bug!("expected opaque for {opaque_ty_def_id:?}");
     };
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index 553bf40ef3a..947d4bbe86e 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -113,7 +113,7 @@ pub struct DuplicateArg<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(ty_utils_impl_trait_not_param)]
+#[diag(ty_utils_impl_trait_not_param, code = "E0792")]
 pub struct NotParam<'tcx> {
     pub arg: GenericArg<'tcx>,
     #[primary_span]
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index f48bba24132..c8c2c8286b0 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -145,17 +145,35 @@ fn layout_of_uncached<'tcx>(
                 return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
             }
 
-            let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
-
             let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type()
                 // Projection eagerly bails out when the pointee references errors,
                 // fall back to structurally deducing metadata.
                 && !pointee.references_error()
             {
-                let metadata_ty = tcx.normalize_erasing_regions(
+                let pointee_metadata = tcx.mk_projection(metadata_def_id, [pointee]);
+                let metadata_ty = match tcx.try_normalize_erasing_regions(
                     param_env,
-                    tcx.mk_projection(metadata_def_id, [pointee]),
-                );
+                    pointee_metadata,
+                ) {
+                    Ok(metadata_ty) => metadata_ty,
+                    Err(mut err) => {
+                        // Usually `<Ty as Pointee>::Metadata` can't be normalized because
+                        // its struct tail cannot be normalized either, so try to get a
+                        // more descriptive layout error here, which will lead to less confusing
+                        // diagnostics.
+                        match tcx.try_normalize_erasing_regions(
+                            param_env,
+                            tcx.struct_tail_without_normalization(pointee),
+                        ) {
+                            Ok(_) => {},
+                            Err(better_err) => {
+                                err = better_err;
+                            }
+                        }
+                        return Err(LayoutError::NormalizationFailure(pointee, err));
+                    },
+                };
+
                 let metadata_layout = cx.layout_of(metadata_ty)?;
                 // If the metadata is a 1-zst, then the pointer is thin.
                 if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 {
@@ -163,10 +181,13 @@ fn layout_of_uncached<'tcx>(
                 }
 
                 let Abi::Scalar(metadata) = metadata_layout.abi else {
-                    return Err(LayoutError::Unknown(unsized_part));
+                    return Err(LayoutError::Unknown(pointee));
                 };
+
                 metadata
             } else {
+                let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
+
                 match unsized_part.kind() {
                     ty::Foreign(..) => {
                         return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
@@ -178,7 +199,7 @@ fn layout_of_uncached<'tcx>(
                         vtable
                     }
                     _ => {
-                        return Err(LayoutError::Unknown(unsized_part));
+                        return Err(LayoutError::Unknown(pointee));
                     }
                 }
             };
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 4e91dd380e8..29de8bf0e53 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -1,12 +1,11 @@
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::ErrorGuaranteed;
 use rustc_hir::{def::DefKind, def_id::LocalDefId};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use rustc_span::Span;
-use rustc_type_ir::AliasKind;
+use rustc_trait_selection::traits::check_substs_compatible;
 use std::ops::ControlFlow;
 
 use crate::errors::{DuplicateArg, NotParam};
@@ -19,21 +18,35 @@ struct OpaqueTypeCollector<'tcx> {
 
     /// Avoid infinite recursion due to recursive declarations.
     seen: FxHashSet<LocalDefId>,
+
+    span: Option<Span>,
 }
 
 impl<'tcx> OpaqueTypeCollector<'tcx> {
-    fn collect(
-        tcx: TyCtxt<'tcx>,
-        item: LocalDefId,
-        val: ty::Binder<'tcx, impl TypeVisitable<TyCtxt<'tcx>>>,
-    ) -> Vec<LocalDefId> {
-        let mut collector = Self { tcx, opaques: Vec::new(), item, seen: Default::default() };
-        val.skip_binder().visit_with(&mut collector);
-        collector.opaques
+    fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
+        Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None }
     }
 
     fn span(&self) -> Span {
-        self.tcx.def_span(self.item)
+        self.span.unwrap_or_else(|| {
+            self.tcx.def_ident_span(self.item).unwrap_or_else(|| self.tcx.def_span(self.item))
+        })
+    }
+
+    fn visit_spanned(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) {
+        let old = self.span;
+        self.span = Some(span);
+        value.visit_with(self);
+        self.span = old;
+    }
+
+    fn parent_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> {
+        let parent = self.parent()?;
+        if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) {
+            Some(self.tcx.impl_trait_ref(parent)?.subst_identity())
+        } else {
+            None
+        }
     }
 
     fn parent(&self) -> Option<LocalDefId> {
@@ -51,91 +64,124 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
-    type BreakTy = ErrorGuaranteed;
-
     #[instrument(skip(self), ret, level = "trace")]
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<ErrorGuaranteed> {
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
+        t.super_visit_with(self)?;
         match t.kind() {
-            ty::Alias(AliasKind::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
+            ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
                 if !self.seen.insert(alias_ty.def_id.expect_local()) {
                     return ControlFlow::Continue(());
                 }
+
+                self.opaques.push(alias_ty.def_id.expect_local());
+
                 match self.tcx.uses_unique_generic_params(alias_ty.substs, CheckRegions::Bound) {
                     Ok(()) => {
                         // FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
                         // supported at all, so this is sound to do, but once we want to support them, you'll
                         // start seeing the error below.
 
-                        self.opaques.push(alias_ty.def_id.expect_local());
-
                         // Collect opaque types nested within the associated type bounds of this opaque type.
-                        for (pred, _span) in self
+                        // We use identity substs here, because we already know that the opaque type uses
+                        // only generic parameters, and thus substituting would not give us more information.
+                        for (pred, span) in self
                             .tcx
                             .explicit_item_bounds(alias_ty.def_id)
-                            .subst_iter_copied(self.tcx, alias_ty.substs)
+                            .subst_identity_iter_copied()
                         {
                             trace!(?pred);
-                            pred.visit_with(self)?;
+                            self.visit_spanned(span, pred);
                         }
-
-                        ControlFlow::Continue(())
                     }
                     Err(NotUniqueParam::NotParam(arg)) => {
-                        let err = self.tcx.sess.emit_err(NotParam {
+                        self.tcx.sess.emit_err(NotParam {
                             arg,
                             span: self.span(),
                             opaque_span: self.tcx.def_span(alias_ty.def_id),
                         });
-                        ControlFlow::Break(err)
                     }
                     Err(NotUniqueParam::DuplicateParam(arg)) => {
-                        let err = self.tcx.sess.emit_err(DuplicateArg {
+                        self.tcx.sess.emit_err(DuplicateArg {
                             arg,
                             span: self.span(),
                             opaque_span: self.tcx.def_span(alias_ty.def_id),
                         });
-                        ControlFlow::Break(err)
                     }
                 }
             }
-            ty::Alias(AliasKind::Projection, alias_ty) => {
-                if let Some(parent) = self.parent() {
-                    trace!(?alias_ty);
-                    let (trait_ref, own_substs) = alias_ty.trait_ref_and_own_substs(self.tcx);
-
-                    trace!(?trait_ref, ?own_substs);
-                    // This avoids having to do normalization of `Self::AssocTy` by only
-                    // supporting the case of a method defining opaque types from assoc types
-                    // in the same impl block.
-                    if trait_ref.self_ty() == self.tcx.type_of(parent).subst_identity() {
-                        for assoc in self.tcx.associated_items(parent).in_definition_order() {
+            ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
+                self.tcx
+                    .type_of(alias_ty.def_id)
+                    .subst(self.tcx, alias_ty.substs)
+                    .visit_with(self)?;
+            }
+            ty::Alias(ty::Projection, alias_ty) => {
+                // This avoids having to do normalization of `Self::AssocTy` by only
+                // supporting the case of a method defining opaque types from assoc types
+                // in the same impl block.
+                if let Some(parent_trait_ref) = self.parent_trait_ref() {
+                    // If the trait ref of the associated item and the impl differs,
+                    // then we can't use the impl's identity substitutions below, so
+                    // just skip.
+                    if alias_ty.trait_ref(self.tcx) == parent_trait_ref {
+                        let parent = self.parent().expect("we should have a parent here");
+
+                        for &assoc in self.tcx.associated_items(parent).in_definition_order() {
                             trace!(?assoc);
-                            if assoc.trait_item_def_id == Some(alias_ty.def_id) {
-                                // We reconstruct the generic args of the associated type within the impl
-                                // from the impl's generics and the generic args passed to the type via the
-                                // projection.
-                                let substs = ty::InternalSubsts::identity_for_item(
-                                    self.tcx,
-                                    parent.to_def_id(),
-                                );
-                                trace!(?substs);
-                                let substs: Vec<_> =
-                                    substs.iter().chain(own_substs.iter().copied()).collect();
-                                trace!(?substs);
-                                // Find opaque types in this associated type.
+                            if assoc.trait_item_def_id != Some(alias_ty.def_id) {
+                                continue;
+                            }
+
+                            // If the type is further specializable, then the type_of
+                            // is not actually correct below.
+                            if !assoc.defaultness(self.tcx).is_final() {
+                                continue;
+                            }
+
+                            let impl_substs = alias_ty.substs.rebase_onto(
+                                self.tcx,
+                                parent_trait_ref.def_id,
+                                ty::InternalSubsts::identity_for_item(self.tcx, parent),
+                            );
+
+                            if check_substs_compatible(self.tcx, assoc, impl_substs) {
                                 return self
                                     .tcx
                                     .type_of(assoc.def_id)
-                                    .subst(self.tcx, &substs)
+                                    .subst(self.tcx, impl_substs)
                                     .visit_with(self);
+                            } else {
+                                self.tcx.sess.delay_span_bug(
+                                    self.tcx.def_span(assoc.def_id),
+                                    "item had incorrect substs",
+                                );
                             }
                         }
                     }
                 }
-                t.super_visit_with(self)
             }
-            _ => t.super_visit_with(self),
+            ty::Adt(def, _) if def.did().is_local() => {
+                if !self.seen.insert(def.did().expect_local()) {
+                    return ControlFlow::Continue(());
+                }
+                for variant in def.variants().iter() {
+                    for field in variant.fields.iter() {
+                        // Don't use the `ty::Adt` substs, we either
+                        // * found the opaque in the substs
+                        // * will find the opaque in the unsubstituted fields
+                        // The only other situation that can occur is that after substituting,
+                        // some projection resolves to an opaque that we would have otherwise
+                        // not found. While we could substitute and walk those, that would mean we
+                        // would have to walk all substitutions of an Adt, which can quickly
+                        // degenerate into looking at an exponential number of types.
+                        let ty = self.tcx.type_of(field.did).subst_identity();
+                        self.visit_spanned(self.tcx.def_span(field.did), ty);
+                    }
+                }
+            }
+            _ => trace!(kind=?t.kind()),
         }
+        ControlFlow::Continue(())
     }
 }
 
@@ -146,21 +192,29 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
     match kind {
         // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
         DefKind::Fn | DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
-            let defined_opaques = match kind {
-                DefKind::Fn => {
-                    OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity())
+            let mut collector = OpaqueTypeCollector::new(tcx, item);
+            match kind {
+                // Walk over the signature of the function-like to find the opaques.
+                DefKind::AssocFn | DefKind::Fn => {
+                    let ty_sig = tcx.fn_sig(item).subst_identity();
+                    let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap();
+                    // Walk over the inputs and outputs manually in order to get good spans for them.
+                    collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output());
+                    for (hir, ty) in hir_sig.decl.inputs.iter().zip(ty_sig.inputs().iter()) {
+                        collector.visit_spanned(hir.span, ty.map_bound(|x| *x));
+                    }
                 }
-                DefKind::AssocFn => {
-                    OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity())
+                // Walk over the type of the item to find opaques.
+                DefKind::AssocTy | DefKind::AssocConst => {
+                    let span = match tcx.hir().get_by_def_id(item).ty() {
+                        Some(ty) => ty.span,
+                        _ => tcx.def_span(item),
+                    };
+                    collector.visit_spanned(span, tcx.type_of(item).subst_identity());
                 }
-                DefKind::AssocTy | DefKind::AssocConst => OpaqueTypeCollector::collect(
-                    tcx,
-                    item,
-                    ty::Binder::dummy(tcx.type_of(item).subst_identity()),
-                ),
                 _ => unreachable!(),
-            };
-            tcx.arena.alloc_from_iter(defined_opaques)
+            }
+            tcx.arena.alloc_from_iter(collector.opaques)
         }
         DefKind::Mod
         | DefKind::Struct
@@ -189,7 +243,9 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
         | DefKind::GlobalAsm
         | DefKind::Impl { .. }
         | DefKind::Closure
-        | DefKind::Generator => &[],
+        | DefKind::Generator => {
+            span_bug!(tcx.def_span(item), "{kind:?} is type checked as part of its parent")
+        }
     }
 }
 
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index 86ea154a886..7437722fd06 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -238,7 +238,7 @@ impl fmt::Debug for c_void {
         not(target_arch = "s390x"),
         not(target_arch = "x86_64")
     ),
-    all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
+    all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")),
     target_family = "wasm",
     target_arch = "asmjs",
     target_os = "uefi",
@@ -267,7 +267,7 @@ pub struct VaListImpl<'f> {
         not(target_arch = "s390x"),
         not(target_arch = "x86_64")
     ),
-    all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
+    all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")),
     target_family = "wasm",
     target_arch = "asmjs",
     target_os = "uefi",
@@ -292,7 +292,7 @@ impl<'f> fmt::Debug for VaListImpl<'f> {
 /// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
 #[cfg(all(
     target_arch = "aarch64",
-    not(any(target_os = "macos", target_os = "ios")),
+    not(any(target_os = "macos", target_os = "ios", target_os = "tvos")),
     not(target_os = "uefi"),
     not(windows),
 ))]
@@ -389,7 +389,10 @@ pub struct VaList<'a, 'f: 'a> {
             not(target_arch = "s390x"),
             not(target_arch = "x86_64")
         ),
-        all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
+        all(
+            target_arch = "aarch64",
+            any(target_os = "macos", target_os = "ios", target_os = "tvos")
+        ),
         target_family = "wasm",
         target_arch = "asmjs",
         target_os = "uefi",
@@ -404,7 +407,10 @@ pub struct VaList<'a, 'f: 'a> {
             target_arch = "s390x",
             target_arch = "x86_64"
         ),
-        any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
+        any(
+            not(target_arch = "aarch64"),
+            not(any(target_os = "macos", target_os = "ios", target_os = "tvos"))
+        ),
         not(target_family = "wasm"),
         not(target_arch = "asmjs"),
         not(target_os = "uefi"),
@@ -422,7 +428,7 @@ pub struct VaList<'a, 'f: 'a> {
         not(target_arch = "s390x"),
         not(target_arch = "x86_64")
     ),
-    all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
+    all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")),
     target_family = "wasm",
     target_arch = "asmjs",
     target_os = "uefi",
@@ -449,7 +455,10 @@ impl<'f> VaListImpl<'f> {
         target_arch = "s390x",
         target_arch = "x86_64"
     ),
-    any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
+    any(
+        not(target_arch = "aarch64"),
+        not(any(target_os = "macos", target_os = "ios", target_os = "tvos"))
+    ),
     not(target_family = "wasm"),
     not(target_arch = "asmjs"),
     not(target_os = "uefi"),
diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs
index 052fd34d0b6..48a6eb03b5e 100644
--- a/library/core/src/slice/raw.rs
+++ b/library/core/src/slice/raw.rs
@@ -32,7 +32,8 @@ use crate::ptr;
 /// * The memory referenced by the returned slice must not be mutated for the duration
 ///   of lifetime `'a`, except inside an `UnsafeCell`.
 ///
-/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
+/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`,
+///   and adding that size to `data` must not "wrap around" the address space.
 ///   See the safety documentation of [`pointer::offset`].
 ///
 /// # Caveat
@@ -125,7 +126,8 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
 ///   (not derived from the return value) for the duration of lifetime `'a`.
 ///   Both read and write accesses are forbidden.
 ///
-/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
+/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`,
+///   and adding that size to `data` must not "wrap around" the address space.
 ///   See the safety documentation of [`pointer::offset`].
 ///
 /// [valid]: ptr#safety
@@ -179,15 +181,16 @@ pub const fn from_mut<T>(s: &mut T) -> &mut [T] {
 ///   the last element, such that the offset from the end to the start pointer is
 ///   the length of the slice.
 ///
-/// * The range must contain `N` consecutive properly initialized values of type `T`:
+/// * The entire memory range of this slice must be contained within a single allocated object!
+///   Slices can never span across multiple allocated objects.
 ///
-///     * The entire memory range of this slice must be contained within a single allocated object!
-///       Slices can never span across multiple allocated objects.
+/// * The range must contain `N` consecutive properly initialized values of type `T`.
 ///
 /// * The memory referenced by the returned slice must not be mutated for the duration
 ///   of lifetime `'a`, except inside an `UnsafeCell`.
 ///
-/// * The total length of the range must be no larger than `isize::MAX`.
+/// * The total length of the range must be no larger than `isize::MAX`,
+///   and adding that size to `data` must not "wrap around" the address space.
 ///   See the safety documentation of [`pointer::offset`].
 ///
 /// Note that a range created from [`slice::as_ptr_range`] fulfills these requirements.
@@ -247,16 +250,17 @@ pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] {
 ///   the last element, such that the offset from the end to the start pointer is
 ///   the length of the slice.
 ///
-/// * The range must contain `N` consecutive properly initialized values of type `T`:
+/// * The entire memory range of this slice must be contained within a single allocated object!
+///   Slices can never span across multiple allocated objects.
 ///
-///     * The entire memory range of this slice must be contained within a single allocated object!
-///       Slices can never span across multiple allocated objects.
+/// * The range must contain `N` consecutive properly initialized values of type `T`.
 ///
 /// * The memory referenced by the returned slice must not be accessed through any other pointer
 ///   (not derived from the return value) for the duration of lifetime `'a`.
 ///   Both read and write accesses are forbidden.
 ///
-/// * The total length of the range must be no larger than `isize::MAX`.
+/// * The total length of the range must be no larger than `isize::MAX`,
+///   and adding that size to `data` must not "wrap around" the address space.
 ///   See the safety documentation of [`pointer::offset`].
 ///
 /// Note that a range created from [`slice::as_mut_ptr_range`] fulfills these requirements.
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index af74efa6bf8..aaaa88624f0 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -18,7 +18,7 @@ panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core", public = true }
 libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-of-std'], public = true }
-compiler_builtins = { version = "0.1.92" }
+compiler_builtins = { version = "0.1.93" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] }
diff --git a/library/std/build.rs b/library/std/build.rs
index d0b37940936..ddf6e84d8d0 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -18,6 +18,7 @@ fn main() {
         || target.contains("illumos")
         || target.contains("apple-darwin")
         || target.contains("apple-ios")
+        || target.contains("apple-tvos")
         || target.contains("apple-watchos")
         || target.contains("uwp")
         || target.contains("windows")
@@ -48,7 +49,6 @@ fn main() {
         // - mipsel-sony-psp
         // - nvptx64-nvidia-cuda
         // - arch=avr
-        // - tvos (aarch64-apple-tvos, x86_64-apple-tvos)
         // - uefi (x86_64-unknown-uefi, i686-unknown-uefi)
         // - JSON targets
         // - Any new targets that have not been explicitly added above.
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index e2480bcbbc7..9ff01b9c35d 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -1640,6 +1640,10 @@ fn test_file_times() {
     use crate::os::ios::fs::FileTimesExt;
     #[cfg(target_os = "macos")]
     use crate::os::macos::fs::FileTimesExt;
+    #[cfg(target_os = "tvos")]
+    use crate::os::tvos::fs::FileTimesExt;
+    #[cfg(target_os = "tvos")]
+    use crate::os::tvos::fs::FileTimesExt;
     #[cfg(target_os = "watchos")]
     use crate::os::watchos::fs::FileTimesExt;
     #[cfg(windows)]
@@ -1651,9 +1655,21 @@ fn test_file_times() {
     let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345);
     let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321);
     times = times.set_accessed(accessed).set_modified(modified);
-    #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    #[cfg(any(
+        windows,
+        target_os = "macos",
+        target_os = "ios",
+        target_os = "watchos",
+        target_os = "tvos",
+    ))]
     let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123);
-    #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    #[cfg(any(
+        windows,
+        target_os = "macos",
+        target_os = "ios",
+        target_os = "watchos",
+        target_os = "tvos",
+    ))]
     {
         times = times.set_created(created);
     }
@@ -1678,7 +1694,13 @@ fn test_file_times() {
     let metadata = file.metadata().unwrap();
     assert_eq!(metadata.accessed().unwrap(), accessed);
     assert_eq!(metadata.modified().unwrap(), modified);
-    #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    #[cfg(any(
+        windows,
+        target_os = "macos",
+        target_os = "ios",
+        target_os = "watchos",
+        target_os = "tvos",
+    ))]
     {
         assert_eq!(metadata.created().unwrap(), created);
     }
diff --git a/library/std/src/os/ios/fs.rs b/library/std/src/os/ios/fs.rs
index 6d4d54b7c78..b319527a541 100644
--- a/library/std/src/os/ios/fs.rs
+++ b/library/std/src/os/ios/fs.rs
@@ -6,7 +6,7 @@ use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
 use crate::time::SystemTime;
 
 #[allow(deprecated)]
-use crate::os::ios::raw;
+use super::raw;
 
 /// OS-specific extensions to [`fs::Metadata`].
 ///
diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs
index 5b54cc5f2e4..634c3cc4a15 100644
--- a/library/std/src/os/mod.rs
+++ b/library/std/src/os/mod.rs
@@ -137,6 +137,9 @@ pub mod redox;
 pub mod solaris;
 #[cfg(target_os = "solid_asp3")]
 pub mod solid;
+#[cfg(target_os = "tvos")]
+#[path = "ios/mod.rs"]
+pub(crate) mod tvos;
 #[cfg(target_os = "vita")]
 pub mod vita;
 #[cfg(target_os = "vxworks")]
diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs
index 6fe1111188a..401ec1e7a01 100644
--- a/library/std/src/os/unix/mod.rs
+++ b/library/std/src/os/unix/mod.rs
@@ -73,6 +73,8 @@ mod platform {
     pub use crate::os::redox::*;
     #[cfg(target_os = "solaris")]
     pub use crate::os::solaris::*;
+    #[cfg(target_os = "tvos")]
+    pub use crate::os::tvos::*;
     #[cfg(target_os = "vita")]
     pub use crate::os::vita::*;
     #[cfg(target_os = "vxworks")]
@@ -96,6 +98,7 @@ pub mod thread;
     target_os = "dragonfly",
     target_os = "freebsd",
     target_os = "ios",
+    target_os = "tvos",
     target_os = "watchos",
     target_os = "macos",
     target_os = "netbsd",
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index bf2a51b5edb..e20170873bb 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -11,6 +11,7 @@ use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Owned
     target_os = "dragonfly",
     target_os = "freebsd",
     target_os = "ios",
+    target_os = "tvos",
     target_os = "macos",
     target_os = "watchos",
     target_os = "netbsd",
@@ -30,6 +31,7 @@ use crate::time::Duration;
     target_os = "dragonfly",
     target_os = "freebsd",
     target_os = "ios",
+    target_os = "tvos",
     target_os = "macos",
     target_os = "watchos",
     target_os = "netbsd",
@@ -238,6 +240,7 @@ impl UnixStream {
         target_os = "dragonfly",
         target_os = "freebsd",
         target_os = "ios",
+        target_os = "tvos",
         target_os = "macos",
         target_os = "watchos",
         target_os = "netbsd",
diff --git a/library/std/src/os/unix/ucred.rs b/library/std/src/os/unix/ucred.rs
index 95967eac295..6a0cc2d2c48 100644
--- a/library/std/src/os/unix/ucred.rs
+++ b/library/std/src/os/unix/ucred.rs
@@ -36,7 +36,7 @@ pub use self::impl_linux::peer_cred;
 ))]
 pub use self::impl_bsd::peer_cred;
 
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
 pub use self::impl_mac::peer_cred;
 
 #[cfg(any(target_os = "linux", target_os = "android"))]
@@ -98,7 +98,7 @@ pub mod impl_bsd {
     }
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
 pub mod impl_mac {
     use super::UCred;
     use crate::os::unix::io::AsRawFd;
diff --git a/library/std/src/os/unix/ucred/tests.rs b/library/std/src/os/unix/ucred/tests.rs
index e63a2fc248e..dd99ecdd819 100644
--- a/library/std/src/os/unix/ucred/tests.rs
+++ b/library/std/src/os/unix/ucred/tests.rs
@@ -8,6 +8,7 @@ use libc::{getegid, geteuid, getpid};
     target_os = "dragonfly",
     target_os = "freebsd",
     target_os = "ios",
+    target_os = "tvos",
     target_os = "macos",
     target_os = "watchos",
     target_os = "openbsd"
@@ -26,7 +27,13 @@ fn test_socket_pair() {
 }
 
 #[test]
-#[cfg(any(target_os = "linux", target_os = "ios", target_os = "macos", target_os = "watchos"))]
+#[cfg(any(
+    target_os = "linux",
+    target_os = "ios",
+    target_os = "macos",
+    target_os = "watchos",
+    target_os = "tvos",
+))]
 fn test_socket_pair_pids(arg: Type) -> RetType {
     // Create two connected sockets and get their peer credentials.
     let (sock_a, sock_b) = UnixStream::pair().unwrap();
diff --git a/library/std/src/personality/gcc.rs b/library/std/src/personality/gcc.rs
index 82edb11cbd1..6552d96ca69 100644
--- a/library/std/src/personality/gcc.rs
+++ b/library/std/src/personality/gcc.rs
@@ -85,7 +85,7 @@ const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1
 // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
 
 cfg_if::cfg_if! {
-    if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "watchos"), not(target_os = "netbsd")))] {
+    if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "tvos"), not(target_os = "watchos"), not(target_os = "netbsd")))] {
         // ARM EHABI personality routine.
         // https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
         //
diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs
index 0e0c87d1c74..71ff4237d00 100644
--- a/library/std/src/sync/mpsc/mod.rs
+++ b/library/std/src/sync/mpsc/mod.rs
@@ -347,8 +347,8 @@ pub struct Sender<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T: Send> Send for Sender<T> {}
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> !Sync for Sender<T> {}
+#[stable(feature = "mpsc_sender_sync", since = "CURRENT_RUSTC_VERSION")]
+unsafe impl<T: Send> Sync for Sender<T> {}
 
 /// The sending-half of Rust's synchronous [`sync_channel`] type.
 ///
diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs
index 0efe2570d67..f8fa81e6ef1 100644
--- a/library/std/src/sys/unix/args.rs
+++ b/library/std/src/sys/unix/args.rs
@@ -168,7 +168,7 @@ mod imp {
     }
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
 mod imp {
     use super::Args;
     use crate::ffi::CStr;
@@ -209,7 +209,7 @@ mod imp {
     // for i in (0..[args count])
     //      res.push([args objectAtIndex:i])
     // res
-    #[cfg(any(target_os = "ios", target_os = "watchos"))]
+    #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))]
     pub fn args() -> Args {
         use crate::ffi::OsString;
         use crate::mem;
diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs
index 8c3ef88d8f8..929e9dae738 100644
--- a/library/std/src/sys/unix/env.rs
+++ b/library/std/src/sys/unix/env.rs
@@ -31,6 +31,17 @@ pub mod os {
     pub const EXE_EXTENSION: &str = "";
 }
 
+#[cfg(target_os = "tvos")]
+pub mod os {
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "tvos";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".dylib";
+    pub const DLL_EXTENSION: &str = "dylib";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
+}
+
 #[cfg(target_os = "watchos")]
 pub mod os {
     pub const FAMILY: &str = "unix";
diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs
index 69c93c92003..85e020ae413 100644
--- a/library/std/src/sys/unix/fd.rs
+++ b/library/std/src/sys/unix/fd.rs
@@ -44,6 +44,7 @@ const READ_LIMIT: usize = libc::ssize_t::MAX as usize;
     target_os = "dragonfly",
     target_os = "freebsd",
     target_os = "ios",
+    target_os = "tvos",
     target_os = "macos",
     target_os = "netbsd",
     target_os = "openbsd",
@@ -69,6 +70,7 @@ const fn max_iov() -> usize {
     target_os = "emscripten",
     target_os = "freebsd",
     target_os = "ios",
+    target_os = "tvos",
     target_os = "linux",
     target_os = "macos",
     target_os = "netbsd",
@@ -181,6 +183,7 @@ impl FileDesc {
         target_os = "fuchsia",
         target_os = "illumos",
         target_os = "ios",
+        target_os = "tvos",
         target_os = "linux",
         target_os = "macos",
         target_os = "netbsd",
@@ -222,6 +225,7 @@ impl FileDesc {
     #[cfg(any(
         all(target_os = "android", target_pointer_width = "32"),
         target_os = "ios",
+        target_os = "tvos",
         target_os = "macos",
     ))]
     pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
@@ -320,6 +324,7 @@ impl FileDesc {
         target_os = "fuchsia",
         target_os = "illumos",
         target_os = "ios",
+        target_os = "tvos",
         target_os = "linux",
         target_os = "macos",
         target_os = "netbsd",
@@ -361,6 +366,7 @@ impl FileDesc {
     #[cfg(any(
         all(target_os = "android", target_pointer_width = "32"),
         target_os = "ios",
+        target_os = "tvos",
         target_os = "macos",
     ))]
     pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index d2fb6238387..9cf5cfcc8d5 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -32,6 +32,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
     all(target_os = "linux", target_env = "gnu"),
     target_os = "macos",
     target_os = "ios",
+    target_os = "tvos",
     target_os = "watchos",
 ))]
 use crate::sys::weak::syscall;
@@ -43,6 +44,7 @@ use libc::{c_int, mode_t};
 #[cfg(any(
     target_os = "macos",
     target_os = "ios",
+    target_os = "tvos",
     target_os = "watchos",
     target_os = "solaris",
     all(target_os = "linux", target_env = "gnu")
@@ -360,7 +362,7 @@ pub struct FilePermissions {
 pub struct FileTimes {
     accessed: Option<SystemTime>,
     modified: Option<SystemTime>,
-    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))]
     created: Option<SystemTime>,
 }
 
@@ -519,6 +521,7 @@ impl FileAttr {
         target_os = "openbsd",
         target_os = "macos",
         target_os = "ios",
+        target_os = "tvos",
         target_os = "watchos",
     ))]
     pub fn created(&self) -> io::Result<SystemTime> {
@@ -530,6 +533,7 @@ impl FileAttr {
         target_os = "openbsd",
         target_os = "macos",
         target_os = "ios",
+        target_os = "tvos",
         target_os = "watchos",
         target_os = "vita",
     )))]
@@ -611,7 +615,7 @@ impl FileTimes {
         self.modified = Some(t);
     }
 
-    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))]
     pub fn set_created(&mut self, t: SystemTime) {
         self.created = Some(t);
     }
@@ -895,6 +899,7 @@ impl DirEntry {
     #[cfg(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "tvos",
         target_os = "watchos",
         target_os = "linux",
         target_os = "emscripten",
@@ -928,6 +933,7 @@ impl DirEntry {
     #[cfg(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "tvos",
         target_os = "watchos",
         target_os = "netbsd",
         target_os = "openbsd",
@@ -946,6 +952,7 @@ impl DirEntry {
     #[cfg(not(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "tvos",
         target_os = "watchos",
         target_os = "netbsd",
         target_os = "openbsd",
@@ -1107,11 +1114,21 @@ impl File {
         cvt_r(|| unsafe { os_fsync(self.as_raw_fd()) })?;
         return Ok(());
 
-        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+        #[cfg(any(
+            target_os = "macos",
+            target_os = "ios",
+            target_os = "tvos",
+            target_os = "watchos",
+        ))]
         unsafe fn os_fsync(fd: c_int) -> c_int {
             libc::fcntl(fd, libc::F_FULLFSYNC)
         }
-        #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "watchos")))]
+        #[cfg(not(any(
+            target_os = "macos",
+            target_os = "ios",
+            target_os = "tvos",
+            target_os = "watchos",
+        )))]
         unsafe fn os_fsync(fd: c_int) -> c_int {
             libc::fsync(fd)
         }
@@ -1121,7 +1138,12 @@ impl File {
         cvt_r(|| unsafe { os_datasync(self.as_raw_fd()) })?;
         return Ok(());
 
-        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+        #[cfg(any(
+            target_os = "macos",
+            target_os = "ios",
+            target_os = "tvos",
+            target_os = "watchos",
+        ))]
         unsafe fn os_datasync(fd: c_int) -> c_int {
             libc::fcntl(fd, libc::F_FULLFSYNC)
         }
@@ -1140,6 +1162,7 @@ impl File {
             target_os = "android",
             target_os = "freebsd",
             target_os = "ios",
+            target_os = "tvos",
             target_os = "linux",
             target_os = "macos",
             target_os = "netbsd",
@@ -1249,7 +1272,7 @@ impl File {
                     io::ErrorKind::Unsupported,
                     "setting file times not supported",
                 ))
-            } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] {
+            } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] {
                 let mut buf = [mem::MaybeUninit::<libc::timespec>::uninit(); 3];
                 let mut num_times = 0;
                 let mut attrlist: libc::attrlist = unsafe { mem::zeroed() };
@@ -1709,6 +1732,7 @@ fn open_to_and_set_permissions(
     target_os = "android",
     target_os = "macos",
     target_os = "ios",
+    target_os = "tvos",
     target_os = "watchos",
 )))]
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
@@ -1736,7 +1760,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     }
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     use crate::sync::atomic::{AtomicBool, Ordering};
 
diff --git a/library/std/src/sys/unix/locks/pthread_condvar.rs b/library/std/src/sys/unix/locks/pthread_condvar.rs
index 192fa216dfa..2dc1b0c601e 100644
--- a/library/std/src/sys/unix/locks/pthread_condvar.rs
+++ b/library/std/src/sys/unix/locks/pthread_condvar.rs
@@ -32,6 +32,7 @@ impl LazyInit for AllocatedCondvar {
             if #[cfg(any(
                 target_os = "macos",
                 target_os = "ios",
+                target_os = "tvos",
                 target_os = "watchos",
                 target_os = "l4re",
                 target_os = "android",
@@ -124,6 +125,7 @@ impl Condvar {
     #[cfg(not(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "tvos",
         target_os = "watchos",
         target_os = "android",
         target_os = "espidf",
@@ -158,6 +160,7 @@ impl Condvar {
     #[cfg(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "tvos",
         target_os = "watchos",
         target_os = "android",
         target_os = "espidf",
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 24566d96bcd..1b72e21a832 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -87,6 +87,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
             // The poll on Darwin doesn't set POLLNVAL for closed fds.
             target_os = "macos",
             target_os = "ios",
+            target_os = "tvos",
             target_os = "watchos",
             target_os = "redox",
             target_os = "l4re",
@@ -387,7 +388,7 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_os = "macos")] {
         #[link(name = "System")]
         extern "C" {}
-    } else if #[cfg(any(target_os = "ios", target_os = "watchos"))] {
+    } else if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))] {
         #[link(name = "System")]
         #[link(name = "objc")]
         #[link(name = "Security", kind = "framework")]
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 8edfd331304..a68c14758ff 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -63,7 +63,13 @@ extern "C" {
     #[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")]
     #[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")]
     #[cfg_attr(
-        any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "watchos"),
+        any(
+            target_os = "macos",
+            target_os = "ios",
+            target_os = "tvos",
+            target_os = "freebsd",
+            target_os = "watchos"
+        ),
         link_name = "__error"
     )]
     #[cfg_attr(target_os = "haiku", link_name = "_errnop")]
@@ -375,7 +381,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
     Ok(PathBuf::from(OsString::from_vec(e)))
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
 pub fn current_exe() -> io::Result<PathBuf> {
     unsafe {
         let mut sz: u32 = 0;
@@ -609,6 +615,7 @@ pub fn home_dir() -> Option<PathBuf> {
     #[cfg(any(
         target_os = "android",
         target_os = "ios",
+        target_os = "tvos",
         target_os = "watchos",
         target_os = "emscripten",
         target_os = "redox",
@@ -623,6 +630,7 @@ pub fn home_dir() -> Option<PathBuf> {
     #[cfg(not(any(
         target_os = "android",
         target_os = "ios",
+        target_os = "tvos",
         target_os = "watchos",
         target_os = "emscripten",
         target_os = "redox",
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 22d9d6141f4..129e7643661 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -15,6 +15,8 @@ use crate::sys::weak::raw_syscall;
 
 #[cfg(any(
     target_os = "macos",
+    target_os = "watchos",
+    target_os = "tvos",
     target_os = "freebsd",
     all(target_os = "linux", target_env = "gnu"),
     all(target_os = "linux", target_env = "musl"),
@@ -28,7 +30,12 @@ use libc::RTP_ID as pid_t;
 #[cfg(not(target_os = "vxworks"))]
 use libc::{c_int, pid_t};
 
-#[cfg(not(any(target_os = "vxworks", target_os = "l4re")))]
+#[cfg(not(any(
+    target_os = "vxworks",
+    target_os = "l4re",
+    target_os = "tvos",
+    target_os = "watchos",
+)))]
 use libc::{gid_t, uid_t};
 
 cfg_if::cfg_if! {
@@ -84,7 +91,6 @@ impl Command {
         if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? {
             return Ok((ret, ours));
         }
-
         let (input, output) = sys::pipe::anon_pipe()?;
 
         // Whatever happens after the fork is almost for sure going to touch or
@@ -166,9 +172,31 @@ impl Command {
         crate::sys_common::process::wait_with_output(proc, pipes)
     }
 
+    // WatchOS and TVOS headers mark the `fork`/`exec*` functions with
+    // `__WATCHOS_PROHIBITED __TVOS_PROHIBITED`, and indicate that the
+    // `posix_spawn*` functions should be used instead. It isn't entirely clear
+    // what `PROHIBITED` means here (e.g. if calls to these functions are
+    // allowed to exist in dead code), but it sounds bad, so we go out of our
+    // way to avoid that all-together.
+    #[cfg(any(target_os = "tvos", target_os = "watchos"))]
+    const ERR_APPLE_TV_WATCH_NO_FORK_EXEC: Error = io::const_io_error!(
+        ErrorKind::Unsupported,
+        "`fork`+`exec`-based process spawning is not supported on this target",
+    );
+
+    #[cfg(any(target_os = "tvos", target_os = "watchos"))]
+    unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
+        return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC);
+    }
+
     // Attempts to fork the process. If successful, returns Ok((0, -1))
     // in the child, and Ok((child_pid, -1)) in the parent.
-    #[cfg(not(any(target_os = "linux", all(target_os = "nto", target_env = "nto71"))))]
+    #[cfg(not(any(
+        target_os = "linux",
+        target_os = "watchos",
+        target_os = "tvos",
+        all(target_os = "nto", target_env = "nto71"),
+    )))]
     unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
         cvt(libc::fork()).map(|res| (res, -1))
     }
@@ -339,6 +367,7 @@ impl Command {
     // allocation). Instead we just close it manually. This will never
     // have the drop glue anyway because this code never returns (the
     // child will either exec() or invoke libc::exit)
+    #[cfg(not(any(target_os = "tvos", target_os = "watchos")))]
     unsafe fn do_exec(
         &mut self,
         stdio: ChildPipes,
@@ -445,8 +474,19 @@ impl Command {
         Err(io::Error::last_os_error())
     }
 
+    #[cfg(any(target_os = "tvos", target_os = "watchos"))]
+    unsafe fn do_exec(
+        &mut self,
+        _stdio: ChildPipes,
+        _maybe_envp: Option<&CStringArray>,
+    ) -> Result<!, io::Error> {
+        return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC);
+    }
+
     #[cfg(not(any(
         target_os = "macos",
+        target_os = "tvos",
+        target_os = "watchos",
         target_os = "freebsd",
         all(target_os = "linux", target_env = "gnu"),
         all(target_os = "linux", target_env = "musl"),
@@ -464,6 +504,9 @@ impl Command {
     // directly.
     #[cfg(any(
         target_os = "macos",
+        // FIXME: `target_os = "ios"`?
+        target_os = "tvos",
+        target_os = "watchos",
         target_os = "freebsd",
         all(target_os = "linux", target_env = "gnu"),
         all(target_os = "linux", target_env = "musl"),
@@ -550,7 +593,7 @@ impl Command {
         }
         let addchdir = match self.get_cwd() {
             Some(cwd) => {
-                if cfg!(target_os = "macos") {
+                if cfg!(any(target_os = "macos", target_os = "tvos", target_os = "watchos")) {
                     // There is a bug in macOS where a relative executable
                     // path like "../myprogram" will cause `posix_spawn` to
                     // successfully launch the program, but erroneously return
diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs
index d8b63546b9e..d471be33ed5 100644
--- a/library/std/src/sys/unix/rand.rs
+++ b/library/std/src/sys/unix/rand.rs
@@ -14,6 +14,7 @@ pub fn hashmap_random_keys() -> (u64, u64) {
     unix,
     not(target_os = "macos"),
     not(target_os = "ios"),
+    not(target_os = "tvos"),
     not(target_os = "watchos"),
     not(target_os = "openbsd"),
     not(target_os = "freebsd"),
@@ -198,7 +199,7 @@ mod imp {
 // once per thread in `hashmap_random_keys`. Therefore `SecRandomCopyBytes` is
 // only used on iOS where direct access to `/dev/urandom` is blocked by the
 // sandbox.
-#[cfg(any(target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))]
 mod imp {
     use crate::io;
     use crate::ptr;
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index 010015667f7..893f8b8df3f 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -150,7 +150,7 @@ impl Thread {
         }
     }
 
-    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
     pub fn set_name(name: &CStr) {
         unsafe {
             let name = truncate_cstr::<{ libc::MAXTHREADNAMESIZE }>(name);
@@ -283,7 +283,13 @@ impl Drop for Thread {
     }
 }
 
-#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(
+    target_os = "linux",
+    target_os = "macos",
+    target_os = "ios",
+    target_os = "tvos",
+    target_os = "watchos",
+))]
 fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] {
     let mut result = [0; MAX_WITH_NUL];
     for (src, dst) in cstr.to_bytes().iter().zip(&mut result[..MAX_WITH_NUL - 1]) {
@@ -299,6 +305,7 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
             target_os = "emscripten",
             target_os = "fuchsia",
             target_os = "ios",
+            target_os = "tvos",
             target_os = "linux",
             target_os = "macos",
             target_os = "solaris",
diff --git a/library/std/src/sys/unix/thread_parking/pthread.rs b/library/std/src/sys/unix/thread_parking/pthread.rs
index 8bf4bae7a3f..ae805d84399 100644
--- a/library/std/src/sys/unix/thread_parking/pthread.rs
+++ b/library/std/src/sys/unix/thread_parking/pthread.rs
@@ -46,6 +46,7 @@ unsafe fn wait_timeout(
     #[cfg(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "tvos",
         target_os = "watchos",
         target_os = "espidf",
         target_os = "horizon",
@@ -73,6 +74,7 @@ unsafe fn wait_timeout(
     #[cfg(not(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "tvos",
         target_os = "watchos",
         target_os = "espidf",
         target_os = "horizon",
@@ -120,6 +122,7 @@ impl Parker {
             if #[cfg(any(
                 target_os = "macos",
                 target_os = "ios",
+                target_os = "tvos",
                 target_os = "watchos",
                 target_os = "l4re",
                 target_os = "android",
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index a9fbc7ab108..17b4130c202 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -219,7 +219,8 @@ impl From<__timespec64> for Timespec {
 #[cfg(any(
     all(target_os = "macos", any(not(target_arch = "aarch64"))),
     target_os = "ios",
-    target_os = "watchos"
+    target_os = "watchos",
+    target_os = "tvos"
 ))]
 mod inner {
     use crate::sync::atomic::{AtomicU64, Ordering};
@@ -339,7 +340,8 @@ mod inner {
 #[cfg(not(any(
     all(target_os = "macos", any(not(target_arch = "aarch64"))),
     target_os = "ios",
-    target_os = "watchos"
+    target_os = "watchos",
+    target_os = "tvos"
 )))]
 mod inner {
     use crate::fmt;
diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs
index 62ffee70bec..61088ff16ed 100644
--- a/library/std/src/sys/unix/weak.rs
+++ b/library/std/src/sys/unix/weak.rs
@@ -28,7 +28,7 @@ use crate::ptr;
 use crate::sync::atomic::{self, AtomicPtr, Ordering};
 
 // We can use true weak linkage on ELF targets.
-#[cfg(not(any(target_os = "macos", target_os = "ios")))]
+#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "tvos")))]
 pub(crate) macro weak {
     (fn $name:ident($($t:ty),*) -> $ret:ty) => (
         let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
@@ -43,7 +43,7 @@ pub(crate) macro weak {
 }
 
 // On non-ELF targets, use the dlsym approximation of weak linkage.
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))]
 pub(crate) use self::dlsym as weak;
 
 pub(crate) struct ExternWeak<F: Copy> {
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index 652c695fc57..2976a9f578e 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -18,7 +18,7 @@ use crate::ffi::{c_int, c_void};
 cfg_if::cfg_if! {
     if #[cfg(any(
         target_os = "dragonfly", target_os = "freebsd",
-        target_os = "ios", target_os = "macos", target_os = "watchos",
+        target_os = "ios", target_os = "tvos", target_os = "macos", target_os = "watchos",
         target_os = "openbsd", target_os = "netbsd", target_os = "illumos",
         target_os = "solaris", target_os = "haiku", target_os = "l4re", target_os = "nto"))] {
         use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index b65e2572cc5..5d6b9e94ee9 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -42,6 +42,7 @@ fn test_named_thread() {
     all(target_os = "linux", target_env = "gnu"),
     target_os = "macos",
     target_os = "ios",
+    target_os = "tvos",
     target_os = "watchos"
 ))]
 #[test]
diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index f6a68073b2f..ec24e137572 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -117,7 +117,7 @@ extern "C" {
 }
 
 cfg_if::cfg_if! {
-if #[cfg(any(target_os = "ios", target_os = "watchos", target_os = "netbsd", not(target_arch = "arm")))] {
+if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "netbsd", not(target_arch = "arm")))] {
     // Not ARM EHABI
     #[repr(C)]
     #[derive(Copy, Clone, PartialEq)]
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index 06f479808b9..cb40521dda7 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -54,9 +54,9 @@ impl Config {
     /// Runs a command, printing out nice contextual information if it fails.
     /// Exits if the command failed to execute at all, otherwise returns its
     /// `status.success()`.
-    pub(crate) fn try_run(&self, cmd: &mut Command) -> bool {
+    pub(crate) fn try_run(&self, cmd: &mut Command) -> Result<(), ()> {
         if self.dry_run() {
-            return true;
+            return Ok(());
         }
         self.verbose(&format!("running: {:?}", cmd));
         try_run(cmd, self.is_verbose())
@@ -156,12 +156,14 @@ impl Config {
                 ];
             }
             ";
-            nix_build_succeeded = self.try_run(Command::new("nix-build").args(&[
-                Path::new("-E"),
-                Path::new(NIX_EXPR),
-                Path::new("-o"),
-                &nix_deps_dir,
-            ]));
+            nix_build_succeeded = self
+                .try_run(Command::new("nix-build").args(&[
+                    Path::new("-E"),
+                    Path::new(NIX_EXPR),
+                    Path::new("-o"),
+                    &nix_deps_dir,
+                ]))
+                .is_ok();
             nix_deps_dir
         });
         if !nix_build_succeeded {
@@ -186,7 +188,7 @@ impl Config {
             patchelf.args(&["--set-interpreter", dynamic_linker.trim_end()]);
         }
 
-        self.try_run(patchelf.arg(fname));
+        self.try_run(patchelf.arg(fname)).unwrap();
     }
 
     fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) {
@@ -237,7 +239,7 @@ impl Config {
                             "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
                             url, tempfile.to_str().expect("invalid UTF-8 not supported with powershell downloads"),
                         ),
-                    ])) {
+                    ])).is_err() {
                         return;
                     }
                     eprintln!("\nspurious failure, trying again");
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index d7e77aeb338..d389b568f56 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -333,7 +333,7 @@ forward! {
     create(path: &Path, s: &str),
     remove(f: &Path),
     tempdir() -> PathBuf,
-    try_run(cmd: &mut Command) -> bool,
+    try_run(cmd: &mut Command) -> Result<(), ()>,
     llvm_link_shared() -> bool,
     download_rustc() -> bool,
     initial_rustfmt() -> Option<PathBuf>,
@@ -614,11 +614,13 @@ impl Build {
         }
 
         // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error).
-        let has_local_modifications = !self.try_run(
-            Command::new("git")
-                .args(&["diff-index", "--quiet", "HEAD"])
-                .current_dir(&absolute_path),
-        );
+        let has_local_modifications = self
+            .try_run(
+                Command::new("git")
+                    .args(&["diff-index", "--quiet", "HEAD"])
+                    .current_dir(&absolute_path),
+            )
+            .is_err();
         if has_local_modifications {
             self.run(Command::new("git").args(&["stash", "push"]).current_dir(&absolute_path));
         }
diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs
index ec01f744b82..c97b7592737 100644
--- a/src/bootstrap/run.rs
+++ b/src/bootstrap/run.rs
@@ -27,7 +27,8 @@ impl Step for ExpandYamlAnchors {
         try_run(
             builder,
             &mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("generate").arg(&builder.src),
-        );
+        )
+        .unwrap();
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -39,17 +40,17 @@ impl Step for ExpandYamlAnchors {
     }
 }
 
-fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool {
+fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> Result<(), ()> {
     if !builder.fail_fast {
-        if !builder.try_run(cmd) {
+        if let Err(e) = builder.try_run(cmd) {
             let mut failures = builder.delayed_failures.borrow_mut();
             failures.push(format!("{:?}", cmd));
-            return false;
+            return Err(e);
         }
     } else {
         builder.run(cmd);
     }
-    true
+    Ok(())
 }
 
 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 9212362f6c9..873ed61daf3 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -48,17 +48,17 @@ const MIR_OPT_BLESS_TARGET_MAPPING: &[(&str, &str)] = &[
     // build for, so there is no entry for "aarch64-apple-darwin" here.
 ];
 
-fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool {
+fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> Result<(), ()> {
     if !builder.fail_fast {
-        if !builder.try_run(cmd) {
+        if let Err(e) = builder.try_run(cmd) {
             let mut failures = builder.delayed_failures.borrow_mut();
             failures.push(format!("{:?}", cmd));
-            return false;
+            return Err(e);
         }
     } else {
         builder.run(cmd);
     }
-    true
+    Ok(())
 }
 
 fn try_run_quiet(builder: &Builder<'_>, cmd: &mut Command) -> bool {
@@ -187,7 +187,8 @@ You can skip linkcheck with --exclude src/tools/linkchecker"
         try_run(
             builder,
             builder.tool_cmd(Tool::Linkchecker).arg(builder.out.join(host.triple).join("doc")),
-        );
+        )
+        .unwrap();
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -240,7 +241,8 @@ impl Step for HtmlCheck {
         builder.default_doc(&[]);
         builder.ensure(crate::doc::Rustc::new(builder.top_stage, self.target, builder));
 
-        try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)));
+        try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)))
+            .unwrap();
     }
 }
 
@@ -286,7 +288,8 @@ impl Step for Cargotest {
                 .args(builder.config.test_args())
                 .env("RUSTC", builder.rustc(compiler))
                 .env("RUSTDOC", builder.rustdoc(compiler)),
-        );
+        )
+        .unwrap();
     }
 }
 
@@ -785,7 +788,7 @@ impl Step for Clippy {
         cargo.add_rustc_lib_path(builder, compiler);
         let mut cargo = prepare_cargo_test(cargo, &[], &[], "clippy", compiler, host, builder);
 
-        if builder.try_run(&mut cargo) {
+        if builder.try_run(&mut cargo).is_ok() {
             // The tests succeeded; nothing to do.
             return;
         }
@@ -858,7 +861,7 @@ impl Step for RustdocTheme {
                 util::lld_flag_no_threads(self.compiler.host.contains("windows")),
             );
         }
-        try_run(builder, &mut cmd);
+        try_run(builder, &mut cmd).unwrap();
     }
 }
 
@@ -1109,7 +1112,7 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy`
         }
 
         builder.info("tidy check");
-        try_run(builder, &mut cmd);
+        try_run(builder, &mut cmd).unwrap();
 
         builder.ensure(ExpandYamlAnchors);
 
@@ -1157,7 +1160,8 @@ impl Step for ExpandYamlAnchors {
         try_run(
             builder,
             &mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("check").arg(&builder.src),
-        );
+        )
+        .unwrap();
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -1936,7 +1940,7 @@ impl BookTest {
             compiler.host,
         );
         let _time = util::timeit(&builder);
-        let toolstate = if try_run(builder, &mut rustbook_cmd) {
+        let toolstate = if try_run(builder, &mut rustbook_cmd).is_ok() {
             ToolState::TestPass
         } else {
             ToolState::TestFail
@@ -2094,7 +2098,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
     cmd.arg("--test-args").arg(test_args);
 
     if builder.config.verbose_tests {
-        try_run(builder, &mut cmd)
+        try_run(builder, &mut cmd).is_ok()
     } else {
         try_run_quiet(builder, &mut cmd)
     }
@@ -2122,7 +2126,7 @@ impl Step for RustcGuide {
 
         let src = builder.src.join(relative_path);
         let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
-        let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)) {
+        let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)).is_ok() {
             ToolState::TestPass
         } else {
             ToolState::TestFail
@@ -2661,7 +2665,7 @@ impl Step for Bootstrap {
     fn run(self, builder: &Builder<'_>) {
         let mut check_bootstrap = Command::new(&builder.python());
         check_bootstrap.arg("bootstrap_test.py").current_dir(builder.src.join("src/bootstrap/"));
-        try_run(builder, &mut check_bootstrap);
+        try_run(builder, &mut check_bootstrap).unwrap();
 
         let host = builder.config.build;
         let compiler = builder.compiler(0, host);
@@ -2733,7 +2737,7 @@ impl Step for TierCheck {
         }
 
         builder.info("platform support check");
-        try_run(builder, &mut cargo.into());
+        try_run(builder, &mut cargo.into()).unwrap();
     }
 }
 
@@ -2813,7 +2817,7 @@ impl Step for RustInstaller {
         cmd.env("CARGO", &builder.initial_cargo);
         cmd.env("RUSTC", &builder.initial_rustc);
         cmd.env("TMP_DIR", &tmpdir);
-        try_run(builder, &mut cmd);
+        try_run(builder, &mut cmd).unwrap();
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 96341b69df0..126f0b1eb31 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -107,7 +107,7 @@ impl Step for ToolBuild {
         );
 
         let mut cargo = Command::from(cargo);
-        let is_expected = builder.try_run(&mut cargo);
+        let is_expected = builder.try_run(&mut cargo).is_ok();
 
         builder.save_toolstate(
             tool,
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 1ec49f80d63..b291584b300 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -228,7 +228,7 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef<Path>>(
 }
 
 pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) {
-    if !try_run(cmd, print_cmd_on_fail) {
+    if try_run(cmd, print_cmd_on_fail).is_err() {
         crate::detail_exit_macro!(1);
     }
 }
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 2b0431a159b..1e17a90a842 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -16,6 +16,7 @@
     - [Target Tier Policy](target-tier-policy.md)
     - [Template for Target-specific Documentation](platform-support/TEMPLATE.md)
     - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md)
+    - [\*-apple-tvos](platform-support/apple-tvos.md)
     - [\*-apple-watchos\*](platform-support/apple-watchos.md)
     - [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md)
     - [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index f69dcd5983d..62f628f8229 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -214,7 +214,7 @@ host tools.
 target | std | host | notes
 -------|:---:|:----:|-------
 `aarch64-apple-ios-macabi` | ? |  | Apple Catalyst on ARM64
-`aarch64-apple-tvos` | * |  | ARM64 tvOS
+[`aarch64-apple-tvos`](platform-support/apple-tvos.md) | ? |  | ARM64 tvOS
 [`aarch64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ |  | ARM64 Apple WatchOS Simulator
 [`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ |  | ARM64 SOLID with TOPPERS/ASP3
 [`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * |  | ARM64 Nintendo Switch, Horizon
@@ -316,7 +316,7 @@ target | std | host | notes
 `thumbv7neon-unknown-linux-musleabihf` | ? |  | Thumb2-mode ARMv7a Linux with NEON, MUSL
 [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? |  | WebAssembly
 `x86_64-apple-ios-macabi` | ✓ |  | Apple Catalyst on x86_64
-`x86_64-apple-tvos` | * | | x86 64-bit tvOS
+[`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ? | | x86 64-bit tvOS
 [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator
 [`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ |  | x86 64-bit QNX Neutrino 7.1 RTOS |
 [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
diff --git a/src/doc/rustc/src/platform-support/apple-tvos.md b/src/doc/rustc/src/platform-support/apple-tvos.md
new file mode 100644
index 00000000000..d87fd1959b4
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/apple-tvos.md
@@ -0,0 +1,85 @@
+# `*-apple-tvos`
+- aarch64-apple-tvos
+- x86_64-apple-tvos
+
+**Tier: 3**
+
+Apple tvOS targets:
+- Apple tvOS on aarch64
+- Apple tvOS Simulator on x86_64
+
+## Target maintainers
+
+* [@thomcc](https://github.com/thomcc)
+
+## Requirements
+
+These targets are cross-compiled. You will need appropriate versions of Xcode
+and the SDKs for tvOS (`AppleTVOS.sdk`) and/or the tvOS Simulator
+(`AppleTVSimulator.sdk`) to build a toolchain and target these platforms.
+
+The targets support most (see below) of the standard library including the
+allocator to the best of my knowledge, however they are very new, not yet
+well-tested, and it is possible that there are various bugs.
+
+In theory we support back to tvOS version 7.0, although the actual minimum
+version you can target may be newer than this, for example due to the versions
+of Xcode and your SDKs.
+
+As with the other Apple targets, `rustc` respects the common environment
+variables used by Xcode to configure this, in this case
+`TVOS_DEPLOYMENT_TARGET`.
+
+#### Incompletely supported library functionality
+
+As mentioned, "most" of the standard library is supported, which means that some portions
+are known to be unsupported. The following APIs are currently known to have
+missing or incomplete support:
+
+- `std::process::Command`'s API will return an error if it is configured in a
+  manner which cannot be performed using `posix_spawn` -- this is because the
+  more flexible `fork`/`exec`-based approach is prohibited on these platforms in
+  favor of `posix_spawn{,p}` (which still probably will get you rejected from
+  app stores, so is likely sideloading-only). A concrete set of cases where this
+  will occur is difficult to enumerate (and would quickly become stale), but in
+  some cases it may be worked around by tweaking the manner in which `Command`
+  is invoked.
+
+## Building the target
+
+The targets can be built by enabling them for a `rustc` build in `config.toml`, by adding, for example:
+
+```toml
+[build]
+build-stage = 1
+target = ["aarch64-apple-tvos", "x86_64-apple-tvos"]
+```
+
+It's possible that cargo under `-Zbuild-std` may also be used to target them.
+
+## Building Rust programs
+
+*Note: Building for this target requires the corresponding TVOS SDK, as provided by Xcode.*
+
+Rust programs can be built for these targets
+
+```text
+$ rustc --target aarch64-apple-tvos your-code.rs
+...
+$ rustc --target x86_64-apple-tvos your-code.rs
+```
+
+## Testing
+
+There is no support for running the Rust or standard library testsuite on tvOS
+or the simulators at the moment. Testing has mostly been done manually with
+builds of static libraries called from Xcode or a simulator.
+
+It hopefully will be possible to improve this in the future.
+
+## Cross-compilation toolchains and C code
+
+This target can be cross-compiled from x86_64 or aarch64 macOS hosts.
+
+Other hosts are not supported for cross-compilation, but might work when also
+providing the required Xcode SDK.
diff --git a/src/doc/style-guide/src/README.md b/src/doc/style-guide/src/README.md
index adb73a7eef6..75013bb3df9 100644
--- a/src/doc/style-guide/src/README.md
+++ b/src/doc/style-guide/src/README.md
@@ -16,9 +16,21 @@ Rust code has similar formatting, less mental effort is required to comprehend a
 new project, lowering the barrier to entry for new developers.
 
 Thus, there are productivity benefits to using a formatting tool (such as
-rustfmt), and even larger benefits by using a community-consistent formatting,
-typically by using a formatting tool's default settings.
+`rustfmt`), and even larger benefits by using a community-consistent
+formatting, typically by using a formatting tool's default settings.
 
+## The default Rust style
+
+The Rust Style Guide defines the default Rust style, and *recommends* that
+developers and tools follow the default Rust style. Tools such as `rustfmt` use
+the style guide as a reference for the default style. Everything in this style
+guide, whether or not it uses language such as "must" or the imperative mood
+such as "insert a space ..." or "break the line after ...", refers to the
+default style.
+
+This should not be interpreted as forbidding developers from following a
+non-default style, or forbidding tools from adding any particular configuration
+options.
 
 ## Formatting conventions
 
@@ -28,8 +40,47 @@ typically by using a formatting tool's default settings.
 * Each level of indentation must be four spaces (that is, all indentation
   outside of string literals and comments must be a multiple of four).
 * The maximum width for a line is 100 characters.
-* A tool should be configurable for all three of these variables.
+* A tool may choose to make some of these configurable.
+
+#### Block indent
+
+Prefer block indent over visual indent:
+
+```rust
+// Block indent
+a_function_call(
+    foo,
+    bar,
+);
+
+// Visual indent
+a_function_call(foo,
+                bar);
+```
 
+This makes for smaller diffs (e.g., if `a_function_call` is renamed in the above
+example) and less rightward drift.
+
+### Trailing commas
+
+Lists should have a trailing comma when followed by a newline:
+
+```rust
+function_call(
+    argument,
+    another_argument,
+);
+
+let array = [
+    element,
+    another_element,
+    yet_another_element,
+];
+```
+
+This makes moving code (e.g., by copy and paste) easier, and makes diffs
+smaller, as appending or removing items does not require modifying another line
+to add or remove a comma.
 
 ### Blank lines
 
@@ -48,11 +99,7 @@ fn bar() {}
 fn baz() {}
 ```
 
-Formatting tools should make the bounds on blank lines configurable: there
-should be separate minimum and maximum numbers of newlines between both
-statements and (top-level) items (i.e., four options). As described above, the
-defaults for both statements and items should be minimum: 1, maximum: 2.
-
+Formatting tools may wish to make the bounds on blank lines configurable.
 
 ### [Module-level items](items.md)
 ### [Statements](statements.md)
diff --git a/src/doc/style-guide/src/SUMMARY.md b/src/doc/style-guide/src/SUMMARY.md
index 004692fa6a2..59fe9fdc669 100644
--- a/src/doc/style-guide/src/SUMMARY.md
+++ b/src/doc/style-guide/src/SUMMARY.md
@@ -2,10 +2,10 @@
 
 [Introduction](README.md)
 
-- [Module-level items](items.md)
+- [Items](items.md)
 - [Statements](statements.md)
 - [Expressions](expressions.md)
-- [Types](types.md)
-- [Non-formatting conventions](advice.md)
+- [Types and Bounds](types.md)
+- [Other style advice](advice.md)
 - [`Cargo.toml` conventions](cargo.md)
-- [Principles used for deciding these guidelines](principles.md)
+- [Guiding principles and rationale](principles.md)
diff --git a/src/doc/style-guide/src/advice.md b/src/doc/style-guide/src/advice.md
index ab4b92b0a24..9a617be509c 100644
--- a/src/doc/style-guide/src/advice.md
+++ b/src/doc/style-guide/src/advice.md
@@ -25,9 +25,9 @@ if y {
  * Local variables shall be `snake_case`,
  * Macro names shall be `snake_case`,
  * Constants (`const`s and immutable `static`s) shall be `SCREAMING_SNAKE_CASE`.
- * When a name is forbidden because it is a reserved word (e.g., `crate`), use a
-   trailing underscore to make the name legal (e.g., `crate_`), or use raw
-   identifiers if possible.
+ * When a name is forbidden because it is a reserved word (such as `crate`),
+   either use a raw identifier (`r#crate`) or use a trailing underscore
+   (`crate_`). Don't misspell the word (`krate`).
 
 ### Modules
 
diff --git a/src/doc/style-guide/src/cargo.md b/src/doc/style-guide/src/cargo.md
index 13b96ca8c5e..d3b67ae4582 100644
--- a/src/doc/style-guide/src/cargo.md
+++ b/src/doc/style-guide/src/cargo.md
@@ -1,4 +1,4 @@
-# Cargo.toml conventions
+# `Cargo.toml` conventions
 
 ## Formatting conventions
 
@@ -25,16 +25,17 @@ not indent any key names; start all key names at the start of a line.
 Use multi-line strings (rather than newline escape sequences) for any string
 values that include multiple lines, such as the crate description.
 
-For array values, such as a list of authors, put the entire list on the same
+For array values, such as a list of features, put the entire list on the same
 line as the key, if it fits. Otherwise, use block indentation: put a newline
 after the opening square bracket, indent each item by one indentation level,
 put a comma after each item (including the last), and put the closing square
 bracket at the start of a line by itself after the last item.
 
 ```rust
-authors = [
-    "A Uthor <a.uthor@example.org>",
-    "Another Author <author@example.net>",
+some_feature = [
+    "another_feature",
+    "yet_another_feature",
+    "some_dependency?/some_feature",
 ]
 ```
 
@@ -54,11 +55,11 @@ version = "4.5.6"
 
 ## Metadata conventions
 
-The authors list should consist of strings that each contain an author name
-followed by an email address in angle brackets: `Full Name <email@address>`.
-It should not contain bare email addresses, or names without email addresses.
-(The authors list may also include a mailing list address without an associated
-name.)
+The authors list, if present, should consist of strings that each contain an
+author name followed by an email address in angle brackets: `Full Name
+<email@address>`. It should not contain bare email addresses, or names without
+email addresses. (The authors list may also include a mailing list address
+without an associated name.)
 
 The license field must contain a valid [SPDX
 expression](https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60),
diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md
index 96f66c89c25..8271b42da4c 100644
--- a/src/doc/style-guide/src/expressions.md
+++ b/src/doc/style-guide/src/expressions.md
@@ -690,7 +690,7 @@ Where it is possible to use a block form on the right-hand side and avoid
 breaking the left-hand side, do that. E.g.
 
 ```rust
-    // Assuming the following line does done fit in the max width
+    // Assuming the following line does not fit in the max width
     a_very_long_pattern | another_pattern => ALongStructName {
         ...
     },
diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md
index 2835975355f..1e0e60248bf 100644
--- a/src/doc/style-guide/src/items.md
+++ b/src/doc/style-guide/src/items.md
@@ -1,5 +1,10 @@
 ## Items
 
+Items consist of the set of things permitted at the top level of a module.
+However, Rust also allows some items to appear within some other types of
+items, such as within a function. The same formatting conventions apply whether
+an item appears at module level or within another item.
+
 `extern crate` statements must be first in a file. They must be ordered
 alphabetically.
 
@@ -15,8 +20,8 @@ Tools should make the above ordering optional.
 
 ### Function definitions
 
-In Rust, one finds functions by searching for `fn [function-name]`; It's
-important that you style your code so that it's very searchable in this way.
+In Rust, people often find functions by searching for `fn [function-name]`, so
+the formatting of function definitions shold enable this.
 
 The proper ordering and spacing is:
 
@@ -63,8 +68,9 @@ let y = (11, 22, 33);
 
 In the declaration, put each variant on its own line, block indented.
 
-Format each variant accordingly as either a struct, tuple struct, or identifier,
-which doesn't require special formatting (but without the `struct` keyword.
+Format each variant accordingly as either a struct (but without the `struct`
+keyword), a tuple struct, or an identifier (which doesn't require special
+formatting):
 
 ```rust
 enum FooBar {
@@ -139,7 +145,7 @@ union Foo {
 
 Put the whole struct on one line if possible. Types in the parentheses should be
 separated by a comma and space with no trailing comma. No spaces around the
-parentheses or semi-colon:
+parentheses or semicolon:
 
 ```rust
 pub struct Foo(String, u8);
@@ -230,7 +236,7 @@ impl Bar
 
 `extern crate foo;`
 
-Use spaces around keywords, no spaces around the semi-colon.
+Use spaces around keywords, no spaces around the semicolon.
 
 
 ### Modules
@@ -245,7 +251,7 @@ mod foo;
 ```
 
 Use spaces around keywords and before the opening brace, no spaces around the
-semi-colon.
+semicolon.
 
 ### macro\_rules!
 
@@ -478,8 +484,8 @@ foo::{
 A *group* of imports is a set of imports on the same or sequential lines. One or
 more blank lines or other items (e.g., a function) separate groups of imports.
 
-Within a group of imports, imports must be sorted ascii-betically. Groups of
-imports must not be merged or re-ordered.
+Within a group of imports, imports must be sorted ASCIIbetically (uppercase
+before lowercase). Groups of imports must not be merged or re-ordered.
 
 
 E.g., input:
@@ -505,13 +511,9 @@ use b;
 Because of `macro_use`, attributes must also start a new group and prevent
 re-ordering.
 
-Note that tools which only have access to syntax (such as Rustfmt) cannot tell
-which imports are from an external crate or the std lib, etc.
-
-
 #### Ordering list import
 
-Names in a list import must be sorted ascii-betically, but with `self` and
+Names in a list import must be sorted ASCIIbetically, but with `self` and
 `super` first, and groups and glob imports last. This applies recursively. For
 example, `a::*` comes before `b::a` but `a::b` comes before `a::*`. E.g.,
 `use foo::bar::{a, b::c, b::d, b::d::{x, y, z}, b::{self, r, s}};`.
diff --git a/src/doc/style-guide/src/principles.md b/src/doc/style-guide/src/principles.md
index 2d203f264e6..d548693e39e 100644
--- a/src/doc/style-guide/src/principles.md
+++ b/src/doc/style-guide/src/principles.md
@@ -1,7 +1,7 @@
 # Guiding principles and rationale
 
-When deciding on style guidelines, the style team tried to be guided by the
-following principles (in rough priority order):
+When deciding on style guidelines, the style team follows these guiding
+principles (in rough priority order):
 
 * readability
     - scan-ability
@@ -19,35 +19,11 @@ following principles (in rough priority order):
 * specifics
     - compatibility with version control practices - preserving diffs,
       merge-friendliness, etc.
-    - preventing right-ward drift
+    - preventing rightward drift
     - minimising vertical space
 
 * application
     - ease of manual application
-    - ease of implementation (in Rustfmt, and in other tools/editors/code generators)
+    - ease of implementation (in `rustfmt`, and in other tools/editors/code generators)
     - internal consistency
     - simplicity of formatting rules
-
-
-## Overarching guidelines
-
-Prefer block indent over visual indent. E.g.,
-
-```rust
-// Block indent
-a_function_call(
-    foo,
-    bar,
-);
-
-// Visual indent
-a_function_call(foo,
-                bar);
-```
-
-This makes for smaller diffs (e.g., if `a_function_call` is renamed in the above
-example) and less rightward drift.
-
-Lists should have a trailing comma when followed by a newline, see the block
-indent example above. This choice makes moving code (e.g., by copy and paste)
-easier and makes smaller diffs.
diff --git a/src/doc/style-guide/src/statements.md b/src/doc/style-guide/src/statements.md
index b6708e6c72a..9bc521e1c7b 100644
--- a/src/doc/style-guide/src/statements.md
+++ b/src/doc/style-guide/src/statements.md
@@ -1,7 +1,9 @@
+## Statements
+
 ### Let statements
 
 There should be spaces after the `:` and on both sides of the `=` (if they are
-present). No space before the semi-colon.
+present). No space before the semicolon.
 
 ```rust
 // A comment.
@@ -213,7 +215,7 @@ fn main() {
 ### Macros in statement position
 
 A macro use in statement position should use parentheses or square brackets as
-delimiters and should be terminated with a semi-colon. There should be no spaces
+delimiters and should be terminated with a semicolon. There should be no spaces
 between the name, `!`, the delimiters, or the `;`.
 
 ```rust
@@ -224,13 +226,13 @@ a_macro!(...);
 
 ### Expressions in statement position
 
-There should be no space between the expression and the semi-colon.
+There should be no space between the expression and the semicolon.
 
 ```
 <expr>;
 ```
 
-All expressions in statement position should be terminated with a semi-colon,
+All expressions in statement position should be terminated with a semicolon,
 unless they end with a block or are used as the value for a block.
 
 E.g.,
@@ -248,7 +250,7 @@ loop {
 }
 ```
 
-Use a semi-colon where an expression has void type, even if it could be
+Use a semicolon where an expression has void type, even if it could be
 propagated. E.g.,
 
 ```rust
diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py
index eade9e04559..5ab1874e9ed 100755
--- a/src/etc/htmldocck.py
+++ b/src/etc/htmldocck.py
@@ -110,6 +110,9 @@ There are a number of supported commands:
 
 * `@has-dir PATH` checks for the existence of the given directory.
 
+* `@files FOLDER_PATH [ENTRIES]`, checks that `FOLDER_PATH` contains exactly
+  `[ENTRIES]`.
+
 All conditions can be negated with `!`. `@!has foo/type.NoSuch.html`
 checks if the given file does not exist, for example.
 
@@ -321,12 +324,15 @@ class CachedFiles(object):
         else:
             return self.last_path
 
+    def get_absolute_path(self, path):
+        return os.path.join(self.root, path)
+
     def get_file(self, path):
         path = self.resolve_path(path)
         if path in self.files:
             return self.files[path]
 
-        abspath = os.path.join(self.root, path)
+        abspath = self.get_absolute_path(path)
         if not(os.path.exists(abspath) and os.path.isfile(abspath)):
             raise FailedCheck('File does not exist {!r}'.format(path))
 
@@ -340,7 +346,7 @@ class CachedFiles(object):
         if path in self.trees:
             return self.trees[path]
 
-        abspath = os.path.join(self.root, path)
+        abspath = self.get_absolute_path(path)
         if not(os.path.exists(abspath) and os.path.isfile(abspath)):
             raise FailedCheck('File does not exist {!r}'.format(path))
 
@@ -356,7 +362,7 @@ class CachedFiles(object):
 
     def get_dir(self, path):
         path = self.resolve_path(path)
-        abspath = os.path.join(self.root, path)
+        abspath = self.get_absolute_path(path)
         if not(os.path.exists(abspath) and os.path.isdir(abspath)):
             raise FailedCheck('Directory does not exist {!r}'.format(path))
 
@@ -538,6 +544,41 @@ def get_nb_matching_elements(cache, c, regexp, stop_at_first):
         return check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first)
 
 
+def check_files_in_folder(c, cache, folder, files):
+    files = files.strip()
+    if not files.startswith('[') or not files.endswith(']'):
+        raise InvalidCheck("Expected list as second argument of @{} (ie '[]')".format(c.cmd))
+
+    folder = cache.get_absolute_path(folder)
+
+    # First we create a set of files to check if there are duplicates.
+    files = shlex.split(files[1:-1].replace(",", ""))
+    files_set = set()
+    for file in files:
+        if file in files_set:
+            raise InvalidCheck("Duplicated file `{}` in @{}".format(file, c.cmd))
+        files_set.add(file)
+    folder_set = set([f for f in os.listdir(folder) if f != "." and f != ".."])
+
+    # Then we remove entries from both sets (we clone `folder_set` so we can iterate it while
+    # removing its elements).
+    for entry in set(folder_set):
+        if entry in files_set:
+            files_set.remove(entry)
+            folder_set.remove(entry)
+
+    error = 0
+    if len(files_set) != 0:
+        print_err(c.lineno, c.context, "Entries not found in folder `{}`: `{}`".format(
+            folder, files_set))
+        error += 1
+    if len(folder_set) != 0:
+        print_err(c.lineno, c.context, "Extra entries in folder `{}`: `{}`".format(
+            folder, folder_set))
+        error += 1
+    return error == 0
+
+
 ERR_COUNT = 0
 
 
@@ -566,6 +607,13 @@ def check_command(c, cache):
             else:
                 raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd))
 
+        elif c.cmd == 'files': # check files in given folder
+            if len(c.args) != 2: # @files <folder path> <file list>
+                raise InvalidCheck("Invalid number of @{} arguments".format(c.cmd))
+            elif c.negated:
+                raise InvalidCheck("@{} doesn't support negative check".format(c.cmd))
+            ret = check_files_in_folder(c, cache, c.args[0], c.args[1])
+
         elif c.cmd == 'count':  # count test
             if len(c.args) == 3:  # @count <path> <pat> <count> = count test
                 expected = int(c.args[2])
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 9a815694e1b..f86c32158e0 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1361,8 +1361,10 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
             }
 
             if let ty::TraitContainer = assoc_item.container {
-                let bounds =
-                    tcx.explicit_item_bounds(assoc_item.def_id).subst_identity_iter_copied();
+                let bounds = tcx
+                    .explicit_item_bounds(assoc_item.def_id)
+                    .subst_identity_iter_copied()
+                    .map(|(c, s)| (c.as_predicate(), s));
                 let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
                 let predicates =
                     tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied()));
@@ -2117,7 +2119,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
 
 fn clean_middle_opaque_bounds<'tcx>(
     cx: &mut DocContext<'tcx>,
-    bounds: Vec<ty::Predicate<'tcx>>,
+    bounds: Vec<ty::Clause<'tcx>>,
 ) -> Type {
     let mut regions = vec![];
     let mut has_sized = false;
@@ -2126,13 +2128,8 @@ fn clean_middle_opaque_bounds<'tcx>(
         .filter_map(|bound| {
             let bound_predicate = bound.kind();
             let trait_ref = match bound_predicate.skip_binder() {
-                ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => {
-                    bound_predicate.rebind(tr.trait_ref)
-                }
-                ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
-                    _ty,
-                    reg,
-                ))) => {
+                ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
+                ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
                     if let Some(r) = clean_middle_region(reg) {
                         regions.push(GenericBound::Outlives(r));
                     }
@@ -2149,9 +2146,7 @@ fn clean_middle_opaque_bounds<'tcx>(
             let bindings: ThinVec<_> = bounds
                 .iter()
                 .filter_map(|bound| {
-                    if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) =
-                        bound.kind().skip_binder()
-                    {
+                    if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() {
                         if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
                             Some(TypeBinding {
                                 assoc: projection_to_path_segment(
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 294de12cea8..f375f0efbd1 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -21,6 +21,7 @@ use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::symbol::{kw, sym, Symbol};
 use std::fmt::Write as _;
 use std::mem;
+use std::sync::LazyLock as Lazy;
 use thin_vec::{thin_vec, ThinVec};
 
 #[cfg(test)]
@@ -582,6 +583,8 @@ pub(crate) fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool {
 ///
 /// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable.
 pub(crate) const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL");
+pub(crate) static DOC_CHANNEL: Lazy<&'static str> =
+    Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit("/").filter(|c| !c.is_empty()).next().unwrap());
 
 /// Render a sequence of macro arms in a format suitable for displaying to the user
 /// as part of an item declaration.
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index f26d74629dd..b710311c858 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -347,13 +347,19 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
             }
         } else {
             let mut br_with_padding = String::with_capacity(6 * indent + 28);
-            br_with_padding.push_str("\n");
+            br_with_padding.push('\n');
 
-            let padding_amount =
-                if ending == Ending::Newline { indent + 4 } else { indent + "fn where ".len() };
+            let where_indent = 3;
+            let padding_amount = if ending == Ending::Newline {
+                indent + 4
+            } else if indent == 0 {
+                4
+            } else {
+                indent + where_indent + "where ".len()
+            };
 
             for _ in 0..padding_amount {
-                br_with_padding.push_str(" ");
+                br_with_padding.push(' ');
             }
             let where_preds = where_preds.to_string().replace('\n', &br_with_padding);
 
@@ -370,7 +376,8 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
                     let where_preds = where_preds.replacen(&br_with_padding, " ", 1);
 
                     let mut clause = br_with_padding;
-                    clause.truncate(clause.len() - "where ".len());
+                    // +1 is for `\n`.
+                    clause.truncate(indent + 1 + where_indent);
 
                     write!(clause, "<span class=\"where\">where{where_preds}</span>")?;
                     clause
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 6ab849c92a0..8c5871d9126 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -55,6 +55,7 @@ struct PageLayout<'a> {
     sidebar: String,
     content: String,
     krate_with_trailing_slash: String,
+    rust_channel: &'static str,
     pub(crate) rustdoc_version: &'a str,
 }
 
@@ -82,6 +83,7 @@ pub(crate) fn render<T: Print, S: Print>(
         sidebar,
         content,
         krate_with_trailing_slash,
+        rust_channel: *crate::clean::utils::DOC_CHANNEL,
         rustdoc_version,
     }
     .render()
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index c5d6771c2fd..f923f905451 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -799,10 +799,11 @@ fn assoc_type(
     if !bounds.is_empty() {
         write!(w, ": {}", print_generic_bounds(bounds, cx))
     }
-    write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline));
+    // Render the default before the where-clause which aligns with the new recommended style. See #89122.
     if let Some(default) = default {
         write!(w, " = {}", default.print(cx))
     }
+    write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline));
 }
 
 fn assoc_method(
@@ -859,8 +860,8 @@ fn assoc_method(
     w.reserve(header_len + "<a href=\"\" class=\"fn\">{".len() + "</a>".len());
     write!(
         w,
-        "{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn <a{href} class=\"fn\">{name}</a>\
-         {generics}{decl}{notable_traits}{where_clause}",
+        "{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn \
+         <a{href} class=\"fn\">{name}</a>{generics}{decl}{notable_traits}{where_clause}",
         indent = indent_str,
         vis = vis,
         constness = constness,
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index f5296abaee6..254b0d8bf5a 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -1050,9 +1050,10 @@ function preLoadCss(cssUrl) {
 
     function buildHelpMenu() {
         const book_info = document.createElement("span");
+        const channel = getVar("channel");
         book_info.className = "top";
-        book_info.innerHTML = "You can find more information in \
-            <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
+        book_info.innerHTML = `You can find more information in \
+<a href="https://doc.rust-lang.org/${channel}/rustdoc/">the rustdoc book</a>.`;
 
         const shortcuts = [
             ["?", "Show this help dialog"],
@@ -1072,6 +1073,9 @@ function preLoadCss(cssUrl) {
         div_shortcuts.innerHTML = "<h2>Keyboard Shortcuts</h2><dl>" + shortcuts + "</dl></div>";
 
         const infos = [
+            `For a full list of all search features, take a look <a \
+href="https://doc.rust-lang.org/${channel}/rustdoc/how-to-read-rustdoc.html\
+#the-search-interface">here</a>.`,
             "Prefix searches with a type followed by a colon (e.g., <code>fn:</code>) to \
              restrict the search to a given item kind.",
             "Accepted kinds are: <code>fn</code>, <code>mod</code>, <code>struct</code>, \
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index 9133f899af6..759c4fd6012 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -31,6 +31,7 @@
          data-themes="{{themes|join(",") }}" {#+ #}
          data-resource-suffix="{{page.resource_suffix}}" {#+ #}
          data-rustdoc-version="{{rustdoc_version}}" {#+ #}
+         data-channel="{{rust_channel}}" {#+ #}
          data-search-js="{{files.search_js}}" {#+ #}
          data-settings-js="{{files.settings_js}}" {#+ #}
          data-settings-css="{{files.settings_css}}" {#+ #}
diff --git a/src/tools/build_helper/src/util.rs b/src/tools/build_helper/src/util.rs
index 731095023a9..11b8a228b8a 100644
--- a/src/tools/build_helper/src/util.rs
+++ b/src/tools/build_helper/src/util.rs
@@ -25,17 +25,21 @@ pub fn fail(s: &str) -> ! {
     detail_exit(1, cfg!(test));
 }
 
-pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
+pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> Result<(), ()> {
     let status = match cmd.status() {
         Ok(status) => status,
         Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
     };
-    if !status.success() && print_cmd_on_fail {
-        println!(
-            "\n\ncommand did not execute successfully: {:?}\n\
-             expected success, got: {}\n\n",
-            cmd, status
-        );
+    if !status.success() {
+        if print_cmd_on_fail {
+            println!(
+                "\n\ncommand did not execute successfully: {:?}\n\
+                 expected success, got: {}\n\n",
+                cmd, status
+            );
+        }
+        Err(())
+    } else {
+        Ok(())
     }
-    status.success()
 }
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject dead4b8740c4b6a8ed5211e37c99cf81d01c3b1
+Subproject 03bc66b55c290324bd46eb22e369c8fae1908f9
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index a391b76910a..818ebd1134d 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -67,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
             let preds = cx.tcx.explicit_item_bounds(def_id);
             let mut is_future = false;
             for (p, _span) in preds.subst_iter_copied(cx.tcx, substs) {
-                if let Some(trait_pred) = p.to_opt_poly_trait_pred() {
+                if let Some(trait_pred) = p.as_trait_clause() {
                     if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() {
                         is_future = true;
                         break;
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 12f18614d71..2b185943c59 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -94,7 +94,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
                         match predicate.kind().skip_binder() {
                             // For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
                             // and check substitutions to find `U`.
-                            ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
+                            ty::ClauseKind::Trait(trait_predicate) => {
                                 if trait_predicate
                                     .trait_ref
                                     .substs
@@ -107,7 +107,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
                             },
                             // For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
                             // so we check the term for `U`.
-                            ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection_predicate)) => {
+                            ty::ClauseKind::Projection(projection_predicate) => {
                                 if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() {
                                     if contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen) {
                                         return true;
@@ -268,7 +268,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
         ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)),
         ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
             for (predicate, _) in cx.tcx.explicit_item_bounds(def_id).skip_binder() {
-                if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() {
+                if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() {
                     if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
                         return true;
                     }
@@ -665,7 +665,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
         ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => sig_from_bounds(
             cx,
             ty,
-            cx.tcx.item_bounds(def_id).subst(cx.tcx, substs),
+            cx.tcx.item_bounds(def_id).subst_iter(cx.tcx, substs).map(|c| c.as_predicate()),
             cx.tcx.opt_parent(def_id),
         ),
         ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)),
@@ -698,7 +698,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
 fn sig_from_bounds<'tcx>(
     cx: &LateContext<'tcx>,
     ty: Ty<'tcx>,
-    predicates: &'tcx [Predicate<'tcx>],
+    predicates: impl IntoIterator<Item = Predicate<'tcx>>,
     predicates_id: Option<DefId>,
 ) -> Option<ExprFnSig<'tcx>> {
     let mut inputs = None;
@@ -747,7 +747,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option
         .subst_iter_copied(cx.tcx, ty.substs)
     {
         match pred.kind().skip_binder() {
-            PredicateKind::Clause(ty::ClauseKind::Trait(p))
+            ty::ClauseKind::Trait(p)
                 if (lang_items.fn_trait() == Some(p.def_id())
                     || lang_items.fn_mut_trait() == Some(p.def_id())
                     || lang_items.fn_once_trait() == Some(p.def_id())) =>
@@ -760,7 +760,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option
                 }
                 inputs = Some(i);
             },
-            PredicateKind::Clause(ty::ClauseKind::Projection(p))
+            ty::ClauseKind::Projection(p)
                 if Some(p.projection_ty.def_id) == lang_items.fn_once_output() =>
             {
                 if output.is_some() {
diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs
index dc902f8cb02..0ddd2c66cf9 100644
--- a/src/tools/rustdoc-gui-test/src/main.rs
+++ b/src/tools/rustdoc-gui-test/src/main.rs
@@ -67,7 +67,7 @@ fn find_librs<P: AsRef<Path>>(path: P) -> Option<PathBuf> {
     None
 }
 
-fn main() {
+fn main() -> Result<(), ()> {
     let config = Arc::new(Config::from_args(env::args().collect()));
 
     // The goal here is to check if the necessary packages are installed, and if not, we
@@ -128,7 +128,10 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse
                 }
             }
 
-            try_run(&mut cargo, config.verbose);
+            if try_run(&mut cargo, config.verbose).is_err() {
+                eprintln!("failed to document `{}`", entry.path().display());
+                panic!("Cannot run rustdoc-gui tests");
+            }
         }
     }
 
@@ -158,5 +161,5 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse
 
     command.args(&config.test_args);
 
-    try_run(&mut command, config.verbose);
+    try_run(&mut command, config.verbose)
 }
diff --git a/tests/codegen/naked-nocoverage.rs b/tests/codegen/naked-nocoverage.rs
index 91a6260bf2a..3c755e49c6d 100644
--- a/tests/codegen/naked-nocoverage.rs
+++ b/tests/codegen/naked-nocoverage.rs
@@ -11,7 +11,7 @@ use std::arch::asm;
 #[naked]
 #[no_mangle]
 pub unsafe extern "C" fn f() {
-    // CHECK:       define void @f()
+    // CHECK:       define {{(dso_local )?}}void @f()
     // CHECK-NEXT:  start:
     // CHECK-NEXT:    call void asm
     // CHECK-NEXT:    unreachable
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
index 472d921ace0..63e63c5d4aa 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
@@ -61,7 +61,19 @@ pub type Type9 = impl Send;
 pub type Type10 = impl Send;
 pub type Type11 = impl Send;
 
-pub fn fn1<'a>() {
+pub fn fn1<'a>() where
+    Type1: 'static,
+    Type2: 'static,
+    Type3: 'static,
+    Type4: 'static,
+    Type5: 'static,
+    Type6: 'static,
+    Type7: 'static,
+    Type8: 'static,
+    Type9: 'static,
+    Type10: 'static,
+    Type11: 'static,
+{
     // Closure
     let closure1 = || { };
     let _: Type1 = closure1;
diff --git a/tests/codegen/stack-protector.rs b/tests/codegen/stack-protector.rs
index a24e6f1e4f1..a680789af15 100644
--- a/tests/codegen/stack-protector.rs
+++ b/tests/codegen/stack-protector.rs
@@ -10,25 +10,25 @@
 pub fn foo() {
     // CHECK: @foo() unnamed_addr #0
 
-    // all-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} }
-    // all-NOT: attributes #0 = { {{.*}} ssp {{.*}} }
-    // all: attributes #0 = { {{.*}} sspreq {{.*}} }
-    // all-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} }
-    // all-NOT: attributes #0 = { {{.*}} ssp {{.*}} }
+    // all-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} }
+    // all-NOT: attributes #0 = { {{.*}}ssp {{.*}} }
+    // all: attributes #0 = { {{.*}}sspreq {{.*}} }
+    // all-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} }
+    // all-NOT: attributes #0 = { {{.*}}ssp {{.*}} }
 
-    // strong-NOT: attributes #0 = { {{.*}} sspreq {{.*}} }
-    // strong-NOT: attributes #0 = { {{.*}} ssp {{.*}} }
-    // strong: attributes #0 = { {{.*}} sspstrong {{.*}} }
-    // strong-NOT: attributes #0 = { {{.*}} sspreq {{.*}} }
-    // strong-NOT: attributes #0 = { {{.*}} ssp {{.*}} }
+    // strong-NOT: attributes #0 = { {{.*}}sspreq {{.*}} }
+    // strong-NOT: attributes #0 = { {{.*}}ssp {{.*}} }
+    // strong: attributes #0 = { {{.*}}sspstrong {{.*}} }
+    // strong-NOT: attributes #0 = { {{.*}}sspreq {{.*}} }
+    // strong-NOT: attributes #0 = { {{.*}}ssp {{.*}} }
 
-    // basic-NOT: attributes #0 = { {{.*}} sspreq {{.*}} }
-    // basic-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} }
-    // basic: attributes #0 = { {{.*}} ssp {{.*}} }
-    // basic-NOT: attributes #0 = { {{.*}} sspreq {{.*}} }
-    // basic-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} }
+    // basic-NOT: attributes #0 = { {{.*}}sspreq {{.*}} }
+    // basic-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} }
+    // basic: attributes #0 = { {{.*}}ssp {{.*}} }
+    // basic-NOT: attributes #0 = { {{.*}}sspreq {{.*}} }
+    // basic-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} }
 
-    // none-NOT: attributes #0 = { {{.*}} sspreq {{.*}} }
-    // none-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} }
-    // none-NOT: attributes #0 = { {{.*}} ssp {{.*}} }
+    // none-NOT: attributes #0 = { {{.*}}sspreq {{.*}} }
+    // none-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} }
+    // none-NOT: attributes #0 = { {{.*}}ssp {{.*}} }
 }
diff --git a/tests/run-make/target-specs/Makefile b/tests/run-make/target-specs/Makefile
index a33f5368e3c..62d5365a73d 100644
--- a/tests/run-make/target-specs/Makefile
+++ b/tests/run-make/target-specs/Makefile
@@ -8,4 +8,5 @@ all:
 	RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-x86_64-unknown-linux-gnu-platform --crate-type=lib --emit=asm
 	$(RUSTC) -Z unstable-options --target=my-awesome-platform.json --print target-spec-json > $(TMPDIR)/test-platform.json && $(RUSTC) -Z unstable-options --target=$(TMPDIR)/test-platform.json --print target-spec-json | diff -q $(TMPDIR)/test-platform.json -
 	$(RUSTC) foo.rs --target=definitely-not-builtin-target 2>&1 | $(CGREP) 'may not set is_builtin'
+	$(RUSTC) foo.rs --target=endianness-mismatch 2>&1 | $(CGREP) '"data-layout" claims architecture is little-endian'
 	$(RUSTC) foo.rs --target=mismatching-data-layout --crate-type=lib
diff --git a/tests/run-make/target-specs/endianness-mismatch.json b/tests/run-make/target-specs/endianness-mismatch.json
new file mode 100644
index 00000000000..431053ea99b
--- /dev/null
+++ b/tests/run-make/target-specs/endianness-mismatch.json
@@ -0,0 +1,11 @@
+{
+    "pre-link-args": {"gcc": ["-m64"]},
+    "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128",
+    "linker-flavor": "gcc",
+    "llvm-target": "x86_64-unknown-linux-gnu",
+    "target-endian": "big",
+    "target-pointer-width": "64",
+    "target-c-int-width": "32",
+    "arch": "x86_64",
+    "os": "linux"
+}
diff --git a/tests/rustdoc-gui/help-page.goml b/tests/rustdoc-gui/help-page.goml
index 1a1c1b28f61..6e880302f28 100644
--- a/tests/rustdoc-gui/help-page.goml
+++ b/tests/rustdoc-gui/help-page.goml
@@ -67,5 +67,5 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 set-window-size: (1000, 1000) // Popover only appears when the screen width is >700px.
 assert-false: "#help"
 click: "#help-button > a"
-click: ".popover a[href='https://doc.rust-lang.org/rustdoc/']"
-wait-for-document-property: {"URL": "https://doc.rust-lang.org/rustdoc/"}
+click: "//*[@id='help']//a[text()='the rustdoc book']"
+wait-for-document-property: ({"URL": "https://doc.rust-lang.org/"}, STARTS_WITH)
diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml
index 193a3eb3fd1..e3c628b366f 100644
--- a/tests/rustdoc-gui/search-result-color.goml
+++ b/tests/rustdoc-gui/search-result-color.goml
@@ -31,7 +31,7 @@ define-function: (
         // color of the typename (struct, module, method, ...) before search results
         assert-css: (
             ".result-name .typename",
-            {"color": "#888"},
+            {"color": |grey|},
             ALL,
         )
     },
@@ -75,6 +75,7 @@ store-value: (entry_color, "#0096cf") // color of the search entry
 store-value: (hover_entry_color, "#fff") // color of the hovered/focused search entry
 store-value: (background_color, "transparent") // background color
 store-value: (hover_background_color, "#3c3c3c") // hover background color
+store-value: (grey, "#999")
 
 call-function: (
     "check-result-color", (
@@ -186,6 +187,7 @@ store-value: (entry_color, "#ddd") // color of the search entry
 store-value: (hover_entry_color, "#ddd") // color of the hovered/focused search entry
 store-value: (background_color, "transparent") // background color
 store-value: (hover_background_color, "#616161") // hover background color
+store-value: (grey, "#ccc")
 
 call-function: (
     "check-result-color", (
@@ -282,6 +284,7 @@ store-value: (entry_color, "#000") // color of the search entry
 store-value: (hover_entry_color, "#000") // color of the hovered/focused search entry
 store-value: (background_color, "transparent") // background color
 store-value: (hover_background_color, "#ccc") // hover background color
+store-value: (grey, "#999")
 
 call-function: (
     "check-result-color", (
diff --git a/tests/rustdoc-gui/settings.goml b/tests/rustdoc-gui/settings.goml
index c37d969324c..e40c637dcf7 100644
--- a/tests/rustdoc-gui/settings.goml
+++ b/tests/rustdoc-gui/settings.goml
@@ -56,19 +56,19 @@ move-cursor-to: "#settings-menu > a"
 assert-css: (
     "#theme-dark",
     {
-        "border-color": "rgb(153, 153, 153)",
-        "box-shadow": "rgb(53, 53, 53) 0px 0px 0px 3px inset",
+        "border-color": "#999",
+        "box-shadow": "#353535 0px 0px 0px 3px inset",
         "border-width": "2px",
     },
 )
-assert-css: ("#theme-light", {"border-color": "rgb(153, 153, 153)", "box-shadow": "none"})
+assert-css: ("#theme-light", {"border-color": "#999", "box-shadow": "none"})
 // Let's start with the hover for radio buttons.
 move-cursor-to: "#theme-dark"
 assert-css: (
     "#theme-dark",
     {
-        "border-color": "rgb(33, 150, 243)",
-        "box-shadow": "rgb(53, 53, 53) 0px 0px 0px 3px inset",
+        "border-color": "#2196f3",
+        "box-shadow": "#353535 0px 0px 0px 3px inset",
         "border-width": "2px",
     },
 )
@@ -76,7 +76,7 @@ move-cursor-to: "#theme-light"
 assert-css: (
     "#theme-light",
     {
-        "border-color": "rgb(33, 150, 243)",
+        "border-color": "#2196f3",
         "box-shadow": "none",
         "border-width": "2px",
     }
@@ -87,8 +87,8 @@ focus: "#theme-dark"
 assert-css: (
     "#theme-dark",
     {
-        "border-color": "rgb(153, 153, 153)",
-        "box-shadow": "rgb(53, 53, 53) 0px 0px 0px 3px inset, rgb(33, 150, 243) 0px 0px 2px 2px",
+        "border-color": "#999",
+        "box-shadow": "#353535 0px 0px 0px 3px inset, #2196f3 0px 0px 2px 2px",
         "border-width": "2px",
     },
 )
@@ -96,8 +96,8 @@ focus: "#theme-light"
 assert-css: (
     "#theme-light",
     {
-        "border-color": "rgb(153, 153, 153)",
-        "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
+        "border-color": "#999",
+        "box-shadow": "#2196f3 0px 0px 1px 1px",
         "border-width": "2px",
     },
 )
@@ -107,8 +107,8 @@ focus: "#theme-dark"
 assert-css: (
     "#theme-dark",
     {
-        "border-color": "rgb(33, 150, 243)",
-        "box-shadow": "rgb(53, 53, 53) 0px 0px 0px 3px inset, rgb(33, 150, 243) 0px 0px 2px 2px",
+        "border-color": "#2196f3",
+        "box-shadow": "#353535 0px 0px 0px 3px inset, #2196f3 0px 0px 2px 2px",
         "border-width": "2px",
     },
 )
@@ -117,8 +117,8 @@ focus: "#theme-light"
 assert-css: (
     "#theme-light",
     {
-        "border-color": "rgb(33, 150, 243)",
-        "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
+        "border-color": "#2196f3",
+        "box-shadow": "#2196f3 0px 0px 1px 1px",
         "border-width": "2px",
     },
 )
@@ -154,8 +154,8 @@ compare-elements-position-near: (
 assert-css: (
     "#auto-hide-large-items",
     {
-        "background-color": "rgb(33, 150, 243)",
-        "border-color": "rgb(153, 153, 153)",
+        "background-color": "#2196f3",
+        "border-color": "#999",
         // 1px border when checked
         "border-width": "1px",
     },
@@ -164,7 +164,7 @@ assert-css: (
     "#auto-hide-method-docs",
     {
         "background-color": "rgba(0, 0, 0, 0)",
-        "border-color": "rgb(153, 153, 153)",
+        "border-color": "#999",
         // 2px border when unchecked
         "border-width": "2px",
     },
@@ -174,8 +174,8 @@ move-cursor-to: "#auto-hide-large-items"
 assert-css: (
     "#auto-hide-large-items",
     {
-        "background-color": "rgb(33, 150, 243)",
-        "border-color": "rgb(33, 150, 243)",
+        "background-color": "#2196f3",
+        "border-color": "#2196f3",
         // 1px border when checked
         "border-width": "1px",
     },
@@ -185,7 +185,7 @@ assert-css: (
     "#auto-hide-method-docs",
     {
         "background-color": "rgba(0, 0, 0, 0)",
-        "border-color": "rgb(33, 150, 243)",
+        "border-color": "#2196f3",
         // 2px border when unchecked
         "border-width": "2px",
     },
@@ -196,9 +196,9 @@ focus: "#auto-hide-large-items"
 assert-css: (
     "#auto-hide-large-items",
     {
-        "background-color": "rgb(33, 150, 243)",
-        "border-color": "rgb(153, 153, 153)",
-        "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
+        "background-color": "#2196f3",
+        "border-color": "#999",
+        "box-shadow": "#2196f3 0px 0px 1px 1px",
         // 1px border when checked
         "border-width": "1px",
     },
@@ -208,8 +208,8 @@ assert-css: (
     "#auto-hide-method-docs",
     {
         "background-color": "rgba(0, 0, 0, 0)",
-        "border-color": "rgb(153, 153, 153)",
-        "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
+        "border-color": "#999",
+        "box-shadow": "#2196f3 0px 0px 1px 1px",
         // 2px border when unchecked
         "border-width": "2px",
     },
@@ -220,9 +220,9 @@ focus: "#auto-hide-large-items"
 assert-css: (
     "#auto-hide-large-items",
     {
-        "background-color": "rgb(33, 150, 243)",
-        "border-color": "rgb(33, 150, 243)",
-        "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
+        "background-color": "#2196f3",
+        "border-color": "#2196f3",
+        "box-shadow": "#2196f3 0px 0px 1px 1px",
         // 1px border when checked
         "border-width": "1px",
     },
@@ -233,8 +233,8 @@ assert-css: (
     "#auto-hide-method-docs",
     {
         "background-color": "rgba(0, 0, 0, 0)",
-        "border-color": "rgb(33, 150, 243)",
-        "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
+        "border-color": "#2196f3",
+        "box-shadow": "#2196f3 0px 0px 1px 1px",
         // 2px border when unchecked
         "border-width": "2px",
     },
diff --git a/tests/rustdoc/files-creation-hidden.rs b/tests/rustdoc/files-creation-hidden.rs
index bcabbfc91e8..498d9cdaef1 100644
--- a/tests/rustdoc/files-creation-hidden.rs
+++ b/tests/rustdoc/files-creation-hidden.rs
@@ -1,5 +1,6 @@
 #![crate_name="foo"]
 
+// @files foo '["index.html", "all.html", "sidebar-items.js"]'
 // @!has "foo/struct.Foo.html"
 #[doc(hidden)]
 pub struct Foo;
diff --git a/tests/rustdoc/files-creation-private.rs b/tests/rustdoc/files-creation-private.rs
index ca2327e0f91..e2fdbc068f8 100644
--- a/tests/rustdoc/files-creation-private.rs
+++ b/tests/rustdoc/files-creation-private.rs
@@ -1,5 +1,9 @@
 #![crate_name="foo"]
 
+// @files "foo" \
+// '["index.html", "all.html", "sidebar-items.js", "foo", "bar", "private", "struct.Bar.html"]'
+// @files "foo/bar" '["index.html", "sidebar-items.js"]'
+
 // @!has "foo/priv/index.html"
 // @!has "foo/priv/struct.Foo.html"
 mod private {
diff --git a/tests/rustdoc/generic-associated-types/gats.rs b/tests/rustdoc/generic-associated-types/gats.rs
index 7ab82bb5829..605176e5fea 100644
--- a/tests/rustdoc/generic-associated-types/gats.rs
+++ b/tests/rustdoc/generic-associated-types/gats.rs
@@ -23,9 +23,9 @@ impl LendingIterator for () {
 pub struct Infinite<T>(T);
 
 // @has foo/trait.LendingIterator.html
-// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a = &'a T"
+// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> = &'a T where Self: 'a"
 impl<T> LendingIterator for Infinite<T> {
-    type Item<'a> where Self: 'a = &'a T;
+    type Item<'a> = &'a T where Self: 'a;
 
     fn next<'a>(&'a self) -> Self::Item<'a> {
         &self.0
diff --git a/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs b/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs
index d6832bb7a09..65c26d6a837 100644
--- a/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs
+++ b/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs
@@ -2,6 +2,12 @@
 #![no_core]
 #![crate_name = "foo"]
 
+// @files "foo" "['sidebar-items.js', 'all.html', 'hidden', 'index.html', 'struct.Bar.html', \
+//        'visible']"
+// @files "foo/hidden" "['inner']"
+// @files "foo/hidden/inner" "['trait.Foo.html']"
+// @files "foo/visible" "['index.html', 'sidebar-items.js', 'trait.Foo.html']"
+
 // @!has 'foo/hidden/index.html'
 // @!has 'foo/hidden/inner/index.html'
 // FIXME: Should be `@!has`: https://github.com/rust-lang/rust/issues/111249
diff --git a/tests/rustdoc/issue-111249-file-creation.rs b/tests/rustdoc/issue-111249-file-creation.rs
index d2042b231e4..afd65ddaf94 100644
--- a/tests/rustdoc/issue-111249-file-creation.rs
+++ b/tests/rustdoc/issue-111249-file-creation.rs
@@ -2,6 +2,12 @@
 #![feature(no_core)]
 #![no_core]
 
+// @files "foo" "['all.html', 'visible', 'index.html', 'sidebar-items.js', 'hidden', \
+//        'struct.Bar.html']"
+// @files "foo/visible" "['trait.Foo.html', 'index.html', 'sidebar-items.js']"
+// @files "foo/hidden" "['inner']"
+// @files "foo/hidden/inner" "['trait.Foo.html']"
+
 // The following five should not fail!
 // @!has 'foo/hidden/index.html'
 // @!has 'foo/hidden/inner/index.html'
diff --git a/tests/rustdoc/where.SWhere_Echo_impl.html b/tests/rustdoc/where.SWhere_Echo_impl.html
new file mode 100644
index 00000000000..7517eb090f4
--- /dev/null
+++ b/tests/rustdoc/where.SWhere_Echo_impl.html
@@ -0,0 +1,2 @@
+<h3 class="code-header">impl&lt;D&gt; <a class="struct" href="struct.Delta.html" title="struct foo::Delta">Delta</a>&lt;D&gt;<span class="where fmt-newline">where
+    D: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a>,</span></h3>
\ No newline at end of file
diff --git a/tests/rustdoc/where.SWhere_Simd_item-decl.html b/tests/rustdoc/where.SWhere_Simd_item-decl.html
index ef4294c8f76..3e72ba2b74f 100644
--- a/tests/rustdoc/where.SWhere_Simd_item-decl.html
+++ b/tests/rustdoc/where.SWhere_Simd_item-decl.html
@@ -1,3 +1,3 @@
 <pre class="rust item-decl"><code>pub struct Simd&lt;T&gt;(_)
 <span class="where">where
-         T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre>
\ No newline at end of file
+    T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre>
diff --git a/tests/rustdoc/where.alpha_trait_decl.html b/tests/rustdoc/where.alpha_trait_decl.html
new file mode 100644
index 00000000000..a7700055c9a
--- /dev/null
+++ b/tests/rustdoc/where.alpha_trait_decl.html
@@ -0,0 +1,3 @@
+<code>pub struct Alpha&lt;A&gt;(_)
+<span class="where">where
+    A: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code>
\ No newline at end of file
diff --git a/tests/rustdoc/where.bravo_trait_decl.html b/tests/rustdoc/where.bravo_trait_decl.html
new file mode 100644
index 00000000000..00524201a8a
--- /dev/null
+++ b/tests/rustdoc/where.bravo_trait_decl.html
@@ -0,0 +1,5 @@
+<code>pub trait Bravo&lt;B&gt;<span class="where fmt-newline">where
+    B: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a>,</span>{
+    // Required method
+    fn <a href="#tymethod.get" class="fn">get</a>(&amp;self, B: B);
+}</code>
\ No newline at end of file
diff --git a/tests/rustdoc/where.charlie_fn_decl.html b/tests/rustdoc/where.charlie_fn_decl.html
new file mode 100644
index 00000000000..8e3bc8b01ec
--- /dev/null
+++ b/tests/rustdoc/where.charlie_fn_decl.html
@@ -0,0 +1,2 @@
+<code>pub fn charlie&lt;C&gt;()<span class="where fmt-newline">where
+    C: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a>,</span></code>
\ No newline at end of file
diff --git a/tests/rustdoc/where.golf_type_alias_decl.html b/tests/rustdoc/where.golf_type_alias_decl.html
new file mode 100644
index 00000000000..8da5402f900
--- /dev/null
+++ b/tests/rustdoc/where.golf_type_alias_decl.html
@@ -0,0 +1,2 @@
+<code>pub type Golf&lt;T&gt;<span class="where fmt-newline">where
+    T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>,</span> = <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T, T)</a>;</code>
\ No newline at end of file
diff --git a/tests/rustdoc/where.rs b/tests/rustdoc/where.rs
index 8b8a126e89d..2aa9c8b5461 100644
--- a/tests/rustdoc/where.rs
+++ b/tests/rustdoc/where.rs
@@ -5,16 +5,20 @@ use std::io::Lines;
 pub trait MyTrait { fn dummy(&self) { } }
 
 // @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_) where A: MyTrait"
+// @snapshot alpha_trait_decl - '//*[@class="rust item-decl"]/code'
 pub struct Alpha<A>(A) where A: MyTrait;
 // @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B>where B: MyTrait"
+// @snapshot bravo_trait_decl - '//*[@class="rust item-decl"]/code'
 pub trait Bravo<B> where B: MyTrait { fn get(&self, B: B); }
 // @has foo/fn.charlie.html '//pre' "pub fn charlie<C>()where C: MyTrait"
+// @snapshot charlie_fn_decl - '//*[@class="rust item-decl"]/code'
 pub fn charlie<C>() where C: MyTrait {}
 
 pub struct Delta<D>(D);
 
 // @has foo/struct.Delta.html '//*[@class="impl"]//h3[@class="code-header"]' \
 //          "impl<D> Delta<D>where D: MyTrait"
+// @snapshot SWhere_Echo_impl - '//*[@id="impl-Delta%3CD%3E"]/h3[@class="code-header"]'
 impl<D> Delta<D> where D: MyTrait {
     pub fn delta() {}
 }
@@ -65,4 +69,5 @@ impl<F> MyTrait for Foxtrot<F>where F: MyTrait {}
 
 // @has foo/type.Golf.html '//pre[@class="rust item-decl"]' \
 //          "type Golf<T>where T: Clone, = (T, T)"
+// @snapshot golf_type_alias_decl - '//*[@class="rust item-decl"]/code'
 pub type Golf<T> where T: Clone = (T, T);
diff --git a/tests/ui/asm/aarch64/may_unwind.rs b/tests/ui/asm/aarch64/may_unwind.rs
index 6af8728bbaa..cfb75078264 100644
--- a/tests/ui/asm/aarch64/may_unwind.rs
+++ b/tests/ui/asm/aarch64/may_unwind.rs
@@ -1,6 +1,7 @@
 // only-aarch64
 // run-pass
 // needs-asm-support
+// needs-unwind
 
 #![feature(asm_unwind)]
 
diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.current.stderr
index 95ef7d82fca..b8be132e6b6 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.current.stderr
@@ -1,11 +1,11 @@
 error: return type notation uses `()` instead of `(..)` for elided arguments
-  --> $DIR/bad-inputs-and-output.rs:18:24
+  --> $DIR/bad-inputs-and-output.rs:20:24
    |
 LL | fn baz<T: Trait<method(..): Send>>() {}
    |                        ^^ help: remove the `..`
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/bad-inputs-and-output.rs:10:17
+  --> $DIR/bad-inputs-and-output.rs:12:17
    |
 LL | fn foo<T: Trait<method(i32): Send>>() {}
    |                 ^^^^^^^^^^^^^^^^^
@@ -14,7 +14,7 @@ LL | fn foo<T: Trait<method(i32): Send>>() {}
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/bad-inputs-and-output.rs:14:17
+  --> $DIR/bad-inputs-and-output.rs:16:17
    |
 LL | fn bar<T: Trait<method() -> (): Send>>() {}
    |                 ^^^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL | fn bar<T: Trait<method() -> (): Send>>() {}
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/bad-inputs-and-output.rs:3:12
+  --> $DIR/bad-inputs-and-output.rs:5:12
    |
 LL | #![feature(return_type_notation, async_fn_in_trait)]
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -32,13 +32,13 @@ LL | #![feature(return_type_notation, async_fn_in_trait)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error: argument types not allowed with return type notation
-  --> $DIR/bad-inputs-and-output.rs:10:23
+  --> $DIR/bad-inputs-and-output.rs:12:23
    |
 LL | fn foo<T: Trait<method(i32): Send>>() {}
    |                       ^^^^^ help: remove the input types: `()`
 
 error: return type not allowed with return type notation
-  --> $DIR/bad-inputs-and-output.rs:14:25
+  --> $DIR/bad-inputs-and-output.rs:16:25
    |
 LL | fn bar<T: Trait<method() -> (): Send>>() {}
    |                         ^^^^^^ help: remove the return type
diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.next.stderr b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.next.stderr
new file mode 100644
index 00000000000..b8be132e6b6
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.next.stderr
@@ -0,0 +1,48 @@
+error: return type notation uses `()` instead of `(..)` for elided arguments
+  --> $DIR/bad-inputs-and-output.rs:20:24
+   |
+LL | fn baz<T: Trait<method(..): Send>>() {}
+   |                        ^^ help: remove the `..`
+
+error[E0658]: associated type bounds are unstable
+  --> $DIR/bad-inputs-and-output.rs:12:17
+   |
+LL | fn foo<T: Trait<method(i32): Send>>() {}
+   |                 ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
+   = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
+
+error[E0658]: associated type bounds are unstable
+  --> $DIR/bad-inputs-and-output.rs:16:17
+   |
+LL | fn bar<T: Trait<method() -> (): Send>>() {}
+   |                 ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
+   = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
+
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/bad-inputs-and-output.rs:5:12
+   |
+LL | #![feature(return_type_notation, async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: argument types not allowed with return type notation
+  --> $DIR/bad-inputs-and-output.rs:12:23
+   |
+LL | fn foo<T: Trait<method(i32): Send>>() {}
+   |                       ^^^^^ help: remove the input types: `()`
+
+error: return type not allowed with return type notation
+  --> $DIR/bad-inputs-and-output.rs:16:25
+   |
+LL | fn bar<T: Trait<method() -> (): Send>>() {}
+   |                         ^^^^^^ help: remove the return type
+
+error: aborting due to 5 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs
index 58ce41d1a89..771acb6c4e7 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs
@@ -1,4 +1,6 @@
 // edition: 2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(return_type_notation, async_fn_in_trait)]
 //~^ WARN the feature `return_type_notation` is incomplete
diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.current_with.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.current_with.stderr
new file mode 100644
index 00000000000..98c1a282779
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/basic.current_with.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/basic.rs:8:12
+   |
+LL | #![feature(return_type_notation, async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.current_without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.current_without.stderr
new file mode 100644
index 00000000000..1066c420c31
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/basic.current_without.stderr
@@ -0,0 +1,29 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/basic.rs:8:12
+   |
+LL | #![feature(return_type_notation, async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: future cannot be sent between threads safely
+  --> $DIR/basic.rs:26:13
+   |
+LL |     is_send(foo::<T>());
+   |             ^^^^^^^^^^ future returned by `foo` is not `Send`
+   |
+   = help: within `impl Future<Output = Result<(), ()>>`, the trait `Send` is not implemented for `impl Future<Output = Result<(), ()>>`
+note: future is not `Send` as it awaits another future which is not `Send`
+  --> $DIR/basic.rs:16:5
+   |
+LL |     T::method().await?;
+   |     ^^^^^^^^^^^ await occurs here on type `impl Future<Output = Result<(), ()>>`, which is not `Send`
+note: required by a bound in `is_send`
+  --> $DIR/basic.rs:20:20
+   |
+LL | fn is_send(_: impl Send) {}
+   |                    ^^^^ required by this bound in `is_send`
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.next_with.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.next_with.stderr
new file mode 100644
index 00000000000..98c1a282779
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/basic.next_with.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/basic.rs:8:12
+   |
+LL | #![feature(return_type_notation, async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.next_without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.next_without.stderr
new file mode 100644
index 00000000000..1066c420c31
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/basic.next_without.stderr
@@ -0,0 +1,29 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/basic.rs:8:12
+   |
+LL | #![feature(return_type_notation, async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: future cannot be sent between threads safely
+  --> $DIR/basic.rs:26:13
+   |
+LL |     is_send(foo::<T>());
+   |             ^^^^^^^^^^ future returned by `foo` is not `Send`
+   |
+   = help: within `impl Future<Output = Result<(), ()>>`, the trait `Send` is not implemented for `impl Future<Output = Result<(), ()>>`
+note: future is not `Send` as it awaits another future which is not `Send`
+  --> $DIR/basic.rs:16:5
+   |
+LL |     T::method().await?;
+   |     ^^^^^^^^^^^ await occurs here on type `impl Future<Output = Result<(), ()>>`, which is not `Send`
+note: required by a bound in `is_send`
+  --> $DIR/basic.rs:20:20
+   |
+LL | fn is_send(_: impl Send) {}
+   |                    ^^^^ required by this bound in `is_send`
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.rs b/tests/ui/associated-type-bounds/return-type-notation/basic.rs
index edc6a8e4caf..d443c9dc11b 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/basic.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/basic.rs
@@ -1,6 +1,9 @@
-// revisions: with without
+// revisions: current_with current_without next_with next_without
+// [next_with] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// [next_without] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
 // edition: 2021
-//[with] check-pass
+// [current_with] check-pass
+// [next_with] check-pass
 
 #![feature(return_type_notation, async_fn_in_trait)]
 //~^ WARN the feature `return_type_notation` is incomplete
@@ -17,11 +20,12 @@ async fn foo<T: Foo>() -> Result<(), ()> {
 fn is_send(_: impl Send) {}
 
 fn test<
-    #[cfg(with)] T: Foo<method(): Send>,
-    #[cfg(without)] T: Foo,
+    #[cfg(any(current_with, next_with))] T: Foo<method(): Send>,
+    #[cfg(any(current_without, next_without))] T: Foo,
 >() {
     is_send(foo::<T>());
-    //[without]~^ ERROR future cannot be sent between threads safely
+    //[current_without]~^ ERROR future cannot be sent between threads safely
+    //[next_without]~^^ ERROR future cannot be sent between threads safely
 }
 
 fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.stderr b/tests/ui/associated-type-bounds/return-type-notation/equality.current.stderr
index 490bfdc4c3c..b631dd0ebb5 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/equality.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/equality.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/equality.rs:3:12
+  --> $DIR/equality.rs:5:12
    |
 LL | #![feature(return_type_notation, async_fn_in_trait)]
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | #![feature(return_type_notation, async_fn_in_trait)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error: return type notation is not allowed to use type equality
-  --> $DIR/equality.rs:12:18
+  --> $DIR/equality.rs:14:18
    |
 LL | fn test<T: Trait<method() = Box<dyn Future<Output = ()>>>>() {}
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.next.stderr b/tests/ui/associated-type-bounds/return-type-notation/equality.next.stderr
new file mode 100644
index 00000000000..b631dd0ebb5
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/equality.next.stderr
@@ -0,0 +1,17 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/equality.rs:5:12
+   |
+LL | #![feature(return_type_notation, async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: return type notation is not allowed to use type equality
+  --> $DIR/equality.rs:14:18
+   |
+LL | fn test<T: Trait<method() = Box<dyn Future<Output = ()>>>>() {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.rs b/tests/ui/associated-type-bounds/return-type-notation/equality.rs
index 6884305d7b3..0d6545cc298 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/equality.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/equality.rs
@@ -1,4 +1,6 @@
 // edition: 2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(return_type_notation, async_fn_in_trait)]
 //~^ WARN the feature `return_type_notation` is incomplete
diff --git a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
index 721234aa4a7..f80bb4242aa 100644
--- a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
+++ b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
@@ -1,18 +1,25 @@
-error[E0277]: `Sender<i32>` cannot be shared between threads safely
-  --> $DIR/issue-70935-complex-spans.rs:13:45
+error[E0277]: `*mut ()` cannot be shared between threads safely
+  --> $DIR/issue-70935-complex-spans.rs:18:23
    |
-LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
-   |                                             ^^^^^^^^^^^^^^^^^^ `Sender<i32>` cannot be shared between threads safely
+LL | fn foo(x: NotSync) -> impl Future + Send {
+   |                       ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely
    |
-   = help: the trait `Sync` is not implemented for `Sender<i32>`
-   = note: required for `&Sender<i32>` to implement `Send`
+   = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`
+note: required because it appears within the type `PhantomData<*mut ()>`
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+note: required because it appears within the type `NotSync`
+  --> $DIR/issue-70935-complex-spans.rs:12:8
+   |
+LL | struct NotSync(PhantomData<*mut ()>);
+   |        ^^^^^^^
+   = note: required for `&NotSync` to implement `Send`
 note: required because it's used within this closure
-  --> $DIR/issue-70935-complex-spans.rs:17:13
+  --> $DIR/issue-70935-complex-spans.rs:22:13
    |
-LL |         baz(|| async{
+LL |         baz(|| async {
    |             ^^
 note: required because it's used within this `async fn` body
-  --> $DIR/issue-70935-complex-spans.rs:10:67
+  --> $DIR/issue-70935-complex-spans.rs:15:67
    |
 LL |   async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
    |  ___________________________________________________________________^
@@ -20,11 +27,11 @@ LL | | }
    | |_^
    = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = ()>`, `()`
 note: required because it's used within this `async` block
-  --> $DIR/issue-70935-complex-spans.rs:16:5
+  --> $DIR/issue-70935-complex-spans.rs:21:5
    |
 LL | /     async move {
-LL | |         baz(|| async{
-LL | |             foo(tx.clone());
+LL | |         baz(|| async {
+LL | |             foo(x.clone());
 LL | |         }).await;
 LL | |     }
    | |_____^
diff --git a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr
index c636be15a58..eb9d93e229f 100644
--- a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr
+++ b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr
@@ -1,18 +1,25 @@
-error[E0277]: `Sender<i32>` cannot be shared between threads safely
-  --> $DIR/issue-70935-complex-spans.rs:13:45
+error[E0277]: `*mut ()` cannot be shared between threads safely
+  --> $DIR/issue-70935-complex-spans.rs:18:23
    |
-LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
-   |                                             ^^^^^^^^^^^^^^^^^^ `Sender<i32>` cannot be shared between threads safely
+LL | fn foo(x: NotSync) -> impl Future + Send {
+   |                       ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely
    |
-   = help: the trait `Sync` is not implemented for `Sender<i32>`
-   = note: required for `&Sender<i32>` to implement `Send`
+   = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`
+note: required because it appears within the type `PhantomData<*mut ()>`
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+note: required because it appears within the type `NotSync`
+  --> $DIR/issue-70935-complex-spans.rs:12:8
+   |
+LL | struct NotSync(PhantomData<*mut ()>);
+   |        ^^^^^^^
+   = note: required for `&NotSync` to implement `Send`
 note: required because it's used within this closure
-  --> $DIR/issue-70935-complex-spans.rs:17:13
+  --> $DIR/issue-70935-complex-spans.rs:22:13
    |
-LL |         baz(|| async{
+LL |         baz(|| async {
    |             ^^
 note: required because it's used within this `async fn` body
-  --> $DIR/issue-70935-complex-spans.rs:10:67
+  --> $DIR/issue-70935-complex-spans.rs:15:67
    |
 LL |   async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
    |  ___________________________________________________________________^
@@ -20,11 +27,11 @@ LL | | }
    | |_^
    = note: required because it captures the following types: `impl Future<Output = ()>`
 note: required because it's used within this `async` block
-  --> $DIR/issue-70935-complex-spans.rs:16:5
+  --> $DIR/issue-70935-complex-spans.rs:21:5
    |
 LL | /     async move {
-LL | |         baz(|| async{
-LL | |             foo(tx.clone());
+LL | |         baz(|| async {
+LL | |             foo(x.clone());
 LL | |         }).await;
 LL | |     }
    | |_____^
diff --git a/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr b/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr
index ef0e182e515..d8ef6a5eedb 100644
--- a/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr
+++ b/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr
@@ -1,21 +1,21 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-70935-complex-spans.rs:13:45
+  --> $DIR/issue-70935-complex-spans.rs:18:23
    |
-LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
-   |                                             ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
+LL | fn foo(x: NotSync) -> impl Future + Send {
+   |                       ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
    |
-   = help: the trait `Sync` is not implemented for `Sender<i32>`
+   = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`
 note: future is not `Send` as this value is used across an await
-  --> $DIR/issue-70935-complex-spans.rs:19:12
+  --> $DIR/issue-70935-complex-spans.rs:24:12
    |
-LL |           baz(|| async{
+LL |           baz(|| async {
    |  _____________-
-LL | |             foo(tx.clone());
+LL | |             foo(x.clone());
 LL | |         }).await;
    | |         -  ^^^^^- the value is later dropped here
    | |         |  |
    | |_________|  await occurs here, with the value maybe used later
-   |           has type `[closure@$DIR/issue-70935-complex-spans.rs:17:13: 17:15]` which is not `Send`
+   |           has type `[closure@$DIR/issue-70935-complex-spans.rs:22:13: 22:15]` which is not `Send`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/async-await/issue-70935-complex-spans.rs b/tests/ui/async-await/issue-70935-complex-spans.rs
index 78625bd393d..9ebde1d3977 100644
--- a/tests/ui/async-await/issue-70935-complex-spans.rs
+++ b/tests/ui/async-await/issue-70935-complex-spans.rs
@@ -6,16 +6,21 @@
 // with newlines which lead complex diagnostics.
 
 use std::future::Future;
+use std::marker::PhantomData;
+
+#[derive(Clone)]
+struct NotSync(PhantomData<*mut ()>);
+unsafe impl Send for NotSync {}
 
 async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
 }
 
-fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
+fn foo(x: NotSync) -> impl Future + Send {
     //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely
-    //[drop_tracking,drop_tracking_mir]~^^ ERROR `Sender<i32>` cannot be shared between threads
+    //[drop_tracking,drop_tracking_mir]~^^ ERROR `*mut ()` cannot be shared between threads
     async move {
-        baz(|| async{
-            foo(tx.clone());
+        baz(|| async {
+            foo(x.clone());
         }).await;
     }
 }
@@ -24,6 +29,6 @@ fn bar(_s: impl Future + Send) {
 }
 
 fn main() {
-    let (tx, _rx) = std::sync::mpsc::channel();
-    bar(foo(tx));
+    let x = NotSync(PhantomData);
+    bar(foo(x));
 }
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.current.stderr
index 33e22dec3f7..1b847b59eb5 100644
--- a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr
+++ b/tests/ui/async-await/return-type-notation/issue-110963-early.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-110963-early.rs:4:12
+  --> $DIR/issue-110963-early.rs:6:12
    |
 LL | #![feature(return_type_notation)]
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | #![feature(return_type_notation)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error: higher-ranked lifetime error
-  --> $DIR/issue-110963-early.rs:15:5
+  --> $DIR/issue-110963-early.rs:17:5
    |
 LL | /     spawn(async move {
 LL | |         let mut hc = hc;
@@ -18,10 +18,10 @@ LL | |         }
 LL | |     });
    | |______^
    |
-   = note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send`
+   = note: could not prove `[async block@$DIR/issue-110963-early.rs:17:11: 22:6]: Send`
 
 error: higher-ranked lifetime error
-  --> $DIR/issue-110963-early.rs:15:5
+  --> $DIR/issue-110963-early.rs:17:5
    |
 LL | /     spawn(async move {
 LL | |         let mut hc = hc;
@@ -31,7 +31,7 @@ LL | |         }
 LL | |     });
    | |______^
    |
-   = note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send`
+   = note: could not prove `[async block@$DIR/issue-110963-early.rs:17:11: 22:6]: Send`
 
 error: aborting due to 2 previous errors; 1 warning emitted
 
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.next.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.next.stderr
new file mode 100644
index 00000000000..1b847b59eb5
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/issue-110963-early.next.stderr
@@ -0,0 +1,37 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-110963-early.rs:6:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: higher-ranked lifetime error
+  --> $DIR/issue-110963-early.rs:17:5
+   |
+LL | /     spawn(async move {
+LL | |         let mut hc = hc;
+LL | |         if !hc.check().await {
+LL | |             log_health_check_failure().await;
+LL | |         }
+LL | |     });
+   | |______^
+   |
+   = note: could not prove `[async block@$DIR/issue-110963-early.rs:17:11: 22:6]: Send`
+
+error: higher-ranked lifetime error
+  --> $DIR/issue-110963-early.rs:17:5
+   |
+LL | /     spawn(async move {
+LL | |         let mut hc = hc;
+LL | |         if !hc.check().await {
+LL | |             log_health_check_failure().await;
+LL | |         }
+LL | |     });
+   | |______^
+   |
+   = note: could not prove `[async block@$DIR/issue-110963-early.rs:17:11: 22:6]: Send`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.rs b/tests/ui/async-await/return-type-notation/issue-110963-early.rs
index 0ecbca5c13b..eee31aa1fe5 100644
--- a/tests/ui/async-await/return-type-notation/issue-110963-early.rs
+++ b/tests/ui/async-await/return-type-notation/issue-110963-early.rs
@@ -1,5 +1,7 @@
 // edition: 2021
 // known-bug: #110963
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(return_type_notation)]
 #![feature(async_fn_in_trait)]
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.stderr b/tests/ui/async-await/return-type-notation/issue-110963-late.current.stderr
index 9c6966537a7..018f4f2207a 100644
--- a/tests/ui/async-await/return-type-notation/issue-110963-late.stderr
+++ b/tests/ui/async-await/return-type-notation/issue-110963-late.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-110963-late.rs:4:12
+  --> $DIR/issue-110963-late.rs:6:12
    |
 LL | #![feature(return_type_notation)]
    |            ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.next.stderr b/tests/ui/async-await/return-type-notation/issue-110963-late.next.stderr
new file mode 100644
index 00000000000..018f4f2207a
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/issue-110963-late.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-110963-late.rs:6:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.rs b/tests/ui/async-await/return-type-notation/issue-110963-late.rs
index 17b5d775d44..ea047cd3b16 100644
--- a/tests/ui/async-await/return-type-notation/issue-110963-late.rs
+++ b/tests/ui/async-await/return-type-notation/issue-110963-late.rs
@@ -1,5 +1,7 @@
 // edition: 2021
 // check-pass
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(return_type_notation)]
 //~^ WARN the feature `return_type_notation` is incomplete
diff --git a/tests/ui/async-await/return-type-notation/super-method-bound.stderr b/tests/ui/async-await/return-type-notation/super-method-bound.current.stderr
index ac0668d3c44..891c802c5f4 100644
--- a/tests/ui/async-await/return-type-notation/super-method-bound.stderr
+++ b/tests/ui/async-await/return-type-notation/super-method-bound.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/super-method-bound.rs:4:31
+  --> $DIR/super-method-bound.rs:6:31
    |
 LL | #![feature(async_fn_in_trait, return_type_notation)]
    |                               ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/async-await/return-type-notation/super-method-bound.next.stderr b/tests/ui/async-await/return-type-notation/super-method-bound.next.stderr
new file mode 100644
index 00000000000..891c802c5f4
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/super-method-bound.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/super-method-bound.rs:6:31
+   |
+LL | #![feature(async_fn_in_trait, return_type_notation)]
+   |                               ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/return-type-notation/super-method-bound.rs b/tests/ui/async-await/return-type-notation/super-method-bound.rs
index 58ea3578db6..0163c62f545 100644
--- a/tests/ui/async-await/return-type-notation/super-method-bound.rs
+++ b/tests/ui/async-await/return-type-notation/super-method-bound.rs
@@ -1,5 +1,7 @@
 // edition:2021
 // check-pass
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait, return_type_notation)]
 //~^ WARN the feature `return_type_notation` is incomplete
diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.stderr b/tests/ui/async-await/return-type-notation/supertrait-bound.current.stderr
index c8cec4946b4..05cb0ca4abd 100644
--- a/tests/ui/async-await/return-type-notation/supertrait-bound.stderr
+++ b/tests/ui/async-await/return-type-notation/supertrait-bound.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/supertrait-bound.rs:3:49
+  --> $DIR/supertrait-bound.rs:5:49
    |
 LL | #![feature(return_position_impl_trait_in_trait, return_type_notation)]
    |                                                 ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.next.stderr b/tests/ui/async-await/return-type-notation/supertrait-bound.next.stderr
new file mode 100644
index 00000000000..05cb0ca4abd
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/supertrait-bound.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/supertrait-bound.rs:5:49
+   |
+LL | #![feature(return_position_impl_trait_in_trait, return_type_notation)]
+   |                                                 ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.rs b/tests/ui/async-await/return-type-notation/supertrait-bound.rs
index 19bcfe3046b..09de32c5d4a 100644
--- a/tests/ui/async-await/return-type-notation/supertrait-bound.rs
+++ b/tests/ui/async-await/return-type-notation/supertrait-bound.rs
@@ -1,4 +1,6 @@
 // check-pass
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait, return_type_notation)]
 //~^ WARN the feature `return_type_notation` is incomplete and may not be safe to use
diff --git a/tests/ui/async-await/return-type-notation/ty-or-ct-params.stderr b/tests/ui/async-await/return-type-notation/ty-or-ct-params.current.stderr
index 76928c5d7a3..1aa008fe469 100644
--- a/tests/ui/async-await/return-type-notation/ty-or-ct-params.stderr
+++ b/tests/ui/async-await/return-type-notation/ty-or-ct-params.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/ty-or-ct-params.rs:3:31
+  --> $DIR/ty-or-ct-params.rs:5:31
    |
 LL | #![feature(async_fn_in_trait, return_type_notation)]
    |                               ^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | #![feature(async_fn_in_trait, return_type_notation)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error: return type notation is not allowed for functions that have type parameters
-  --> $DIR/ty-or-ct-params.rs:14:12
+  --> $DIR/ty-or-ct-params.rs:16:12
    |
 LL |     async fn bar<T>() {}
    |                  - type parameter declared here
@@ -17,7 +17,7 @@ LL |     T: Foo<bar(): Send, baz(): Send>,
    |            ^^^^^^^^^^^
 
 error: return type notation is not allowed for functions that have const parameters
-  --> $DIR/ty-or-ct-params.rs:14:25
+  --> $DIR/ty-or-ct-params.rs:16:25
    |
 LL |     async fn baz<const N: usize>() {}
    |                  -------------- const parameter declared here
diff --git a/tests/ui/async-await/return-type-notation/ty-or-ct-params.next.stderr b/tests/ui/async-await/return-type-notation/ty-or-ct-params.next.stderr
new file mode 100644
index 00000000000..1aa008fe469
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/ty-or-ct-params.next.stderr
@@ -0,0 +1,29 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/ty-or-ct-params.rs:5:31
+   |
+LL | #![feature(async_fn_in_trait, return_type_notation)]
+   |                               ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: return type notation is not allowed for functions that have type parameters
+  --> $DIR/ty-or-ct-params.rs:16:12
+   |
+LL |     async fn bar<T>() {}
+   |                  - type parameter declared here
+...
+LL |     T: Foo<bar(): Send, baz(): Send>,
+   |            ^^^^^^^^^^^
+
+error: return type notation is not allowed for functions that have const parameters
+  --> $DIR/ty-or-ct-params.rs:16:25
+   |
+LL |     async fn baz<const N: usize>() {}
+   |                  -------------- const parameter declared here
+...
+LL |     T: Foo<bar(): Send, baz(): Send>,
+   |                         ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
diff --git a/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs b/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs
index 7871a2fed03..3141da1d296 100644
--- a/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs
+++ b/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs
@@ -1,4 +1,6 @@
 // edition: 2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait, return_type_notation)]
 //~^ WARN the feature `return_type_notation` is incomplete
diff --git a/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.rs b/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.rs
new file mode 100644
index 00000000000..d8034d57e8d
--- /dev/null
+++ b/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.rs
@@ -0,0 +1,40 @@
+use std::ops::Deref;
+use std::rc::Rc;
+
+struct Value<T>(T);
+
+pub trait Wrap<T> {
+    fn wrap() -> Self;
+}
+
+impl<R, A1, A2> Wrap<fn(A1, A2) -> R> for Value<fn(A1, A2) -> R> {
+    fn wrap() -> Self {
+        todo!()
+    }
+}
+
+impl<F, R, A1, A2> Wrap<F> for Value<Rc<dyn Fn(A1, A2) -> R>> {
+    fn wrap() -> Self {
+        todo!()
+    }
+}
+
+impl<F> Deref for Value<Rc<F>> {
+    type Target = F;
+
+    fn deref(&self) -> &Self::Target {
+        &*self.0
+    }
+}
+
+fn main() {
+    let var_fn = Value::wrap();
+    //~^ ERROR type annotations needed for `Value<Rc<_>>`
+
+    // The combination of `Value: Wrap` obligation plus the autoderef steps
+    // (caused by the `Deref` impl above) actually means that the self type
+    // of the method fn below is constrained to be `Value<Rc<dyn Fn(?0, ?1) -> ?2>>`.
+    // However, that's only known to us on the error path -- we still need
+    // to emit an ambiguity error, though.
+    let _ = var_fn.clone();
+}
diff --git a/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr b/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr
new file mode 100644
index 00000000000..06a7e90858c
--- /dev/null
+++ b/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr
@@ -0,0 +1,17 @@
+error[E0282]: type annotations needed for `Value<Rc<_>>`
+  --> $DIR/deref-ambiguity-becomes-nonambiguous.rs:31:9
+   |
+LL |     let var_fn = Value::wrap();
+   |         ^^^^^^
+...
+LL |     let _ = var_fn.clone();
+   |                    ----- type must be known at this point
+   |
+help: consider giving `var_fn` an explicit type, where the placeholders `_` are specified
+   |
+LL |     let var_fn: Value<Rc<_>> = Value::wrap();
+   |               ++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/cfg/diagnostics-reexport.rs b/tests/ui/cfg/diagnostics-reexport.rs
index 1d43d6ba02f..b9548e91183 100644
--- a/tests/ui/cfg/diagnostics-reexport.rs
+++ b/tests/ui/cfg/diagnostics-reexport.rs
@@ -9,6 +9,30 @@ pub mod inner {
     //~^ NOTE found an item that was configured out
 }
 
+pub use a::x;
+//~^ ERROR unresolved import `a::x`
+//~| NOTE no `x` in `a`
+
+mod a {
+    #[cfg(no)]
+    pub fn x() {}
+    //~^ NOTE found an item that was configured out
+}
+
+pub use b::{x, y};
+//~^ ERROR unresolved imports `b::x`, `b::y`
+//~| NOTE no `x` in `b`
+//~| NOTE no `y` in `b`
+
+mod b {
+    #[cfg(no)]
+    pub fn x() {}
+    //~^ NOTE found an item that was configured out
+    #[cfg(no)]
+    pub fn y() {}
+    //~^ NOTE found an item that was configured out
+}
+
 fn main() {
     // There is no uwu at this path - no diagnostic.
     inner::uwu(); //~ ERROR cannot find function
diff --git a/tests/ui/cfg/diagnostics-reexport.stderr b/tests/ui/cfg/diagnostics-reexport.stderr
index 6c977cbfa41..e25b7cf86e2 100644
--- a/tests/ui/cfg/diagnostics-reexport.stderr
+++ b/tests/ui/cfg/diagnostics-reexport.stderr
@@ -1,5 +1,36 @@
+error[E0432]: unresolved import `a::x`
+  --> $DIR/diagnostics-reexport.rs:12:9
+   |
+LL | pub use a::x;
+   |         ^^^^ no `x` in `a`
+   |
+note: found an item that was configured out
+  --> $DIR/diagnostics-reexport.rs:18:12
+   |
+LL |     pub fn x() {}
+   |            ^
+
+error[E0432]: unresolved imports `b::x`, `b::y`
+  --> $DIR/diagnostics-reexport.rs:22:13
+   |
+LL | pub use b::{x, y};
+   |             ^  ^ no `y` in `b`
+   |             |
+   |             no `x` in `b`
+   |
+note: found an item that was configured out
+  --> $DIR/diagnostics-reexport.rs:29:12
+   |
+LL |     pub fn x() {}
+   |            ^
+note: found an item that was configured out
+  --> $DIR/diagnostics-reexport.rs:32:12
+   |
+LL |     pub fn y() {}
+   |            ^
+
 error[E0425]: cannot find function `uwu` in module `inner`
-  --> $DIR/diagnostics-reexport.rs:14:12
+  --> $DIR/diagnostics-reexport.rs:38:12
    |
 LL |     inner::uwu();
    |            ^^^ not found in `inner`
@@ -10,6 +41,7 @@ note: found an item that was configured out
 LL |     pub use super::uwu;
    |                    ^^^
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0425`.
+Some errors have detailed explanations: E0425, E0432.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/closures/cannot-call-unsized-via-ptr-2.rs b/tests/ui/closures/cannot-call-unsized-via-ptr-2.rs
new file mode 100644
index 00000000000..2d8565517e8
--- /dev/null
+++ b/tests/ui/closures/cannot-call-unsized-via-ptr-2.rs
@@ -0,0 +1,11 @@
+#![feature(unsized_fn_params)]
+
+fn main() {
+    // CoerceMany "LUB"
+    let f = if true { |_a| {} } else { |_b| {} };
+    //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+    //~| ERROR the size for values of type `[u8]` cannot be known at compilation time
+
+    let slice: Box<[u8]> = Box::new([1; 8]);
+    f(*slice);
+}
diff --git a/tests/ui/closures/cannot-call-unsized-via-ptr-2.stderr b/tests/ui/closures/cannot-call-unsized-via-ptr-2.stderr
new file mode 100644
index 00000000000..d88b84365df
--- /dev/null
+++ b/tests/ui/closures/cannot-call-unsized-via-ptr-2.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/cannot-call-unsized-via-ptr-2.rs:5:24
+   |
+LL |     let f = if true { |_a| {} } else { |_b| {} };
+   |                        ^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: all function arguments must have a statically known size
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/cannot-call-unsized-via-ptr-2.rs:5:41
+   |
+LL |     let f = if true { |_a| {} } else { |_b| {} };
+   |                                         ^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: all function arguments must have a statically known size
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/closures/cannot-call-unsized-via-ptr.rs b/tests/ui/closures/cannot-call-unsized-via-ptr.rs
new file mode 100644
index 00000000000..5ce4650b033
--- /dev/null
+++ b/tests/ui/closures/cannot-call-unsized-via-ptr.rs
@@ -0,0 +1,10 @@
+#![feature(unsized_fn_params)]
+
+fn main() {
+    // Simple coercion
+    let f: fn([u8]) = |_result| {};
+    //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+
+    let slice: Box<[u8]> = Box::new([1; 8]);
+    f(*slice);
+}
diff --git a/tests/ui/closures/cannot-call-unsized-via-ptr.stderr b/tests/ui/closures/cannot-call-unsized-via-ptr.stderr
new file mode 100644
index 00000000000..9ecc66d5ce8
--- /dev/null
+++ b/tests/ui/closures/cannot-call-unsized-via-ptr.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/cannot-call-unsized-via-ptr.rs:5:24
+   |
+LL |     let f: fn([u8]) = |_result| {};
+   |                        ^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: all function arguments must have a statically known size
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/closures/closure-move-sync.rs b/tests/ui/closures/closure-move-sync.rs
index ea2d1434c4a..3ee2b35f59f 100644
--- a/tests/ui/closures/closure-move-sync.rs
+++ b/tests/ui/closures/closure-move-sync.rs
@@ -13,10 +13,4 @@ fn bar() {
     t.join().unwrap();
 }
 
-fn foo() {
-    let (tx, _rx) = channel();
-    thread::spawn(|| tx.send(()).unwrap());
-    //~^ ERROR `Sender<()>` cannot be shared between threads safely
-}
-
 fn main() {}
diff --git a/tests/ui/closures/closure-move-sync.stderr b/tests/ui/closures/closure-move-sync.stderr
index 64e3b51ea71..aee903ac950 100644
--- a/tests/ui/closures/closure-move-sync.stderr
+++ b/tests/ui/closures/closure-move-sync.stderr
@@ -20,24 +20,6 @@ LL |     let t = thread::spawn(|| {
 note: required by a bound in `spawn`
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
 
-error[E0277]: `Sender<()>` cannot be shared between threads safely
-  --> $DIR/closure-move-sync.rs:18:19
-   |
-LL |     thread::spawn(|| tx.send(()).unwrap());
-   |     ------------- ^^^^^^^^^^^^^^^^^^^^^^^ `Sender<()>` cannot be shared between threads safely
-   |     |
-   |     required by a bound introduced by this call
-   |
-   = help: the trait `Sync` is not implemented for `Sender<()>`
-   = note: required for `&Sender<()>` to implement `Send`
-note: required because it's used within this closure
-  --> $DIR/closure-move-sync.rs:18:19
-   |
-LL |     thread::spawn(|| tx.send(()).unwrap());
-   |                   ^^
-note: required by a bound in `spawn`
-  --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/const-generics/issue-112505-overflow.stderr b/tests/ui/const-generics/issue-112505-overflow.stderr
index 0432f2fa8be..bd8a4feeff5 100644
--- a/tests/ui/const-generics/issue-112505-overflow.stderr
+++ b/tests/ui/const-generics/issue-112505-overflow.stderr
@@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
 LL |     unsafe { std::mem::transmute(v) }
    |              ^^^^^^^^^^^^^^^^^^^
    |
-   = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture)
-   = note: target type: `[[[u32; 9999999]; 777777777]; 239]` (59484438436515561504 bits)
+   = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture)
+   = note: target type: `[[[u32; 9999999]; 777777777]; 239]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
 
 error: aborting due to previous error
 
diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr
index 3d1197afd0f..9e308620a9c 100644
--- a/tests/ui/const-generics/transmute-fail.stderr
+++ b/tests/ui/const-generics/transmute-fail.stderr
@@ -43,8 +43,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
    |
-   = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture)
-   = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[[u32; 9999999]; 777777777]; 8888888]` are too big for the current architecture)
+   = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture)
+   = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/consts/timeout.rs b/tests/ui/consts/timeout.rs
new file mode 100644
index 00000000000..c9094999ee2
--- /dev/null
+++ b/tests/ui/consts/timeout.rs
@@ -0,0 +1,25 @@
+//! This test checks that external macros don't hide
+//! the const eval timeout lint and then subsequently
+//! ICE.
+
+// compile-flags: --crate-type=lib -Ztiny-const-eval-limit
+// error-pattern: constant evaluation is taking a long time
+
+static ROOK_ATTACKS_TABLE: () = {
+    0_u64.count_ones();
+    0_u64.count_ones();
+    0_u64.count_ones();
+    0_u64.count_ones();
+    0_u64.count_ones();
+    0_u64.count_ones();
+    0_u64.count_ones();
+    0_u64.count_ones();
+    0_u64.count_ones();
+    0_u64.count_ones();
+    0_u64.count_ones();
+    0_u64.count_ones();
+    0_u64.count_ones();
+    0_u64.count_ones();
+    0_u64.count_ones();
+    0_u64.count_ones();
+};
diff --git a/tests/ui/consts/timeout.stderr b/tests/ui/consts/timeout.stderr
new file mode 100644
index 00000000000..799b5ec8dd9
--- /dev/null
+++ b/tests/ui/consts/timeout.stderr
@@ -0,0 +1,15 @@
+error: constant evaluation is taking a long time
+  --> $SRC_DIR/core/src/num/mod.rs:LL:COL
+   |
+   = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
+           If your compilation actually takes a long time, you can safely allow the lint.
+help: the constant being evaluated
+  --> $DIR/timeout.rs:8:1
+   |
+LL | static ROOK_ATTACKS_TABLE: () = {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `#[deny(long_running_const_eval)]` on by default
+   = note: this error originates in the macro `uint_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/tests/ui/error-codes/E0283.stderr b/tests/ui/error-codes/E0283.stderr
index 90316c6e981..89e634a7064 100644
--- a/tests/ui/error-codes/E0283.stderr
+++ b/tests/ui/error-codes/E0283.stderr
@@ -9,8 +9,8 @@ LL |     let cont: u32 = Generator::create();
    |
 help: use a fully-qualified path to a specific available implementation (2 found)
    |
-LL |     let cont: u32 = <Impl as Generator>::create();
-   |                     ++++++++          +
+LL |     let cont: u32 = </* self type */ as Generator>::create();
+   |                     +++++++++++++++++++          +
 
 error[E0283]: type annotations needed
   --> $DIR/E0283.rs:35:24
diff --git a/tests/ui/error-codes/E0790.stderr b/tests/ui/error-codes/E0790.stderr
index fc025a3fca2..7248766285d 100644
--- a/tests/ui/error-codes/E0790.stderr
+++ b/tests/ui/error-codes/E0790.stderr
@@ -65,8 +65,8 @@ LL |     MyTrait2::my_fn();
    |
 help: use a fully-qualified path to a specific available implementation (2 found)
    |
-LL |     <Impl1 as MyTrait2>::my_fn();
-   |     +++++++++         +
+LL |     </* self type */ as MyTrait2>::my_fn();
+   |     +++++++++++++++++++         +
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/extern/extern-crate-visibility.stderr b/tests/ui/extern/extern-crate-visibility.stderr
index 9eeb83ae1a7..b239727092a 100644
--- a/tests/ui/extern/extern-crate-visibility.stderr
+++ b/tests/ui/extern/extern-crate-visibility.stderr
@@ -9,6 +9,10 @@ note: the crate import `core` is defined here
    |
 LL |     extern crate core;
    |     ^^^^^^^^^^^^^^^^^^
+help: consider importing this module instead
+   |
+LL | use std::cell;
+   |     ~~~~~~~~~
 
 error[E0603]: crate import `core` is private
   --> $DIR/extern-crate-visibility.rs:9:10
@@ -21,6 +25,10 @@ note: the crate import `core` is defined here
    |
 LL |     extern crate core;
    |     ^^^^^^^^^^^^^^^^^^
+help: consider importing this struct instead
+   |
+LL |     std::cell::Cell::new(0);
+   |     ~~~~~~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr
new file mode 100644
index 00000000000..ce39f6b2971
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr
@@ -0,0 +1,27 @@
+error[E0658]: return type notation is experimental
+  --> $DIR/feature-gate-return_type_notation.rs:17:17
+   |
+LL | fn foo<T: Trait<m(): Send>>() {}
+   |                 ^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = help: add `#![feature(return_type_notation)]` to the crate attributes to enable
+
+error: parenthesized generic arguments cannot be used in associated type constraints
+  --> $DIR/feature-gate-return_type_notation.rs:17:17
+   |
+LL | fn foo<T: Trait<m(): Send>>() {}
+   |                 ^--
+   |                  |
+   |                  help: remove these parentheses
+
+error[E0220]: associated type `m` not found for `Trait`
+  --> $DIR/feature-gate-return_type_notation.rs:17:17
+   |
+LL | fn foo<T: Trait<m(): Send>>() {}
+   |                 ^ associated type `m` not found
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0220, E0658.
+For more information about an error, try `rustc --explain E0220`.
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr
new file mode 100644
index 00000000000..ce39f6b2971
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr
@@ -0,0 +1,27 @@
+error[E0658]: return type notation is experimental
+  --> $DIR/feature-gate-return_type_notation.rs:17:17
+   |
+LL | fn foo<T: Trait<m(): Send>>() {}
+   |                 ^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = help: add `#![feature(return_type_notation)]` to the crate attributes to enable
+
+error: parenthesized generic arguments cannot be used in associated type constraints
+  --> $DIR/feature-gate-return_type_notation.rs:17:17
+   |
+LL | fn foo<T: Trait<m(): Send>>() {}
+   |                 ^--
+   |                  |
+   |                  help: remove these parentheses
+
+error[E0220]: associated type `m` not found for `Trait`
+  --> $DIR/feature-gate-return_type_notation.rs:17:17
+   |
+LL | fn foo<T: Trait<m(): Send>>() {}
+   |                 ^ associated type `m` not found
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0220, E0658.
+For more information about an error, try `rustc --explain E0220`.
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.no_current.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.no_current.stderr
new file mode 100644
index 00000000000..d11359e7f48
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.no_current.stderr
@@ -0,0 +1,13 @@
+warning: return type notation is experimental
+  --> $DIR/feature-gate-return_type_notation.rs:17:17
+   |
+LL | fn foo<T: Trait<m(): Send>>() {}
+   |                 ^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = help: add `#![feature(return_type_notation)]` to the crate attributes to enable
+   = warning: unstable syntax can change at any point in the future, causing a hard error!
+   = note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.no_next.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.no_next.stderr
new file mode 100644
index 00000000000..d11359e7f48
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.no_next.stderr
@@ -0,0 +1,13 @@
+warning: return type notation is experimental
+  --> $DIR/feature-gate-return_type_notation.rs:17:17
+   |
+LL | fn foo<T: Trait<m(): Send>>() {}
+   |                 ^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = help: add `#![feature(return_type_notation)]` to the crate attributes to enable
+   = warning: unstable syntax can change at any point in the future, causing a hard error!
+   = note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.rs b/tests/ui/feature-gates/feature-gate-return_type_notation.rs
index d9bcb65feba..7e8c1eb95ca 100644
--- a/tests/ui/feature-gates/feature-gate-return_type_notation.rs
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.rs
@@ -1,7 +1,10 @@
 // edition: 2021
-// revisions: cfg no
+// revisions: cfg_current cfg_next no_current no_next
+// [cfg_next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// [no_next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
 
-//[no] check-pass
+// [no_current] check-pass
+// [no_next] check-pass
 // Since we're not adding new syntax, `cfg`'d out RTN must pass.
 
 #![feature(async_fn_in_trait)]
@@ -10,12 +13,17 @@ trait Trait {
     async fn m();
 }
 
-#[cfg(cfg)]
+#[cfg(any(cfg_current, cfg_next))]
 fn foo<T: Trait<m(): Send>>() {}
-//[cfg]~^ ERROR return type notation is experimental
-//[cfg]~| ERROR parenthesized generic arguments cannot be used in associated type constraints
-//[cfg]~| ERROR associated type `m` not found for `Trait`
-//[no]~^^^^ WARN return type notation is experimental
-//[no]~| WARN unstable syntax can change at any point in the future, causing a hard error!
+//[cfg_current]~^ ERROR return type notation is experimental
+//[cfg_current]~| ERROR parenthesized generic arguments cannot be used in associated type constraints
+//[cfg_current]~| ERROR associated type `m` not found for `Trait`
+//[cfg_next]~^^^^ ERROR return type notation is experimental
+//[cfg_next]~| ERROR parenthesized generic arguments cannot be used in associated type constraints
+//[cfg_next]~| ERROR associated type `m` not found for `Trait`
+//[no_current]~^^^^^^^ WARN return type notation is experimental
+//[no_current]~| WARN unstable syntax can change at any point in the future, causing a hard error!
+//[no_next]~^^^^^^^^^ WARN return type notation is experimental
+//[no_next]~| WARN unstable syntax can change at any point in the future, causing a hard error!
 
 fn main() {}
diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr
index 5362a68c834..a96a53ca93e 100644
--- a/tests/ui/for/issue-20605.next.stderr
+++ b/tests/ui/for/issue-20605.next.stderr
@@ -14,7 +14,7 @@ LL |     for item in *things { *item = 0 }
    = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
 
-error: the type `<_ as IntoIterator>::IntoIter` is not well-formed
+error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
   --> $DIR/issue-20605.rs:5:17
    |
 LL |     for item in *things { *item = 0 }
diff --git a/tests/ui/for/issue-20605.rs b/tests/ui/for/issue-20605.rs
index 499271fa92f..64156b35705 100644
--- a/tests/ui/for/issue-20605.rs
+++ b/tests/ui/for/issue-20605.rs
@@ -4,7 +4,7 @@
 fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) {
     for item in *things { *item = 0 }
     //~^ ERROR the size for values of type
-    //[next]~^^ ERROR the type `<_ as IntoIterator>::IntoIter` is not well-formed
+    //[next]~^^ ERROR the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
     //[next]~| ERROR the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
 }
 
diff --git a/tests/ui/generic-associated-types/issue-88595.rs b/tests/ui/generic-associated-types/issue-88595.rs
index 7de906e7ef3..5a40a612972 100644
--- a/tests/ui/generic-associated-types/issue-88595.rs
+++ b/tests/ui/generic-associated-types/issue-88595.rs
@@ -19,5 +19,4 @@ impl<'a> A<'a> for C {
     type B<'b> = impl Clone;
 
     fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
-    //~^ ERROR: mismatched types
 }
diff --git a/tests/ui/generic-associated-types/issue-88595.stderr b/tests/ui/generic-associated-types/issue-88595.stderr
index d6caed85459..2b1a25acfa4 100644
--- a/tests/ui/generic-associated-types/issue-88595.stderr
+++ b/tests/ui/generic-associated-types/issue-88595.stderr
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/issue-88595.rs:21:5
+  --> $DIR/issue-88595.rs:21:23
    |
 LL |     fn a(&'a self) -> Self::B<'a> {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ generic argument `'a` used twice
+   |                       ^^^^^^^^^^^ generic argument `'a` used twice
    |
 note: for this opaque type
   --> $DIR/issue-88595.rs:19:18
@@ -10,25 +10,5 @@ note: for this opaque type
 LL |     type B<'b> = impl Clone;
    |                  ^^^^^^^^^^
 
-error[E0308]: mismatched types
-  --> $DIR/issue-88595.rs:21:23
-   |
-LL |     type B<'b> = impl Clone;
-   |                  ---------- the expected opaque type
-LL |
-LL |     fn a(&'a self) -> Self::B<'a> {}
-   |        -              ^^^^^^^^^^^ expected opaque type, found `()`
-   |        |
-   |        implicitly returns `()` as its body has no tail or `return` expression
-   |
-   = note: expected opaque type `<C as A<'a>>::B<'a>`
-                found unit type `()`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/issue-88595.rs:21:5
-   |
-LL |     fn a(&'a self) -> Self::B<'a> {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr
index 1097cd0f452..8e61a65abe4 100644
--- a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr
+++ b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr
@@ -40,10 +40,10 @@ LL |         fn method() -> Self::Ty;
    = note: expected signature `fn() -> <() as compare_method::Trait>::Ty`
               found signature `fn()`
 note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/in-assoc-type-unconstrained.rs:22:9
+  --> $DIR/in-assoc-type-unconstrained.rs:22:12
    |
 LL |         fn method() -> () {}
-   |         ^^^^^^^^^^^^^^^^^
+   |            ^^^^^^
 
 error: unconstrained opaque type
   --> $DIR/in-assoc-type-unconstrained.rs:20:19
diff --git a/tests/ui/impl-trait/in-assoc-type.stderr b/tests/ui/impl-trait/in-assoc-type.stderr
index f0a272dc2d5..ab3f3a14410 100644
--- a/tests/ui/impl-trait/in-assoc-type.stderr
+++ b/tests/ui/impl-trait/in-assoc-type.stderr
@@ -12,10 +12,10 @@ LL |     fn foo(&self) -> <Self as Foo<()>>::Bar {}
    = note: expected opaque type `<() as Foo<()>>::Bar`
                 found unit type `()`
 note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/in-assoc-type.rs:17:5
+  --> $DIR/in-assoc-type.rs:17:8
    |
 LL |     fn foo(&self) -> <Self as Foo<()>>::Bar {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |        ^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
index bbd60d4398b..fe765271bd2 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
@@ -20,11 +20,6 @@ LL |         fn eq(&self, _other: &(Foo, i32)) -> bool {
    |
    = note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _`
               found signature `fn(&a::Bar, &(a::Foo, i32)) -> _`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:9
-   |
-LL |         fn eq(&self, _other: &(Foo, i32)) -> bool {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unconstrained opaque type
   --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16
@@ -49,10 +44,10 @@ LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
    = note: expected signature `fn(&b::Bar, &(b::Foo, i32)) -> _`
               found signature `fn(&b::Bar, &(b::Bar, i32)) -> _`
 note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:9
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:12
    |
 LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/issues/issue-11680.stderr b/tests/ui/issues/issue-11680.stderr
index ea224af8ed7..5bcf93de811 100644
--- a/tests/ui/issues/issue-11680.stderr
+++ b/tests/ui/issues/issue-11680.stderr
@@ -2,7 +2,9 @@ error[E0603]: enum `Foo` is private
   --> $DIR/issue-11680.rs:6:21
    |
 LL |     let _b = other::Foo::Bar(1);
-   |                     ^^^ private enum
+   |                     ^^^  --- tuple variant `Bar` is not publicly re-exported
+   |                     |
+   |                     private enum
    |
 note: the enum `Foo` is defined here
   --> $DIR/auxiliary/issue-11680.rs:1:1
@@ -14,7 +16,9 @@ error[E0603]: enum `Foo` is private
   --> $DIR/issue-11680.rs:9:27
    |
 LL |     let _b = other::test::Foo::Bar(1);
-   |                           ^^^ private enum
+   |                           ^^^  --- tuple variant `Bar` is not publicly re-exported
+   |                           |
+   |                           private enum
    |
 note: the enum `Foo` is defined here
   --> $DIR/auxiliary/issue-11680.rs:6:5
diff --git a/tests/ui/issues/issue-5883.rs b/tests/ui/issues/issue-5883.rs
index 82866b35557..f9dd2c54d99 100644
--- a/tests/ui/issues/issue-5883.rs
+++ b/tests/ui/issues/issue-5883.rs
@@ -6,7 +6,7 @@ struct Struct {
 
 fn new_struct(
     r: dyn A + 'static //~ ERROR the size for values of type
-) -> Struct {          //~ ERROR the size for values of type
+) -> Struct {
     Struct { r: r }
 }
 
diff --git a/tests/ui/issues/issue-5883.stderr b/tests/ui/issues/issue-5883.stderr
index ffff403e0d4..a3e2531b5ca 100644
--- a/tests/ui/issues/issue-5883.stderr
+++ b/tests/ui/issues/issue-5883.stderr
@@ -15,22 +15,6 @@ help: function arguments must have a statically known size, borrowed types alway
 LL |     r: &dyn A + 'static
    |        +
 
-error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time
-  --> $DIR/issue-5883.rs:9:6
-   |
-LL | ) -> Struct {
-   |      ^^^^^^ doesn't have a size known at compile-time
-LL |     Struct { r: r }
-   |     --------------- this returned value is of type `Struct`
-   |
-   = help: within `Struct`, the trait `Sized` is not implemented for `(dyn A + 'static)`
-note: required because it appears within the type `Struct`
-  --> $DIR/issue-5883.rs:3:8
-   |
-LL | struct Struct {
-   |        ^^^^^^
-   = note: the return type of a function must have a statically known size
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/layout/cannot-transmute-unnormalizable-type.rs b/tests/ui/layout/cannot-transmute-unnormalizable-type.rs
new file mode 100644
index 00000000000..d2b6e1d8eba
--- /dev/null
+++ b/tests/ui/layout/cannot-transmute-unnormalizable-type.rs
@@ -0,0 +1,22 @@
+trait Trait {
+    type RefTarget;
+}
+
+impl Trait for ()
+where
+    Missing: Trait,
+    //~^ ERROR cannot find type `Missing` in this scope
+{
+    type RefTarget = ();
+}
+
+struct Other {
+    data: <() as Trait>::RefTarget,
+}
+
+fn main() {
+    unsafe {
+        std::mem::transmute::<Option<()>, Option<&Other>>(None);
+        //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+    }
+}
diff --git a/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr b/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr
new file mode 100644
index 00000000000..dd5119318ff
--- /dev/null
+++ b/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr
@@ -0,0 +1,19 @@
+error[E0412]: cannot find type `Missing` in this scope
+  --> $DIR/cannot-transmute-unnormalizable-type.rs:7:5
+   |
+LL |     Missing: Trait,
+   |     ^^^^^^^ not found in this scope
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/cannot-transmute-unnormalizable-type.rs:19:9
+   |
+LL |         std::mem::transmute::<Option<()>, Option<&Other>>(None);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `Option<()>` (8 bits)
+   = note: target type: `Option<&Other>` (unable to determine layout for `Other` because `<() as Trait>::RefTarget` cannot be normalized)
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0412, E0512.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/macros/issue-88228.stderr b/tests/ui/macros/issue-88228.stderr
index 1dbe2b77be2..f9d0ac95da7 100644
--- a/tests/ui/macros/issue-88228.stderr
+++ b/tests/ui/macros/issue-88228.stderr
@@ -4,7 +4,7 @@ error: cannot find macro `bla` in this scope
 LL |     bla!();
    |     ^^^
    |
-help: consider importing this macro
+help: consider importing this macro through its public re-export
    |
 LL + use crate::hey::bla;
    |
@@ -23,7 +23,7 @@ error: cannot find derive macro `Bla` in this scope
 LL | #[derive(Bla)]
    |          ^^^
    |
-help: consider importing this derive macro
+help: consider importing this derive macro through its public re-export
    |
 LL + use crate::hey::Bla;
    |
diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr
index da4b9595c0e..ba885d1b97e 100644
--- a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr
+++ b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr
@@ -1,4 +1,4 @@
-error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(0, 'a)])` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a), T, ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a)])` captures lifetime that does not appear in bounds
   --> $DIR/impl-trait-captures.rs:11:5
    |
 LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
@@ -8,7 +8,7 @@ LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
 LL |     x
    |     ^
    |
-help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` lifetime bound
+help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a), T, ReEarlyBound(DefId(0:14 ~ impl_trait_captures[aeb9]::foo::{opaque#0}::'a), 2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` lifetime bound
    |
 LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) {
    |                                      ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/tests/ui/privacy/export-tag-variant.stderr b/tests/ui/privacy/export-tag-variant.stderr
index f73bd454d35..e8906985e05 100644
--- a/tests/ui/privacy/export-tag-variant.stderr
+++ b/tests/ui/privacy/export-tag-variant.stderr
@@ -2,7 +2,9 @@ error[E0603]: enum `Y` is private
   --> $DIR/export-tag-variant.rs:7:26
    |
 LL | fn main() { let z = foo::Y::Y1; }
-   |                          ^ private enum
+   |                          ^  -- unit variant `Y1` is not publicly re-exported
+   |                          |
+   |                          private enum
    |
 note: the enum `Y` is defined here
   --> $DIR/export-tag-variant.rs:4:5
diff --git a/tests/ui/privacy/privacy-in-paths.stderr b/tests/ui/privacy/privacy-in-paths.stderr
index 2eb3ebb51c2..9c3d5e97c62 100644
--- a/tests/ui/privacy/privacy-in-paths.stderr
+++ b/tests/ui/privacy/privacy-in-paths.stderr
@@ -2,7 +2,9 @@ error[E0603]: module `bar` is private
   --> $DIR/privacy-in-paths.rs:24:16
    |
 LL |         ::foo::bar::baz::f();
-   |                ^^^ private module
+   |                ^^^       - function `f` is not publicly re-exported
+   |                |
+   |                private module
    |
 note: the module `bar` is defined here
   --> $DIR/privacy-in-paths.rs:3:5
@@ -21,12 +23,18 @@ note: the module `bar` is defined here
    |
 LL |     mod bar {
    |     ^^^^^^^
+help: consider importing this struct through its public re-export instead
+   |
+LL |         foo::S::f();
+   |         ~~~~~~
 
 error[E0603]: trait `T` is private
   --> $DIR/privacy-in-paths.rs:26:23
    |
 LL |         <() as ::foo::T>::Assoc::f();
-   |                       ^ private trait
+   |                       ^   ----- associated type `Assoc` is not publicly re-exported
+   |                       |
+   |                       private trait
    |
 note: the trait `T` is defined here
   --> $DIR/privacy-in-paths.rs:8:5
diff --git a/tests/ui/privacy/privacy-ufcs.stderr b/tests/ui/privacy/privacy-ufcs.stderr
index e93a458ce6c..f45f3d8ec37 100644
--- a/tests/ui/privacy/privacy-ufcs.stderr
+++ b/tests/ui/privacy/privacy-ufcs.stderr
@@ -2,7 +2,9 @@ error[E0603]: trait `Bar` is private
   --> $DIR/privacy-ufcs.rs:12:20
    |
 LL |     <i32 as ::foo::Bar>::baz();
-   |                    ^^^ private trait
+   |                    ^^^   --- associated function `baz` is not publicly re-exported
+   |                    |
+   |                    private trait
    |
 note: the trait `Bar` is defined here
   --> $DIR/privacy-ufcs.rs:4:5
diff --git a/tests/ui/privacy/privacy1.stderr b/tests/ui/privacy/privacy1.stderr
index 6ebed8ee062..ca8f242e0be 100644
--- a/tests/ui/privacy/privacy1.stderr
+++ b/tests/ui/privacy/privacy1.stderr
@@ -50,7 +50,9 @@ error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:104:16
    |
 LL |         ::bar::baz::A::foo();
-   |                ^^^ private module
+   |                ^^^  - struct `A` is not publicly re-exported
+   |                |
+   |                private module
    |
 note: the module `baz` is defined here
   --> $DIR/privacy1.rs:50:5
@@ -62,7 +64,9 @@ error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:105:16
    |
 LL |         ::bar::baz::A::bar();
-   |                ^^^ private module
+   |                ^^^  - struct `A` is not publicly re-exported
+   |                |
+   |                private module
    |
 note: the module `baz` is defined here
   --> $DIR/privacy1.rs:50:5
@@ -74,7 +78,9 @@ error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:107:16
    |
 LL |         ::bar::baz::A.foo2();
-   |                ^^^ private module
+   |                ^^^  - unit struct `A` is not publicly re-exported
+   |                |
+   |                private module
    |
 note: the module `baz` is defined here
   --> $DIR/privacy1.rs:50:5
@@ -86,7 +92,9 @@ error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:108:16
    |
 LL |         ::bar::baz::A.bar2();
-   |                ^^^ private module
+   |                ^^^  - unit struct `A` is not publicly re-exported
+   |                |
+   |                private module
    |
 note: the module `baz` is defined here
   --> $DIR/privacy1.rs:50:5
@@ -98,7 +106,9 @@ error[E0603]: trait `B` is private
   --> $DIR/privacy1.rs:112:16
    |
 LL |         ::bar::B::foo();
-   |                ^ private trait
+   |                ^  --- associated function `foo` is not publicly re-exported
+   |                |
+   |                private trait
    |
 note: the trait `B` is defined here
   --> $DIR/privacy1.rs:40:5
@@ -129,6 +139,10 @@ note: the module `baz` is defined here
    |
 LL |     mod baz {
    |     ^^^^^^^
+help: consider importing this function through its public re-export instead
+   |
+LL |         bar::foo();
+   |         ~~~~~~~~
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:128:16
@@ -141,6 +155,10 @@ note: the module `baz` is defined here
    |
 LL |     mod baz {
    |     ^^^^^^^
+help: consider importing this function through its public re-export instead
+   |
+LL |         bar::bar();
+   |         ~~~~~~~~
 
 error[E0603]: trait `B` is private
   --> $DIR/privacy1.rs:157:17
diff --git a/tests/ui/privacy/sealed-traits/private-trait-non-local.rs b/tests/ui/privacy/sealed-traits/private-trait-non-local.rs
new file mode 100644
index 00000000000..426f21cc7de
--- /dev/null
+++ b/tests/ui/privacy/sealed-traits/private-trait-non-local.rs
@@ -0,0 +1,4 @@
+extern crate core;
+use core::slice::index::private_slice_index::Sealed; //~ ERROR module `index` is private
+fn main() {
+}
diff --git a/tests/ui/privacy/sealed-traits/private-trait-non-local.stderr b/tests/ui/privacy/sealed-traits/private-trait-non-local.stderr
new file mode 100644
index 00000000000..29499979866
--- /dev/null
+++ b/tests/ui/privacy/sealed-traits/private-trait-non-local.stderr
@@ -0,0 +1,12 @@
+error[E0603]: module `index` is private
+  --> $DIR/private-trait-non-local.rs:2:18
+   |
+LL | use core::slice::index::private_slice_index::Sealed;
+   |                  ^^^^^ private module        ------ trait `Sealed` is not publicly re-exported
+   |
+note: the module `index` is defined here
+  --> $SRC_DIR/core/src/slice/mod.rs:LL:COL
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/tests/ui/privacy/sealed-traits/private-trait.rs b/tests/ui/privacy/sealed-traits/private-trait.rs
new file mode 100644
index 00000000000..bbcbaabfaf4
--- /dev/null
+++ b/tests/ui/privacy/sealed-traits/private-trait.rs
@@ -0,0 +1,10 @@
+pub mod a {
+    mod b {
+        pub trait Hidden {}
+    }
+}
+
+struct S;
+impl a::b::Hidden for S {} //~ ERROR module `b` is private
+
+fn main() {}
diff --git a/tests/ui/privacy/sealed-traits/private-trait.stderr b/tests/ui/privacy/sealed-traits/private-trait.stderr
new file mode 100644
index 00000000000..c7ec72ff166
--- /dev/null
+++ b/tests/ui/privacy/sealed-traits/private-trait.stderr
@@ -0,0 +1,17 @@
+error[E0603]: module `b` is private
+  --> $DIR/private-trait.rs:8:9
+   |
+LL | impl a::b::Hidden for S {}
+   |         ^  ------ trait `Hidden` is not publicly re-exported
+   |         |
+   |         private module
+   |
+note: the module `b` is defined here
+  --> $DIR/private-trait.rs:2:5
+   |
+LL |     mod b {
+   |     ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.fixed b/tests/ui/privacy/sealed-traits/re-exported-trait.fixed
new file mode 100644
index 00000000000..79b6a6516ab
--- /dev/null
+++ b/tests/ui/privacy/sealed-traits/re-exported-trait.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+
+pub mod a {
+    pub use self::b::Trait;
+    mod b {
+        pub trait Trait {}
+    }
+}
+
+struct S;
+impl a::Trait for S {} //~ ERROR module `b` is private
+
+fn main() {}
diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.rs b/tests/ui/privacy/sealed-traits/re-exported-trait.rs
new file mode 100644
index 00000000000..5f96dfdcbd6
--- /dev/null
+++ b/tests/ui/privacy/sealed-traits/re-exported-trait.rs
@@ -0,0 +1,13 @@
+// run-rustfix
+
+pub mod a {
+    pub use self::b::Trait;
+    mod b {
+        pub trait Trait {}
+    }
+}
+
+struct S;
+impl a::b::Trait for S {} //~ ERROR module `b` is private
+
+fn main() {}
diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.stderr b/tests/ui/privacy/sealed-traits/re-exported-trait.stderr
new file mode 100644
index 00000000000..b630565d023
--- /dev/null
+++ b/tests/ui/privacy/sealed-traits/re-exported-trait.stderr
@@ -0,0 +1,19 @@
+error[E0603]: module `b` is private
+  --> $DIR/re-exported-trait.rs:11:9
+   |
+LL | impl a::b::Trait for S {}
+   |         ^ private module
+   |
+note: the module `b` is defined here
+  --> $DIR/re-exported-trait.rs:5:5
+   |
+LL |     mod b {
+   |     ^^^^^
+help: consider importing this trait through its public re-export instead
+   |
+LL | impl a::Trait for S {}
+   |      ~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/tests/ui/privacy/sealed-traits/sealed-trait-local.rs b/tests/ui/privacy/sealed-traits/sealed-trait-local.rs
new file mode 100644
index 00000000000..778ddf0f817
--- /dev/null
+++ b/tests/ui/privacy/sealed-traits/sealed-trait-local.rs
@@ -0,0 +1,19 @@
+// provide custom privacy error for sealed traits
+pub mod a {
+    pub trait Sealed: self::b::Hidden {
+        fn foo() {}
+    }
+
+    struct X;
+    impl Sealed for X {}
+    impl self::b::Hidden for X {}
+
+    mod b {
+        pub trait Hidden {}
+    }
+}
+
+struct S;
+impl a::Sealed for S {} //~ ERROR the trait bound `S: Hidden` is not satisfied
+
+fn main() {}
diff --git a/tests/ui/privacy/sealed-traits/sealed-trait-local.stderr b/tests/ui/privacy/sealed-traits/sealed-trait-local.stderr
new file mode 100644
index 00000000000..d1052ce3508
--- /dev/null
+++ b/tests/ui/privacy/sealed-traits/sealed-trait-local.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `S: Hidden` is not satisfied
+  --> $DIR/sealed-trait-local.rs:17:20
+   |
+LL | impl a::Sealed for S {}
+   |                    ^ the trait `Hidden` is not implemented for `S`
+   |
+note: required by a bound in `Sealed`
+  --> $DIR/sealed-trait-local.rs:3:23
+   |
+LL |     pub trait Sealed: self::b::Hidden {
+   |                       ^^^^^^^^^^^^^^^ required by this bound in `Sealed`
+   = note: `Sealed` is a "sealed trait", because to implement it you also need to implelement `a::b::Hidden`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/proc-macro/derive-helper-shadowing.stderr b/tests/ui/proc-macro/derive-helper-shadowing.stderr
index 7e7870b2951..566c4130846 100644
--- a/tests/ui/proc-macro/derive-helper-shadowing.stderr
+++ b/tests/ui/proc-macro/derive-helper-shadowing.stderr
@@ -17,7 +17,7 @@ LL |             #[derive(GenHelperUse)]
    |                      ^^^^^^^^^^^^
    |
    = note: this error originates in the derive macro `GenHelperUse` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider importing this attribute macro
+help: consider importing this attribute macro through its public re-export
    |
 LL +             use empty_helper;
    |
@@ -32,7 +32,7 @@ LL |             gen_helper_use!();
    |             ----------------- in this macro invocation
    |
    = note: this error originates in the macro `gen_helper_use` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider importing this attribute macro
+help: consider importing this attribute macro through its public re-export
    |
 LL +             use crate::empty_helper;
    |
diff --git a/tests/ui/reachable/unreachable-variant.stderr b/tests/ui/reachable/unreachable-variant.stderr
index 6c27a2756f7..ca1d2be65ce 100644
--- a/tests/ui/reachable/unreachable-variant.stderr
+++ b/tests/ui/reachable/unreachable-variant.stderr
@@ -2,7 +2,7 @@ error[E0603]: module `super_sekrit` is private
   --> $DIR/unreachable-variant.rs:6:21
    |
 LL |     let _x = other::super_sekrit::sooper_sekrit::baz;
-   |                     ^^^^^^^^^^^^ private module
+   |                     ^^^^^^^^^^^^ private module  --- unit variant `baz` is not publicly re-exported
    |
 note: the module `super_sekrit` is defined here
   --> $DIR/auxiliary/unreachable_variant.rs:1:1
diff --git a/tests/ui/resolve/privacy-enum-ctor.stderr b/tests/ui/resolve/privacy-enum-ctor.stderr
index 0bb09090569..b10eded015f 100644
--- a/tests/ui/resolve/privacy-enum-ctor.stderr
+++ b/tests/ui/resolve/privacy-enum-ctor.stderr
@@ -228,7 +228,9 @@ error[E0603]: enum `Z` is private
   --> $DIR/privacy-enum-ctor.rs:61:22
    |
 LL |     let _: Z = m::n::Z::Fn;
-   |                      ^ private enum
+   |                      ^  -- tuple variant `Fn` is not publicly re-exported
+   |                      |
+   |                      private enum
    |
 note: the enum `Z` is defined here
   --> $DIR/privacy-enum-ctor.rs:11:9
@@ -252,7 +254,9 @@ error[E0603]: enum `Z` is private
   --> $DIR/privacy-enum-ctor.rs:68:22
    |
 LL |     let _: Z = m::n::Z::Unit {};
-   |                      ^ private enum
+   |                      ^  ---- variant `Unit` is not publicly re-exported
+   |                      |
+   |                      private enum
    |
 note: the enum `Z` is defined here
   --> $DIR/privacy-enum-ctor.rs:11:9
diff --git a/tests/ui/stability-attribute/stability-in-private-module.stderr b/tests/ui/stability-attribute/stability-in-private-module.stderr
index 2f02a24960e..cc8758714fc 100644
--- a/tests/ui/stability-attribute/stability-in-private-module.stderr
+++ b/tests/ui/stability-attribute/stability-in-private-module.stderr
@@ -2,7 +2,9 @@ error[E0603]: module `thread_info` is private
   --> $DIR/stability-in-private-module.rs:2:26
    |
 LL |     let _ = std::thread::thread_info::current_thread();
-   |                          ^^^^^^^^^^^ private module
+   |                          ^^^^^^^^^^^  -------------- function `current_thread` is not publicly re-exported
+   |                          |
+   |                          private module
    |
 note: the module `thread_info` is defined here
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
diff --git a/tests/ui/stdlib-unit-tests/not-sync.rs b/tests/ui/stdlib-unit-tests/not-sync.rs
index f4648994fa9..e9395ae9e81 100644
--- a/tests/ui/stdlib-unit-tests/not-sync.rs
+++ b/tests/ui/stdlib-unit-tests/not-sync.rs
@@ -17,6 +17,4 @@ fn main() {
 
     test::<Receiver<i32>>();
     //~^ ERROR `std::sync::mpsc::Receiver<i32>` cannot be shared between threads safely [E0277]
-    test::<Sender<i32>>();
-    //~^ ERROR `Sender<i32>` cannot be shared between threads safely [E0277]
 }
diff --git a/tests/ui/stdlib-unit-tests/not-sync.stderr b/tests/ui/stdlib-unit-tests/not-sync.stderr
index 4e34e10e377..b9a266e4eb9 100644
--- a/tests/ui/stdlib-unit-tests/not-sync.stderr
+++ b/tests/ui/stdlib-unit-tests/not-sync.stderr
@@ -65,19 +65,6 @@ note: required by a bound in `test`
 LL | fn test<T: Sync>() {}
    |            ^^^^ required by this bound in `test`
 
-error[E0277]: `Sender<i32>` cannot be shared between threads safely
-  --> $DIR/not-sync.rs:20:12
-   |
-LL |     test::<Sender<i32>>();
-   |            ^^^^^^^^^^^ `Sender<i32>` cannot be shared between threads safely
-   |
-   = help: the trait `Sync` is not implemented for `Sender<i32>`
-note: required by a bound in `test`
-  --> $DIR/not-sync.rs:5:12
-   |
-LL | fn test<T: Sync>() {}
-   |            ^^^^ required by this bound in `test`
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/structs/struct-variant-privacy-xc.stderr b/tests/ui/structs/struct-variant-privacy-xc.stderr
index 1c1caaef8b7..7a1c84badef 100644
--- a/tests/ui/structs/struct-variant-privacy-xc.stderr
+++ b/tests/ui/structs/struct-variant-privacy-xc.stderr
@@ -14,7 +14,9 @@ error[E0603]: enum `Bar` is private
   --> $DIR/struct-variant-privacy-xc.rs:7:33
    |
 LL |         struct_variant_privacy::Bar::Baz { a: _a } => {}
-   |                                 ^^^ private enum
+   |                                 ^^^  --- variant `Baz` is not publicly re-exported
+   |                                 |
+   |                                 private enum
    |
 note: the enum `Bar` is defined here
   --> $DIR/auxiliary/struct_variant_privacy.rs:1:1
diff --git a/tests/ui/structs/struct-variant-privacy.stderr b/tests/ui/structs/struct-variant-privacy.stderr
index eafd26c716f..eabd66907f6 100644
--- a/tests/ui/structs/struct-variant-privacy.stderr
+++ b/tests/ui/structs/struct-variant-privacy.stderr
@@ -14,7 +14,9 @@ error[E0603]: enum `Bar` is private
   --> $DIR/struct-variant-privacy.rs:10:14
    |
 LL |         foo::Bar::Baz { a: _a } => {}
-   |              ^^^ private enum
+   |              ^^^  --- variant `Baz` is not publicly re-exported
+   |              |
+   |              private enum
    |
 note: the enum `Bar` is defined here
   --> $DIR/struct-variant-privacy.rs:2:5
diff --git a/tests/ui/test-attrs/test-panic-abort-disabled.rs b/tests/ui/test-attrs/test-panic-abort-disabled.rs
index 874dbdb42c3..fa67a784de4 100644
--- a/tests/ui/test-attrs/test-panic-abort-disabled.rs
+++ b/tests/ui/test-attrs/test-panic-abort-disabled.rs
@@ -3,6 +3,7 @@
 // compile-flags: --test -Cpanic=abort -Zpanic-abort-tests=no
 // run-flags: --test-threads=1
 
+// needs-unwind
 // ignore-wasm no panic or subprocess support
 // ignore-emscripten no panic or subprocess support
 
diff --git a/tests/ui/test-attrs/test-type.rs b/tests/ui/test-attrs/test-type.rs
index 8416270fd81..d6d44a6b446 100644
--- a/tests/ui/test-attrs/test-type.rs
+++ b/tests/ui/test-attrs/test-type.rs
@@ -1,9 +1,8 @@
-// compile-flags: --test
+// compile-flags: --test -Zpanic-abort-tests
 // run-flags: --test-threads=1
 // check-run-results
 // normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
 // ignore-emscripten no threads support
-// needs-unwind
 // run-pass
 
 #[test]
diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.rs b/tests/ui/traits/new-solver/alias-bound-unsound.rs
index 00294c708f1..6b6a77e2c7e 100644
--- a/tests/ui/traits/new-solver/alias-bound-unsound.rs
+++ b/tests/ui/traits/new-solver/alias-bound-unsound.rs
@@ -23,5 +23,7 @@ fn main() {
     drop(<() as Foo>::copy_me(&x));
     //~^ ERROR `<() as Foo>::Item: Copy` is not satisfied
     //~| ERROR `<() as Foo>::Item` is not well-formed
+    //~| ERROR `<() as Foo>::Item` is not well-formed
+    //~| ERROR `<() as Foo>::Item` is not well-formed
     println!("{x}");
 }
diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.stderr b/tests/ui/traits/new-solver/alias-bound-unsound.stderr
index 9a43d2a6639..89abc608213 100644
--- a/tests/ui/traits/new-solver/alias-bound-unsound.stderr
+++ b/tests/ui/traits/new-solver/alias-bound-unsound.stderr
@@ -19,6 +19,18 @@ error: the type `<() as Foo>::Item` is not well-formed
 LL |     drop(<() as Foo>::copy_me(&x));
    |          ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: the type `<() as Foo>::Item` is not well-formed
+  --> $DIR/alias-bound-unsound.rs:23:5
+   |
+LL |     drop(<() as Foo>::copy_me(&x));
+   |     ^^^^
+
+error: the type `<() as Foo>::Item` is not well-formed
+  --> $DIR/alias-bound-unsound.rs:23:10
+   |
+LL |     drop(<() as Foo>::copy_me(&x));
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/new-solver/member-constraints-in-root-universe.rs b/tests/ui/traits/new-solver/member-constraints-in-root-universe.rs
new file mode 100644
index 00000000000..97c44305864
--- /dev/null
+++ b/tests/ui/traits/new-solver/member-constraints-in-root-universe.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+trait Trait {
+    type Ty;
+}
+
+impl Trait for for<'a> fn(&'a u8, &'a u8) {
+    type Ty = ();
+}
+
+// argument is necessary to create universes before registering the hidden type.
+fn test<'a>(_: <fn(&u8, &u8) as Trait>::Ty) -> impl Sized {
+    "hidden type is `&'?0 str` with '?0 member of ['static,]"
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs
new file mode 100644
index 00000000000..eb19b49c7e2
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs
@@ -0,0 +1,28 @@
+//! This test shows that a field type that is a projection that resolves to an opaque,
+//! is not a defining use. While we could substitute the struct generics, that would
+//! mean we would have to walk all substitutions of an `Foo`, which can quickly
+//! degenerate into looking at an exponential number of types depending on the complexity
+//! of a program.
+
+#![feature(impl_trait_in_assoc_type)]
+
+struct Bar;
+
+trait Trait: Sized {
+    type Assoc;
+    fn foo() -> Foo<Self>;
+}
+
+impl Trait for Bar {
+    type Assoc = impl std::fmt::Debug;
+    fn foo() -> Foo<Bar> {
+        Foo { field: () }
+        //~^ ERROR: mismatched types
+    }
+}
+
+struct Foo<T: Trait> {
+    field: <T as Trait>::Assoc,
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr
new file mode 100644
index 00000000000..648efd1cbfe
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/hidden_behind_projection_behind_struct_field.rs:19:22
+   |
+LL |     type Assoc = impl std::fmt::Debug;
+   |                  -------------------- the expected opaque type
+LL |     fn foo() -> Foo<Bar> {
+LL |         Foo { field: () }
+   |                      ^^ expected opaque type, found `()`
+   |
+   = note: expected opaque type `<Bar as Trait>::Assoc`
+                found unit type `()`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/hidden_behind_projection_behind_struct_field.rs:18:8
+   |
+LL |     fn foo() -> Foo<Bar> {
+   |        ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field.rs b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field.rs
new file mode 100644
index 00000000000..58778702de6
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field.rs
@@ -0,0 +1,30 @@
+//! This test shows that the appearance of an opaque type
+//! in the substs of a struct are enough to make it count
+//! for making the function a defining use. It doesn't matter
+//! if the opaque type is actually used in the field.
+
+#![feature(impl_trait_in_assoc_type)]
+// check-pass
+
+use std::marker::PhantomData;
+
+struct Bar;
+
+trait Trait: Sized {
+    type Assoc;
+    fn foo() -> Foo<Self::Assoc>;
+}
+
+impl Trait for Bar {
+    type Assoc = impl std::fmt::Debug;
+    fn foo() -> Foo<Self::Assoc> {
+        let foo: Foo<()> = Foo { field: PhantomData };
+        foo
+    }
+}
+
+struct Foo<T> {
+    field: PhantomData<T>,
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs
new file mode 100644
index 00000000000..e440dce5e51
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs
@@ -0,0 +1,26 @@
+//! This test shows that we can even follow projections
+//! into associated types of the same impl if they are
+//! indirectly mentioned in a struct field.
+
+#![feature(impl_trait_in_assoc_type)]
+// check-pass
+
+struct Bar;
+
+trait Trait: Sized {
+    type Assoc;
+    fn foo() -> Foo;
+}
+
+impl Trait for Bar {
+    type Assoc = impl std::fmt::Debug;
+    fn foo() -> Foo {
+        Foo { field: () }
+    }
+}
+
+struct Foo {
+    field: <Bar as Trait>::Assoc,
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
new file mode 100644
index 00000000000..839a611cb71
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
@@ -0,0 +1,35 @@
+//! This test checks that we can't actually have an opaque type behind
+//! a binder that references variables from that binder.
+
+// edition: 2021
+
+#![feature(type_alias_impl_trait)]
+
+trait B {
+    type C;
+}
+
+struct A;
+
+impl<'a> B for &'a A {
+    type C = Tait<'a>;
+}
+
+type Tait<'a> = impl std::fmt::Debug + 'a;
+
+struct Terminator;
+
+type Successors<'a> = impl std::fmt::Debug + 'a;
+
+impl Terminator {
+    fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
+        f = g;
+        //~^ ERROR: mismatched types
+    }
+}
+
+fn g(x: &()) -> &() {
+    x
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
new file mode 100644
index 00000000000..aaba9ad5ca7
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/higher_kinded_params3.rs:26:9
+   |
+LL | type Tait<'a> = impl std::fmt::Debug + 'a;
+   |                 ------------------------- the expected opaque type
+...
+LL |         f = g;
+   |         ^^^^^ one type is more general than the other
+   |
+   = note: expected fn pointer `for<'x> fn(&'x ()) -> Tait<'x>`
+              found fn pointer `for<'a> fn(&'a ()) -> &'a ()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.rs b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.rs
new file mode 100644
index 00000000000..a3f65146f75
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.rs
@@ -0,0 +1,28 @@
+#![feature(impl_trait_in_assoc_type)]
+
+// We weren't checking that the trait and impl generics line up in the
+// normalization-shortcut code in `OpaqueTypeCollector`.
+
+use std::ops::Deref;
+
+trait Foo {
+    type Bar<'a>;
+
+    type Baz<'a>;
+
+    fn test<'a>() -> Self::Bar<'a>;
+}
+
+impl Foo for () {
+    type Bar<'a> = impl Deref<Target = Self::Baz<'a>>;
+
+    type Baz<T> = impl Sized;
+    //~^ ERROR type `Baz` has 1 type parameter but its trait declaration has 0 type parameters
+    //~| ERROR unconstrained opaque type
+
+    fn test<'a>() -> Self::Bar<'a> {
+        &()
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr
new file mode 100644
index 00000000000..13f5d8b8ea6
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr
@@ -0,0 +1,20 @@
+error[E0049]: type `Baz` has 1 type parameter but its trait declaration has 0 type parameters
+  --> $DIR/impl-trait-in-type-alias-with-bad-substs.rs:19:14
+   |
+LL |     type Baz<'a>;
+   |              -- expected 0 type parameters
+...
+LL |     type Baz<T> = impl Sized;
+   |              ^ found 1 type parameter
+
+error: unconstrained opaque type
+  --> $DIR/impl-trait-in-type-alias-with-bad-substs.rs:19:19
+   |
+LL |     type Baz<T> = impl Sized;
+   |                   ^^^^^^^^^^
+   |
+   = note: `Baz` must be used in combination with a concrete type within the same impl
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0049`.
diff --git a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr
index 2beed73cb85..6ec5d13f812 100644
--- a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr
+++ b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr
@@ -12,10 +12,10 @@ LL |         let x: Self::Foo = ();
    = note: expected opaque type `<() as Foo>::Foo`
                 found unit type `()`
 note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/invalid_impl_trait_in_assoc_ty.rs:10:5
+  --> $DIR/invalid_impl_trait_in_assoc_ty.rs:10:8
    |
 LL |     fn bar() {
-   |     ^^^^^^^^
+   |        ^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/type-alias-impl-trait/multi-error.rs b/tests/ui/type-alias-impl-trait/multi-error.rs
new file mode 100644
index 00000000000..b5ff06572d0
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/multi-error.rs
@@ -0,0 +1,23 @@
+//! This test checks that we don't follow up
+//! with type mismatch errors of opaque types
+//! with their hidden types if we failed the
+//! defining scope check at the signature level.
+
+#![feature(impl_trait_in_assoc_type)]
+
+trait Foo {
+    type Bar<T>;
+    type Baz;
+    fn foo() -> (Self::Bar<u32>, Self::Baz);
+}
+
+impl Foo for () {
+    type Bar<T> = impl Sized;
+    type Baz = impl Sized;
+    fn foo() -> (Self::Bar<u32>, Self::Baz) {
+        //~^ ERROR non-defining opaque type use
+        ((), ())
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/multi-error.stderr b/tests/ui/type-alias-impl-trait/multi-error.stderr
new file mode 100644
index 00000000000..b2de2effea6
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/multi-error.stderr
@@ -0,0 +1,15 @@
+error[E0792]: non-defining opaque type use in defining scope
+  --> $DIR/multi-error.rs:17:17
+   |
+LL |     fn foo() -> (Self::Bar<u32>, Self::Baz) {
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument `u32` is not a generic parameter
+   |
+note: for this opaque type
+  --> $DIR/multi-error.rs:15:19
+   |
+LL |     type Bar<T> = impl Sized;
+   |                   ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/non-defining-method.rs b/tests/ui/type-alias-impl-trait/non-defining-method.rs
new file mode 100644
index 00000000000..2f4a7052f72
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/non-defining-method.rs
@@ -0,0 +1,21 @@
+//! This test checks that we don't follow up
+//! with type mismatch errors of opaque types
+//! with their hidden types if we failed the
+//! defining scope check at the signature level.
+
+#![feature(impl_trait_in_assoc_type)]
+
+trait Foo {
+    type Bar<T>;
+    fn foo() -> Self::Bar<u32>;
+    fn bar<T>() -> Self::Bar<T>;
+}
+
+impl Foo for () {
+    type Bar<T> = impl Sized;
+    fn foo() -> Self::Bar<u32> {}
+    //~^ ERROR non-defining opaque type use
+    fn bar<T>() -> Self::Bar<T> {}
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/non-defining-method.stderr b/tests/ui/type-alias-impl-trait/non-defining-method.stderr
new file mode 100644
index 00000000000..ed5590f9d71
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/non-defining-method.stderr
@@ -0,0 +1,15 @@
+error[E0792]: non-defining opaque type use in defining scope
+  --> $DIR/non-defining-method.rs:16:17
+   |
+LL |     fn foo() -> Self::Bar<u32> {}
+   |                 ^^^^^^^^^^^^^^ argument `u32` is not a generic parameter
+   |
+note: for this opaque type
+  --> $DIR/non-defining-method.rs:15:19
+   |
+LL |     type Bar<T> = impl Sized;
+   |                   ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
new file mode 100644
index 00000000000..dd2737c706d
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
@@ -0,0 +1,55 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/normalize-hidden-types.rs:25:20
+   |
+LL |     fn define() -> Opaque {
+   |                    ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
+   |
+note: previous use here
+  --> $DIR/normalize-hidden-types.rs:27:9
+   |
+LL |         dyn_hoops::<_>(0)
+   |         ^^^^^^^^^^^^^^^^^
+
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/normalize-hidden-types.rs:34:22
+   |
+LL |     fn define_1() -> Opaque { dyn_hoops::<_>(0) }
+   |                      ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
+   |
+note: previous use here
+  --> $DIR/normalize-hidden-types.rs:34:31
+   |
+LL |     fn define_1() -> Opaque { dyn_hoops::<_>(0) }
+   |                               ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/normalize-hidden-types.rs:44:25
+   |
+LL |     type Opaque = impl Sized;
+   |                   ---------- the expected opaque type
+...
+LL |         let _: Opaque = dyn_hoops::<u8>(0);
+   |                ------   ^^^^^^^^^^^^^^^^^^ expected opaque type, found `*const dyn FnOnce(())`
+   |                |
+   |                expected due to this
+   |
+   = note: expected opaque type `typeck::Opaque`
+              found raw pointer `*const (dyn FnOnce(()) + 'static)`
+   = help: consider constraining the associated type `<u8 as Trait>::Gat<'_>` to `()` or calling a method that returns `<u8 as Trait>::Gat<'_>`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/normalize-hidden-types.rs:54:25
+   |
+LL |         let _: Opaque = dyn_hoops::<_>(0);
+   |                         ^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
+   |
+note: previous use here
+  --> $DIR/normalize-hidden-types.rs:56:9
+   |
+LL |         None
+   |         ^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs b/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs
new file mode 100644
index 00000000000..8d80546444a
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs
@@ -0,0 +1,60 @@
+// Regression test for #112691
+//
+// revisions: current next
+// [next] compile-flags: -Ztrait-solver=next
+// [next] check-pass
+// [current]: known-bug: #112691
+
+#![feature(type_alias_impl_trait)]
+
+trait Trait {
+    type Gat<'lt>;
+}
+
+impl Trait for u8 {
+    type Gat<'lt> = ();
+}
+
+fn dyn_hoops<T: Trait>(_: T) -> *const dyn FnOnce(T::Gat<'_>) {
+    loop {}
+}
+
+mod typeof_1 {
+    use super::*;
+    type Opaque = impl Sized;
+    fn define() -> Opaque {
+        //[current]~^ ERROR concrete type differs
+        dyn_hoops::<_>(0)
+    }
+}
+
+mod typeof_2 {
+    use super::*;
+    type Opaque = impl Sized;
+    fn define_1() -> Opaque { dyn_hoops::<_>(0) }
+    //[current]~^ ERROR concrete type differs
+    fn define_2() -> Opaque { dyn_hoops::<u8>(0) }
+}
+
+mod typeck {
+    use super::*;
+    type Opaque = impl Sized;
+    fn define() -> Option<Opaque> {
+        let _: Opaque = dyn_hoops::<_>(0);
+        let _: Opaque = dyn_hoops::<u8>(0);
+        //[current]~^ ERROR mismatched types
+        None
+    }
+}
+
+mod borrowck {
+    use super::*;
+    type Opaque = impl Sized;
+    fn define() -> Option<Opaque> {
+        let _: Opaque = dyn_hoops::<_>(0);
+        //[current]~^ ERROR concrete type differs
+        None
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.rs b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.rs
new file mode 100644
index 00000000000..131f8d999d8
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.rs
@@ -0,0 +1,33 @@
+#![feature(impl_trait_in_assoc_type)]
+
+trait Foo<T> {
+    type Assoc;
+
+    fn test() -> u32;
+}
+
+struct DefinesOpaque;
+impl Foo<DefinesOpaque> for () {
+    type Assoc = impl Sized;
+
+    // This test's return type is `u32`, *not* the opaque that is defined above.
+    // Previously we were only checking that the self type of the assoc matched,
+    // but this doesn't account for other impls with different trait substs.
+    fn test() -> <() as Foo<NoOpaques>>::Assoc {
+        let _: <Self as Foo<DefinesOpaque>>::Assoc = "";
+        //~^ ERROR mismatched types
+
+        1
+    }
+}
+
+struct NoOpaques;
+impl Foo<NoOpaques> for () {
+    type Assoc = u32;
+
+    fn test() -> u32 {
+        1
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr
new file mode 100644
index 00000000000..a621bb519cd
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/not-matching-trait-refs-isnt-defining.rs:17:54
+   |
+LL |     type Assoc = impl Sized;
+   |                  ---------- the expected opaque type
+...
+LL |         let _: <Self as Foo<DefinesOpaque>>::Assoc = "";
+   |                -----------------------------------   ^^ expected opaque type, found `&str`
+   |                |
+   |                expected due to this
+   |
+   = note: expected opaque type `<() as Foo<DefinesOpaque>>::Assoc`
+                found reference `&'static str`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/not-matching-trait-refs-isnt-defining.rs:16:8
+   |
+LL |     fn test() -> <() as Foo<NoOpaques>>::Assoc {
+   |        ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.stderr b/tests/ui/type-alias-impl-trait/unnameable_type.stderr
index 24f5cc8c733..e9032433494 100644
--- a/tests/ui/type-alias-impl-trait/unnameable_type.stderr
+++ b/tests/ui/type-alias-impl-trait/unnameable_type.stderr
@@ -25,11 +25,6 @@ LL |         fn dont_define_this(_private: Private) {}
    |                                       ^^^^^^^
    = note: expected signature `fn(Private)`
               found signature `fn(MyPrivate)`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/unnameable_type.rs:20:5
-   |
-LL |     fn dont_define_this(_private: MyPrivate) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/use/use-keyword.rs b/tests/ui/use/use-keyword.rs
index c30c2e06c45..840cddcb907 100644
--- a/tests/ui/use/use-keyword.rs
+++ b/tests/ui/use/use-keyword.rs
@@ -1,4 +1,4 @@
-// Check that imports with nakes super and self don't fail during parsing
+// Check that imports with naked super and self don't fail during parsing
 // FIXME: this shouldn't fail during name resolution either
 
 mod a {
diff --git a/tests/ui/xcrate/xcrate-private-by-default.stderr b/tests/ui/xcrate/xcrate-private-by-default.stderr
index 0bdd4002f40..25bbbf5f62a 100644
--- a/tests/ui/xcrate/xcrate-private-by-default.stderr
+++ b/tests/ui/xcrate/xcrate-private-by-default.stderr
@@ -62,7 +62,9 @@ error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:35:29
    |
 LL |     static_priv_by_default::foo::a;
-   |                             ^^^ private module
+   |                             ^^^  - static `a` is not publicly re-exported
+   |                             |
+   |                             private module
    |
 note: the module `foo` is defined here
   --> $DIR/auxiliary/static_priv_by_default.rs:12:1
@@ -74,7 +76,9 @@ error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:37:29
    |
 LL |     static_priv_by_default::foo::b;
-   |                             ^^^ private module
+   |                             ^^^  - function `b` is not publicly re-exported
+   |                             |
+   |                             private module
    |
 note: the module `foo` is defined here
   --> $DIR/auxiliary/static_priv_by_default.rs:12:1
@@ -86,7 +90,9 @@ error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:39:29
    |
 LL |     static_priv_by_default::foo::c;
-   |                             ^^^ private module
+   |                             ^^^  - unit struct `c` is not publicly re-exported
+   |                             |
+   |                             private module
    |
 note: the module `foo` is defined here
   --> $DIR/auxiliary/static_priv_by_default.rs:12:1
@@ -98,7 +104,9 @@ error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:41:35
    |
 LL |     foo::<static_priv_by_default::foo::d>();
-   |                                   ^^^ private module
+   |                                   ^^^  - enum `d` is not publicly re-exported
+   |                                   |
+   |                                   private module
    |
 note: the module `foo` is defined here
   --> $DIR/auxiliary/static_priv_by_default.rs:12:1
@@ -110,7 +118,9 @@ error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:43:35
    |
 LL |     foo::<static_priv_by_default::foo::e>();
-   |                                   ^^^ private module
+   |                                   ^^^  - type alias `e` is not publicly re-exported
+   |                                   |
+   |                                   private module
    |
 note: the module `foo` is defined here
   --> $DIR/auxiliary/static_priv_by_default.rs:12:1