about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--RELEASES.md1
-rw-r--r--compiler/rustc_ast/src/ast.rs16
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs1
-rw-r--r--compiler/rustc_ast/src/visit.rs1
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl12
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs22
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs68
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs38
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs14
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs29
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs12
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs3
-rw-r--r--compiler/rustc_codegen_gcc/Cargo.lock26
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs115
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs7
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs6
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs10
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs2
-rw-r--r--compiler/rustc_data_structures/src/lib.rs2
-rw-r--r--compiler/rustc_data_structures/src/sharded.rs3
-rw-r--r--compiler/rustc_data_structures/src/sync.rs65
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs2
-rw-r--r--compiler/rustc_error_messages/src/lib.rs2
-rw-r--r--compiler/rustc_expand/src/build.rs2
-rw-r--r--compiler/rustc_expand/src/proc_macro.rs10
-rw-r--r--compiler/rustc_feature/src/active.rs4
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs4
-rw-r--r--compiler/rustc_feature/src/lib.rs2
-rw-r--r--compiler/rustc_hir/src/definitions.rs6
-rw-r--r--compiler/rustc_hir/src/hir.rs22
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl11
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs204
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs56
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs28
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs8
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs100
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs20
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/intrinsicck.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs11
-rw-r--r--compiler/rustc_index/src/vec.rs230
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs3
-rw-r--r--compiler/rustc_interface/src/interface.rs2
-rw-r--r--compiler/rustc_interface/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/types.rs2
-rw-r--r--compiler/rustc_macros/src/diagnostics/fluent.rs23
-rw-r--r--compiler/rustc_metadata/src/lib.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs11
-rw-r--r--compiler/rustc_middle/src/hir/place.rs4
-rw-r--r--compiler/rustc_middle/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs6
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs20
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs1
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs2
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs4
-rw-r--r--compiler/rustc_middle/src/thir.rs2
-rw-r--r--compiler/rustc_middle/src/ty/adjustment.rs3
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs8
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs10
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs6
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs15
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs4
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs11
-rw-r--r--compiler/rustc_middle/src/ty/util.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs2
-rw-r--r--compiler/rustc_mir_build/src/lib.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs6
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs6
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs1
-rw-r--r--compiler/rustc_mir_transform/src/check_alignment.rs227
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_box_derefs.rs5
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs3
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs13
-rw-r--r--compiler/rustc_parse/messages.ftl4
-rw-r--r--compiler/rustc_parse/src/errors.rs8
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs3
-rw-r--r--compiler/rustc_parse/src/parser/path.rs31
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs7
-rw-r--r--compiler/rustc_passes/messages.ftl3
-rw-r--r--compiler/rustc_passes/src/check_attr.rs11
-rw-r--r--compiler/rustc_passes/src/dead.rs3
-rw-r--r--compiler/rustc_passes/src/errors.rs4
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs3
-rw-r--r--compiler/rustc_query_impl/src/lib.rs1
-rw-r--r--compiler/rustc_query_system/src/query/caches.rs3
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs70
-rw-r--r--compiler/rustc_resolve/src/late.rs1
-rw-r--r--compiler/rustc_resolve/src/lib.rs1
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs8
-rw-r--r--compiler/rustc_session/src/filesearch.rs44
-rw-r--r--compiler/rustc_session/src/lib.rs2
-rw-r--r--compiler/rustc_span/src/lib.rs23
-rw-r--r--compiler/rustc_span/src/profiling.rs16
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonicalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs102
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs61
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs17
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs1
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs35
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs5
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs4
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs20
-rw-r--r--library/alloc/src/str.rs4
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/core/src/cell.rs97
-rw-r--r--library/core/src/cell/lazy.rs18
-rw-r--r--library/core/src/cell/once.rs52
-rw-r--r--library/core/src/panicking.rs14
-rw-r--r--library/core/src/primitive_docs.rs75
-rw-r--r--library/core/src/slice/mod.rs20
-rw-r--r--library/core/src/str/mod.rs1
-rw-r--r--library/core/tests/lib.rs2
-rw-r--r--library/std/src/lib.rs2
-rw-r--r--library/std/src/primitive_docs.rs75
-rw-r--r--library/std/src/sync/lazy_lock.rs24
-rw-r--r--library/std/src/sync/mod.rs9
-rw-r--r--library/std/src/sync/once_lock.rs59
-rw-r--r--library/std/src/sys/unix/time.rs50
-rw-r--r--src/bootstrap/llvm.rs5
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rw-r--r--src/doc/rustc/src/platform-support/openharmony.md2
-rw-r--r--src/doc/rustdoc/src/unstable-features.md6
-rw-r--r--src/librustdoc/clean/mod.rs3
-rw-r--r--src/librustdoc/clean/types.rs44
-rw-r--r--src/librustdoc/core.rs3
-rw-r--r--src/librustdoc/html/static/js/main.js4
-rw-r--r--src/librustdoc/json/conversions.rs4
-rw-r--r--src/librustdoc/json/mod.rs2
-rw-r--r--src/librustdoc/lib.rs2
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs390
-rw-r--r--src/tools/clippy/clippy_dev/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/ref_option_ref.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/types/borrowed_box.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/utils.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs5
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs7
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs1
-rw-r--r--src/tools/clippy/src/driver.rs2
-rw-r--r--src/tools/clippy/tests/compile-test.rs2
-rw-r--r--src/tools/clippy/tests/dogfood.rs2
-rw-r--r--src/tools/clippy/tests/lint_message_convention.rs2
-rw-r--r--src/tools/clippy/tests/workspace.rs2
-rw-r--r--src/tools/compiletest/src/main.rs37
-rw-r--r--src/tools/miri/src/shims/panic.rs28
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/alignment.rs1
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.rs2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/intptrcast_alignment_check.rs2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.rs2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr1.rs2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr2.rs2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr3.rs2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr4.rs2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr_addr_of.rs2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr_zst.rs2
-rw-r--r--src/tools/miri/tests/panic/alignment-assertion.rs9
-rw-r--r--src/tools/miri/tests/panic/alignment-assertion.stderr2
-rw-r--r--src/tools/miri/tests/pass/disable-alignment-check.rs2
-rw-r--r--tests/assembly/static-relocation-model.rs1
-rw-r--r--tests/codegen/issues/issue-37945.rs1
-rw-r--r--tests/codegen/virtual-function-elimination.rs1
-rw-r--r--tests/mir-opt/inline/inline_into_box_place.main.Inline.diff8
-rw-r--r--tests/mir-opt/inline/inline_into_box_place.rs1
-rw-r--r--tests/run-make/fmt-write-bloat/Makefile4
-rw-r--r--tests/run-make/libtest-thread-limit/test.rs2
-rw-r--r--tests/rustdoc-gui/go-to-collapsed-elem.goml21
-rw-r--r--tests/rustdoc-json/impls/local_for_local_primitive.rs4
-rw-r--r--tests/rustdoc-json/primitives/local_primitive.rs2
-rw-r--r--tests/rustdoc-json/primitives/primitive_impls.rs2
-rw-r--r--tests/rustdoc-json/primitives/primitive_overloading.rs4
-rw-r--r--tests/rustdoc-json/primitives/use_primitive.rs4
-rw-r--r--tests/rustdoc-ui/const_arg_in_type_position.rs6
-rw-r--r--tests/rustdoc-ui/const_arg_in_type_position.stderr9
-rw-r--r--tests/rustdoc-ui/coverage/exotic.rs3
-rw-r--r--tests/rustdoc-ui/intra-doc/ambiguity.rs2
-rw-r--r--tests/rustdoc-ui/intra-doc/ambiguity.stderr54
-rw-r--r--tests/rustdoc-ui/intra-doc/errors.rs4
-rw-r--r--tests/rustdoc-ui/intra-doc/errors.stderr4
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-10.rs22
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-2.rs17
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-2.stderr37
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-3.rs16
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-3.stderr37
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-4.rs21
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-4.stderr22
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-5.rs8
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-5.stderr22
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-6.rs8
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-6.stderr22
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-7.rs12
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-7.stderr22
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-8.rs12
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-8.stderr22
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items-9.rs11
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items.rs35
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-108653-associated-items.stderr67
-rw-r--r--tests/rustdoc-ui/intra-doc/non-path-primitives.stderr8
-rw-r--r--tests/rustdoc-ui/intra-doc/prim-conflict.rs10
-rw-r--r--tests/rustdoc-ui/intra-doc/prim-conflict.stderr12
-rw-r--r--tests/rustdoc-ui/invalid_associated_const.rs10
-rw-r--r--tests/rustdoc-ui/invalid_associated_const.stderr9
-rw-r--r--tests/rustdoc-ui/invalid_const_in_lifetime_position.rs6
-rw-r--r--tests/rustdoc-ui/invalid_const_in_lifetime_position.stderr33
-rw-r--r--tests/rustdoc-ui/invalid_infered_static_and_const.rs2
-rw-r--r--tests/rustdoc-ui/invalid_infered_static_and_const.stderr15
-rw-r--r--tests/rustdoc-ui/issue-105742.rs37
-rw-r--r--tests/rustdoc-ui/issue-105742.stderr331
-rw-r--r--tests/rustdoc-ui/issue-106226.stderr8
-rw-r--r--tests/rustdoc-ui/issue-79465.rs1
-rw-r--r--tests/rustdoc-ui/issue-79465.stderr8
-rw-r--r--tests/rustdoc-ui/issue-96287.rs1
-rw-r--r--tests/rustdoc-ui/issue-96287.stderr8
-rw-r--r--tests/rustdoc-ui/mismatched_arg_count.rs8
-rw-r--r--tests/rustdoc-ui/mismatched_arg_count.stderr17
-rw-r--r--tests/rustdoc/auto-impl-primitive.rs4
-rw-r--r--tests/rustdoc/auxiliary/issue-15318.rs3
-rw-r--r--tests/rustdoc/auxiliary/primitive-doc.rs3
-rw-r--r--tests/rustdoc/check-source-code-urls-to-def.rs4
-rw-r--r--tests/rustdoc/intra-doc/auxiliary/my-core.rs2
-rw-r--r--tests/rustdoc/intra-doc/no-doc-primitive.rs2
-rw-r--r--tests/rustdoc/intra-doc/prim-methods-local.rs2
-rw-r--r--tests/rustdoc/intra-doc/prim-self.rs2
-rw-r--r--tests/rustdoc/issue-15318-3.rs4
-rw-r--r--tests/rustdoc/issue-23511.rs2
-rw-r--r--tests/rustdoc/notable-trait/doc-notable_trait-mut_t_is_not_an_iterator.rs4
-rw-r--r--tests/rustdoc/notable-trait/doc-notable_trait-mut_t_is_not_ref_t.rs4
-rw-r--r--tests/rustdoc/primitive-reference.rs4
-rw-r--r--tests/rustdoc/primitive-slice-auto-trait.rs4
-rw-r--r--tests/rustdoc/primitive-tuple-auto-trait.rs4
-rw-r--r--tests/rustdoc/primitive-unit-auto-trait.rs4
-rw-r--r--tests/rustdoc/primitive/primitive-generic-impl.rs4
-rw-r--r--tests/rustdoc/primitive/primitive.rs (renamed from tests/rustdoc/primitive.rs)6
-rw-r--r--tests/rustdoc/sidebar-all-page.rs4
-rw-r--r--tests/rustdoc/tab_title.rs3
-rw-r--r--tests/rustdoc/titles.rs4
-rw-r--r--tests/ui-fulldeps/fluent-messages/test.rs2
-rw-r--r--tests/ui-fulldeps/fluent-messages/test.stderr14
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs20
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr37
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/basic.rs28
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/basic.with.stderr19
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr37
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/equality.rs16
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/equality.stderr25
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/missing.rs14
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/missing.stderr25
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs11
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr22
-rw-r--r--tests/ui/attributes/no-mangle-closure.rs11
-rw-r--r--tests/ui/attributes/no-mangle-closure.stderr8
-rw-r--r--tests/ui/closures/2229_closure_analysis/array_subslice.rs13
-rw-r--r--tests/ui/closures/2229_closure_analysis/array_subslice.stderr26
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr21
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr21
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.rs15
-rw-r--r--tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs7
-rw-r--r--tests/ui/impl-trait/in-trait/doesnt-satisfy.next.stderr2
-rw-r--r--tests/ui/impl-trait/in-trait/foreign.rs14
-rw-r--r--tests/ui/impl-trait/in-trait/nested-rpitit.rs2
-rw-r--r--tests/ui/impl-trait/multiple-lifetimes/multiple-lifetimes.rs (renamed from tests/ui/impl-trait/multiple-lifetimes.rs)0
-rw-r--r--tests/ui/mir/mir_alignment_check.rs12
-rw-r--r--tests/ui/modules_and_files_visibility/mod_file_disambig_aux/compiletest-ignore-dir0
-rw-r--r--tests/ui/non_modrs_mods_and_inline_mods/x/y/z/compiletest-ignore-dir0
-rw-r--r--tests/ui/privacy/effective_visibilities.rs1
-rw-r--r--tests/ui/privacy/effective_visibilities.stderr60
-rw-r--r--tests/ui/process/signal-exit-status.rs6
-rw-r--r--tests/ui/rfc-1937-termination-trait/issue-103052-2.current.stderr (renamed from tests/ui/rfc-1937-termination-trait/issue-103052-2.stderr)4
-rw-r--r--tests/ui/rfc-1937-termination-trait/issue-103052-2.next.stderr15
-rw-r--r--tests/ui/rfc-1937-termination-trait/issue-103052-2.rs6
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/nested-closure.rs2
-rw-r--r--tests/ui/rustdoc/doc-primitive.rs8
-rw-r--r--tests/ui/rustdoc/doc-primitive.stderr16
-rw-r--r--tests/ui/rustdoc/feature-gate-doc_primitive.rs6
-rw-r--r--tests/ui/rustdoc/feature-gate-doc_primitive.stderr15
-rw-r--r--tests/ui/sync/suggest-once-cell.rs2
-rw-r--r--tests/ui/sync/suggest-once-cell.stderr4
-rw-r--r--tests/ui/sync/suggest-ref-cell.rs2
-rw-r--r--tests/ui/sync/suggest-ref-cell.stderr4
-rw-r--r--tests/ui/traits/new-solver/closure-inference-guidance.rs11
-rw-r--r--tests/ui/traits/new-solver/const-param-placeholder.fail.stderr16
-rw-r--r--tests/ui/traits/new-solver/const-param-placeholder.rs21
-rw-r--r--tests/ui/traits/new-solver/float-canonical.rs8
-rw-r--r--tests/ui/traits/new-solver/param-discr-kind.rs8
-rw-r--r--tests/ui/traits/new-solver/pointee.rs18
-rw-r--r--tests/ui/traits/new-solver/projection-discr-kind.rs18
-rw-r--r--tests/ui/traits/new-solver/projection-discr-kind.stderr17
-rw-r--r--tests/ui/use/use-mod/use-mod.rs (renamed from tests/ui/use/use-mod.rs)0
-rw-r--r--tests/ui/use/use-mod/use-mod.stderr (renamed from tests/ui/use/use-mod.stderr)0
-rw-r--r--tests/ui/use/use.rs (renamed from tests/ui/use.rs)0
317 files changed, 3854 insertions, 1291 deletions
diff --git a/RELEASES.md b/RELEASES.md
index e453b8d6891..b923f87abfd 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -94,6 +94,7 @@ Misc
 Compatibility Notes
 -------------------
 
+- [Only support Android NDK 25 or newer](https://blog.rust-lang.org/2023/01/09/android-ndk-update-r25.html)
 - [Add `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` to future-incompat report](https://github.com/rust-lang/rust/pull/103418/)
 - [Only specify `--target` by default for `-Zgcc-ld=lld` on wasm](https://github.com/rust-lang/rust/pull/101792/)
 - [Bump `IMPLIED_BOUNDS_ENTAILMENT` to Deny + ReportNow](https://github.com/rust-lang/rust/pull/106465/)
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index cc0fc7b8358..9b6bfaadef0 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -167,6 +167,9 @@ pub enum GenericArgs {
     AngleBracketed(AngleBracketedArgs),
     /// The `(A, B)` and `C` in `Foo(A, B) -> C`.
     Parenthesized(ParenthesizedArgs),
+    /// Associated return type bounds, like `T: Trait<method(..): Send>`
+    /// which applies the `Send` bound to the return-type of `method`.
+    ReturnTypeNotation(Span),
 }
 
 impl GenericArgs {
@@ -178,6 +181,7 @@ impl GenericArgs {
         match self {
             AngleBracketed(data) => data.span,
             Parenthesized(data) => data.span,
+            ReturnTypeNotation(span) => *span,
         }
     }
 }
@@ -231,15 +235,15 @@ impl AngleBracketedArg {
     }
 }
 
-impl Into<Option<P<GenericArgs>>> for AngleBracketedArgs {
-    fn into(self) -> Option<P<GenericArgs>> {
-        Some(P(GenericArgs::AngleBracketed(self)))
+impl Into<P<GenericArgs>> for AngleBracketedArgs {
+    fn into(self) -> P<GenericArgs> {
+        P(GenericArgs::AngleBracketed(self))
     }
 }
 
-impl Into<Option<P<GenericArgs>>> for ParenthesizedArgs {
-    fn into(self) -> Option<P<GenericArgs>> {
-        Some(P(GenericArgs::Parenthesized(self)))
+impl Into<P<GenericArgs>> for ParenthesizedArgs {
+    fn into(self) -> P<GenericArgs> {
+        P(GenericArgs::Parenthesized(self))
     }
 }
 
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 46e46ab575e..514978f5569 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -561,6 +561,7 @@ pub fn noop_visit_generic_args<T: MutVisitor>(generic_args: &mut GenericArgs, vi
     match generic_args {
         GenericArgs::AngleBracketed(data) => vis.visit_angle_bracketed_parameter_data(data),
         GenericArgs::Parenthesized(data) => vis.visit_parenthesized_parameter_data(data),
+        GenericArgs::ReturnTypeNotation(_span) => {}
     }
 }
 
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 608f87ab6eb..e5a0ad1f1e4 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -481,6 +481,7 @@ where
             walk_list!(visitor, visit_ty, &data.inputs);
             walk_fn_ret_ty(visitor, &data.output);
         }
+        GenericArgs::ReturnTypeNotation(_span) => {}
     }
 }
 
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index 3ccd84398ec..21b2a3c22fa 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -139,3 +139,15 @@ ast_lowering_trait_fn_async =
     .label = `async` because of this
     .note = `async` trait functions are not currently supported
     .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait
+
+ast_lowering_bad_return_type_notation_inputs =
+    argument types not allowed with return type notation
+    .suggestion = remove the input types
+
+ast_lowering_bad_return_type_notation_needs_dots =
+    return type notation arguments must be elided with `..`
+    .suggestion = add `..`
+
+ast_lowering_bad_return_type_notation_output =
+    return type not allowed with return type notation
+    .suggestion = remove the return type
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 5e6b6050bc0..f4e55619ebb 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -347,3 +347,25 @@ pub struct TraitFnAsync {
     #[label]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+pub enum BadReturnTypeNotation {
+    #[diag(ast_lowering_bad_return_type_notation_inputs)]
+    Inputs {
+        #[primary_span]
+        #[suggestion(code = "(..)", applicability = "maybe-incorrect")]
+        span: Span,
+    },
+    #[diag(ast_lowering_bad_return_type_notation_needs_dots)]
+    NeedsDots {
+        #[primary_span]
+        #[suggestion(code = "(..)", applicability = "maybe-incorrect")]
+        span: Span,
+    },
+    #[diag(ast_lowering_bad_return_type_notation_output)]
+    Output {
+        #[primary_span]
+        #[suggestion(code = "", applicability = "maybe-incorrect")]
+        span: Span,
+    },
+}
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 0b6b02ba00f..c5d39634c44 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -66,7 +66,7 @@ use rustc_middle::{
     span_bug,
     ty::{ResolverAstLowering, TyCtxt},
 };
-use rustc_session::parse::feature_err;
+use rustc_session::parse::{add_feature_diagnostics, feature_err};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -482,7 +482,7 @@ enum ParamMode {
 }
 
 enum ParenthesizedGenericArgs {
-    Ok,
+    ParenSugar,
     Err,
 }
 
@@ -987,14 +987,56 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 GenericArgs::AngleBracketed(data) => {
                     self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0
                 }
+                &GenericArgs::ReturnTypeNotation(span) => GenericArgsCtor {
+                    args: Default::default(),
+                    bindings: &[],
+                    parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
+                    span,
+                },
                 GenericArgs::Parenthesized(data) => {
-                    self.emit_bad_parenthesized_trait_in_assoc_ty(data);
-                    self.lower_angle_bracketed_parameter_data(
-                        &data.as_angle_bracketed_args(),
-                        ParamMode::Explicit,
-                        itctx,
-                    )
-                    .0
+                    if let Some(start_char) = constraint.ident.as_str().chars().next()
+                        && start_char.is_ascii_lowercase()
+                    {
+                        let mut err = if !data.inputs.is_empty() {
+                            self.tcx.sess.create_err(errors::BadReturnTypeNotation::Inputs {
+                                span: data.inputs_span,
+                            })
+                        } else if let FnRetTy::Ty(ty) = &data.output {
+                            self.tcx.sess.create_err(errors::BadReturnTypeNotation::Output {
+                                span: data.inputs_span.shrink_to_hi().to(ty.span),
+                            })
+                        } else {
+                            self.tcx.sess.create_err(errors::BadReturnTypeNotation::NeedsDots {
+                                span: data.inputs_span,
+                            })
+                        };
+                        if !self.tcx.features().return_type_notation
+                            && self.tcx.sess.is_nightly_build()
+                        {
+                            add_feature_diagnostics(
+                                &mut err,
+                                &self.tcx.sess.parse_sess,
+                                sym::return_type_notation,
+                            );
+                        }
+                        err.emit();
+                        GenericArgsCtor {
+                            args: Default::default(),
+                            bindings: &[],
+                            parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
+                            span: data.span,
+                        }
+                    } else {
+                        self.emit_bad_parenthesized_trait_in_assoc_ty(data);
+                        // FIXME(return_type_notation): we could issue a feature error
+                        // if the parens are empty and there's no return type.
+                        self.lower_angle_bracketed_parameter_data(
+                            &data.as_angle_bracketed_args(),
+                            ParamMode::Explicit,
+                            itctx,
+                        )
+                        .0
+                    }
                 }
             };
             gen_args_ctor.into_generic_args(self)
@@ -2075,7 +2117,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let future_args = self.arena.alloc(hir::GenericArgs {
             args: &[],
             bindings: arena_vec![self; self.output_ty_binding(span, output_ty)],
-            parenthesized: false,
+            parenthesized: hir::GenericArgsParentheses::No,
             span_ext: DUMMY_SP,
         });
 
@@ -2595,13 +2637,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 struct GenericArgsCtor<'hir> {
     args: SmallVec<[hir::GenericArg<'hir>; 4]>,
     bindings: &'hir [hir::TypeBinding<'hir>],
-    parenthesized: bool,
+    parenthesized: hir::GenericArgsParentheses,
     span: Span,
 }
 
 impl<'hir> GenericArgsCtor<'hir> {
     fn is_empty(&self) -> bool {
-        self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized
+        self.args.is_empty()
+            && self.bindings.is_empty()
+            && self.parenthesized == hir::GenericArgsParentheses::No
     }
 
     fn into_generic_args(self, this: &LoweringContext<'_, 'hir>) -> &'hir hir::GenericArgs<'hir> {
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 592fc5aa645..1c47a969696 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -13,6 +13,7 @@ use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span, DUMMY_SP};
 
 use smallvec::{smallvec, SmallVec};
+use thin_vec::ThinVec;
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
     #[instrument(level = "trace", skip(self))]
@@ -51,7 +52,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     let parenthesized_generic_args = match base_res {
                         // `a::b::Trait(Args)`
                         Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
-                            ParenthesizedGenericArgs::Ok
+                            ParenthesizedGenericArgs::ParenSugar
                         }
                         // `a::b::Trait(Args)::TraitItem`
                         Res::Def(DefKind::AssocFn, _)
@@ -59,10 +60,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         | Res::Def(DefKind::AssocTy, _)
                             if i + 2 == proj_start =>
                         {
-                            ParenthesizedGenericArgs::Ok
+                            ParenthesizedGenericArgs::ParenSugar
                         }
                         // Avoid duplicated errors.
-                        Res::Err => ParenthesizedGenericArgs::Ok,
+                        Res::Err => ParenthesizedGenericArgs::ParenSugar,
                         // An error
                         _ => ParenthesizedGenericArgs::Err,
                     };
@@ -180,7 +181,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
                 }
                 GenericArgs::Parenthesized(data) => match parenthesized_generic_args {
-                    ParenthesizedGenericArgs::Ok => {
+                    ParenthesizedGenericArgs::ParenSugar => {
                         self.lower_parenthesized_parameter_data(data, itctx)
                     }
                     ParenthesizedGenericArgs::Err => {
@@ -218,13 +219,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         )
                     }
                 },
+                &GenericArgs::ReturnTypeNotation(span) => {
+                    self.tcx.sess.emit_err(GenericTypeWithParentheses { span, sub: None });
+                    (
+                        self.lower_angle_bracketed_parameter_data(
+                            &AngleBracketedArgs { span, args: ThinVec::default() },
+                            param_mode,
+                            itctx,
+                        )
+                        .0,
+                        false,
+                    )
+                }
             }
         } else {
             (
                 GenericArgsCtor {
                     args: Default::default(),
                     bindings: &[],
-                    parenthesized: false,
+                    parenthesized: hir::GenericArgsParentheses::No,
                     span: path_span.shrink_to_hi(),
                 },
                 param_mode == ParamMode::Optional,
@@ -233,7 +246,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let has_lifetimes =
             generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
-        if !generic_args.parenthesized && !has_lifetimes {
+
+        // FIXME(return_type_notation): Is this correct? I think so.
+        if generic_args.parenthesized != hir::GenericArgsParentheses::ParenSugar && !has_lifetimes {
             self.maybe_insert_elided_lifetimes_in_path(
                 path_span,
                 segment.id,
@@ -328,7 +343,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             AngleBracketedArg::Constraint(c) => Some(self.lower_assoc_ty_constraint(c, itctx)),
             AngleBracketedArg::Arg(_) => None,
         }));
-        let ctor = GenericArgsCtor { args, bindings, parenthesized: false, span: data.span };
+        let ctor = GenericArgsCtor {
+            args,
+            bindings,
+            parenthesized: hir::GenericArgsParentheses::No,
+            span: data.span,
+        };
         (ctor, !has_non_lt_args && param_mode == ParamMode::Optional)
     }
 
@@ -376,7 +396,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             GenericArgsCtor {
                 args,
                 bindings: arena_vec![self; binding],
-                parenthesized: true,
+                parenthesized: hir::GenericArgsParentheses::ParenSugar,
                 span: data.inputs_span,
             },
             false,
@@ -396,7 +416,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let gen_args = self.arena.alloc(hir::GenericArgs {
             args,
             bindings,
-            parenthesized: false,
+            parenthesized: hir::GenericArgsParentheses::No,
             span_ext: DUMMY_SP,
         });
         hir::TypeBinding {
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 93c854cc809..44b6c77fc41 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1075,6 +1075,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     self.with_impl_trait(None, |this| this.visit_ty(ty));
                 }
             }
+            GenericArgs::ReturnTypeNotation(_span) => {}
         }
     }
 
@@ -1387,16 +1388,19 @@ fn deny_equality_constraints(
                                     match &mut assoc_path.segments[len].args {
                                         Some(args) => match args.deref_mut() {
                                             GenericArgs::Parenthesized(_) => continue,
+                                            GenericArgs::ReturnTypeNotation(_span) => continue,
                                             GenericArgs::AngleBracketed(args) => {
                                                 args.args.push(arg);
                                             }
                                         },
                                         empty_args => {
-                                            *empty_args = AngleBracketedArgs {
-                                                span: ident.span,
-                                                args: thin_vec![arg],
-                                            }
-                                            .into();
+                                            *empty_args = Some(
+                                                AngleBracketedArgs {
+                                                    span: ident.span,
+                                                    args: thin_vec![arg],
+                                                }
+                                                .into(),
+                                            );
                                         }
                                     }
                                     err.assoc = Some(errors::AssociatedSuggestion {
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 344a1e7f5e7..de94c1bc477 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -482,12 +482,28 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
 
     fn visit_assoc_constraint(&mut self, constraint: &'a AssocConstraint) {
         if let AssocConstraintKind::Bound { .. } = constraint.kind {
-            gate_feature_post!(
-                &self,
-                associated_type_bounds,
-                constraint.span,
-                "associated type bounds are unstable"
-            )
+            if let Some(args) = constraint.gen_args.as_ref()
+                && matches!(
+                    args,
+                    ast::GenericArgs::ReturnTypeNotation(..) | ast::GenericArgs::Parenthesized(..)
+                )
+            {
+                // RTN is gated elsewhere, and parenthesized args will turn into
+                // another error.
+                if matches!(args, ast::GenericArgs::Parenthesized(..)) {
+                    self.sess.delay_span_bug(
+                        constraint.span,
+                        "should have emitted a parenthesized generics error",
+                    );
+                }
+            } else {
+                gate_feature_post!(
+                    &self,
+                    associated_type_bounds,
+                    constraint.span,
+                    "associated type bounds are unstable"
+                )
+            }
         }
         visit::walk_assoc_constraint(self, constraint)
     }
@@ -577,6 +593,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
     gate_all!(yeet_expr, "`do yeet` expression is experimental");
     gate_all!(dyn_star, "`dyn*` trait objects are experimental");
     gate_all!(const_closures, "const closures are experimental");
+    gate_all!(return_type_notation, "return type notation is experimental");
 
     // All uses of `gate_all!` below this point were added in #65742,
     // and subsequently disabled (with the non-early gating readded).
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 694d688bf1f..80c451d6753 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -936,6 +936,10 @@ impl<'a> PrintState<'a> for State<'a> {
                 self.word(")");
                 self.print_fn_ret_ty(&data.output);
             }
+
+            ast::GenericArgs::ReturnTypeNotation(_span) => {
+                self.word("(..)");
+            }
         }
     }
 }
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 5827fa81cff..da0456856ac 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -350,7 +350,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     if !including_tuple_field.0 && variant.ctor_kind() == Some(CtorKind::Fn) {
                         return None;
                     }
-                    Some(variant.fields[field.index()].name.to_string())
+                    Some(variant.fields[field].name.to_string())
                 }
                 ty::Tuple(_) => Some(field.index().to_string()),
                 ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 2f64ccee686..8b463a018a8 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -5,7 +5,7 @@
 #![feature(let_chains)]
 #![feature(min_specialization)]
 #![feature(never_type)]
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![feature(trusted_step)]
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 04da6d6beff..10bbce37760 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -854,7 +854,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
             },
         };
 
-        if let Some(field) = variant.fields.get(field.index()) {
+        if let Some(field) = variant.fields.get(field) {
             Ok(self.cx.normalize(field.ty(tcx, substs), location))
         } else {
             Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
@@ -1725,7 +1725,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             AggregateKind::Adt(adt_did, variant_index, substs, _, active_field_index) => {
                 let def = tcx.adt_def(adt_did);
                 let variant = &def.variant(variant_index);
-                let adj_field_index = active_field_index.unwrap_or(field_index);
+                let adj_field_index =
+                    FieldIdx::from_usize(active_field_index.unwrap_or(field_index));
                 if let Some(field) = variant.fields.get(adj_field_index) {
                     Ok(self.normalize(field.ty(tcx, substs), location))
                 } else {
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 615ef58ff58..98112fe0830 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -379,6 +379,18 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                             source_info.span,
                         );
                     }
+                    AssertKind::MisalignedPointerDereference { ref required, ref found } => {
+                        let required = codegen_operand(fx, required).load_scalar(fx);
+                        let found = codegen_operand(fx, found).load_scalar(fx);
+                        let location = fx.get_caller_location(source_info).load_scalar(fx);
+
+                        codegen_panic_inner(
+                            fx,
+                            rustc_hir::LangItem::PanicBoundsCheck,
+                            &[required, found, location],
+                            source_info.span,
+                        );
+                    }
                     _ => {
                         let msg_str = msg.description();
                         codegen_panic(fx, msg_str, source_info);
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index ffe3ccb0eca..1b69862ce2c 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -701,7 +701,8 @@ impl<'tcx> CPlace<'tcx> {
                     };
                 }
                 ty::Adt(adt_def, substs) if layout.ty.is_simd() => {
-                    let f0_ty = adt_def.non_enum_variant().fields[0].ty(fx.tcx, substs);
+                    let f0 = &adt_def.non_enum_variant().fields[FieldIdx::from_u32(0)];
+                    let f0_ty = f0.ty(fx.tcx, substs);
 
                     match f0_ty.kind() {
                         ty::Array(_, _) => {
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index 80e57418940..0f2e152f8ce 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#eefb8c662d61477f34b7c32d26bcda5f1ef08432"
+source = "git+https://github.com/antoyo/gccjit.rs#fe242b7eb26980e6c78859d51c8d4cc1e43381a3"
 dependencies = [
  "gccjit_sys",
 ]
@@ -43,9 +43,9 @@ dependencies = [
 [[package]]
 name = "gccjit_sys"
 version = "0.0.1"
-source = "git+https://github.com/antoyo/gccjit.rs#eefb8c662d61477f34b7c32d26bcda5f1ef08432"
+source = "git+https://github.com/antoyo/gccjit.rs#fe242b7eb26980e6c78859d51c8d4cc1e43381a3"
 dependencies = [
- "libc 0.1.12",
+ "libc",
 ]
 
 [[package]]
@@ -64,7 +64,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
 dependencies = [
  "cfg-if",
- "libc 0.2.112",
+ "libc",
  "wasi",
 ]
 
@@ -74,7 +74,7 @@ version = "0.1.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
 dependencies = [
- "libc 0.2.112",
+ "libc",
 ]
 
 [[package]]
@@ -85,7 +85,7 @@ checksum = "96bd995a092cac79868250589869b5a5d656b02a02bd74c8ebdc566dc7203090"
 dependencies = [
  "fm",
  "getopts",
- "libc 0.2.112",
+ "libc",
  "num_cpus",
  "termcolor",
  "threadpool",
@@ -95,12 +95,6 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.1.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
-
-[[package]]
-name = "libc"
 version = "0.2.112"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
@@ -118,7 +112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
 dependencies = [
  "hermit-abi",
- "libc 0.2.112",
+ "libc",
 ]
 
 [[package]]
@@ -133,7 +127,7 @@ version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
 dependencies = [
- "libc 0.2.112",
+ "libc",
  "rand_chacha",
  "rand_core",
  "rand_hc",
@@ -234,7 +228,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
 dependencies = [
  "cfg-if",
- "libc 0.2.112",
+ "libc",
  "rand",
  "redox_syscall",
  "remove_dir_all",
@@ -271,7 +265,7 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
 dependencies = [
- "libc 0.2.112",
+ "libc",
 ]
 
 [[package]]
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index 3e4765fba57..c3439591b92 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -274,7 +274,8 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
                 .map(|field_index| {
                     let field_name = if variant_def.ctor_kind() != Some(CtorKind::Fn) {
                         // Fields have names
-                        Cow::from(variant_def.fields[field_index].name.as_str())
+                        let field = &variant_def.fields[FieldIdx::from_usize(field_index)];
+                        Cow::from(field.name.as_str())
                     } else {
                         // Tuple-like
                         super::tuple_field_name(field_index)
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index e5bae009ed6..3f77ea77eff 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -10,7 +10,6 @@
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
 #![feature(never_type)]
-#![feature(once_cell)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
 #![deny(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 57856b4ddb1..8542bab689d 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -89,44 +89,39 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         };
 
         match name {
-            sym::cold => {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
-            }
-            sym::rustc_allocator => {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
-            }
+            sym::cold => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD,
+            sym::rustc_allocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR,
             sym::ffi_returns_twice => {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
-            }
-            sym::ffi_pure => {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
-            }
-            sym::ffi_const => {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
-            }
-            sym::rustc_nounwind => {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
-            }
-            sym::rustc_reallocator => {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR;
-            }
-            sym::rustc_deallocator => {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR;
+                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE
             }
+            sym::ffi_pure => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE,
+            sym::ffi_const => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST,
+            sym::rustc_nounwind => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND,
+            sym::rustc_reallocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR,
+            sym::rustc_deallocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR,
             sym::rustc_allocator_zeroed => {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED;
-            }
-            sym::naked => {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
+                codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
             }
+            sym::naked => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED,
             sym::no_mangle => {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
-            }
-            sym::no_coverage => {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
+                if tcx.opt_item_name(did.to_def_id()).is_some() {
+                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE
+                } else {
+                    tcx.sess
+                        .struct_span_err(
+                            attr.span,
+                            format!(
+                                "`#[no_mangle]` cannot be used on {} {} as it has no name",
+                                tcx.def_descr_article(did.to_def_id()),
+                                tcx.def_descr(did.to_def_id()),
+                            ),
+                        )
+                        .emit();
+                }
             }
+            sym::no_coverage => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE,
             sym::rustc_std_internal_symbol => {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
+                codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
             }
             sym::used => {
                 let inner = attr.meta_item_list();
@@ -207,11 +202,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                     struct_span_err!(tcx.sess, attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
                     .emit();
                 }
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY;
-            }
-            sym::thread_local => {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
+                codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY
             }
+            sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
             sym::track_caller => {
                 if !tcx.is_closure(did.to_def_id())
                     && let Some(fn_sig) = fn_sig()
@@ -229,7 +222,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                     )
                     .emit();
                 }
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
+                codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER
             }
             sym::export_name => {
                 if let Some(s) = attr.value_str() {
@@ -306,20 +299,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
             sym::link_section => {
                 if let Some(val) = attr.value_str() {
                     if val.as_str().bytes().any(|b| b == 0) {
-                        let msg = format!(
-                            "illegal null byte in link_section \
-                             value: `{}`",
-                            &val
-                        );
+                        let msg = format!("illegal null byte in link_section value: `{}`", &val);
                         tcx.sess.span_err(attr.span, &msg);
                     } else {
                         codegen_fn_attrs.link_section = Some(val);
                     }
                 }
             }
-            sym::link_name => {
-                codegen_fn_attrs.link_name = attr.value_str();
-            }
+            sym::link_name => codegen_fn_attrs.link_name = attr.value_str(),
             sym::link_ordinal => {
                 link_ordinal_span = Some(attr.span);
                 if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
@@ -330,37 +317,27 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                 no_sanitize_span = Some(attr.span);
                 if let Some(list) = attr.meta_item_list() {
                     for item in list.iter() {
-                        match item.ident().map(|ident| ident.name) {
-                            Some(sym::address) => {
+                        match item.name_or_empty() {
+                            sym::address => {
                                 codegen_fn_attrs.no_sanitize |=
-                                    SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS;
-                            }
-                            Some(sym::cfi) => {
-                                codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
+                                    SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
                             }
-                            Some(sym::kcfi) => {
-                                codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI;
+                            sym::cfi => codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI,
+                            sym::kcfi => codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI,
+                            sym::memory => codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY,
+                            sym::memtag => codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG,
+                            sym::shadow_call_stack => {
+                                codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK
                             }
-                            Some(sym::memory) => {
-                                codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
-                            }
-                            Some(sym::memtag) => {
-                                codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG;
-                            }
-                            Some(sym::shadow_call_stack) => {
-                                codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK;
-                            }
-                            Some(sym::thread) => {
-                                codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
-                            }
-                            Some(sym::hwaddress) => {
-                                codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS;
+                            sym::thread => codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD,
+                            sym::hwaddress => {
+                                codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS
                             }
                             _ => {
                                 tcx.sess
-                                .struct_span_err(item.span(), "invalid argument for `no_sanitize`")
-                                .note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
-                                .emit();
+                                    .struct_span_err(item.span(), "invalid argument for `no_sanitize`")
+                                    .note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
+                                    .emit();
                             }
                         }
                     }
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 81227b04e8a..0ab12314b3c 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -5,7 +5,6 @@
 #![feature(int_roundings)]
 #![feature(let_chains)]
 #![feature(never_type)]
-#![feature(once_cell)]
 #![feature(strict_provenance)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 2d647f5d7f2..c086d1b7f5a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -600,6 +600,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 // and `#[track_caller]` adds an implicit third argument.
                 (LangItem::PanicBoundsCheck, vec![index, len, location])
             }
+            AssertKind::MisalignedPointerDereference { ref required, ref found } => {
+                let required = self.codegen_operand(bx, required).immediate();
+                let found = self.codegen_operand(bx, found).immediate();
+                // It's `fn panic_bounds_check(index: usize, len: usize)`,
+                // and `#[track_caller]` adds an implicit third argument.
+                (LangItem::PanicMisalignedPointerDereference, vec![required, found, location])
+            }
             _ => {
                 let msg = bx.const_str(msg.description());
                 // It's `pub fn panic(expr: &str)`, with the wide reference being passed
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 350ce529ef5..c87ea18af4f 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -544,6 +544,12 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
             RemainderByZero(op) => RemainderByZero(eval_to_int(op)?),
             ResumedAfterReturn(generator_kind) => ResumedAfterReturn(*generator_kind),
             ResumedAfterPanic(generator_kind) => ResumedAfterPanic(*generator_kind),
+            MisalignedPointerDereference { ref required, ref found } => {
+                MisalignedPointerDereference {
+                    required: eval_to_int(required)?,
+                    found: eval_to_int(found)?,
+                }
+            }
         };
         Err(ConstEvalErrKind::AssertFailure(err).into())
     }
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index 8e4454d7cec..4d54c01830b 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -8,7 +8,7 @@ use crate::interpret::{
 use crate::interpret::{MPlaceTy, Value};
 use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
 use rustc_span::source_map::DUMMY_SP;
-use rustc_target::abi::{Align, VariantIdx, FIRST_VARIANT};
+use rustc_target::abi::{Align, FieldIdx, VariantIdx, FIRST_VARIANT};
 
 #[instrument(skip(ecx), level = "debug")]
 fn branches<'tcx>(
@@ -412,6 +412,7 @@ fn valtree_into_mplace<'tcx>(
 
                         let inner_ty = match ty.kind() {
                             ty::Adt(def, substs) => {
+                                let i = FieldIdx::from_usize(i);
                                 def.variant(FIRST_VARIANT).fields[i].ty(tcx, substs)
                             }
                             ty::Tuple(inner_tys) => inner_tys[i],
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index f7881c50960..93b5273e1b1 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -16,7 +16,9 @@ use rustc_middle::mir::interpret::InterpError;
 use rustc_middle::ty;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_span::symbol::{sym, Symbol};
-use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange};
+use rustc_target::abi::{
+    Abi, FieldIdx, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
+};
 
 use std::hash::Hash;
 
@@ -269,14 +271,16 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 match layout.variants {
                     Variants::Single { index } => {
                         // Inside a variant
-                        PathElem::Field(def.variant(index).fields[field].name)
+                        PathElem::Field(def.variant(index).fields[FieldIdx::from_usize(field)].name)
                     }
                     Variants::Multiple { .. } => bug!("we handled variants above"),
                 }
             }
 
             // other ADTs
-            ty::Adt(def, _) => PathElem::Field(def.non_enum_variant().fields[field].name),
+            ty::Adt(def, _) => {
+                PathElem::Field(def.non_enum_variant().fields[FieldIdx::from_usize(field)].name)
+            }
 
             // arrays/slices
             ty::Array(..) | ty::Slice(..) => PathElem::ArrayElem(field),
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 2be385d551e..cd5c92f7342 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -360,7 +360,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     }
                     ty::Adt(adt_def, substs) => {
                         let var = parent_ty.variant_index.unwrap_or(FIRST_VARIANT);
-                        let Some(field) = adt_def.variant(var).fields.get(f.as_usize()) else {
+                        let Some(field) = adt_def.variant(var).fields.get(f) else {
                             fail_out_of_bounds(self, location);
                             return;
                         };
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 0339fb925d4..9b52638e612 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -20,7 +20,7 @@
 #![feature(never_type)]
 #![feature(type_alias_impl_trait)]
 #![feature(new_uninit)]
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![feature(rustc_attrs)]
 #![feature(negative_impls)]
 #![feature(test)]
diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs
index 01d292dde8d..f88c055a9b5 100644
--- a/compiler/rustc_data_structures/src/sharded.rs
+++ b/compiler/rustc_data_structures/src/sharded.rs
@@ -5,7 +5,7 @@ use std::collections::hash_map::RawEntryMut;
 use std::hash::{Hash, Hasher};
 use std::mem;
 
-#[derive(Clone, Default)]
+#[derive(Default)]
 #[cfg_attr(parallel_compiler, repr(align(64)))]
 struct CacheAligned<T>(T);
 
@@ -21,7 +21,6 @@ const SHARD_BITS: usize = 0;
 pub const SHARDS: usize = 1 << SHARD_BITS;
 
 /// An array of cache-line aligned inner locked structures with convenience methods.
-#[derive(Clone)]
 pub struct Sharded<T> {
     shards: [CacheAligned<Lock<T>>; SHARDS],
 }
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index 31323c21df0..4e2126fff7b 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -1,21 +1,46 @@
-//! This module defines types which are thread safe if cfg!(parallel_compiler) is true.
+//! This module defines various operations and types that are implemented in
+//! one way for the serial compiler, and another way the parallel compiler.
 //!
-//! `Lrc` is an alias of `Arc` if cfg!(parallel_compiler) is true, `Rc` otherwise.
+//! Operations
+//! ----------
+//! The parallel versions of operations use Rayon to execute code in parallel,
+//! while the serial versions degenerate straightforwardly to serial execution.
+//! The operations include `join`, `parallel`, `par_iter`, and `par_for_each`.
 //!
-//! `Lock` is a mutex.
-//! It internally uses `parking_lot::Mutex` if cfg!(parallel_compiler) is true,
-//! `RefCell` otherwise.
+//! `rustc_erase_owner!` erases an `OwningRef` owner into `Erased` for the
+//! serial version and `Erased + Send + Sync` for the parallel version.
 //!
-//! `RwLock` is a read-write lock.
-//! It internally uses `parking_lot::RwLock` if cfg!(parallel_compiler) is true,
-//! `RefCell` otherwise.
+//! Types
+//! -----
+//! The parallel versions of types provide various kinds of synchronization,
+//! while the serial compiler versions do not.
 //!
-//! `MTLock` is a mutex which disappears if cfg!(parallel_compiler) is false.
+//! The following table shows how the types are implemented internally. Except
+//! where noted otherwise, the type in column one is defined as a
+//! newtype around the type from column two or three.
 //!
-//! `MTRef` is an immutable reference if cfg!(parallel_compiler), and a mutable reference otherwise.
+//! | Type                    | Serial version      | Parallel version                |
+//! | ----------------------- | ------------------- | ------------------------------- |
+//! | `Lrc<T>`                | `rc::Rc<T>`         | `sync::Arc<T>`                  |
+//! |` Weak<T>`               | `rc::Weak<T>`       | `sync::Weak<T>`                 |
+//! |                         |                     |                                 |
+//! | `AtomicBool`            | `Cell<bool>`        | `atomic::AtomicBool`            |
+//! | `AtomicU32`             | `Cell<u32>`         | `atomic::AtomicU32`             |
+//! | `AtomicU64`             | `Cell<u64>`         | `atomic::AtomicU64`             |
+//! | `AtomicUsize`           | `Cell<usize>`       | `atomic::AtomicUsize`           |
+//! |                         |                     |                                 |
+//! | `Lock<T>`               | `RefCell<T>`        | `parking_lot::Mutex<T>`         |
+//! | `RwLock<T>`             | `RefCell<T>`        | `parking_lot::RwLock<T>`        |
+//! | `MTLock<T>`        [^1] | `T`                 | `Lock<T>`                       |
+//! | `MTLockRef<'a, T>` [^2] | `&'a mut MTLock<T>` | `&'a MTLock<T>`                 |
+//! |                         |                     |                                 |
+//! | `ParallelIterator`      | `Iterator`          | `rayon::iter::ParallelIterator` |
 //!
-//! `rustc_erase_owner!` erases an OwningRef owner into Erased or Erased + Send + Sync
-//! depending on the value of cfg!(parallel_compiler).
+//! [^1] `MTLock` is similar to `Lock`, but the serial version avoids the cost
+//! of a `RefCell`. This is appropriate when interior mutability is not
+//! required.
+//!
+//! [^2] `MTLockRef` is a typedef.
 
 use crate::owning_ref::{Erased, OwningRef};
 use std::collections::HashMap;
@@ -209,7 +234,7 @@ cfg_if! {
             }
         }
 
-        pub type MTRef<'a, T> = &'a mut T;
+        pub type MTLockRef<'a, T> = &'a mut MTLock<T>;
 
         #[derive(Debug, Default)]
         pub struct MTLock<T>(T);
@@ -267,7 +292,7 @@ cfg_if! {
         pub use std::sync::Arc as Lrc;
         pub use std::sync::Weak as Weak;
 
-        pub type MTRef<'a, T> = &'a T;
+        pub type MTLockRef<'a, T> = &'a MTLock<T>;
 
         #[derive(Debug, Default)]
         pub struct MTLock<T>(Lock<T>);
@@ -555,18 +580,6 @@ impl<T> RwLock<T> {
 
     #[cfg(not(parallel_compiler))]
     #[inline(always)]
-    pub fn clone_guard<'a>(rg: &ReadGuard<'a, T>) -> ReadGuard<'a, T> {
-        ReadGuard::clone(rg)
-    }
-
-    #[cfg(parallel_compiler)]
-    #[inline(always)]
-    pub fn clone_guard<'a>(rg: &ReadGuard<'a, T>) -> ReadGuard<'a, T> {
-        ReadGuard::rwlock(&rg).read()
-    }
-
-    #[cfg(not(parallel_compiler))]
-    #[inline(always)]
     pub fn leak(&self) -> &T {
         ReadGuard::leak(self.read())
     }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 1e835f6065a..b96b356f551 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -6,7 +6,7 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(is_terminal)]
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![feature(decl_macro)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 301dacc2824..6f319b96f2f 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -1,5 +1,5 @@
 #![feature(let_chains)]
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![feature(rustc_attrs)]
 #![feature(type_alias_impl_trait)]
 #![deny(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 8a78c3296f9..8a16143311b 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -36,7 +36,7 @@ impl<'a> ExtCtxt<'a> {
         );
         let args = if !args.is_empty() {
             let args = args.into_iter().map(ast::AngleBracketedArg::Arg).collect();
-            ast::AngleBracketedArgs { args, span }.into()
+            Some(ast::AngleBracketedArgs { args, span }.into())
         } else {
             None
         };
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index ddba1441719..26bc216f678 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -54,7 +54,7 @@ impl base::BangProcMacro for BangProcMacro {
     ) -> Result<TokenStream, ErrorGuaranteed> {
         let _timer =
             ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
-                recorder.record_arg_with_span(ecx.expansion_descr(), span);
+                recorder.record_arg_with_span(ecx.sess.source_map(), ecx.expansion_descr(), span);
             });
 
         let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
@@ -85,7 +85,7 @@ impl base::AttrProcMacro for AttrProcMacro {
     ) -> Result<TokenStream, ErrorGuaranteed> {
         let _timer =
             ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
-                recorder.record_arg_with_span(ecx.expansion_descr(), span);
+                recorder.record_arg_with_span(ecx.sess.source_map(), ecx.expansion_descr(), span);
             });
 
         let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
@@ -134,7 +134,11 @@ impl MultiItemModifier for DeriveProcMacro {
         let stream = {
             let _timer =
                 ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
-                    recorder.record_arg_with_span(ecx.expansion_descr(), span);
+                    recorder.record_arg_with_span(
+                        ecx.sess.source_map(),
+                        ecx.expansion_descr(),
+                        span,
+                    );
                 });
             let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
             let strategy = exec_strategy(ecx);
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index b7d280b8751..84114b27f41 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -225,7 +225,7 @@ declare_features! (
     (active, rustc_allow_const_fn_unstable, "1.49.0", Some(69399), None),
     /// Allows using compiler's own crates.
     (active, rustc_private, "1.0.0", Some(27812), None),
-    /// Allows using internal rustdoc features like `doc(primitive)` or `doc(keyword)`.
+    /// Allows using internal rustdoc features like `doc(keyword)`.
     (active, rustdoc_internals, "1.58.0", Some(90418), None),
     /// Allows using the `rustdoc::missing_doc_code_examples` lint
     (active, rustdoc_missing_doc_code_examples, "1.31.0", Some(101730), None),
@@ -495,6 +495,8 @@ declare_features! (
     (active, repr_simd, "1.4.0", Some(27731), None),
     /// Allows return-position `impl Trait` in traits.
     (incomplete, return_position_impl_trait_in_trait, "1.65.0", Some(91611), None),
+    /// Allows bounding the return type of AFIT/RPITIT.
+    (incomplete, return_type_notation, "CURRENT_RUSTC_VERSION", Some(109417), None),
     /// Allows `extern "rust-cold"`.
     (active, rust_cold_cc, "1.63.0", Some(97544), None),
     /// Allows the use of SIMD types in functions declared in `extern` blocks.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 493a9cd89e3..c77292fdd16 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -778,6 +778,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         definition of a trait, it's currently in experimental form and should be changed before \
         being exposed outside of the std"
     ),
+    rustc_attr!(
+        rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing,
+        r#"`rustc_doc_primitive` is a rustc internal attribute"#,
+    ),
 
     // ==========================================================================
     // Internal attributes, Testing:
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index 93d16716346..3ce16e15667 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -11,7 +11,7 @@
 //! even if it is stabilized or removed, *do not remove it*. Instead, move the
 //! symbol to the `accepted` or `removed` modules respectively.
 
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 3c4fc9cb530..8ceb176491b 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -404,12 +404,8 @@ impl DefPathData {
         match *self {
             TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
 
-            // We use this name when collecting `ModChild`s.
-            // FIXME this could probably be removed with some refactoring to the name resolver.
-            ImplTraitAssocTy => Some(kw::Empty),
-
             Impl | ForeignMod | CrateRoot | Use | GlobalAsm | ClosureExpr | Ctor | AnonConst
-            | ImplTrait => None,
+            | ImplTrait | ImplTraitAssocTy => None,
         }
     }
 
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index f4b46b9a131..35a72f868fb 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -328,7 +328,7 @@ pub struct GenericArgs<'hir> {
     /// Were arguments written in parenthesized form `Fn(T) -> U`?
     /// This is required mostly for pretty-printing and diagnostics,
     /// but also for changing lifetime elision rules to be "function-like".
-    pub parenthesized: bool,
+    pub parenthesized: GenericArgsParentheses,
     /// The span encompassing arguments and the surrounding brackets `<>` or `()`
     ///       Foo<A, B, AssocTy = D>           Fn(T, U, V) -> W
     ///          ^^^^^^^^^^^^^^^^^^^             ^^^^^^^^^
@@ -340,11 +340,16 @@ pub struct GenericArgs<'hir> {
 
 impl<'hir> GenericArgs<'hir> {
     pub const fn none() -> Self {
-        Self { args: &[], bindings: &[], parenthesized: false, span_ext: DUMMY_SP }
+        Self {
+            args: &[],
+            bindings: &[],
+            parenthesized: GenericArgsParentheses::No,
+            span_ext: DUMMY_SP,
+        }
     }
 
     pub fn inputs(&self) -> &[Ty<'hir>] {
-        if self.parenthesized {
+        if self.parenthesized == GenericArgsParentheses::ParenSugar {
             for arg in self.args {
                 match arg {
                     GenericArg::Lifetime(_) => {}
@@ -417,6 +422,17 @@ impl<'hir> GenericArgs<'hir> {
     }
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
+#[derive(HashStable_Generic)]
+pub enum GenericArgsParentheses {
+    No,
+    /// Bounds for `feature(return_type_notation)`, like `T: Trait<method(..): Send>`,
+    /// where the args are explicitly elided with `..`
+    ReturnTypeNotation,
+    /// parenthesized function-family traits, like `T: Fn(u32) -> i32`
+    ParenSugar,
+}
+
 /// A modifier on a bound, currently this is only used for `?Sized`, where the
 /// modifier is `Maybe`. Negative bounds should also be handled here.
 #[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 07faecdb6a7..eac8fd29429 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -240,6 +240,7 @@ language_item_table! {
     PanicDisplay,            sym::panic_display,       panic_display,              Target::Fn,             GenericRequirement::None;
     ConstPanicFmt,           sym::const_panic_fmt,     const_panic_fmt,            Target::Fn,             GenericRequirement::None;
     PanicBoundsCheck,        sym::panic_bounds_check,  panic_bounds_check_fn,      Target::Fn,             GenericRequirement::Exact(0);
+    PanicMisalignedPointerDereference,        sym::panic_misaligned_pointer_dereference,  panic_misaligned_pointer_dereference_fn,      Target::Fn,             GenericRequirement::Exact(0);
     PanicInfo,               sym::panic_info,          panic_info,                 Target::Struct,         GenericRequirement::None;
     PanicLocation,           sym::panic_location,      panic_location,             Target::Struct,         GenericRequirement::None;
     PanicImpl,               sym::panic_impl,          panic_impl,                 Target::Fn,             GenericRequirement::None;
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 0105cbf36de..a57f3987849 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -178,3 +178,14 @@ hir_analysis_invalid_union_field =
 
 hir_analysis_invalid_union_field_sugg =
     wrap the field type in `ManuallyDrop<...>`
+
+hir_analysis_return_type_notation_on_non_rpitit =
+    return type notation used on function that is not `async` and does not return `impl Trait`
+    .note = function returns `{$ty}`, which is not compatible with associated type return bounds
+    .label = this function must be `async` or return `impl Trait`
+
+hir_analysis_return_type_notation_equality_bound =
+    return type notation is not allowed to use type equality
+
+hir_analysis_return_type_notation_missing_method =
+    cannot find associated function `{$assoc_name}` in trait `{$trait_name}`
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index 156334fe785..672e7176fde 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -55,7 +55,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         let trait_def = self.tcx().trait_def(trait_def_id);
         if !trait_def.paren_sugar {
-            if trait_segment.args().parenthesized {
+            if trait_segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar {
                 // For now, require that parenthetical notation be used only with `Fn()` etc.
                 let mut err = feature_err(
                     &self.tcx().sess.parse_sess,
@@ -71,7 +71,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         let sess = self.tcx().sess;
 
-        if !trait_segment.args().parenthesized {
+        if trait_segment.args().parenthesized != hir::GenericArgsParentheses::ParenSugar {
             // For now, require that parenthetical notation be used only with `Fn()` etc.
             let mut err = feature_err(
                 &sess.parse_sess,
@@ -607,11 +607,19 @@ pub fn prohibit_assoc_ty_binding(
     span: Span,
     segment: Option<(&hir::PathSegment<'_>, Span)>,
 ) {
-    tcx.sess.emit_err(AssocTypeBindingNotAllowed { span, fn_trait_expansion: if let Some((segment, span)) = segment && segment.args().parenthesized {
-        Some(ParenthesizedFnTraitExpansion { span, expanded_type: fn_trait_to_string(tcx, segment, false) })
-    } else {
-        None
-    }});
+    tcx.sess.emit_err(AssocTypeBindingNotAllowed {
+        span,
+        fn_trait_expansion: if let Some((segment, span)) = segment
+            && segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar
+        {
+            Some(ParenthesizedFnTraitExpansion {
+                span,
+                expanded_type: fn_trait_to_string(tcx, segment, false),
+            })
+        } else {
+            None
+        },
+    });
 }
 
 pub(crate) fn fn_trait_to_string(
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 4ab6bb5908b..e25b07d9392 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -854,16 +854,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         )
     }
 
-    fn trait_defines_associated_type_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
-        self.tcx()
-            .associated_items(trait_def_id)
-            .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id)
-            .is_some()
-    }
-    fn trait_defines_associated_const_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
+    fn trait_defines_associated_item_named(
+        &self,
+        trait_def_id: DefId,
+        assoc_kind: ty::AssocKind,
+        assoc_name: Ident,
+    ) -> bool {
         self.tcx()
             .associated_items(trait_def_id)
-            .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Const, trait_def_id)
+            .find_by_name_and_kind(self.tcx(), assoc_name, assoc_kind, trait_def_id)
             .is_some()
     }
 
@@ -1087,24 +1086,44 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         let tcx = self.tcx();
 
-        let candidate =
-            if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
-                // Simple case: X is defined in the current trait.
+        let return_type_notation =
+            binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation;
+
+        let candidate = if return_type_notation {
+            if self.trait_defines_associated_item_named(
+                trait_ref.def_id(),
+                ty::AssocKind::Fn,
+                binding.item_name,
+            ) {
                 trait_ref
             } else {
-                // Otherwise, we have to walk through the supertraits to find
-                // those that do.
-                self.one_bound_for_assoc_type(
-                    || traits::supertraits(tcx, trait_ref),
-                    trait_ref.print_only_trait_path(),
-                    binding.item_name,
-                    path_span,
-                    match binding.kind {
-                        ConvertedBindingKind::Equality(term) => Some(term),
-                        _ => None,
-                    },
-                )?
-            };
+                return Err(tcx.sess.emit_err(crate::errors::ReturnTypeNotationMissingMethod {
+                    span: binding.span,
+                    trait_name: tcx.item_name(trait_ref.def_id()),
+                    assoc_name: binding.item_name.name,
+                }));
+            }
+        } else if self.trait_defines_associated_item_named(
+            trait_ref.def_id(),
+            ty::AssocKind::Type,
+            binding.item_name,
+        ) {
+            // Simple case: X is defined in the current trait.
+            trait_ref
+        } else {
+            // Otherwise, we have to walk through the supertraits to find
+            // those that do.
+            self.one_bound_for_assoc_type(
+                || traits::supertraits(tcx, trait_ref),
+                trait_ref.print_only_trait_path(),
+                binding.item_name,
+                path_span,
+                match binding.kind {
+                    ConvertedBindingKind::Equality(term) => Some(term),
+                    _ => None,
+                },
+            )?
+        };
 
         let (assoc_ident, def_scope) =
             tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
@@ -1116,9 +1135,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 .filter_by_name_unhygienic(assoc_ident.name)
                 .find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident)
         };
-        let assoc_item = find_item_of_kind(ty::AssocKind::Type)
-            .or_else(|| find_item_of_kind(ty::AssocKind::Const))
-            .expect("missing associated type");
+        let assoc_item = if return_type_notation {
+            find_item_of_kind(ty::AssocKind::Fn)
+        } else {
+            find_item_of_kind(ty::AssocKind::Type)
+                .or_else(|| find_item_of_kind(ty::AssocKind::Const))
+        }
+        .expect("missing associated type");
 
         if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) {
             tcx.sess
@@ -1135,7 +1158,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             dup_bindings
                 .entry(assoc_item.def_id)
                 .and_modify(|prev_span| {
-                    self.tcx().sess.emit_err(ValueOfAssociatedStructAlreadySpecified {
+                    tcx.sess.emit_err(ValueOfAssociatedStructAlreadySpecified {
                         span: binding.span,
                         prev_span: *prev_span,
                         item_name: binding.item_name,
@@ -1145,28 +1168,100 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 .or_insert(binding.span);
         }
 
-        // Include substitutions for generic parameters of associated types
-        let projection_ty = candidate.map_bound(|trait_ref| {
-            let ident = Ident::new(assoc_item.name, binding.item_name.span);
-            let item_segment = hir::PathSegment {
-                ident,
-                hir_id: binding.hir_id,
-                res: Res::Err,
-                args: Some(binding.gen_args),
-                infer_args: false,
+        let projection_ty = if return_type_notation {
+            // If we have an method return type bound, then we need to substitute
+            // the method's early bound params with suitable late-bound params.
+            let mut num_bound_vars = candidate.bound_vars().len();
+            let substs =
+                candidate.skip_binder().substs.extend_to(tcx, assoc_item.def_id, |param, _| {
+                    let subst = match param.kind {
+                        GenericParamDefKind::Lifetime => tcx
+                            .mk_re_late_bound(
+                                ty::INNERMOST,
+                                ty::BoundRegion {
+                                    var: ty::BoundVar::from_usize(num_bound_vars),
+                                    kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name),
+                                },
+                            )
+                            .into(),
+                        GenericParamDefKind::Type { .. } => tcx
+                            .mk_bound(
+                                ty::INNERMOST,
+                                ty::BoundTy {
+                                    var: ty::BoundVar::from_usize(num_bound_vars),
+                                    kind: ty::BoundTyKind::Param(param.def_id, param.name),
+                                },
+                            )
+                            .into(),
+                        GenericParamDefKind::Const { .. } => {
+                            let ty = tcx
+                                .type_of(param.def_id)
+                                .no_bound_vars()
+                                .expect("ct params cannot have early bound vars");
+                            tcx.mk_const(
+                                ty::ConstKind::Bound(
+                                    ty::INNERMOST,
+                                    ty::BoundVar::from_usize(num_bound_vars),
+                                ),
+                                ty,
+                            )
+                            .into()
+                        }
+                    };
+                    num_bound_vars += 1;
+                    subst
+                });
+
+            // Next, we need to check that the return-type notation is being used on
+            // 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
+            {
+                alias_ty
+            } else {
+                return Err(self.tcx().sess.emit_err(
+                    crate::errors::ReturnTypeNotationOnNonRpitit {
+                        span: binding.span,
+                        ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output),
+                        fn_span: tcx.hir().span_if_local(assoc_item.def_id),
+                        note: (),
+                    },
+                ));
             };
 
-            let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
-                path_span,
-                assoc_item.def_id,
-                &item_segment,
-                trait_ref.substs,
-            );
+            // Finally, move the fn return type's bound vars over to account for the early bound
+            // params (and trait ref's late bound params). This logic is very similar to
+            // `Predicate::subst_supertrait`, and it's no coincidence why.
+            let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
+            let subst_output = ty::EarlyBinder(shifted_output).subst(tcx, substs);
+
+            let bound_vars = tcx.late_bound_vars(binding.hir_id);
+            ty::Binder::bind_with_vars(subst_output, bound_vars)
+        } else {
+            // Include substitutions for generic parameters of associated types
+            candidate.map_bound(|trait_ref| {
+                let ident = Ident::new(assoc_item.name, binding.item_name.span);
+                let item_segment = hir::PathSegment {
+                    ident,
+                    hir_id: binding.hir_id,
+                    res: Res::Err,
+                    args: Some(binding.gen_args),
+                    infer_args: false,
+                };
 
-            debug!(?substs_trait_ref_and_assoc_item);
+                let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
+                    path_span,
+                    assoc_item.def_id,
+                    &item_segment,
+                    trait_ref.substs,
+                );
 
-            self.tcx().mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
-        });
+                debug!(?substs_trait_ref_and_assoc_item);
+
+                tcx.mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
+            })
+        };
 
         if !speculative {
             // Find any late-bound regions declared in `ty` that are not
@@ -1206,6 +1301,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         }
 
         match binding.kind {
+            ConvertedBindingKind::Equality(..) if return_type_notation => {
+                return Err(self.tcx().sess.emit_err(
+                    crate::errors::ReturnTypeNotationEqualityBound { span: binding.span },
+                ));
+            }
             ConvertedBindingKind::Equality(mut term) => {
                 // "Desugar" a constraint like `T: Iterator<Item = u32>` this to
                 // the "projection predicate" for:
@@ -1267,7 +1367,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
                 // parameter to have a skipped binder.
                 let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
-                self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars());
+                self.add_bounds(param_ty, ast_bounds.iter(), bounds, projection_ty.bound_vars());
             }
         }
         Ok(())
@@ -1808,10 +1908,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     where
         I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
     {
-        let mut matching_candidates = all_candidates()
-            .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name));
-        let mut const_candidates = all_candidates()
-            .filter(|r| self.trait_defines_associated_const_named(r.def_id(), assoc_name));
+        let mut matching_candidates = all_candidates().filter(|r| {
+            self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Type, assoc_name)
+        });
+        let mut const_candidates = all_candidates().filter(|r| {
+            self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Const, assoc_name)
+        });
 
         let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) {
             (Some(bound), _) => (bound, matching_candidates.next()),
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index d8dda7a93be..8617bca0825 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -27,6 +27,7 @@ use rustc_middle::ty::{
 use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
 use rustc_span::symbol::sym;
 use rustc_span::{self, Span};
+use rustc_target::abi::FieldIdx;
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
@@ -474,7 +475,7 @@ fn is_enum_of_nonnullable_ptr<'tcx>(
     let [var_one, var_two] = &adt_def.variants().raw[..] else {
         return false;
     };
-    let (([], [field]) | ([field], [])) = (&var_one.fields[..], &var_two.fields[..]) else {
+    let (([], [field]) | ([field], [])) = (&var_one.fields.raw[..], &var_two.fields.raw[..]) else {
         return false;
     };
     matches!(field.ty(tcx, substs).kind(), ty::FnPtr(..) | ty::Ref(..))
@@ -893,7 +894,7 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
             struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
             return;
         }
-        let e = fields[0].ty(tcx, substs);
+        let e = fields[FieldIdx::from_u32(0)].ty(tcx, substs);
         if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
             struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous")
                 .span_label(sp, "SIMD elements must have the same type")
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 172b84bafb2..0d482b53afe 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -5,6 +5,7 @@ use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableE
 use rustc_session::lint;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{Symbol, DUMMY_SP};
+use rustc_target::abi::FieldIdx;
 use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType};
 
 pub struct InlineAsmCtxt<'a, 'tcx> {
@@ -82,7 +83,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
             }
             ty::Adt(adt, substs) if adt.repr().simd() => {
                 let fields = &adt.non_enum_variant().fields;
-                let elem_ty = fields[0].ty(self.tcx, substs);
+                let elem_ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, substs);
                 match elem_ty.kind() {
                     ty::Never | ty::Error(_) => return None,
                     ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => {
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index d126f7beb10..24cc58ee344 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1030,7 +1030,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
             // intermediate types must be sized.
             let needs_drop_copy = || {
                 packed && {
-                    let ty = tcx.type_of(variant.fields.last().unwrap().did).subst_identity();
+                    let ty = tcx.type_of(variant.fields.raw.last().unwrap().did).subst_identity();
                     let ty = tcx.erase_regions(ty);
                     if ty.needs_infer() {
                         tcx.sess
@@ -1046,7 +1046,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
             let all_sized = all_sized || variant.fields.is_empty() || needs_drop_copy();
             let unsized_len = if all_sized { 0 } else { 1 };
             for (idx, field) in
-                variant.fields[..variant.fields.len() - unsized_len].iter().enumerate()
+                variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate()
             {
                 let last = idx == variant.fields.len() - 1;
                 let field_id = field.did.expect_local();
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 25d56ea45c1..ac7c68d9c4b 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -486,8 +486,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
             // U` can be coerced to `*mut V` if `U: Unsize<V>`.
             let fields = &def_a.non_enum_variant().fields;
             let diff_fields = fields
-                .iter()
-                .enumerate()
+                .iter_enumerated()
                 .filter_map(|(i, f)| {
                     let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));
 
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index f1769415797..5e4f377a1e7 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1461,7 +1461,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         depth: usize,
         generic_args: &'tcx hir::GenericArgs<'tcx>,
     ) {
-        if generic_args.parenthesized {
+        if generic_args.parenthesized == hir::GenericArgsParentheses::ParenSugar {
             self.visit_fn_like_elision(
                 generic_args.inputs(),
                 Some(generic_args.bindings[0].ty()),
@@ -1640,7 +1640,59 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 },
                 s: self.scope,
             };
-            if let Some(type_def_id) = type_def_id {
+            // If the binding is parenthesized, then this must be `feature(return_type_notation)`.
+            // In that case, introduce a binder over all of the function's early and late bound vars.
+            //
+            // For example, given
+            // ```
+            // trait Foo {
+            //     async fn x<'r, T>();
+            // }
+            // ```
+            // and a bound that looks like:
+            //    `for<'a> T::Trait<'a, x(): for<'b> Other<'b>>`
+            // this is going to expand to something like:
+            //    `for<'a> for<'r, T> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
+            if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation {
+                let bound_vars = if let Some(type_def_id) = type_def_id
+                    && self.tcx.def_kind(type_def_id) == DefKind::Trait
+                    // FIXME(return_type_notation): We could bound supertrait methods.
+                    && let Some(assoc_fn) = self
+                        .tcx
+                        .associated_items(type_def_id)
+                        .find_by_name_and_kind(self.tcx, binding.ident, ty::AssocKind::Fn, type_def_id)
+                {
+                    self.tcx
+                        .generics_of(assoc_fn.def_id)
+                        .params
+                        .iter()
+                        .map(|param| match param.kind {
+                            ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region(
+                                ty::BoundRegionKind::BrNamed(param.def_id, param.name),
+                            ),
+                            ty::GenericParamDefKind::Type { .. } => ty::BoundVariableKind::Ty(
+                                ty::BoundTyKind::Param(param.def_id, param.name),
+                            ),
+                            ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
+                        })
+                        .chain(self.tcx.fn_sig(assoc_fn.def_id).subst_identity().bound_vars())
+                        .collect()
+                } else {
+                    self.tcx.sess.delay_span_bug(
+                        binding.ident.span,
+                        "bad return type notation here",
+                    );
+                    vec![]
+                };
+                self.with(scope, |this| {
+                    let scope = Scope::Supertrait { bound_vars, s: this.scope };
+                    this.with(scope, |this| {
+                        let (bound_vars, _) = this.poly_trait_ref_binder_info();
+                        this.record_late_bound_vars(binding.hir_id, bound_vars);
+                        this.visit_assoc_type_binding(binding)
+                    });
+                });
+            } else if let Some(type_def_id) = type_def_id {
                 let bound_vars =
                     BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident);
                 self.with(scope, |this| {
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index f57197edeb7..c71ce9a0bc7 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -471,6 +471,18 @@ pub(crate) struct InvalidUnionField {
     pub note: (),
 }
 
+#[derive(Diagnostic)]
+#[diag(hir_analysis_return_type_notation_on_non_rpitit)]
+pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub ty: Ty<'tcx>,
+    #[label]
+    pub fn_span: Option<Span>,
+    #[note]
+    pub note: (),
+}
+
 #[derive(Subdiagnostic)]
 #[multipart_suggestion(hir_analysis_invalid_union_field_sugg, applicability = "machine-applicable")]
 pub(crate) struct InvalidUnionFieldSuggestion {
@@ -479,3 +491,19 @@ pub(crate) struct InvalidUnionFieldSuggestion {
     #[suggestion_part(code = ">")]
     pub hi: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_return_type_notation_equality_bound)]
+pub(crate) struct ReturnTypeNotationEqualityBound {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_return_type_notation_missing_method)]
+pub(crate) struct ReturnTypeNotationMissingMethod {
+    #[primary_span]
+    pub span: Span,
+    pub trait_name: Symbol,
+    pub assoc_name: Symbol,
+}
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index d43230cb563..2a9025d60ab 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -67,7 +67,7 @@ This API is completely unstable and subject to change.
 #![feature(let_chains)]
 #![feature(min_specialization)]
 #![feature(never_type)]
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![feature(slice_partition_dedup)]
 #![feature(try_blocks)]
 #![feature(is_some_and)]
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index cae884ae8fb..8f4d81ec3a9 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -565,7 +565,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
     /// type Map = HashMap<String>;
     /// ```
     fn suggest_adding_args(&self, err: &mut Diagnostic) {
-        if self.gen_args.parenthesized {
+        if self.gen_args.parenthesized != hir::GenericArgsParentheses::No {
             return;
         }
 
@@ -962,7 +962,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
 
             let msg = format!(
                 "remove these {}generics",
-                if self.gen_args.parenthesized { "parenthetical " } else { "" },
+                if self.gen_args.parenthesized == hir::GenericArgsParentheses::ParenSugar {
+                    "parenthetical "
+                } else {
+                    ""
+                },
             );
 
             err.span_suggestion(span, &msg, "", Applicability::MaybeIncorrect);
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 63ea6c90477..4f27c01fad2 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1652,61 +1652,65 @@ impl<'a> State<'a> {
         generic_args: &hir::GenericArgs<'_>,
         colons_before_params: bool,
     ) {
-        if generic_args.parenthesized {
-            self.word("(");
-            self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(ty));
-            self.word(")");
+        match generic_args.parenthesized {
+            hir::GenericArgsParentheses::No => {
+                let start = if colons_before_params { "::<" } else { "<" };
+                let empty = Cell::new(true);
+                let start_or_comma = |this: &mut Self| {
+                    if empty.get() {
+                        empty.set(false);
+                        this.word(start)
+                    } else {
+                        this.word_space(",")
+                    }
+                };
+
+                let mut nonelided_generic_args: bool = false;
+                let elide_lifetimes = generic_args.args.iter().all(|arg| match arg {
+                    GenericArg::Lifetime(lt) if lt.is_elided() => true,
+                    GenericArg::Lifetime(_) => {
+                        nonelided_generic_args = true;
+                        false
+                    }
+                    _ => {
+                        nonelided_generic_args = true;
+                        true
+                    }
+                });
 
-            self.space_if_not_bol();
-            self.word_space("->");
-            self.print_type(generic_args.bindings[0].ty());
-        } else {
-            let start = if colons_before_params { "::<" } else { "<" };
-            let empty = Cell::new(true);
-            let start_or_comma = |this: &mut Self| {
-                if empty.get() {
-                    empty.set(false);
-                    this.word(start)
-                } else {
-                    this.word_space(",")
+                if nonelided_generic_args {
+                    start_or_comma(self);
+                    self.commasep(Inconsistent, generic_args.args, |s, generic_arg| {
+                        match generic_arg {
+                            GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt),
+                            GenericArg::Lifetime(_) => {}
+                            GenericArg::Type(ty) => s.print_type(ty),
+                            GenericArg::Const(ct) => s.print_anon_const(&ct.value),
+                            GenericArg::Infer(_inf) => s.word("_"),
+                        }
+                    });
                 }
-            };
 
-            let mut nonelided_generic_args: bool = false;
-            let elide_lifetimes = generic_args.args.iter().all(|arg| match arg {
-                GenericArg::Lifetime(lt) if lt.is_elided() => true,
-                GenericArg::Lifetime(_) => {
-                    nonelided_generic_args = true;
-                    false
+                for binding in generic_args.bindings {
+                    start_or_comma(self);
+                    self.print_type_binding(binding);
                 }
-                _ => {
-                    nonelided_generic_args = true;
-                    true
-                }
-            });
-
-            if nonelided_generic_args {
-                start_or_comma(self);
-                self.commasep(
-                    Inconsistent,
-                    generic_args.args,
-                    |s, generic_arg| match generic_arg {
-                        GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt),
-                        GenericArg::Lifetime(_) => {}
-                        GenericArg::Type(ty) => s.print_type(ty),
-                        GenericArg::Const(ct) => s.print_anon_const(&ct.value),
-                        GenericArg::Infer(_inf) => s.word("_"),
-                    },
-                );
-            }
 
-            for binding in generic_args.bindings {
-                start_or_comma(self);
-                self.print_type_binding(binding);
+                if !empty.get() {
+                    self.word(">")
+                }
             }
+            hir::GenericArgsParentheses::ParenSugar => {
+                self.word("(");
+                self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(ty));
+                self.word(")");
 
-            if !empty.get() {
-                self.word(">")
+                self.space_if_not_bol();
+                self.word_space("->");
+                self.print_type(generic_args.bindings[0].ty());
+            }
+            hir::GenericArgsParentheses::ReturnTypeNotation => {
+                self.word("(..)");
             }
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index d28b3b3ce7b..1481c038cfe 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -103,13 +103,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         Ok(match *t.kind() {
             ty::Slice(_) | ty::Str => Some(PointerKind::Length),
             ty::Dynamic(ref tty, _, ty::Dyn) => Some(PointerKind::VTable(tty.principal_def_id())),
-            ty::Adt(def, substs) if def.is_struct() => match def.non_enum_variant().fields.last() {
-                None => Some(PointerKind::Thin),
-                Some(f) => {
-                    let field_ty = self.field_ty(span, f, substs);
-                    self.pointer_kind(field_ty, span)?
+            ty::Adt(def, substs) if def.is_struct() => {
+                match def.non_enum_variant().fields.raw.last() {
+                    None => Some(PointerKind::Thin),
+                    Some(f) => {
+                        let field_ty = self.field_ty(span, f, substs);
+                        self.pointer_kind(field_ty, span)?
+                    }
                 }
-            },
+            }
             ty::Tuple(fields) => match fields.last() {
                 None => Some(PointerKind::Thin),
                 Some(&f) => self.pointer_kind(f, span)?,
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 4846579b980..30d307948a6 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -19,6 +19,7 @@ use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeVisitableExt};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{BytePos, Span};
+use rustc_target::abi::FieldIdx;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::method_chain::CollectAllMismatches;
 use rustc_trait_selection::traits::ObligationCause;
@@ -850,7 +851,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     variant.fields.len() == 1
                 })
                 .filter_map(|variant| {
-                    let sole_field = &variant.fields[0];
+                    let sole_field = &variant.fields[FieldIdx::from_u32(0)];
 
                     let field_is_local = sole_field.did.is_local();
                     let field_is_accessible =
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index fb7cb86d734..c17aae22ba5 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -50,6 +50,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::{Span, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_target::abi::FieldIdx;
 use rustc_target::spec::abi::Abi::RustIntrinsic;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::{self, ObligationCauseCode};
@@ -1561,8 +1562,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let mut remaining_fields = variant
             .fields
-            .iter()
-            .enumerate()
+            .iter_enumerated()
             .map(|(i, field)| (field.ident(tcx).normalize_to_macros_2_0(), (i, field)))
             .collect::<FxHashMap<_, _>>();
 
@@ -1815,7 +1815,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         adt_ty: Ty<'tcx>,
         span: Span,
-        remaining_fields: FxHashMap<Ident, (usize, &ty::FieldDef)>,
+        remaining_fields: FxHashMap<Ident, (FieldIdx, &ty::FieldDef)>,
         variant: &'tcx ty::VariantDef,
         ast_fields: &'tcx [hir::ExprField<'tcx>],
         substs: SubstsRef<'tcx>,
@@ -2209,11 +2209,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let (ident, def_scope) =
                         self.tcx.adjust_ident_and_get_scope(field, base_def.did(), body_hir_id);
                     let fields = &base_def.non_enum_variant().fields;
-                    if let Some(index) = fields
-                        .iter()
-                        .position(|f| f.ident(self.tcx).normalize_to_macros_2_0() == ident)
+                    if let Some((index, field)) = fields
+                        .iter_enumerated()
+                        .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == ident)
                     {
-                        let field = &fields[index];
                         let field_ty = self.field_ty(expr.span, field, substs);
                         // Save the index of all fields regardless of their visibility in case
                         // of error recovery.
@@ -2230,15 +2229,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 }
                 ty::Tuple(tys) => {
-                    let fstr = field.as_str();
-                    if let Ok(index) = fstr.parse::<usize>() {
-                        if fstr == index.to_string() {
+                    if let Ok(index) = field.as_str().parse::<usize>() {
+                        if field.name == sym::integer(index) {
                             if let Some(&field_ty) = tys.get(index) {
                                 let adjustments = self.adjust_steps(&autoderef);
                                 self.apply_adjustments(base, adjustments);
                                 self.register_predicates(autoderef.into_obligations());
 
-                                self.write_field_index(expr.hir_id, index);
+                                self.write_field_index(expr.hir_id, FieldIdx::from_usize(index));
                                 return field_ty;
                             }
                         }
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 5ca4087cdd3..58902cd292c 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -539,7 +539,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
         match with_place.place.ty().kind() {
             ty::Adt(adt, substs) if adt.is_struct() => {
                 // Consume those fields of the with expression that are needed.
-                for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() {
+                for (f_index, with_field) in adt.non_enum_variant().fields.iter_enumerated() {
                     let is_mentioned = fields
                         .iter()
                         .any(|f| self.mc.typeck_results.opt_field_index(f.hir_id) == Some(f_index));
@@ -548,7 +548,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                             &*with_expr,
                             with_place.clone(),
                             with_field.ty(self.tcx(), substs),
-                            ProjectionKind::Field(f_index as u32, FIRST_VARIANT),
+                            ProjectionKind::Field(f_index, FIRST_VARIANT),
                         );
                         self.delegate_consume(&field_place, field_place.hir_id);
                     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 50fc48f68a4..fdf178c3ea7 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -33,6 +33,7 @@ use rustc_span::def_id::LocalDefId;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Span;
+use rustc_target::abi::FieldIdx;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCauseCode, ObligationCtxt};
 
@@ -147,7 +148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    pub fn write_field_index(&self, hir_id: hir::HirId, index: usize) {
+    pub fn write_field_index(&self, hir_id: hir::HirId, index: FieldIdx) {
         self.typeck_results.borrow_mut().field_indices_mut().insert(hir_id, index);
     }
 
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index 19d2befc438..901acffe1c8 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -4,7 +4,7 @@ use rustc_hir as hir;
 use rustc_index::vec::Idx;
 use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
-use rustc_target::abi::{Pointer, VariantIdx};
+use rustc_target::abi::{FieldIdx, Pointer, VariantIdx};
 
 use super::FnCtxt;
 
@@ -28,7 +28,7 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
         }
 
         if def.variant(data_idx).fields.len() == 1 {
-            return def.variant(data_idx).fields[0].ty(tcx, substs);
+            return def.variant(data_idx).fields[FieldIdx::from_u32(0)].ty(tcx, substs);
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index 19c4146de89..6c861b5930a 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -61,7 +61,7 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::PatKind;
 use rustc_infer::infer::InferCtxt;
 use rustc_span::Span;
-use rustc_target::abi::{VariantIdx, FIRST_VARIANT};
+use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 use rustc_trait_selection::infer::InferCtxtExt;
 
 pub(crate) trait HirNode {
@@ -330,7 +330,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
                     expr,
                     base,
                     expr_ty,
-                    ProjectionKind::Field(field_idx as u32, FIRST_VARIANT),
+                    ProjectionKind::Field(field_idx, FIRST_VARIANT),
                 ))
             }
 
@@ -674,7 +674,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
 
                 for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) {
                     let subpat_ty = self.pat_ty_adjusted(subpat)?;
-                    let projection_kind = ProjectionKind::Field(i as u32, FIRST_VARIANT);
+                    let projection_kind =
+                        ProjectionKind::Field(FieldIdx::from_usize(i), FIRST_VARIANT);
                     let sub_place =
                         self.cat_projection(pat, place_with_id.clone(), subpat_ty, projection_kind);
                     self.cat_pattern_(sub_place, subpat, op)?;
@@ -689,7 +690,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
 
                 for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) {
                     let subpat_ty = self.pat_ty_adjusted(subpat)?;
-                    let projection_kind = ProjectionKind::Field(i as u32, variant_index);
+                    let projection_kind =
+                        ProjectionKind::Field(FieldIdx::from_usize(i), variant_index);
                     let sub_place =
                         self.cat_projection(pat, place_with_id.clone(), subpat_ty, projection_kind);
                     self.cat_pattern_(sub_place, subpat, op)?;
@@ -714,7 +716,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
                         pat,
                         place_with_id.clone(),
                         field_ty,
-                        ProjectionKind::Field(field_index as u32, variant_index),
+                        ProjectionKind::Field(field_index, variant_index),
                     );
                     self.cat_pattern_(field_place, fp.pat, op)?;
                 }
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 95d1a7df698..5c50619f4c3 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1815,7 +1815,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .variants()
                     .iter()
                     .flat_map(|variant| {
-                        let [field] = &variant.fields[..] else { return None; };
+                        let [field] = &variant.fields.raw[..] else { return None; };
                         let field_ty = field.ty(tcx, substs);
 
                         // Skip `_`, since that'll just lead to ambiguity.
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 11ff65d0c37..241535b29c5 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -19,6 +19,7 @@ use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::{Span, Spanned};
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, DUMMY_SP};
+use rustc_target::abi::FieldIdx;
 use rustc_trait_selection::traits::{ObligationCause, Pattern};
 use ty::VariantDef;
 
@@ -1091,11 +1092,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 bug!("unexpected pattern type {:?}", pat_ty);
             };
             for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
-                let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
+                let field = &variant.fields[FieldIdx::from_usize(i)];
+                let field_ty = self.field_ty(subpat.span, field, substs);
                 self.check_pat(subpat, field_ty, def_bm, ti);
 
                 self.tcx.check_stability(
-                    variant.fields[i].did,
+                    variant.fields[FieldIdx::from_usize(i)].did,
                     Some(pat.hir_id),
                     subpat.span,
                     None,
@@ -1103,7 +1105,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         } else {
             // Pattern has wrong number of fields.
-            let e = self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected, had_err);
+            let e =
+                self.e0023(pat.span, res, qpath, subpats, &variant.fields.raw, expected, had_err);
             on_error(e);
             return tcx.ty_error(e);
         }
@@ -1333,8 +1336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Index the struct fields' types.
         let field_map = variant
             .fields
-            .iter()
-            .enumerate()
+            .iter_enumerated()
             .map(|(i, field)| (field.ident(self.tcx).normalize_to_macros_2_0(), (i, field)))
             .collect::<FxHashMap<_, _>>();
 
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 8fe5a3cc789..41a6ad80b65 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -1405,7 +1405,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ProjectionKind::Field(..)
                     ))
                 );
-                def.variants().get(FIRST_VARIANT).unwrap().fields.iter().enumerate().any(
+                def.variants().get(FIRST_VARIANT).unwrap().fields.iter_enumerated().any(
                     |(i, field)| {
                         let paths_using_field = captured_by_move_projs
                             .iter()
@@ -1413,7 +1413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 if let ProjectionKind::Field(field_idx, _) =
                                     projs.first().unwrap().kind
                                 {
-                                    if (field_idx as usize) == i { Some(&projs[1..]) } else { None }
+                                    if field_idx == i { Some(&projs[1..]) } else { None }
                                 } else {
                                     unreachable!();
                                 }
@@ -1446,7 +1446,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .filter_map(|projs| {
                             if let ProjectionKind::Field(field_idx, _) = projs.first().unwrap().kind
                             {
-                                if (field_idx as usize) == i { Some(&projs[1..]) } else { None }
+                                if field_idx.index() == i { Some(&projs[1..]) } else { None }
                             } else {
                                 unreachable!();
                             }
@@ -1893,14 +1893,13 @@ fn restrict_capture_precision(
 
     for (i, proj) in place.projections.iter().enumerate() {
         match proj.kind {
-            ProjectionKind::Index => {
-                // Arrays are completely captured, so we drop Index projections
+            ProjectionKind::Index | ProjectionKind::Subslice => {
+                // Arrays are completely captured, so we drop Index and Subslice projections
                 truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i);
                 return (place, curr_mode);
             }
             ProjectionKind::Deref => {}
             ProjectionKind::Field(..) => {} // ignore
-            ProjectionKind::Subslice => {}  // We never capture this
         }
     }
 
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index acf883fe90c..596849bd456 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -5,7 +5,7 @@ use std::fmt;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
-use std::ops::{Index, IndexMut, RangeBounds};
+use std::ops::{Deref, DerefMut, Index, IndexMut, RangeBounds};
 use std::slice;
 use std::vec;
 
@@ -52,15 +52,27 @@ impl Idx for u32 {
 }
 
 #[derive(Clone, PartialEq, Eq, Hash)]
+#[repr(transparent)]
 pub struct IndexVec<I: Idx, T> {
     pub raw: Vec<T>,
     _marker: PhantomData<fn(&I)>,
 }
 
+#[derive(PartialEq, Eq, Hash)]
+#[repr(transparent)]
+pub struct IndexSlice<I: Idx, T> {
+    _marker: PhantomData<fn(&I)>,
+    pub raw: [T],
+}
+
 // Whether `IndexVec` is `Send` depends only on the data,
 // not the phantom data.
 unsafe impl<I: Idx, T> Send for IndexVec<I, T> where T: Send {}
 
+// Whether `IndexSlice` is `Send` depends only on the data,
+// not the phantom data.
+unsafe impl<I: Idx, T> Send for IndexSlice<I, T> where T: Send {}
+
 #[cfg(feature = "rustc_serialize")]
 impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for IndexVec<I, T> {
     fn encode(&self, s: &mut S) {
@@ -123,6 +135,16 @@ impl<I: Idx, T> IndexVec<I, T> {
     }
 
     #[inline]
+    pub fn as_slice(&self) -> &IndexSlice<I, T> {
+        IndexSlice::from_raw(&self.raw)
+    }
+
+    #[inline]
+    pub fn as_mut_slice(&mut self) -> &mut IndexSlice<I, T> {
+        IndexSlice::from_raw_mut(&mut self.raw)
+    }
+
+    #[inline]
     pub fn push(&mut self, d: T) -> I {
         let idx = I::new(self.len());
         self.raw.push(d);
@@ -135,32 +157,119 @@ impl<I: Idx, T> IndexVec<I, T> {
     }
 
     #[inline]
-    pub fn len(&self) -> usize {
-        self.raw.len()
+    pub fn into_iter(self) -> vec::IntoIter<T> {
+        self.raw.into_iter()
     }
 
-    /// Gives the next index that will be assigned when `push` is
-    /// called.
     #[inline]
-    pub fn next_index(&self) -> I {
-        I::new(self.len())
+    pub fn into_iter_enumerated(
+        self,
+    ) -> impl DoubleEndedIterator<Item = (I, T)> + ExactSizeIterator {
+        self.raw.into_iter().enumerate().map(|(n, t)| (I::new(n), t))
     }
 
     #[inline]
-    pub fn is_empty(&self) -> bool {
-        self.raw.is_empty()
+    pub fn drain<'a, R: RangeBounds<usize>>(
+        &'a mut self,
+        range: R,
+    ) -> impl Iterator<Item = T> + 'a {
+        self.raw.drain(range)
     }
 
     #[inline]
-    pub fn into_iter(self) -> vec::IntoIter<T> {
-        self.raw.into_iter()
+    pub fn drain_enumerated<'a, R: RangeBounds<usize>>(
+        &'a mut self,
+        range: R,
+    ) -> impl Iterator<Item = (I, T)> + 'a {
+        let begin = match range.start_bound() {
+            std::ops::Bound::Included(i) => *i,
+            std::ops::Bound::Excluded(i) => i.checked_add(1).unwrap(),
+            std::ops::Bound::Unbounded => 0,
+        };
+        self.raw.drain(range).enumerate().map(move |(n, t)| (I::new(begin + n), t))
     }
 
     #[inline]
-    pub fn into_iter_enumerated(
-        self,
-    ) -> impl DoubleEndedIterator<Item = (I, T)> + ExactSizeIterator {
-        self.raw.into_iter().enumerate().map(|(n, t)| (I::new(n), t))
+    pub fn shrink_to_fit(&mut self) {
+        self.raw.shrink_to_fit()
+    }
+
+    #[inline]
+    pub fn truncate(&mut self, a: usize) {
+        self.raw.truncate(a)
+    }
+
+    pub fn convert_index_type<Ix: Idx>(self) -> IndexVec<Ix, T> {
+        IndexVec { raw: self.raw, _marker: PhantomData }
+    }
+
+    /// Grows the index vector so that it contains an entry for
+    /// `elem`; if that is already true, then has no
+    /// effect. Otherwise, inserts new values as needed by invoking
+    /// `fill_value`.
+    #[inline]
+    pub fn ensure_contains_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) {
+        let min_new_len = elem.index() + 1;
+        if self.len() < min_new_len {
+            self.raw.resize_with(min_new_len, fill_value);
+        }
+    }
+
+    #[inline]
+    pub fn resize_to_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) {
+        let min_new_len = elem.index() + 1;
+        self.raw.resize_with(min_new_len, fill_value);
+    }
+}
+
+impl<I: Idx, T> Deref for IndexVec<I, T> {
+    type Target = IndexSlice<I, T>;
+
+    #[inline]
+    fn deref(&self) -> &Self::Target {
+        self.as_slice()
+    }
+}
+
+impl<I: Idx, T> DerefMut for IndexVec<I, T> {
+    #[inline]
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        self.as_mut_slice()
+    }
+}
+
+impl<I: Idx, T> IndexSlice<I, T> {
+    #[inline]
+    pub fn from_raw(raw: &[T]) -> &Self {
+        let ptr: *const [T] = raw;
+        // SAFETY: `IndexSlice` is `repr(transparent)` over a normal slice
+        unsafe { &*(ptr as *const Self) }
+    }
+
+    #[inline]
+    pub fn from_raw_mut(raw: &mut [T]) -> &mut Self {
+        let ptr: *mut [T] = raw;
+        // SAFETY: `IndexSlice` is `repr(transparent)` over a normal slice
+        unsafe { &mut *(ptr as *mut Self) }
+    }
+
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.raw.len()
+    }
+
+    /// Gives the next index that will be assigned when `push` is called.
+    ///
+    /// Manual bounds checks can be done using `idx < slice.next_index()`
+    /// (as opposed to `idx.index() < slice.len()`).
+    #[inline]
+    pub fn next_index(&self) -> I {
+        I::new(self.len())
+    }
+
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.raw.is_empty()
     }
 
     #[inline]
@@ -195,47 +304,16 @@ impl<I: Idx, T> IndexVec<I, T> {
     }
 
     #[inline]
-    pub fn drain<'a, R: RangeBounds<usize>>(
-        &'a mut self,
-        range: R,
-    ) -> impl Iterator<Item = T> + 'a {
-        self.raw.drain(range)
-    }
-
-    #[inline]
-    pub fn drain_enumerated<'a, R: RangeBounds<usize>>(
-        &'a mut self,
-        range: R,
-    ) -> impl Iterator<Item = (I, T)> + 'a {
-        let begin = match range.start_bound() {
-            std::ops::Bound::Included(i) => *i,
-            std::ops::Bound::Excluded(i) => i.checked_add(1).unwrap(),
-            std::ops::Bound::Unbounded => 0,
-        };
-        self.raw.drain(range).enumerate().map(move |(n, t)| (I::new(begin + n), t))
-    }
-
-    #[inline]
     pub fn last_index(&self) -> Option<I> {
         self.len().checked_sub(1).map(I::new)
     }
 
     #[inline]
-    pub fn shrink_to_fit(&mut self) {
-        self.raw.shrink_to_fit()
-    }
-
-    #[inline]
     pub fn swap(&mut self, a: I, b: I) {
         self.raw.swap(a.index(), b.index())
     }
 
     #[inline]
-    pub fn truncate(&mut self, a: usize) {
-        self.raw.truncate(a)
-    }
-
-    #[inline]
     pub fn get(&self, index: I) -> Option<&T> {
         self.raw.get(index.index())
     }
@@ -274,28 +352,6 @@ impl<I: Idx, T> IndexVec<I, T> {
         let ptr = self.raw.as_mut_ptr();
         unsafe { (&mut *ptr.add(ai), &mut *ptr.add(bi), &mut *ptr.add(ci)) }
     }
-
-    pub fn convert_index_type<Ix: Idx>(self) -> IndexVec<Ix, T> {
-        IndexVec { raw: self.raw, _marker: PhantomData }
-    }
-
-    /// Grows the index vector so that it contains an entry for
-    /// `elem`; if that is already true, then has no
-    /// effect. Otherwise, inserts new values as needed by invoking
-    /// `fill_value`.
-    #[inline]
-    pub fn ensure_contains_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) {
-        let min_new_len = elem.index() + 1;
-        if self.len() < min_new_len {
-            self.raw.resize_with(min_new_len, fill_value);
-        }
-    }
-
-    #[inline]
-    pub fn resize_to_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) {
-        let min_new_len = elem.index() + 1;
-        self.raw.resize_with(min_new_len, fill_value);
-    }
 }
 
 /// `IndexVec` is often used as a map, so it provides some map-like APIs.
@@ -336,7 +392,7 @@ impl<I: Idx, T: Ord> IndexVec<I, T> {
     }
 }
 
-impl<I: Idx, T> Index<I> for IndexVec<I, T> {
+impl<I: Idx, T> Index<I> for IndexSlice<I, T> {
     type Output = T;
 
     #[inline]
@@ -345,7 +401,7 @@ impl<I: Idx, T> Index<I> for IndexVec<I, T> {
     }
 }
 
-impl<I: Idx, T> IndexMut<I> for IndexVec<I, T> {
+impl<I: Idx, T> IndexMut<I> for IndexSlice<I, T> {
     #[inline]
     fn index_mut(&mut self, index: I) -> &mut T {
         &mut self.raw[index.index()]
@@ -359,6 +415,20 @@ impl<I: Idx, T> Default for IndexVec<I, T> {
     }
 }
 
+impl<I: Idx, T> Default for &IndexSlice<I, T> {
+    #[inline]
+    fn default() -> Self {
+        IndexSlice::from_raw(Default::default())
+    }
+}
+
+impl<I: Idx, T> Default for &mut IndexSlice<I, T> {
+    #[inline]
+    fn default() -> Self {
+        IndexSlice::from_raw_mut(Default::default())
+    }
+}
+
 impl<I: Idx, T> Extend<T> for IndexVec<I, T> {
     #[inline]
     fn extend<J: IntoIterator<Item = T>>(&mut self, iter: J) {
@@ -418,5 +488,25 @@ impl<'a, I: Idx, T> IntoIterator for &'a mut IndexVec<I, T> {
     }
 }
 
+impl<'a, I: Idx, T> IntoIterator for &'a IndexSlice<I, T> {
+    type Item = &'a T;
+    type IntoIter = slice::Iter<'a, T>;
+
+    #[inline]
+    fn into_iter(self) -> slice::Iter<'a, T> {
+        self.raw.iter()
+    }
+}
+
+impl<'a, I: Idx, T> IntoIterator for &'a mut IndexSlice<I, T> {
+    type Item = &'a mut T;
+    type IntoIter = slice::IterMut<'a, T>;
+
+    #[inline]
+    fn into_iter(self) -> slice::IterMut<'a, T> {
+        self.raw.iter_mut()
+    }
+}
+
 #[cfg(test)]
 mod tests;
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index ec122dc039f..8ad143247e8 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -10,6 +10,7 @@ use rustc_middle::traits::{
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TypeVisitableExt};
 use rustc_span::{sym, BytePos, Span};
+use rustc_target::abi::FieldIdx;
 
 use crate::errors::{
     ConsiderAddingAwait, SuggAddLetForLetChains, SuggestRemoveSemiOrReturnBinding,
@@ -109,7 +110,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
                     })
                     .filter_map(|variant| {
-                        let sole_field = &variant.fields[0];
+                        let sole_field = &variant.fields[FieldIdx::from_u32(0)];
                         let sole_field_ty = sole_field.ty(self.tcx, substs);
                         if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
                             let variant_path =
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 5e38ca034ac..be7fa9378ca 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -292,7 +292,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
                 override_queries: config.override_queries,
             };
 
-            rustc_span::with_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
+            rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
                 let r = {
                     let _sess_abort_error = OnDrop(|| {
                         compiler.sess.finish_diagnostics(registry);
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index 15e02671075..9664ba8bd8a 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -2,7 +2,7 @@
 #![feature(decl_macro)]
 #![feature(internal_output_capture)]
 #![feature(thread_spawn_unchecked)]
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index f6bca7045c8..a6ba742201a 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -770,7 +770,7 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
     debug!("is_repr_nullable_ptr(cx, ty = {:?})", ty);
     if let ty::Adt(ty_def, substs) = ty.kind() {
         let field_ty = match &ty_def.variants().raw[..] {
-            [var_one, var_two] => match (&var_one.fields[..], &var_two.fields[..]) {
+            [var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) {
                 ([], [field]) | ([field], []) => field.ty(cx.tcx, substs),
                 _ => return None,
             },
diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs
index 3b2f5cfdc73..9f96a041487 100644
--- a/compiler/rustc_macros/src/diagnostics/fluent.rs
+++ b/compiler/rustc_macros/src/diagnostics/fluent.rs
@@ -15,8 +15,7 @@ use proc_macro2::TokenStream;
 use quote::quote;
 use std::{
     collections::{HashMap, HashSet},
-    fs::File,
-    io::Read,
+    fs::read_to_string,
     path::{Path, PathBuf},
 };
 use syn::{parse_macro_input, Ident, LitStr};
@@ -95,22 +94,18 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
 
     // As this macro also outputs an `include_str!` for this file, the macro will always be
     // re-executed when the file changes.
-    let mut resource_file = match File::open(absolute_ftl_path) {
-        Ok(resource_file) => resource_file,
+    let resource_contents = match read_to_string(absolute_ftl_path) {
+        Ok(resource_contents) => resource_contents,
         Err(e) => {
-            Diagnostic::spanned(resource_span, Level::Error, "could not open Fluent resource")
-                .note(e.to_string())
-                .emit();
+            Diagnostic::spanned(
+                resource_span,
+                Level::Error,
+                format!("could not open Fluent resource: {}", e.to_string()),
+            )
+            .emit();
             return failed(&crate_name);
         }
     };
-    let mut resource_contents = String::new();
-    if let Err(e) = resource_file.read_to_string(&mut resource_contents) {
-        Diagnostic::spanned(resource_span, Level::Error, "could not read Fluent resource")
-            .note(e.to_string())
-            .emit();
-        return failed(&crate_name);
-    }
     let mut bad = false;
     for esc in ["\\n", "\\\"", "\\'"] {
         for _ in resource_contents.matches(esc) {
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index 98d9ad31fe0..880da5ca593 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -4,7 +4,6 @@
 #![feature(generators)]
 #![feature(iter_from_generator)]
 #![feature(let_chains)]
-#![feature(once_cell)]
 #![feature(proc_macro_internals)]
 #![feature(macro_metavar_expr)]
 #![feature(min_specialization)]
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 06a64f0db0e..43e5946f313 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1021,7 +1021,9 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             } else {
                 // Iterate over all children.
                 for child_index in self.root.tables.children.get(self, id).unwrap().decode(self) {
-                    yield self.get_mod_child(child_index, sess);
+                    if self.root.tables.opt_rpitit_info.get(self, child_index).is_none() {
+                        yield self.get_mod_child(child_index, sess);
+                    }
                 }
 
                 if let Some(reexports) = self.root.tables.module_reexports.get(self, id) {
@@ -1067,8 +1069,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem {
-        let name = self.item_name(id);
-
+        let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some() {
+            kw::Empty
+        } else {
+            self.item_name(id)
+        };
         let (kind, has_self) = match self.def_kind(id) {
             DefKind::AssocConst => (ty::AssocKind::Const, false),
             DefKind::AssocFn => (ty::AssocKind::Fn, self.get_fn_has_self_parameter(id, sess)),
diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs
index 83d3b0100b8..80b4c964ce4 100644
--- a/compiler/rustc_middle/src/hir/place.rs
+++ b/compiler/rustc_middle/src/hir/place.rs
@@ -2,7 +2,7 @@ use crate::ty;
 use crate::ty::Ty;
 
 use rustc_hir::HirId;
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{FieldIdx, VariantIdx};
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
 #[derive(TypeFoldable, TypeVisitable)]
@@ -27,7 +27,7 @@ pub enum ProjectionKind {
     /// the field. The field is identified by which variant
     /// it appears in along with a field index. The variant
     /// is used for enums.
-    Field(u32, VariantIdx),
+    Field(FieldIdx, VariantIdx),
 
     /// Some index like `B[x]`, where `B` is the base
     /// expression. We don't preserve the index `x` because
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 45c4a1057d2..0e883424fd4 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -39,7 +39,6 @@
 #![feature(never_type)]
 #![feature(extern_types)]
 #![feature(new_uninit)]
-#![feature(once_cell)]
 #![feature(let_chains)]
 #![feature(min_specialization)]
 #![feature(trusted_len)]
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index 171cf1c1ab1..967fed687b6 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
-use rustc_span::def_id::LocalDefId;
+use rustc_span::def_id::{LocalDefId, CRATE_DEF_ID};
 use std::hash::Hash;
 
 /// Represents the levels of effective visibility an item can have.
@@ -107,6 +107,10 @@ impl EffectiveVisibilities {
         })
     }
 
+    pub fn update_root(&mut self) {
+        self.map.insert(CRATE_DEF_ID, EffectiveVisibility::from_vis(Visibility::Public));
+    }
+
     // FIXME: Share code with `fn update`.
     pub fn update_eff_vis(
         &mut self,
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 37356b53c02..de7e8bc861d 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1277,7 +1277,7 @@ impl<O> AssertKind<O> {
 
     /// Getting a description does not require `O` to be printable, and does not
     /// require allocation.
-    /// The caller is expected to handle `BoundsCheck` separately.
+    /// The caller is expected to handle `BoundsCheck` and `MisalignedPointerDereference` separately.
     pub fn description(&self) -> &'static str {
         use AssertKind::*;
         match self {
@@ -1296,7 +1296,9 @@ impl<O> AssertKind<O> {
             ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion",
             ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking",
             ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking",
-            BoundsCheck { .. } => bug!("Unexpected AssertKind"),
+            BoundsCheck { .. } | MisalignedPointerDereference { .. } => {
+                bug!("Unexpected AssertKind")
+            }
         }
     }
 
@@ -1353,6 +1355,13 @@ impl<O> AssertKind<O> {
             Overflow(BinOp::Shl, _, r) => {
                 write!(f, "\"attempt to shift left by `{{}}`, which would overflow\", {:?}", r)
             }
+            MisalignedPointerDereference { required, found } => {
+                write!(
+                    f,
+                    "\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\", {:?}, {:?}",
+                    required, found
+                )
+            }
             _ => write!(f, "\"{}\"", self.description()),
         }
     }
@@ -1397,6 +1406,13 @@ impl<O: fmt::Debug> fmt::Debug for AssertKind<O> {
             Overflow(BinOp::Shl, _, r) => {
                 write!(f, "attempt to shift left by `{:#?}`, which would overflow", r)
             }
+            MisalignedPointerDereference { required, found } => {
+                write!(
+                    f,
+                    "misaligned pointer dereference: address must be a multiple of {:?} but is {:?}",
+                    required, found
+                )
+            }
             _ => write!(f, "{}", self.description()),
         }
     }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 8fb693055fa..413a7629b9a 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -760,6 +760,7 @@ pub enum AssertKind<O> {
     RemainderByZero(O),
     ResumedAfterReturn(GeneratorKind),
     ResumedAfterPanic(GeneratorKind),
+    MisalignedPointerDereference { required: O, found: O },
 }
 
 #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 4a28aabf8a3..ac28ef5276c 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -43,7 +43,7 @@ impl<'tcx> PlaceTy<'tcx> {
                         &adt_def.variant(variant_index)
                     }
                 };
-                let field_def = &variant_def.fields[f.index()];
+                let field_def = &variant_def.fields[f];
                 field_def.ty(tcx, substs)
             }
             ty::Tuple(tys) => tys[f.index()],
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index b39fc3aaaff..7aa446ae966 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -610,6 +610,10 @@ macro_rules! make_mir_visitor {
                     ResumedAfterReturn(_) | ResumedAfterPanic(_) => {
                         // Nothing to visit
                     }
+                    MisalignedPointerDereference { required, found } => {
+                        self.visit_operand(required, location);
+                        self.visit_operand(found, location);
+                    }
                 }
             }
 
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 29e3055a4b8..82a7cf78517 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -784,7 +784,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
                             if let PatKind::Wild = p.pattern.kind {
                                 continue;
                             }
-                            let name = variant.fields[p.field.index()].name;
+                            let name = variant.fields[p.field].name;
                             write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
                             printed += 1;
                         }
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index 8ce06404de0..cd0f7e8daf1 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -3,6 +3,7 @@ use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
 use rustc_macros::HashStable;
 use rustc_span::Span;
+use rustc_target::abi::FieldIdx;
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
 pub enum PointerCast {
@@ -208,5 +209,5 @@ pub struct CoerceUnsizedInfo {
 #[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, HashStable)]
 pub enum CustomCoerceUnsized {
     /// Records the index of the field being coerced.
-    Struct(usize),
+    Struct(FieldIdx),
 }
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index dc2bd54b7fe..f29bf92b0ed 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -158,12 +158,12 @@ impl<'tcx> CapturedPlace<'tcx> {
         for proj in self.place.projections.iter() {
             match proj.kind {
                 HirProjectionKind::Field(idx, variant) => match ty.kind() {
-                    ty::Tuple(_) => write!(&mut symbol, "__{}", idx).unwrap(),
+                    ty::Tuple(_) => write!(&mut symbol, "__{}", idx.index()).unwrap(),
                     ty::Adt(def, ..) => {
                         write!(
                             &mut symbol,
                             "__{}",
-                            def.variant(variant).fields[idx as usize].name.as_str(),
+                            def.variant(variant).fields[idx].name.as_str(),
                         )
                         .unwrap();
                     }
@@ -356,11 +356,11 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc
                     curr_string = format!(
                         "{}.{}",
                         curr_string,
-                        def.variant(variant).fields[idx as usize].name.as_str()
+                        def.variant(variant).fields[idx].name.as_str()
                     );
                 }
                 ty::Tuple(_) => {
-                    curr_string = format!("{}.{}", curr_string, idx);
+                    curr_string = format!("{}.{}", curr_string, idx.index());
                 }
                 _ => {
                     bug!(
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 0a6e94248e6..31d00b65e98 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -312,6 +312,7 @@ impl DeepRejectCtxt {
             // Impls cannot contain these types as these cannot be named directly.
             ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
 
+            // Placeholder types don't unify with anything on their own
             ty::Placeholder(..) | ty::Bound(..) => false,
 
             // Depending on the value of `treat_obligation_params`, we either
@@ -321,6 +322,10 @@ impl DeepRejectCtxt {
                 TreatParams::AsCandidateKey => true,
             },
 
+            ty::Infer(ty::IntVar(_)) => impl_ty.is_integral(),
+
+            ty::Infer(ty::FloatVar(_)) => impl_ty.is_floating_point(),
+
             ty::Infer(_) => true,
 
             // As we're walking the whole type, it may encounter projections
@@ -359,6 +364,9 @@ impl DeepRejectCtxt {
                 TreatParams::AsCandidateKey => true,
             },
 
+            // Placeholder consts don't unify with anything on their own
+            ty::ConstKind::Placeholder(_) => false,
+
             // As we don't necessarily eagerly evaluate constants,
             // they might unify with any value.
             ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => {
@@ -371,7 +379,7 @@ impl DeepRejectCtxt {
 
             ty::ConstKind::Infer(_) => true,
 
-            ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
+            ty::ConstKind::Bound(..) => {
                 bug!("unexpected obl const: {:?}", obligation_ct)
             }
         }
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 42fb5d031bb..0f70b315aa6 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -5,7 +5,6 @@ use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
 use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_index::vec::Idx;
 use rustc_session::config::OptLevel;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -335,7 +334,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
 
                 // Get a zero-sized variant or a pointer newtype.
                 let zero_or_ptr_variant = |i| {
-                    let i = VariantIdx::new(i);
+                    let i = VariantIdx::from_usize(i);
                     let fields =
                         def.variant(i).fields.iter().map(|field| {
                             SizeSkeleton::compute(field.ty(tcx, substs), tcx, param_env)
@@ -798,7 +797,8 @@ where
                 ty::Adt(def, substs) => {
                     match this.variants {
                         Variants::Single { index } => {
-                            TyMaybeWithLayout::Ty(def.variant(index).fields[i].ty(tcx, substs))
+                            let field = &def.variant(index).fields[FieldIdx::from_usize(i)];
+                            TyMaybeWithLayout::Ty(field.ty(tcx, substs))
                         }
 
                         // Discriminant field for enums (where applicable).
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 7df90fab56f..800a230b654 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -50,7 +50,7 @@ pub use rustc_session::lint::RegisteredTools;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{ExpnId, ExpnKind, Span};
-use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx};
+use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
 pub use rustc_target::abi::{ReprFlags, ReprOptions};
 use rustc_type_ir::WithCachedTypeInfo;
 pub use subst::*;
@@ -1891,7 +1891,7 @@ pub struct VariantDef {
     /// Discriminant of this variant.
     pub discr: VariantDiscr,
     /// Fields of this variant.
-    pub fields: Vec<FieldDef>,
+    pub fields: IndexVec<FieldIdx, FieldDef>,
     /// Flags of the variant (e.g. is field list non-exhaustive)?
     flags: VariantFlags,
 }
@@ -1918,7 +1918,7 @@ impl VariantDef {
         variant_did: Option<DefId>,
         ctor: Option<(CtorKind, DefId)>,
         discr: VariantDiscr,
-        fields: Vec<FieldDef>,
+        fields: IndexVec<FieldIdx, FieldDef>,
         adt_kind: AdtKind,
         parent_did: DefId,
         recovered: bool,
@@ -2270,11 +2270,10 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
-    pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> {
-        variant
-            .fields
-            .iter()
-            .position(|field| self.hygienic_eq(ident, field.ident(self), variant.def_id))
+    pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<FieldIdx> {
+        variant.fields.iter_enumerated().find_map(|(i, field)| {
+            self.hygienic_eq(ident, field.ident(self), variant.def_id).then_some(i)
+        })
     }
 
     /// Returns `true` if the impls are the same polarity and the trait either
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index d03cc324e51..5ea77833af2 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -22,7 +22,7 @@ use rustc_index::vec::Idx;
 use rustc_macros::HashStable;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
-use rustc_target::abi::{VariantIdx, FIRST_VARIANT};
+use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 use rustc_target::spec::abi::{self, Abi};
 use std::borrow::Cow;
 use std::cmp::Ordering;
@@ -1903,7 +1903,7 @@ impl<'tcx> Ty<'tcx> {
             Adt(def, substs) => {
                 assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type");
                 let variant = def.non_enum_variant();
-                let f0_ty = variant.fields[0].ty(tcx, substs);
+                let f0_ty = variant.fields[FieldIdx::from_u32(0)].ty(tcx, substs);
 
                 match f0_ty.kind() {
                     // If the first field is an array, we assume it is the only field and its
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 2b0fb4dc2b7..47943b94c3b 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -25,6 +25,7 @@ use rustc_macros::HashStable;
 use rustc_middle::mir::FakeReadCause;
 use rustc_session::Session;
 use rustc_span::Span;
+use rustc_target::abi::FieldIdx;
 use std::{collections::hash_map::Entry, hash::Hash, iter};
 
 use super::RvalueScopes;
@@ -42,7 +43,7 @@ pub struct TypeckResults<'tcx> {
     /// or patterns (`S { field }`). The index is often useful by itself, but to learn more
     /// about the field you also need definition of the variant to which the field
     /// belongs, but it may not exist if it's a tuple field (`tuple.0`).
-    field_indices: ItemLocalMap<usize>,
+    field_indices: ItemLocalMap<FieldIdx>,
 
     /// Stores the types for various nodes in the AST. Note that this table
     /// is not guaranteed to be populated outside inference. See
@@ -313,19 +314,19 @@ impl<'tcx> TypeckResults<'tcx> {
         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
     }
 
-    pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
+    pub fn field_indices(&self) -> LocalTableInContext<'_, FieldIdx> {
         LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
     }
 
-    pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
+    pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, FieldIdx> {
         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
     }
 
-    pub fn field_index(&self, id: hir::HirId) -> usize {
+    pub fn field_index(&self, id: hir::HirId) -> FieldIdx {
         self.field_indices().get(id).cloned().expect("no index for a field")
     }
 
-    pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> {
+    pub fn opt_field_index(&self, id: hir::HirId) -> Option<FieldIdx> {
         self.field_indices().get(id).cloned()
     }
 
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index e9c0552812b..d3565b28ae5 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -235,7 +235,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     if !def.is_struct() {
                         break;
                     }
-                    match def.non_enum_variant().fields.last() {
+                    match def.non_enum_variant().fields.raw.last() {
                         Some(field) => {
                             f();
                             ty = field.ty(self, substs);
@@ -309,7 +309,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
                     if a_def == b_def && a_def.is_struct() =>
                 {
-                    if let Some(f) = a_def.non_enum_variant().fields.last() {
+                    if let Some(f) = a_def.non_enum_variant().fields.raw.last() {
                         a = f.ty(self, a_substs);
                         b = f.ty(self, b_substs);
                     } else {
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 0fc99e57d12..fb775766c65 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -90,7 +90,7 @@ fn convert_to_hir_projections_and_truncate_for_capture(
             ProjectionElem::Deref => HirProjectionKind::Deref,
             ProjectionElem::Field(field, _) => {
                 let variant = variant.unwrap_or(FIRST_VARIANT);
-                HirProjectionKind::Field(field.index() as u32, variant)
+                HirProjectionKind::Field(*field, variant)
             }
             ProjectionElem::Downcast(.., idx) => {
                 // We don't expect to see multi-variant enums here, as earlier
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 04709197578..3f9236c9dd9 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -8,7 +8,6 @@
 #![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(min_specialization)]
-#![feature(once_cell)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
 
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 2a0b5d04733..8e2e92e6f6a 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -733,7 +733,7 @@ impl<'tcx> Cx<'tcx> {
             hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
                 lhs: self.mirror_expr(source),
                 variant_index: FIRST_VARIANT,
-                name: FieldIdx::new(self.typeck_results.field_index(expr.hir_id)),
+                name: self.typeck_results.field_index(expr.hir_id),
             },
             hir::ExprKind::Cast(ref source, ref cast_ty) => {
                 // Check for a user-given type annotation on this `cast`
@@ -1053,7 +1053,7 @@ impl<'tcx> Cx<'tcx> {
                 HirProjectionKind::Field(field, variant_index) => ExprKind::Field {
                     lhs: self.thir.exprs.push(captured_place_expr),
                     variant_index,
-                    name: FieldIdx::new(field as usize),
+                    name: field,
                 },
                 HirProjectionKind::Index | HirProjectionKind::Subslice => {
                     // We don't capture these projections, so we can ignore them here
@@ -1107,7 +1107,7 @@ impl<'tcx> Cx<'tcx> {
         fields
             .iter()
             .map(|field| FieldExpr {
-                name: FieldIdx::new(self.typeck_results.field_index(field.hir_id)),
+                name: self.typeck_results.field_index(field.hir_id),
                 expr: self.mirror_expr(field.expr),
             })
             .collect()
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 72b4041aa1b..9ac92f6e0a6 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -357,7 +357,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 let subpatterns = fields
                     .iter()
                     .map(|field| FieldPat {
-                        field: FieldIdx::new(self.typeck_results.field_index(field.hir_id)),
+                        field: self.typeck_results.field_index(field.hir_id),
                         pattern: self.lower_pattern(&field.pat),
                     })
                     .collect();
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 37787d99c2d..c8661bbcc44 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -411,9 +411,9 @@ where
     fn open_drop_for_box(&mut self, adt: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> BasicBlock {
         // drop glue is sent straight to codegen
         // box cannot be directly dereferenced
-        let unique_ty = adt.non_enum_variant().fields[0].ty(self.tcx(), substs);
-        let nonnull_ty =
-            unique_ty.ty_adt_def().unwrap().non_enum_variant().fields[0].ty(self.tcx(), substs);
+        let unique_ty = adt.non_enum_variant().fields[FieldIdx::new(0)].ty(self.tcx(), substs);
+        let unique_variant = unique_ty.ty_adt_def().unwrap().non_enum_variant();
+        let nonnull_ty = unique_variant.fields[FieldIdx::from_u32(0)].ty(self.tcx(), substs);
         let ptr_ty = self.tcx().mk_imm_ptr(substs[0].expect_ty());
 
         let unique_place = self.tcx().mk_place_field(self.place, FieldIdx::new(0), unique_ty);
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index 4ed6f7e90ff..43caa2ea973 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -3,7 +3,6 @@
 #![feature(exact_size_is_empty)]
 #![feature(let_chains)]
 #![feature(min_specialization)]
-#![feature(once_cell)]
 #![feature(stmt_expr_attributes)]
 #![feature(trusted_step)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
new file mode 100644
index 00000000000..996416ef22e
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -0,0 +1,227 @@
+use crate::MirPass;
+use rustc_hir::def_id::DefId;
+use rustc_index::vec::IndexVec;
+use rustc_middle::mir::*;
+use rustc_middle::mir::{
+    interpret::{ConstValue, Scalar},
+    visit::{PlaceContext, Visitor},
+};
+use rustc_middle::ty::{Ty, TyCtxt, TypeAndMut};
+use rustc_session::Session;
+
+pub struct CheckAlignment;
+
+impl<'tcx> MirPass<'tcx> for CheckAlignment {
+    fn is_enabled(&self, sess: &Session) -> bool {
+        sess.opts.debug_assertions
+    }
+
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        let basic_blocks = body.basic_blocks.as_mut();
+        let local_decls = &mut body.local_decls;
+
+        for block in (0..basic_blocks.len()).rev() {
+            let block = block.into();
+            for statement_index in (0..basic_blocks[block].statements.len()).rev() {
+                let location = Location { block, statement_index };
+                let statement = &basic_blocks[block].statements[statement_index];
+                let source_info = statement.source_info;
+
+                let mut finder = PointerFinder {
+                    local_decls,
+                    tcx,
+                    pointers: Vec::new(),
+                    def_id: body.source.def_id(),
+                };
+                for (pointer, pointee_ty) in finder.find_pointers(statement) {
+                    debug!("Inserting alignment check for {:?}", pointer.ty(&*local_decls, tcx).ty);
+
+                    let new_block = split_block(basic_blocks, location);
+                    insert_alignment_check(
+                        tcx,
+                        local_decls,
+                        &mut basic_blocks[block],
+                        pointer,
+                        pointee_ty,
+                        source_info,
+                        new_block,
+                    );
+                }
+            }
+        }
+    }
+}
+
+impl<'tcx, 'a> PointerFinder<'tcx, 'a> {
+    fn find_pointers(&mut self, statement: &Statement<'tcx>) -> Vec<(Place<'tcx>, Ty<'tcx>)> {
+        self.pointers.clear();
+        self.visit_statement(statement, Location::START);
+        core::mem::take(&mut self.pointers)
+    }
+}
+
+struct PointerFinder<'tcx, 'a> {
+    local_decls: &'a mut LocalDecls<'tcx>,
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    pointers: Vec<(Place<'tcx>, Ty<'tcx>)>,
+}
+
+impl<'tcx, 'a> Visitor<'tcx> for PointerFinder<'tcx, 'a> {
+    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
+        if let PlaceContext::NonUse(_) = context {
+            return;
+        }
+        if !place.is_indirect() {
+            return;
+        }
+
+        let pointer = Place::from(place.local);
+        let pointer_ty = pointer.ty(&*self.local_decls, self.tcx).ty;
+
+        // We only want to check unsafe pointers
+        if !pointer_ty.is_unsafe_ptr() {
+            trace!("Indirect, but not an unsafe ptr, not checking {:?}", pointer_ty);
+            return;
+        }
+
+        let Some(pointee) = pointer_ty.builtin_deref(true) else {
+            debug!("Indirect but no builtin deref: {:?}", pointer_ty);
+            return;
+        };
+        let mut pointee_ty = pointee.ty;
+        if pointee_ty.is_array() || pointee_ty.is_slice() || pointee_ty.is_str() {
+            pointee_ty = pointee_ty.sequence_element_type(self.tcx);
+        }
+
+        if !pointee_ty.is_sized(self.tcx, self.tcx.param_env_reveal_all_normalized(self.def_id)) {
+            debug!("Unsafe pointer, but unsized: {:?}", pointer_ty);
+            return;
+        }
+
+        if [self.tcx.types.bool, self.tcx.types.i8, self.tcx.types.u8, self.tcx.types.str_]
+            .contains(&pointee_ty)
+        {
+            debug!("Trivially aligned pointee type: {:?}", pointer_ty);
+            return;
+        }
+
+        self.pointers.push((pointer, pointee_ty))
+    }
+}
+
+fn split_block(
+    basic_blocks: &mut IndexVec<BasicBlock, BasicBlockData<'_>>,
+    location: Location,
+) -> BasicBlock {
+    let block_data = &mut basic_blocks[location.block];
+
+    // Drain every statement after this one and move the current terminator to a new basic block
+    let new_block = BasicBlockData {
+        statements: block_data.statements.split_off(location.statement_index),
+        terminator: block_data.terminator.take(),
+        is_cleanup: block_data.is_cleanup,
+    };
+
+    basic_blocks.push(new_block)
+}
+
+fn insert_alignment_check<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    local_decls: &mut LocalDecls<'tcx>,
+    block_data: &mut BasicBlockData<'tcx>,
+    pointer: Place<'tcx>,
+    pointee_ty: Ty<'tcx>,
+    source_info: SourceInfo,
+    new_block: BasicBlock,
+) {
+    // Cast the pointer to a *const ()
+    let const_raw_ptr = tcx.mk_ptr(TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Not });
+    let rvalue = Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(pointer), const_raw_ptr);
+    let thin_ptr = local_decls.push(LocalDecl::with_source_info(const_raw_ptr, source_info)).into();
+    block_data
+        .statements
+        .push(Statement { source_info, kind: StatementKind::Assign(Box::new((thin_ptr, rvalue))) });
+
+    // Transmute the pointer to a usize (equivalent to `ptr.addr()`)
+    let rvalue = Rvalue::Cast(CastKind::Transmute, Operand::Copy(thin_ptr), tcx.types.usize);
+    let addr = local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
+    block_data
+        .statements
+        .push(Statement { source_info, kind: StatementKind::Assign(Box::new((addr, rvalue))) });
+
+    // Get the alignment of the pointee
+    let alignment =
+        local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
+    let rvalue = Rvalue::NullaryOp(NullOp::AlignOf, pointee_ty);
+    block_data.statements.push(Statement {
+        source_info,
+        kind: StatementKind::Assign(Box::new((alignment, rvalue))),
+    });
+
+    // Subtract 1 from the alignment to get the alignment mask
+    let alignment_mask =
+        local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
+    let one = Operand::Constant(Box::new(Constant {
+        span: source_info.span,
+        user_ty: None,
+        literal: ConstantKind::Val(
+            ConstValue::Scalar(Scalar::from_target_usize(1, &tcx)),
+            tcx.types.usize,
+        ),
+    }));
+    block_data.statements.push(Statement {
+        source_info,
+        kind: StatementKind::Assign(Box::new((
+            alignment_mask,
+            Rvalue::BinaryOp(BinOp::Sub, Box::new((Operand::Copy(alignment), one))),
+        ))),
+    });
+
+    // BitAnd the alignment mask with the pointer
+    let alignment_bits =
+        local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
+    block_data.statements.push(Statement {
+        source_info,
+        kind: StatementKind::Assign(Box::new((
+            alignment_bits,
+            Rvalue::BinaryOp(
+                BinOp::BitAnd,
+                Box::new((Operand::Copy(addr), Operand::Copy(alignment_mask))),
+            ),
+        ))),
+    });
+
+    // Check if the alignment bits are all zero
+    let is_ok = local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into();
+    let zero = Operand::Constant(Box::new(Constant {
+        span: source_info.span,
+        user_ty: None,
+        literal: ConstantKind::Val(
+            ConstValue::Scalar(Scalar::from_target_usize(0, &tcx)),
+            tcx.types.usize,
+        ),
+    }));
+    block_data.statements.push(Statement {
+        source_info,
+        kind: StatementKind::Assign(Box::new((
+            is_ok,
+            Rvalue::BinaryOp(BinOp::Eq, Box::new((Operand::Copy(alignment_bits), zero.clone()))),
+        ))),
+    });
+
+    // Set this block's terminator to our assert, continuing to new_block if we pass
+    block_data.terminator = Some(Terminator {
+        source_info,
+        kind: TerminatorKind::Assert {
+            cond: Operand::Copy(is_ok),
+            expected: true,
+            target: new_block,
+            msg: AssertKind::MisalignedPointerDereference {
+                required: Operand::Copy(alignment),
+                found: Operand::Copy(addr),
+            },
+            cleanup: None,
+        },
+    });
+}
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index 58bc083280a..85623499439 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -92,13 +92,14 @@ pub struct ElaborateBoxDerefs;
 impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         if let Some(def_id) = tcx.lang_items().owned_box() {
-            let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[0].did;
+            let unique_did =
+                tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::from_u32(0)].did;
 
             let Some(nonnull_def) = tcx.type_of(unique_did).subst_identity().ty_adt_def() else {
                 span_bug!(tcx.def_span(unique_did), "expected Box to contain Unique")
             };
 
-            let nonnull_did = nonnull_def.non_enum_variant().fields[0].did;
+            let nonnull_did = nonnull_def.non_enum_variant().fields[FieldIdx::from_u32(0)].did;
 
             let patch = MirPatch::new(body);
 
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 98d2df71978..15b31d38394 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -907,7 +907,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
                 }
                 ty::Adt(adt_def, substs) => {
                     let var = parent_ty.variant_index.unwrap_or(FIRST_VARIANT);
-                    let Some(field) = adt_def.variant(var).fields.get(f.as_usize()) else {
+                    let Some(field) = adt_def.variant(var).fields.get(f) else {
                         self.validation = Err("malformed MIR");
                         return;
                     };
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 3a515fe8323..b52de4b72c9 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -5,7 +5,6 @@
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
 #![feature(never_type)]
-#![feature(once_cell)]
 #![feature(option_get_or_insert_default)]
 #![feature(trusted_step)]
 #![feature(try_blocks)]
@@ -91,6 +90,7 @@ mod separate_const_switch;
 mod shim;
 mod ssa;
 // This pass is public to allow external drivers to perform MIR cleanup
+mod check_alignment;
 pub mod simplify;
 mod simplify_branches;
 mod simplify_comparison_integral;
@@ -546,6 +546,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         tcx,
         body,
         &[
+            &check_alignment::CheckAlignment,
             &reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode.
             &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first
             &unreachable_prop::UnreachablePropagation,
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index af0222c8172..d34fa39352f 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -174,7 +174,7 @@
 //! regardless of whether it is actually needed or not.
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::sync::{par_for_each_in, MTLock, MTRef};
+use rustc_data_structures::sync::{par_for_each_in, MTLock, MTLockRef};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
@@ -341,8 +341,8 @@ pub fn collect_crate_mono_items(
     let recursion_limit = tcx.recursion_limit();
 
     {
-        let visited: MTRef<'_, _> = &mut visited;
-        let inlining_map: MTRef<'_, _> = &mut inlining_map;
+        let visited: MTLockRef<'_, _> = &mut visited;
+        let inlining_map: MTLockRef<'_, _> = &mut inlining_map;
 
         tcx.sess.time("monomorphization_collector_graph_walk", || {
             par_for_each_in(roots, |root| {
@@ -407,10 +407,10 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
 fn collect_items_rec<'tcx>(
     tcx: TyCtxt<'tcx>,
     starting_point: Spanned<MonoItem<'tcx>>,
-    visited: MTRef<'_, MTLock<FxHashSet<MonoItem<'tcx>>>>,
+    visited: MTLockRef<'_, FxHashSet<MonoItem<'tcx>>>,
     recursion_depths: &mut DefIdMap<usize>,
     recursion_limit: Limit,
-    inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>,
+    inlining_map: MTLockRef<'_, InliningMap<'tcx>>,
 ) {
     if !visited.lock_mut().insert(starting_point.node) {
         // We've been here already, no need to search again.
@@ -1119,7 +1119,8 @@ fn find_vtable_types_for_unsizing<'tcx>(
             let target_fields = &target_adt_def.non_enum_variant().fields;
 
             assert!(
-                coerce_index < source_fields.len() && source_fields.len() == target_fields.len()
+                coerce_index.index() < source_fields.len()
+                    && source_fields.len() == target_fields.len()
             );
 
             find_vtable_types_for_unsizing(
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 96765c296e7..e21bbd0217b 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -734,3 +734,7 @@ parse_unknown_start_of_token = unknown start of token: {$escaped}
 
 parse_box_syntax_removed = `box_syntax` has been removed
     .suggestion = use `Box::new()` instead
+
+parse_bad_return_type_notation_output =
+    return type not allowed with return type notation
+    .suggestion = remove the return type
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index a9d116012ae..aead216b61c 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2316,3 +2316,11 @@ pub struct BoxSyntaxRemoved<'a> {
     pub span: Span,
     pub code: &'a str,
 }
+
+#[derive(Diagnostic)]
+#[diag(parse_bad_return_type_notation_output)]
+pub(crate) struct BadReturnTypeNotationOutput {
+    #[primary_span]
+    #[suggestion(code = "", applicability = "maybe-incorrect")]
+    pub span: Span,
+}
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 9544afd3d6d..5210b8fe69d 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -989,8 +989,7 @@ impl<'a> Parser<'a> {
                     }
                     if self.token.kind == token::OpenDelim(Delimiter::Parenthesis) {
                         // Recover from bad turbofish: `foo.collect::Vec<_>()`.
-                        let args = AngleBracketedArgs { args, span }.into();
-                        segment.args = args;
+                        segment.args = Some(AngleBracketedArgs { args, span }.into());
 
                         self.sess.emit_err(GenericParamsWithoutAngleBrackets {
                             span,
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index b50d2984a4e..f1c9f0109f8 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -1,6 +1,6 @@
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{Parser, Restrictions, TokenType};
-use crate::maybe_whole;
+use crate::{errors, maybe_whole};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
 use rustc_ast::{
@@ -290,6 +290,25 @@ impl<'a> Parser<'a> {
                     })?;
                     let span = lo.to(self.prev_token.span);
                     AngleBracketedArgs { args, span }.into()
+                } else if self.token.kind == token::OpenDelim(Delimiter::Parenthesis)
+                    // FIXME(return_type_notation): Could also recover `...` here.
+                    && self.look_ahead(1, |tok| tok.kind == token::DotDot)
+                {
+                    let lo = self.token.span;
+                    self.bump();
+                    self.bump();
+                    self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
+                    let span = lo.to(self.prev_token.span);
+                    self.sess.gated_spans.gate(sym::return_type_notation, span);
+
+                    if self.eat_noexpect(&token::RArrow) {
+                        let lo = self.prev_token.span;
+                        let ty = self.parse_ty()?;
+                        self.sess
+                            .emit_err(errors::BadReturnTypeNotationOutput { span: lo.to(ty.span) });
+                    }
+
+                    P(GenericArgs::ReturnTypeNotation(span))
                 } else {
                     // `(T, U) -> R`
                     let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
@@ -300,7 +319,7 @@ impl<'a> Parser<'a> {
                     ParenthesizedArgs { span, inputs, inputs_span, output }.into()
                 };
 
-                PathSegment { ident, args, id: ast::DUMMY_NODE_ID }
+                PathSegment { ident, args: Some(args), id: ast::DUMMY_NODE_ID }
             } else {
                 // Generic arguments are not found.
                 PathSegment::from_ident(ident)
@@ -550,7 +569,13 @@ impl<'a> Parser<'a> {
 
                     // Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
                     if let AssocConstraintKind::Bound { .. } = kind {
-                        self.sess.gated_spans.gate(sym::associated_type_bounds, span);
+                        if gen_args.as_ref().map_or(false, |args| {
+                            matches!(args, GenericArgs::ReturnTypeNotation(..))
+                        }) {
+                            // This is already gated in `parse_path_segment`
+                        } else {
+                            self.sess.gated_spans.gate(sym::associated_type_bounds, span);
+                        }
                     }
                     let constraint =
                         AssocConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span };
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 3d9d2cc62e3..400c8dbe9bc 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -1059,8 +1059,11 @@ impl<'a> Parser<'a> {
             output,
         }
         .into();
-        *fn_path_segment =
-            ast::PathSegment { ident: fn_path_segment.ident, args, id: ast::DUMMY_NODE_ID };
+        *fn_path_segment = ast::PathSegment {
+            ident: fn_path_segment.ident,
+            args: Some(args),
+            id: ast::DUMMY_NODE_ID,
+        };
 
         // Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`.
         let mut generic_params = lifetimes
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index d063b51c8b8..b354dca7cc4 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -148,9 +148,6 @@ passes_doc_test_unknown =
 passes_doc_test_takes_list =
     `#[doc(test(...)]` takes a list of attributes
 
-passes_doc_primitive =
-    `doc(primitive)` should never have been stable
-
 passes_doc_cfg_hide_takes_list =
     `#[doc(cfg_hide(...)]` takes a list of attributes
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 1c459edabb8..80a93da2b45 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1109,17 +1109,6 @@ impl CheckAttrVisitor<'_> {
                             }
                         }
 
-                        sym::primitive => {
-                            if !self.tcx.features().rustdoc_internals {
-                                self.tcx.emit_spanned_lint(
-                                    INVALID_DOC_ATTRIBUTES,
-                                    hir_id,
-                                    i_meta.span,
-                                    errors::DocPrimitive,
-                                );
-                            }
-                        }
-
                         _ => {
                             let path = rustc_ast_pretty::pprust::path_to_string(&i_meta.path);
                             if i_meta.has_name(sym::spotlight) {
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 75ce446e6b4..91483fe3de7 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -16,6 +16,7 @@ use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint;
 use rustc_span::symbol::{sym, Symbol};
+use rustc_target::abi::FieldIdx;
 use std::mem;
 
 use crate::errors::{
@@ -232,7 +233,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             if let PatKind::Wild = pat.kind {
                 continue;
             }
-            self.insert_def_id(variant.fields[idx].did);
+            self.insert_def_id(variant.fields[FieldIdx::from_usize(idx)].did);
         }
     }
 
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 1b0cd5d91ab..139ba8c9677 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -289,10 +289,6 @@ pub struct DocTestTakesList;
 pub struct DocCfgHideTakesList;
 
 #[derive(LintDiagnostic)]
-#[diag(passes_doc_primitive)]
-pub struct DocPrimitive;
-
-#[derive(LintDiagnostic)]
 #[diag(passes_doc_test_unknown_any)]
 pub struct DocTestUnknownAny {
     pub path: String,
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 47e032758f2..ce44f709f3b 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -666,7 +666,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     fn visit_generic_args(&mut self, g: &'v ast::GenericArgs) {
         record_variants!(
             (self, g, g, Id::None, ast, GenericArgs, GenericArgs),
-            [AngleBracketed, Parenthesized]
+            [AngleBracketed, Parenthesized, ReturnTypeNotation]
         );
         ast_visit::walk_generic_args(self, g)
     }
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 3be0160d561..d27505d1ac8 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1082,7 +1082,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
                 // If the expression uses FRU we need to make sure all the unmentioned fields
                 // are checked for privacy (RFC 736). Rather than computing the set of
                 // unmentioned fields, just check them all.
-                for (vf_index, variant_field) in variant.fields.iter().enumerate() {
+                for (vf_index, variant_field) in variant.fields.iter_enumerated() {
                     let field = fields
                         .iter()
                         .find(|f| self.typeck_results().field_index(f.hir_id) == vf_index);
@@ -2149,6 +2149,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
 
     let mut check_visitor =
         TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities };
+    check_visitor.effective_visibility_diagnostic(CRATE_DEF_ID);
     tcx.hir().visit_all_item_likes_in_crate(&mut check_visitor);
 
     tcx.arena.alloc(visitor.effective_visibilities)
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 4cd94237061..021a67c9513 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -5,7 +5,6 @@
 #![feature(const_mut_refs)]
 #![feature(min_specialization)]
 #![feature(never_type)]
-#![feature(once_cell)]
 #![feature(rustc_attrs)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index 5f554a54dea..d3efc22a194 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -21,9 +21,6 @@ pub trait QueryCache: Sized {
     type Value: Copy + Debug;
 
     /// Checks if the query is already computed and in the cache.
-    /// It returns the shard index and a lock guard to the shard,
-    /// which will be used if the query is not in the cache and we need
-    /// to compute it.
     fn lookup(&self, key: &Self::Key) -> Option<(Self::Value, DepNodeIndex)>;
 
     fn complete(&self, key: Self::Key, value: Self::Value, index: DepNodeIndex);
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index a1ae9b8a521..3673f603d16 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -61,7 +61,7 @@ impl Resolver<'_, '_> {
         // For mod items `nearest_normal_mod` returns its argument, but we actually need its parent.
         let normal_mod_id = self.nearest_normal_mod(def_id);
         if normal_mod_id == def_id {
-            self.tcx.opt_local_parent(def_id).map_or(Visibility::Public, Visibility::Restricted)
+            Visibility::Restricted(self.tcx.local_parent(def_id))
         } else {
             Visibility::Restricted(normal_mod_id)
         }
@@ -80,12 +80,11 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
             r,
             def_effective_visibilities: Default::default(),
             import_effective_visibilities: Default::default(),
-            current_private_vis: Visibility::Public,
+            current_private_vis: Visibility::Restricted(CRATE_DEF_ID),
             changed: false,
         };
 
-        visitor.update(CRATE_DEF_ID, CRATE_DEF_ID);
-        visitor.current_private_vis = Visibility::Restricted(CRATE_DEF_ID);
+        visitor.def_effective_visibilities.update_root();
         visitor.set_bindings_effective_visibilities(CRATE_DEF_ID);
 
         while visitor.changed {
@@ -125,43 +124,32 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
 
         for (_, name_resolution) in resolutions.borrow().iter() {
             if let Some(mut binding) = name_resolution.borrow().binding() {
-                if !binding.is_ambiguity() {
-                    // Set the given effective visibility level to `Level::Direct` and
-                    // sets the rest of the `use` chain to `Level::Reexported` until
-                    // we hit the actual exported item.
-                    let mut parent_id = ParentId::Def(module_id);
-                    while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind
-                    {
-                        let binding_id = ImportId::new_unchecked(binding);
-                        self.update_import(binding_id, parent_id);
-
-                        parent_id = ParentId::Import(binding_id);
-                        binding = nested_binding;
-                    }
-
-                    if let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) {
-                        self.update_def(def_id, binding.vis.expect_local(), parent_id);
+                // Set the given effective visibility level to `Level::Direct` and
+                // sets the rest of the `use` chain to `Level::Reexported` until
+                // we hit the actual exported item.
+                //
+                // If the binding is ambiguous, put the root ambiguity binding and all reexports
+                // leading to it into the table. They are used by the `ambiguous_glob_reexports`
+                // lint. For all bindings added to the table this way `is_ambiguity` returns true.
+                let mut parent_id = ParentId::Def(module_id);
+                while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind {
+                    let binding_id = ImportId::new_unchecked(binding);
+                    self.update_import(binding_id, parent_id);
+
+                    if binding.ambiguity.is_some() {
+                        // Stop at the root ambiguity, further bindings in the chain should not
+                        // be reexported because the root ambiguity blocks any access to them.
+                        // (Those further bindings are most likely not ambiguities themselves.)
+                        break;
                     }
-                } else {
-                    // Put the root ambiguity binding and all reexports leading to it into the
-                    // table. They are used by the `ambiguous_glob_reexports` lint. For all
-                    // bindings added to the table here `is_ambiguity` returns true.
-                    let mut parent_id = ParentId::Def(module_id);
-                    while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind
-                    {
-                        let binding_id = ImportId::new_unchecked(binding);
-                        self.update_import(binding_id, parent_id);
 
-                        if binding.ambiguity.is_some() {
-                            // Stop at the root ambiguity, further bindings in the chain should not
-                            // be reexported because the root ambiguity blocks any access to them.
-                            // (Those further bindings are most likely not ambiguities themselves.)
-                            break;
-                        }
+                    parent_id = ParentId::Import(binding_id);
+                    binding = nested_binding;
+                }
 
-                        parent_id = ParentId::Import(binding_id);
-                        binding = nested_binding;
-                    }
+                if binding.ambiguity.is_none()
+                    && let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) {
+                    self.update_def(def_id, binding.vis.expect_local(), parent_id);
                 }
             }
         }
@@ -213,7 +201,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
         );
     }
 
-    fn update(&mut self, def_id: LocalDefId, parent_id: LocalDefId) {
+    fn update_field(&mut self, def_id: LocalDefId, parent_id: LocalDefId) {
         self.update_def(def_id, self.r.visibilities[&def_id], ParentId::Def(parent_id));
     }
 }
@@ -245,14 +233,14 @@ impl<'r, 'ast, 'tcx> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r, 't
                 for variant in variants {
                     let variant_def_id = self.r.local_def_id(variant.id);
                     for field in variant.data.fields() {
-                        self.update(self.r.local_def_id(field.id), variant_def_id);
+                        self.update_field(self.r.local_def_id(field.id), variant_def_id);
                     }
                 }
             }
 
             ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => {
                 for field in def.fields() {
-                    self.update(self.r.local_def_id(field.id), def_id);
+                    self.update_field(self.r.local_def_id(field.id), def_id);
                 }
             }
 
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 4ca54bab31a..f66bad1d429 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1110,6 +1110,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                         }
                     }
                 }
+                GenericArgs::ReturnTypeNotation(_span) => {}
             }
         }
     }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 0e84432a5b4..99fad22d4a1 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -312,6 +312,7 @@ impl<'a> From<&'a ast::PathSegment> for Segment {
                     (args.span, found_lifetimes)
                 }
                 GenericArgs::Parenthesized(args) => (args.span, true),
+                GenericArgs::ReturnTypeNotation(span) => (*span, false),
             }
         } else {
             (DUMMY_SP, false)
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 44a27bbc175..9eae99be2e9 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -339,12 +339,14 @@ pub fn inner_docs(attrs: &[ast::Attribute]) -> bool {
     attrs.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == ast::AttrStyle::Inner)
 }
 
-/// Has `#[doc(primitive)]` or `#[doc(keyword)]`.
+/// Has `#[rustc_doc_primitive]` or `#[doc(keyword)]`.
 pub fn has_primitive_or_keyword_docs(attrs: &[ast::Attribute]) -> bool {
     for attr in attrs {
-        if attr.has_name(sym::doc) && let Some(items) = attr.meta_item_list() {
+        if attr.has_name(sym::rustc_doc_primitive) {
+            return true;
+        } else if attr.has_name(sym::doc) && let Some(items) = attr.meta_item_list() {
             for item in items {
-                if item.has_name(sym::primitive) || item.has_name(sym::keyword) {
+                if item.has_name(sym::keyword) {
                     return true;
                 }
             }
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 2404928b254..40879db49de 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -68,6 +68,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
     use std::ffi::{CStr, OsStr};
     use std::os::unix::prelude::*;
 
+    #[cfg(not(target_os = "aix"))]
     unsafe {
         let addr = current_dll_path as usize as *mut _;
         let mut info = std::mem::zeroed();
@@ -81,6 +82,49 @@ fn current_dll_path() -> Result<PathBuf, String> {
         let os = OsStr::from_bytes(bytes);
         Ok(PathBuf::from(os))
     }
+
+    #[cfg(target_os = "aix")]
+    unsafe {
+        // On AIX, the symbol `current_dll_path` references a function descriptor.
+        // A function descriptor is consisted of (See https://reviews.llvm.org/D62532)
+        // * The address of the entry point of the function.
+        // * The TOC base address for the function.
+        // * The environment pointer.
+        // The function descriptor is in the data section.
+        let addr = current_dll_path as u64;
+        let mut buffer = vec![std::mem::zeroed::<libc::ld_info>(); 64];
+        loop {
+            if libc::loadquery(
+                libc::L_GETINFO,
+                buffer.as_mut_ptr() as *mut i8,
+                (std::mem::size_of::<libc::ld_info>() * buffer.len()) as u32,
+            ) >= 0
+            {
+                break;
+            } else {
+                if std::io::Error::last_os_error().raw_os_error().unwrap() != libc::ENOMEM {
+                    return Err("loadquery failed".into());
+                }
+                buffer.resize(buffer.len() * 2, std::mem::zeroed::<libc::ld_info>());
+            }
+        }
+        let mut current = buffer.as_mut_ptr() as *mut libc::ld_info;
+        loop {
+            let data_base = (*current).ldinfo_dataorg as u64;
+            let data_end = data_base + (*current).ldinfo_datasize;
+            if (data_base..data_end).contains(&addr) {
+                let bytes = CStr::from_ptr(&(*current).ldinfo_filename[0]).to_bytes();
+                let os = OsStr::from_bytes(bytes);
+                return Ok(PathBuf::from(os));
+            }
+            if (*current).ldinfo_next == 0 {
+                break;
+            }
+            current =
+                (current as *mut i8).offset((*current).ldinfo_next as isize) as *mut libc::ld_info;
+        }
+        return Err(format!("current dll's address {} is not in the load map", addr));
+    }
 }
 
 #[cfg(windows)]
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index 74aef785163..968728905e7 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -2,7 +2,7 @@
 #![feature(let_chains)]
 #![feature(min_specialization)]
 #![feature(never_type)]
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![feature(option_get_or_insert_default)]
 #![feature(rustc_attrs)]
 #![feature(map_many_mut)]
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 02cffc762be..e14760aa018 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -87,6 +87,14 @@ pub struct SessionGlobals {
     symbol_interner: symbol::Interner,
     span_interner: Lock<span_encoding::SpanInterner>,
     hygiene_data: Lock<hygiene::HygieneData>,
+
+    /// A reference to the source map in the `Session`. It's an `Option`
+    /// because it can't be initialized until `Session` is created, which
+    /// happens after `SessionGlobals`. `set_source_map` does the
+    /// initialization.
+    ///
+    /// This field should only be used in places where the `Session` is truly
+    /// not available, such as `<Span as Debug>::fmt`.
     source_map: Lock<Option<Lrc<SourceMap>>>,
 }
 
@@ -1013,16 +1021,9 @@ impl<D: Decoder> Decodable<D> for Span {
     }
 }
 
-/// Calls the provided closure, using the provided `SourceMap` to format
-/// any spans that are debug-printed during the closure's execution.
-///
-/// Normally, the global `TyCtxt` is used to retrieve the `SourceMap`
-/// (see `rustc_interface::callbacks::span_debug1`). However, some parts
-/// of the compiler (e.g. `rustc_parse`) may debug-print `Span`s before
-/// a `TyCtxt` is available. In this case, we fall back to
-/// the `SourceMap` provided to this function. If that is not available,
-/// we fall back to printing the raw `Span` field values.
-pub fn with_source_map<T, F: FnOnce() -> T>(source_map: Lrc<SourceMap>, f: F) -> T {
+/// Insert `source_map` into the session globals for the duration of the
+/// closure's execution.
+pub fn set_source_map<T, F: FnOnce() -> T>(source_map: Lrc<SourceMap>, f: F) -> T {
     with_session_globals(|session_globals| {
         *session_globals.source_map.borrow_mut() = Some(source_map);
     });
@@ -1041,6 +1042,8 @@ pub fn with_source_map<T, F: FnOnce() -> T>(source_map: Lrc<SourceMap>, f: F) ->
 
 impl fmt::Debug for Span {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // Use the global `SourceMap` to print the span. If that's not
+        // available, fall back to printing the raw values.
         with_session_globals(|session_globals| {
             if let Some(source_map) = &*session_globals.source_map.borrow() {
                 write!(f, "{} ({:?})", source_map.span_to_diagnostic_string(*self), self.ctxt())
diff --git a/compiler/rustc_span/src/profiling.rs b/compiler/rustc_span/src/profiling.rs
index 0ab890b9f01..66e5369da3a 100644
--- a/compiler/rustc_span/src/profiling.rs
+++ b/compiler/rustc_span/src/profiling.rs
@@ -1,3 +1,5 @@
+use crate::source_map::SourceMap;
+
 use std::borrow::Borrow;
 
 use rustc_data_structures::profiling::EventArgRecorder;
@@ -11,25 +13,17 @@ pub trait SpannedEventArgRecorder {
     ///
     /// Note: when self-profiling with costly event arguments, at least one argument
     /// needs to be recorded. A panic will be triggered if that doesn't happen.
-    fn record_arg_with_span<A>(&mut self, event_arg: A, span: crate::Span)
+    fn record_arg_with_span<A>(&mut self, source_map: &SourceMap, event_arg: A, span: crate::Span)
     where
         A: Borrow<str> + Into<String>;
 }
 
 impl SpannedEventArgRecorder for EventArgRecorder<'_> {
-    fn record_arg_with_span<A>(&mut self, event_arg: A, span: crate::Span)
+    fn record_arg_with_span<A>(&mut self, source_map: &SourceMap, event_arg: A, span: crate::Span)
     where
         A: Borrow<str> + Into<String>,
     {
         self.record_arg(event_arg);
-
-        let span_arg = crate::with_session_globals(|session_globals| {
-            if let Some(source_map) = &*session_globals.source_map.borrow() {
-                source_map.span_to_embeddable_string(span)
-            } else {
-                format!("{span:?}")
-            }
-        });
-        self.record_arg(span_arg);
+        self.record_arg(source_map.span_to_embeddable_string(span));
     }
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 0ed99353145..0e55e81143d 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1069,6 +1069,7 @@ symbols! {
         panic_implementation,
         panic_info,
         panic_location,
+        panic_misaligned_pointer_dereference,
         panic_nounwind,
         panic_runtime,
         panic_str,
@@ -1195,6 +1196,7 @@ symbols! {
         residual,
         result,
         return_position_impl_trait_in_trait,
+        return_type_notation,
         rhs,
         rintf32,
         rintf64,
@@ -1245,6 +1247,7 @@ symbols! {
         rustc_diagnostic_macros,
         rustc_dirty,
         rustc_do_not_const_check,
+        rustc_doc_primitive,
         rustc_dummy,
         rustc_dump_env_program_clauses,
         rustc_dump_program_clauses,
diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
index 7ee4f332306..2e5a8b7debc 100644
--- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
@@ -291,7 +291,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
                 if nt != t {
                     return self.fold_ty(nt);
                 } else {
-                    CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
+                    CanonicalVarKind::Ty(CanonicalTyVarKind::Float)
                 }
             }
             ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index e64b4a7656f..705e79aebd8 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -67,7 +67,20 @@ pub(super) enum IsNormalizesToHack {
 
 #[derive(Debug, Clone)]
 pub(super) struct NestedGoals<'tcx> {
+    /// This normalizes-to goal that is treated specially during the evaluation
+    /// loop. In each iteration we take the RHS of the projection, replace it with
+    /// a fresh inference variable, and only after evaluating that goal do we
+    /// equate the fresh inference variable with the actual RHS of the predicate.
+    ///
+    /// This is both to improve caching, and to avoid using the RHS of the
+    /// projection predicate to influence the normalizes-to candidate we select.
+    ///
+    /// This is not a 'real' nested goal. We must not forget to replace the RHS
+    /// with a fresh inference variable when we evaluate this goal. That can result
+    /// in a trait solver cycle. This would currently result in overflow but can be
+    /// can be unsound with more powerful coinduction in the future.
     pub(super) normalizes_to_hack_goal: Option<Goal<'tcx, ty::ProjectionPredicate<'tcx>>>,
+    /// The rest of the goals which have not yet processed or remain ambiguous.
     pub(super) goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
 }
 
@@ -182,6 +195,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
             canonical_response,
         )?;
 
+        if !has_changed && !nested_goals.is_empty() {
+            bug!("an unchanged goal shouldn't have any side-effects on instantiation");
+        }
+
         // Check that rerunning this query with its inference constraints applied
         // doesn't result in new inference constraints and has the same result.
         //
@@ -199,9 +216,17 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
             let canonical_response =
                 EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
             if !canonical_response.value.var_values.is_identity() {
-                bug!("unstable result: {goal:?} {canonical_goal:?} {canonical_response:?}");
+                bug!(
+                    "unstable result: re-canonicalized goal={canonical_goal:#?} \
+                     response={canonical_response:#?}"
+                );
+            }
+            if certainty != canonical_response.value.certainty {
+                bug!(
+                    "unstable certainty: {certainty:#?} re-canonicalized goal={canonical_goal:#?} \
+                     response={canonical_response:#?}"
+                );
             }
-            assert_eq!(certainty, canonical_response.value.certainty);
         }
 
         Ok((has_changed, certainty, nested_goals))
@@ -281,15 +306,44 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
                 let mut has_changed = Err(Certainty::Yes);
 
                 if let Some(goal) = goals.normalizes_to_hack_goal.take() {
-                    let (_, certainty, nested_goals) = match this.evaluate_goal(
-                        IsNormalizesToHack::Yes,
-                        goal.with(this.tcx(), ty::Binder::dummy(goal.predicate)),
+                    // Replace the goal with an unconstrained infer var, so the
+                    // RHS does not affect projection candidate assembly.
+                    let unconstrained_rhs = this.next_term_infer_of_kind(goal.predicate.term);
+                    let unconstrained_goal = goal.with(
+                        this.tcx(),
+                        ty::Binder::dummy(ty::ProjectionPredicate {
+                            projection_ty: goal.predicate.projection_ty,
+                            term: unconstrained_rhs,
+                        }),
+                    );
+
+                    let (_, certainty, instantiate_goals) =
+                        match this.evaluate_goal(IsNormalizesToHack::Yes, unconstrained_goal) {
+                            Ok(r) => r,
+                            Err(NoSolution) => return Some(Err(NoSolution)),
+                        };
+                    new_goals.goals.extend(instantiate_goals);
+
+                    // Finally, equate the goal's RHS with the unconstrained var.
+                    // We put the nested goals from this into goals instead of
+                    // next_goals to avoid needing to process the loop one extra
+                    // time if this goal returns something -- I don't think this
+                    // matters in practice, though.
+                    match this.eq_and_get_goals(
+                        goal.param_env,
+                        goal.predicate.term,
+                        unconstrained_rhs,
                     ) {
-                        Ok(r) => r,
+                        Ok(eq_goals) => {
+                            goals.goals.extend(eq_goals);
+                        }
                         Err(NoSolution) => return Some(Err(NoSolution)),
                     };
-                    new_goals.goals.extend(nested_goals);
 
+                    // We only look at the `projection_ty` part here rather than
+                    // looking at the "has changed" return from evaluate_goal,
+                    // because we expect the `unconstrained_rhs` part of the predicate
+                    // to have changed -- that means we actually normalized successfully!
                     if goal.predicate.projection_ty
                         != this.resolve_vars_if_possible(goal.predicate.projection_ty)
                     {
@@ -299,40 +353,22 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
                     match certainty {
                         Certainty::Yes => {}
                         Certainty::Maybe(_) => {
-                            let goal = this.resolve_vars_if_possible(goal);
-
-                            // The rhs of this `normalizes-to` must always be an unconstrained infer var as it is
-                            // the hack used by `normalizes-to` to ensure that every `normalizes-to` behaves the same
-                            // regardless of the rhs.
-                            //
-                            // However it is important not to unconditionally replace the rhs with a new infer var
-                            // as otherwise we may replace the original unconstrained infer var with a new infer var
-                            // and never propagate any constraints on the new var back to the original var.
-                            let term = this
-                                .term_is_fully_unconstrained(goal)
-                                .then_some(goal.predicate.term)
-                                .unwrap_or_else(|| {
-                                    this.next_term_infer_of_kind(goal.predicate.term)
-                                });
-                            let projection_pred = ty::ProjectionPredicate {
-                                term,
-                                projection_ty: goal.predicate.projection_ty,
-                            };
+                            // We need to resolve vars here so that we correctly
+                            // deal with `has_changed` in the next iteration.
                             new_goals.normalizes_to_hack_goal =
-                                Some(goal.with(this.tcx(), projection_pred));
-
+                                Some(this.resolve_vars_if_possible(goal));
                             has_changed = has_changed.map_err(|c| c.unify_and(certainty));
                         }
                     }
                 }
 
-                for nested_goal in goals.goals.drain(..) {
-                    let (changed, certainty, nested_goals) =
-                        match this.evaluate_goal(IsNormalizesToHack::No, nested_goal) {
+                for goal in goals.goals.drain(..) {
+                    let (changed, certainty, instantiate_goals) =
+                        match this.evaluate_goal(IsNormalizesToHack::No, goal) {
                             Ok(result) => result,
                             Err(NoSolution) => return Some(Err(NoSolution)),
                         };
-                    new_goals.goals.extend(nested_goals);
+                    new_goals.goals.extend(instantiate_goals);
 
                     if changed {
                         has_changed = Ok(());
@@ -341,7 +377,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
                     match certainty {
                         Certainty::Yes => {}
                         Certainty::Maybe(_) => {
-                            new_goals.goals.push(nested_goal);
+                            new_goals.goals.push(goal);
                             has_changed = has_changed.map_err(|c| c.unify_and(certainty));
                         }
                     }
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 48f7d3e3e40..e0a69438dec 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -34,16 +34,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             let candidates = self.assemble_and_evaluate_candidates(goal);
             self.merge_candidates(candidates)
         } else {
-            let predicate = goal.predicate;
-            let unconstrained_rhs = self.next_term_infer_of_kind(predicate.term);
-            let unconstrained_predicate = ProjectionPredicate {
-                projection_ty: goal.predicate.projection_ty,
-                term: unconstrained_rhs,
-            };
-
-            self.set_normalizes_to_hack_goal(goal.with(self.tcx(), unconstrained_predicate));
-            self.try_evaluate_added_goals()?;
-            self.eq(goal.param_env, unconstrained_rhs, predicate.term)?;
+            self.set_normalizes_to_hack_goal(goal);
             self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
         }
     }
@@ -344,14 +335,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                         LangItem::Sized,
                         [ty::GenericArg::from(goal.predicate.self_ty())],
                     ));
-
                     ecx.add_goal(goal.with(tcx, sized_predicate));
-                    ecx.eq(goal.param_env, goal.predicate.term, tcx.types.unit.into())?;
-                    return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
+                    tcx.types.unit
                 }
 
                 ty::Adt(def, substs) if def.is_struct() => {
-                    match def.non_enum_variant().fields.last() {
+                    match def.non_enum_variant().fields.raw.last() {
                         None => tcx.types.unit,
                         Some(field_def) => {
                             let self_ty = field_def.ty(tcx, substs);
@@ -483,9 +472,49 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
-        let discriminant = goal.predicate.self_ty().discriminant_ty(ecx.tcx());
+        let self_ty = goal.predicate.self_ty();
+        let discriminant_ty = match *self_ty.kind() {
+            ty::Bool
+            | ty::Char
+            | ty::Int(..)
+            | ty::Uint(..)
+            | ty::Float(..)
+            | ty::Array(..)
+            | ty::RawPtr(..)
+            | ty::Ref(..)
+            | ty::FnDef(..)
+            | ty::FnPtr(..)
+            | ty::Closure(..)
+            | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
+            | ty::Generator(..)
+            | ty::GeneratorWitness(..)
+            | ty::GeneratorWitnessMIR(..)
+            | ty::Never
+            | ty::Foreign(..)
+            | ty::Adt(_, _)
+            | ty::Str
+            | ty::Slice(_)
+            | ty::Dynamic(_, _, _)
+            | ty::Tuple(_)
+            | ty::Error(_) => self_ty.discriminant_ty(ecx.tcx()),
+
+            // We do not call `Ty::discriminant_ty` on alias, param, or placeholder
+            // types, which return `<self_ty as DiscriminantKind>::Discriminant`
+            // (or ICE in the case of placeholders). Projecting a type to itself
+            // is never really productive.
+            ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
+                return Err(NoSolution);
+            }
+
+            ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
+            | ty::Bound(..) => bug!(
+                "unexpected self ty `{:?}` when normalizing `<T as DiscriminantKind>::Discriminant`",
+                goal.predicate.self_ty()
+            ),
+        };
+
         ecx.probe(|ecx| {
-            ecx.eq(goal.param_env, goal.predicate.term, discriminant.into())?;
+            ecx.eq(goal.param_env, goal.predicate.term, discriminant_ty.into())?;
             ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
         })
     }
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index f522a8f7e65..ce3db83d33d 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -407,6 +407,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
                     let tail_field = a_def
                         .non_enum_variant()
                         .fields
+                        .raw
                         .last()
                         .expect("expected unsized ADT to have a tail field");
                     let tail_field_ty = tcx.type_of(tail_field.did);
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
index 9817186b874..fcb965dd725 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
@@ -214,9 +214,20 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
         ty::Closure(_, substs) => {
             let closure_substs = substs.as_closure();
             match closure_substs.kind_ty().to_opt_closure_kind() {
-                Some(closure_kind) if closure_kind.extends(goal_kind) => {}
-                None => return Ok(None),
-                _ => return Err(NoSolution),
+                // If the closure's kind doesn't extend the goal kind,
+                // then the closure doesn't implement the trait.
+                Some(closure_kind) => {
+                    if !closure_kind.extends(goal_kind) {
+                        return Err(NoSolution);
+                    }
+                }
+                // Closure kind is not yet determined, so we return ambiguity unless
+                // the expected kind is `FnOnce` as that is always implemented.
+                None => {
+                    if goal_kind != ty::ClosureKind::FnOnce {
+                        return Ok(None);
+                    }
+                }
             }
             Ok(Some(closure_substs.sig().map_bound(|sig| (sig.inputs()[0], sig.output()))))
         }
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index eb354bc3f50..5e60bc01bb6 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -1078,6 +1078,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 let tail_field = def
                     .non_enum_variant()
                     .fields
+                    .raw
                     .last()
                     .expect("expected unsized ADT to have a tail field");
                 let tail_field_ty = tcx.type_of(tail_field.did);
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index bf0bc202852..de1e1a527d5 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -1,3 +1,4 @@
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
@@ -196,20 +197,26 @@ fn associated_types_for_impl_traits_in_associated_fn(
 
     match tcx.def_kind(parent_def_id) {
         DefKind::Trait => {
-            struct RPITVisitor {
-                rpits: Vec<LocalDefId>,
+            struct RPITVisitor<'tcx> {
+                rpits: FxIndexSet<LocalDefId>,
+                tcx: TyCtxt<'tcx>,
             }
 
-            impl<'v> Visitor<'v> for RPITVisitor {
-                fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
-                    if let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind {
-                        self.rpits.push(item_id.owner_id.def_id)
+            impl<'tcx> Visitor<'tcx> for RPITVisitor<'tcx> {
+                fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
+                    if let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind
+                        && self.rpits.insert(item_id.owner_id.def_id)
+                    {
+                        let opaque_item = self.tcx.hir().expect_item(item_id.owner_id.def_id).expect_opaque_ty();
+                        for bound in opaque_item.bounds {
+                            intravisit::walk_param_bound(self, bound);
+                        }
                     }
                     intravisit::walk_ty(self, ty)
                 }
             }
 
-            let mut visitor = RPITVisitor { rpits: Vec::new() };
+            let mut visitor = RPITVisitor { tcx, rpits: FxIndexSet::default() };
 
             if let Some(output) = tcx.hir().get_fn_output(fn_def_id) {
                 visitor.visit_fn_ret_ty(output);
@@ -227,13 +234,9 @@ fn associated_types_for_impl_traits_in_associated_fn(
 
             tcx.arena.alloc_from_iter(
                 tcx.associated_types_for_impl_traits_in_associated_fn(trait_fn_def_id).iter().map(
-                    move |trait_assoc_def_id| {
-                        associated_type_for_impl_trait_in_impl(
-                            tcx,
-                            trait_assoc_def_id.expect_local(),
-                            fn_def_id,
-                        )
-                        .to_def_id()
+                    move |&trait_assoc_def_id| {
+                        associated_type_for_impl_trait_in_impl(tcx, trait_assoc_def_id, fn_def_id)
+                            .to_def_id()
                     },
                 ),
             )
@@ -355,7 +358,7 @@ fn associated_type_for_impl_trait_in_trait(
 /// that inherits properties that we infer from the method and the associated type.
 fn associated_type_for_impl_trait_in_impl(
     tcx: TyCtxt<'_>,
-    trait_assoc_def_id: LocalDefId,
+    trait_assoc_def_id: DefId,
     impl_fn_def_id: LocalDefId,
 ) -> LocalDefId {
     let impl_local_def_id = tcx.local_parent(impl_fn_def_id);
@@ -380,7 +383,7 @@ fn associated_type_for_impl_trait_in_impl(
         name: kw::Empty,
         kind: ty::AssocKind::Type,
         def_id,
-        trait_item_def_id: Some(trait_assoc_def_id.to_def_id()),
+        trait_item_def_id: Some(trait_assoc_def_id),
         container: ty::ImplContainer,
         fn_has_self_parameter: false,
         opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }),
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 380931742e3..73f86f74d14 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -320,7 +320,7 @@ fn layout_of_uncached<'tcx>(
             }
 
             // Type of the first ADT field:
-            let f0_ty = def.non_enum_variant().fields[0].ty(tcx, substs);
+            let f0_ty = def.non_enum_variant().fields[FieldIdx::from_u32(0)].ty(tcx, substs);
 
             // Heterogeneous SIMD vectors are not supported:
             // (should be caught by typeck)
@@ -456,7 +456,8 @@ fn layout_of_uncached<'tcx>(
                     {
                         let param_env = tcx.param_env(def.did());
                         def.is_struct()
-                            && match def.variants().iter().next().and_then(|x| x.fields.last()) {
+                            && match def.variants().iter().next().and_then(|x| x.fields.raw.last())
+                            {
                                 Some(last_field) => tcx
                                     .type_of(last_field.did)
                                     .subst_identity()
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 50aeb7f440f..cb06c7acff0 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -107,7 +107,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
     let result = tcx.mk_type_list_from_iter(
         def.variants()
             .iter()
-            .flat_map(|v| v.fields.last())
+            .filter_map(|v| v.fields.raw.last())
             .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did).subst_identity())),
     );
 
@@ -542,7 +542,7 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32
 
     // The last field of the structure has to exist and contain type/const parameters.
     let Some((tail_field, prefix_fields)) =
-        def.non_enum_variant().fields.split_last() else
+        def.non_enum_variant().fields.raw.split_last() else
     {
         return BitSet::new_empty(num_params);
     };
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index 48e907e402c..05dbcdc904e 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -2394,7 +2394,8 @@ impl<T, A: Allocator> VecDeque<T, A> {
     }
 
     /// Binary searches this `VecDeque` for a given element.
-    /// This behaves similarly to [`contains`] if this `VecDeque` is sorted.
+    /// If the `VecDeque` is not sorted, the returned result is unspecified and
+    /// meaningless.
     ///
     /// If the value is found then [`Result::Ok`] is returned, containing the
     /// index of the matching element. If there are multiple matches, then any
@@ -2404,7 +2405,6 @@ impl<T, A: Allocator> VecDeque<T, A> {
     ///
     /// See also [`binary_search_by`], [`binary_search_by_key`], and [`partition_point`].
     ///
-    /// [`contains`]: VecDeque::contains
     /// [`binary_search_by`]: VecDeque::binary_search_by
     /// [`binary_search_by_key`]: VecDeque::binary_search_by_key
     /// [`partition_point`]: VecDeque::partition_point
@@ -2450,12 +2450,13 @@ impl<T, A: Allocator> VecDeque<T, A> {
     }
 
     /// Binary searches this `VecDeque` with a comparator function.
-    /// This behaves similarly to [`contains`] if this `VecDeque` is sorted.
     ///
-    /// The comparator function should implement an order consistent
-    /// with the sort order of the deque, returning an order code that
-    /// indicates whether its argument is `Less`, `Equal` or `Greater`
-    /// than the desired target.
+    /// The comparator function should return an order code that indicates
+    /// whether its argument is `Less`, `Equal` or `Greater` the desired
+    /// target.
+    /// If the `VecDeque` is not sorted or if the comparator function does not
+    /// implement an order consistent with the sort order of the underlying
+    /// `VecDeque`, the returned result is unspecified and meaningless.
     ///
     /// If the value is found then [`Result::Ok`] is returned, containing the
     /// index of the matching element. If there are multiple matches, then any
@@ -2465,7 +2466,6 @@ impl<T, A: Allocator> VecDeque<T, A> {
     ///
     /// See also [`binary_search`], [`binary_search_by_key`], and [`partition_point`].
     ///
-    /// [`contains`]: VecDeque::contains
     /// [`binary_search`]: VecDeque::binary_search
     /// [`binary_search_by_key`]: VecDeque::binary_search_by_key
     /// [`partition_point`]: VecDeque::partition_point
@@ -2505,10 +2505,11 @@ impl<T, A: Allocator> VecDeque<T, A> {
     }
 
     /// Binary searches this `VecDeque` with a key extraction function.
-    /// This behaves similarly to [`contains`] if this `VecDeque` is sorted.
     ///
     /// Assumes that the deque is sorted by the key, for instance with
     /// [`make_contiguous().sort_by_key()`] using the same key extraction function.
+    /// If the deque is not sorted by the key, the returned result is
+    /// unspecified and meaningless.
     ///
     /// If the value is found then [`Result::Ok`] is returned, containing the
     /// index of the matching element. If there are multiple matches, then any
@@ -2518,7 +2519,6 @@ impl<T, A: Allocator> VecDeque<T, A> {
     ///
     /// See also [`binary_search`], [`binary_search_by`], and [`partition_point`].
     ///
-    /// [`contains`]: VecDeque::contains
     /// [`make_contiguous().sort_by_key()`]: VecDeque::make_contiguous
     /// [`binary_search`]: VecDeque::binary_search
     /// [`binary_search_by`]: VecDeque::binary_search_by
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index afbe5cfaf8e..b87ef59f64a 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -256,7 +256,7 @@ impl str {
     /// assert_eq!("than an old", s.replace("is", "an"));
     /// ```
     ///
-    /// When the pattern doesn't match:
+    /// When the pattern doesn't match, it returns this string slice as [`String`]:
     ///
     /// ```
     /// let s = "this is old";
@@ -297,7 +297,7 @@ impl str {
     /// assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1));
     /// ```
     ///
-    /// When the pattern doesn't match:
+    /// When the pattern doesn't match, it returns this string slice as [`String`]:
     ///
     /// ```
     /// let s = "this is old";
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index c27ca642e9b..cd5301ee77f 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -42,7 +42,6 @@
 #![feature(slice_flatten)]
 #![feature(thin_box)]
 #![feature(strict_provenance)]
-#![feature(once_cell)]
 #![feature(drain_keep_rest)]
 #![deny(fuzzy_provenance_casts)]
 #![deny(unsafe_op_in_unsafe_fn)]
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 9d1720acf36..63bce5d0ccd 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -11,36 +11,77 @@
 //! mutate it.
 //!
 //! Shareable mutable containers exist to permit mutability in a controlled manner, even in the
-//! presence of aliasing. Both [`Cell<T>`] and [`RefCell<T>`] allow doing this in a single-threaded
-//! way. However, neither `Cell<T>` nor `RefCell<T>` are thread safe (they do not implement
-//! [`Sync`]). If you need to do aliasing and mutation between multiple threads it is possible to
-//! use [`Mutex<T>`], [`RwLock<T>`] or [`atomic`] types.
+//! presence of aliasing. [`Cell<T>`], [`RefCell<T>`], and [`OnceCell<T>`] allow doing this in
+//! a single-threaded way—they do not implement [`Sync`]. (If you need to do aliasing and
+//! mutation among multiple threads, [`Mutex<T>`], [`RwLock<T>`], [`OnceLock<T>`] or [`atomic`]
+//! types are the correct data structures to do so).
 //!
-//! Values of the `Cell<T>` and `RefCell<T>` types may be mutated through shared references (i.e.
-//! the common `&T` type), whereas most Rust types can only be mutated through unique (`&mut T`)
-//! references. We say that `Cell<T>` and `RefCell<T>` provide 'interior mutability', in contrast
-//! with typical Rust types that exhibit 'inherited mutability'.
+//! Values of the `Cell<T>`, `RefCell<T>`, and `OnceCell<T>` types may be mutated through shared
+//! references (i.e. the common `&T` type), whereas most Rust types can only be mutated through
+//! unique (`&mut T`) references. We say these cell types provide 'interior mutability'
+//! (mutable via `&T`), in contrast with typical Rust types that exhibit 'inherited mutability'
+//! (mutable only via `&mut T`).
 //!
-//! Cell types come in two flavors: `Cell<T>` and `RefCell<T>`. `Cell<T>` implements interior
-//! mutability by moving values in and out of the `Cell<T>`. To use references instead of values,
-//! one must use the `RefCell<T>` type, acquiring a write lock before mutating. `Cell<T>` provides
-//! methods to retrieve and change the current interior value:
+//! Cell types come in three flavors: `Cell<T>`, `RefCell<T>`, and `OnceCell<T>`. Each provides
+//! a different way of providing safe interior mutability.
+//!
+//! ## `Cell<T>`
+//!
+//! [`Cell<T>`] implements interior mutability by moving values in and out of the cell. That is, an
+//! `&mut T` to the inner value can never be obtained, and the value itself cannot be directly
+//! obtained without replacing it with something else. Both of these rules ensure that there is
+//! never more than one reference pointing to the inner value. This type provides the following
+//! methods:
 //!
 //!  - For types that implement [`Copy`], the [`get`](Cell::get) method retrieves the current
-//!    interior value.
+//!    interior value by duplicating it.
 //!  - For types that implement [`Default`], the [`take`](Cell::take) method replaces the current
 //!    interior value with [`Default::default()`] and returns the replaced value.
-//!  - For all types, the [`replace`](Cell::replace) method replaces the current interior value and
-//!    returns the replaced value and the [`into_inner`](Cell::into_inner) method consumes the
-//!    `Cell<T>` and returns the interior value. Additionally, the [`set`](Cell::set) method
-//!    replaces the interior value, dropping the replaced value.
+//!  - All types have:
+//!    - [`replace`](Cell::replace): replaces the current interior value and returns the replaced
+//!      value.
+//!    - [`into_inner`](Cell::into_inner): this method consumes the `Cell<T>` and returns the
+//!      interior value.
+//!    - [`set`](Cell::set): this method replaces the interior value, dropping the replaced value.
+//!
+//! `Cell<T>` is typically used for more simple types where copying or moving values isn't too
+//! resource intensive (e.g. numbers), and should usually be preferred over other cell types when
+//! possible. For larger and non-copy types, `RefCell` provides some advantages.
 //!
-//! `RefCell<T>` uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can
+//! ## `RefCell<T>`
+//!
+//! [`RefCell<T>`] uses Rust's lifetimes to implement "dynamic borrowing", a process whereby one can
 //! claim temporary, exclusive, mutable access to the inner value. Borrows for `RefCell<T>`s are
-//! tracked 'at runtime', unlike Rust's native reference types which are entirely tracked
-//! statically, at compile time. Because `RefCell<T>` borrows are dynamic it is possible to attempt
-//! to borrow a value that is already mutably borrowed; when this happens it results in thread
-//! panic.
+//! tracked at _runtime_, unlike Rust's native reference types which are entirely tracked
+//! statically, at compile time.
+//!
+//! An immutable reference to a `RefCell`'s inner value (`&T`) can be obtained with
+//! [`borrow`](`RefCell::borrow`), and a mutable borrow (`&mut T`) can be obtained with
+//! [`borrow_mut`](`RefCell::borrow_mut`). When these functions are called, they first verify that
+//! Rust's borrow rules will be satisfied: any number of immutable borrows are allowed or a
+//! single immutable borrow is allowed, but never both. If a borrow is attempted that would violate
+//! these rules, the thread will panic.
+//!
+//! The corresponding [`Sync`] version of `RefCell<T>` is [`RwLock<T>`].
+//!
+//! ## `OnceCell<T>`
+//!
+//! [`OnceCell<T>`] is somewhat of a hybrid of `Cell` and `RefCell` that works for values that
+//! typically only need to be set once. This means that a reference `&T` can be obtained without
+//! moving or copying the inner value (unlike `Cell`) but also without runtime checks (unlike
+//! `RefCell`). However, its value can also not be updated once set unless you have a mutable
+//! reference to the `OnceCell`.
+//!
+//! `OnceCell` provides the following methods:
+//!
+//! - [`get`](OnceCell::get): obtain a reference to the inner value
+//! - [`set`](OnceCell::set): set the inner value if it is unset (returns a `Result`)
+//! - [`get_or_init`](OnceCell::get_or_init): return the inner value, initializing it if needed
+//! - [`get_mut`](OnceCell::get_mut): provide a mutable reference to the inner value, only available
+//!   if you have a mutable reference to the cell itself.
+//!
+//! The corresponding [`Sync`] version of `OnceCell<T>` is [`OnceLock<T>`].
+//!
 //!
 //! # When to choose interior mutability
 //!
@@ -188,6 +229,8 @@
 //! [`Rc<T>`]: ../../std/rc/struct.Rc.html
 //! [`RwLock<T>`]: ../../std/sync/struct.RwLock.html
 //! [`Mutex<T>`]: ../../std/sync/struct.Mutex.html
+//! [`OnceLock<T>`]: ../../std/sync/struct.OnceLock.html
+//! [`Sync`]: ../../std/marker/trait.Sync.html
 //! [`atomic`]: crate::sync::atomic
 
 #![stable(feature = "rust1", since = "1.0.0")]
@@ -202,9 +245,9 @@ use crate::ptr::{self, NonNull};
 mod lazy;
 mod once;
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
 pub use lazy::LazyCell;
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 pub use once::OnceCell;
 
 /// A mutable memory location.
@@ -419,7 +462,7 @@ impl<T> Cell<T> {
         mem::replace(unsafe { &mut *self.value.get() }, val)
     }
 
-    /// Unwraps the value.
+    /// Unwraps the value, consuming the cell.
     ///
     /// # Examples
     ///
@@ -1969,7 +2012,7 @@ impl<T> UnsafeCell<T> {
         UnsafeCell { value }
     }
 
-    /// Unwraps the value.
+    /// Unwraps the value, consuming the cell.
     ///
     /// # Examples
     ///
@@ -2133,7 +2176,7 @@ impl<T> SyncUnsafeCell<T> {
         Self { value: UnsafeCell { value } }
     }
 
-    /// Unwraps the value.
+    /// Unwraps the value, consuming the cell.
     #[inline]
     pub const fn into_inner(self) -> T {
         self.value.into_inner()
diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs
index 65d12c25c51..64a6ce51b2e 100644
--- a/library/core/src/cell/lazy.rs
+++ b/library/core/src/cell/lazy.rs
@@ -11,7 +11,7 @@ use crate::ops::Deref;
 /// # Examples
 ///
 /// ```
-/// #![feature(once_cell)]
+/// #![feature(lazy_cell)]
 ///
 /// use std::cell::LazyCell;
 ///
@@ -29,7 +29,7 @@ use crate::ops::Deref;
 /// //   92
 /// //   92
 /// ```
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
 pub struct LazyCell<T, F = fn() -> T> {
     cell: OnceCell<T>,
     init: Cell<Option<F>>,
@@ -41,7 +41,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_cell)]
+    /// #![feature(lazy_cell)]
     ///
     /// use std::cell::LazyCell;
     ///
@@ -52,7 +52,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
     /// assert_eq!(&*lazy, "HELLO, WORLD!");
     /// ```
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[unstable(feature = "lazy_cell", issue = "109736")]
     pub const fn new(init: F) -> LazyCell<T, F> {
         LazyCell { cell: OnceCell::new(), init: Cell::new(Some(init)) }
     }
@@ -65,7 +65,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_cell)]
+    /// #![feature(lazy_cell)]
     ///
     /// use std::cell::LazyCell;
     ///
@@ -75,7 +75,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
     /// assert_eq!(&*lazy, &92);
     /// ```
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[unstable(feature = "lazy_cell", issue = "109736")]
     pub fn force(this: &LazyCell<T, F>) -> &T {
         this.cell.get_or_init(|| match this.init.take() {
             Some(f) => f(),
@@ -84,7 +84,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
 impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
     type Target = T;
     #[inline]
@@ -93,7 +93,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
 impl<T: Default> Default for LazyCell<T> {
     /// Creates a new lazy value using `Default` as the initializing function.
     #[inline]
@@ -102,7 +102,7 @@ impl<T: Default> Default for LazyCell<T> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
 impl<T: fmt::Debug, F> fmt::Debug for LazyCell<T, F> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish()
diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs
index f74e563f1b9..5dc2d523198 100644
--- a/library/core/src/cell/once.rs
+++ b/library/core/src/cell/once.rs
@@ -4,8 +4,10 @@ use crate::mem;
 
 /// A cell which can be written to only once.
 ///
-/// Unlike [`RefCell`], a `OnceCell` only provides shared `&T` references to its value.
-/// Unlike [`Cell`], a `OnceCell` doesn't require copying or replacing the value to access it.
+/// This allows obtaining a shared `&T` reference to its inner value without copying or replacing
+/// it (unlike [`Cell`]), and without runtime borrow checks (unlike [`RefCell`]). However,
+/// only immutable references can be obtained unless one has a mutable reference to the cell
+/// itself.
 ///
 /// For a thread-safe version of this struct, see [`std::sync::OnceLock`].
 ///
@@ -16,8 +18,6 @@ use crate::mem;
 /// # Examples
 ///
 /// ```
-/// #![feature(once_cell)]
-///
 /// use std::cell::OnceCell;
 ///
 /// let cell = OnceCell::new();
@@ -29,7 +29,7 @@ use crate::mem;
 /// assert_eq!(value, "Hello, World!");
 /// assert!(cell.get().is_some());
 /// ```
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 pub struct OnceCell<T> {
     // Invariant: written to at most once.
     inner: UnsafeCell<Option<T>>,
@@ -39,7 +39,8 @@ impl<T> OnceCell<T> {
     /// Creates a new empty cell.
     #[inline]
     #[must_use]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
     pub const fn new() -> OnceCell<T> {
         OnceCell { inner: UnsafeCell::new(None) }
     }
@@ -48,7 +49,7 @@ impl<T> OnceCell<T> {
     ///
     /// Returns `None` if the cell is empty.
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
     pub fn get(&self) -> Option<&T> {
         // SAFETY: Safe due to `inner`'s invariant
         unsafe { &*self.inner.get() }.as_ref()
@@ -58,7 +59,7 @@ impl<T> OnceCell<T> {
     ///
     /// Returns `None` if the cell is empty.
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
     pub fn get_mut(&mut self) -> Option<&mut T> {
         self.inner.get_mut().as_mut()
     }
@@ -73,8 +74,6 @@ impl<T> OnceCell<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_cell)]
-    ///
     /// use std::cell::OnceCell;
     ///
     /// let cell = OnceCell::new();
@@ -86,7 +85,7 @@ impl<T> OnceCell<T> {
     /// assert!(cell.get().is_some());
     /// ```
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
     pub fn set(&self, value: T) -> Result<(), T> {
         // SAFETY: Safe because we cannot have overlapping mutable borrows
         let slot = unsafe { &*self.inner.get() };
@@ -117,8 +116,6 @@ impl<T> OnceCell<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_cell)]
-    ///
     /// use std::cell::OnceCell;
     ///
     /// let cell = OnceCell::new();
@@ -128,7 +125,7 @@ impl<T> OnceCell<T> {
     /// assert_eq!(value, &92);
     /// ```
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
     pub fn get_or_init<F>(&self, f: F) -> &T
     where
         F: FnOnce() -> T,
@@ -153,7 +150,7 @@ impl<T> OnceCell<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_cell)]
+    /// #![feature(once_cell_try)]
     ///
     /// use std::cell::OnceCell;
     ///
@@ -166,7 +163,7 @@ impl<T> OnceCell<T> {
     /// assert_eq!(value, Ok(&92));
     /// assert_eq!(cell.get(), Some(&92))
     /// ```
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[unstable(feature = "once_cell_try", issue = "109737")]
     pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
     where
         F: FnOnce() -> Result<T, E>,
@@ -199,8 +196,6 @@ impl<T> OnceCell<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_cell)]
-    ///
     /// use std::cell::OnceCell;
     ///
     /// let cell: OnceCell<String> = OnceCell::new();
@@ -211,7 +206,7 @@ impl<T> OnceCell<T> {
     /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
     /// ```
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
     pub fn into_inner(self) -> Option<T> {
         // Because `into_inner` takes `self` by value, the compiler statically verifies
         // that it is not currently borrowed. So it is safe to move out `Option<T>`.
@@ -227,8 +222,6 @@ impl<T> OnceCell<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_cell)]
-    ///
     /// use std::cell::OnceCell;
     ///
     /// let mut cell: OnceCell<String> = OnceCell::new();
@@ -240,13 +233,13 @@ impl<T> OnceCell<T> {
     /// assert_eq!(cell.get(), None);
     /// ```
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
     pub fn take(&mut self) -> Option<T> {
         mem::take(self).into_inner()
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T> Default for OnceCell<T> {
     #[inline]
     fn default() -> Self {
@@ -254,7 +247,7 @@ impl<T> Default for OnceCell<T> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.get() {
@@ -264,7 +257,7 @@ impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: Clone> Clone for OnceCell<T> {
     #[inline]
     fn clone(&self) -> OnceCell<T> {
@@ -279,7 +272,7 @@ impl<T: Clone> Clone for OnceCell<T> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: PartialEq> PartialEq for OnceCell<T> {
     #[inline]
     fn eq(&self, other: &Self) -> bool {
@@ -287,10 +280,11 @@ impl<T: PartialEq> PartialEq for OnceCell<T> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: Eq> Eq for OnceCell<T> {}
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
+#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
 impl<T> const From<T> for OnceCell<T> {
     /// Creates a new `OnceCell<T>` which already contains the given `value`.
     #[inline]
@@ -300,5 +294,5 @@ impl<T> const From<T> for OnceCell<T> {
 }
 
 // Just like for `Cell<T>` this isn't needed, but results in nicer error messages.
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T> !Sync for OnceCell<T> {}
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 35da9151b6f..efeb726ab8e 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -162,6 +162,20 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
     panic!("index out of bounds: the len is {len} but the index is {index}")
 }
 
+#[cold]
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+#[track_caller]
+#[cfg_attr(not(bootstrap), lang = "panic_misaligned_pointer_dereference")] // needed by codegen for panic on misaligned pointer deref
+fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! {
+    if cfg!(feature = "panic_immediate_abort") {
+        super::intrinsics::abort()
+    }
+
+    panic!(
+        "misaligned pointer dereference: address must be a multiple of {required:#x} but is {found:#x}"
+    )
+}
+
 /// Panic because we cannot unwind out of a function.
 ///
 /// This function is called directly by the codegen backend, and must not have
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index e12a3e378a6..bf8339335dd 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1,7 +1,8 @@
 // `library/{std,core}/src/primitive_docs.rs` should have the same contents.
 // These are different files so that relative links work properly without
 // having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same.
-#[doc(primitive = "bool")]
+#[cfg_attr(bootstrap, doc(primitive = "bool"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "bool")]
 #[doc(alias = "true")]
 #[doc(alias = "false")]
 /// The boolean type.
@@ -63,7 +64,8 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_bool {}
 
-#[doc(primitive = "never")]
+#[cfg_attr(bootstrap, doc(primitive = "never"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "never")]
 #[doc(alias = "!")]
 //
 /// The `!` type, also called "never".
@@ -274,7 +276,8 @@ mod prim_bool {}
 #[unstable(feature = "never_type", issue = "35121")]
 mod prim_never {}
 
-#[doc(primitive = "char")]
+#[cfg_attr(bootstrap, doc(primitive = "char"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "char")]
 #[allow(rustdoc::invalid_rust_codeblocks)]
 /// A character type.
 ///
@@ -398,7 +401,8 @@ mod prim_never {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_char {}
 
-#[doc(primitive = "unit")]
+#[cfg_attr(bootstrap, doc(primitive = "unit"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "unit")]
 #[doc(alias = "(")]
 #[doc(alias = ")")]
 #[doc(alias = "()")]
@@ -460,7 +464,8 @@ impl Copy for () {
     // empty
 }
 
-#[doc(primitive = "pointer")]
+#[cfg_attr(bootstrap, doc(primitive = "pointer"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "pointer")]
 #[doc(alias = "ptr")]
 #[doc(alias = "*")]
 #[doc(alias = "*const")]
@@ -577,7 +582,8 @@ impl Copy for () {
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_pointer {}
 
-#[doc(primitive = "array")]
+#[cfg_attr(bootstrap, doc(primitive = "array"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "array")]
 #[doc(alias = "[]")]
 #[doc(alias = "[T;N]")] // unfortunately, rustdoc doesn't have fuzzy search for aliases
 #[doc(alias = "[T; N]")]
@@ -778,7 +784,8 @@ mod prim_pointer {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_array {}
 
-#[doc(primitive = "slice")]
+#[cfg_attr(bootstrap, doc(primitive = "slice"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "slice")]
 #[doc(alias = "[")]
 #[doc(alias = "]")]
 #[doc(alias = "[]")]
@@ -870,7 +877,8 @@ mod prim_array {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_slice {}
 
-#[doc(primitive = "str")]
+#[cfg_attr(bootstrap, doc(primitive = "str"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "str")]
 /// String slices.
 ///
 /// *[See also the `std::str` module](crate::str).*
@@ -937,7 +945,8 @@ mod prim_slice {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_str {}
 
-#[doc(primitive = "tuple")]
+#[cfg_attr(bootstrap, doc(primitive = "tuple"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "tuple")]
 #[doc(alias = "(")]
 #[doc(alias = ")")]
 #[doc(alias = "()")]
@@ -1081,7 +1090,8 @@ impl<T: Copy> Copy for (T,) {
     // empty
 }
 
-#[doc(primitive = "f32")]
+#[cfg_attr(bootstrap, doc(primitive = "f32"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "f32")]
 /// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
 ///
 /// This type can represent a wide range of decimal numbers, like `3.5`, `27`,
@@ -1147,7 +1157,8 @@ impl<T: Copy> Copy for (T,) {
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_f32 {}
 
-#[doc(primitive = "f64")]
+#[cfg_attr(bootstrap, doc(primitive = "f64"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "f64")]
 /// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008).
 ///
 /// This type is very similar to [`f32`], but has increased
@@ -1162,67 +1173,78 @@ mod prim_f32 {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_f64 {}
 
-#[doc(primitive = "i8")]
+#[cfg_attr(bootstrap, doc(primitive = "i8"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i8")]
 //
 /// The 8-bit signed integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i8 {}
 
-#[doc(primitive = "i16")]
+#[cfg_attr(bootstrap, doc(primitive = "i16"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i16")]
 //
 /// The 16-bit signed integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i16 {}
 
-#[doc(primitive = "i32")]
+#[cfg_attr(bootstrap, doc(primitive = "i32"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i32")]
 //
 /// The 32-bit signed integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i32 {}
 
-#[doc(primitive = "i64")]
+#[cfg_attr(bootstrap, doc(primitive = "i64"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i64")]
 //
 /// The 64-bit signed integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i64 {}
 
-#[doc(primitive = "i128")]
+#[cfg_attr(bootstrap, doc(primitive = "i128"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i128")]
 //
 /// The 128-bit signed integer type.
 #[stable(feature = "i128", since = "1.26.0")]
 mod prim_i128 {}
 
-#[doc(primitive = "u8")]
+#[cfg_attr(bootstrap, doc(primitive = "u8"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u8")]
 //
 /// The 8-bit unsigned integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u8 {}
 
-#[doc(primitive = "u16")]
+#[cfg_attr(bootstrap, doc(primitive = "u16"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u16")]
 //
 /// The 16-bit unsigned integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u16 {}
 
-#[doc(primitive = "u32")]
+#[cfg_attr(bootstrap, doc(primitive = "u32"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u32")]
 //
 /// The 32-bit unsigned integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u32 {}
 
-#[doc(primitive = "u64")]
+#[cfg_attr(bootstrap, doc(primitive = "u64"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u64")]
 //
 /// The 64-bit unsigned integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u64 {}
 
-#[doc(primitive = "u128")]
+#[cfg_attr(bootstrap, doc(primitive = "u128"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u128")]
 //
 /// The 128-bit unsigned integer type.
 #[stable(feature = "i128", since = "1.26.0")]
 mod prim_u128 {}
 
-#[doc(primitive = "isize")]
+#[cfg_attr(bootstrap, doc(primitive = "isize"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "isize")]
 //
 /// The pointer-sized signed integer type.
 ///
@@ -1232,7 +1254,8 @@ mod prim_u128 {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_isize {}
 
-#[doc(primitive = "usize")]
+#[cfg_attr(bootstrap, doc(primitive = "usize"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "usize")]
 //
 /// The pointer-sized unsigned integer type.
 ///
@@ -1242,7 +1265,8 @@ mod prim_isize {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_usize {}
 
-#[doc(primitive = "reference")]
+#[cfg_attr(bootstrap, doc(primitive = "reference"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "reference")]
 #[doc(alias = "&")]
 #[doc(alias = "&mut")]
 //
@@ -1373,7 +1397,8 @@ mod prim_usize {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_ref {}
 
-#[doc(primitive = "fn")]
+#[cfg_attr(bootstrap, doc(primitive = "fn"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "fn")]
 //
 /// Function pointers, like `fn(usize) -> bool`.
 ///
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 57b6e0ce4bb..f541808a618 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -2387,7 +2387,8 @@ impl<T> [T] {
     }
 
     /// Binary searches this slice for a given element.
-    /// This behaves similarly to [`contains`] if this slice is sorted.
+    /// If the slice is not sorted, the returned result is unspecified and
+    /// meaningless.
     ///
     /// If the value is found then [`Result::Ok`] is returned, containing the
     /// index of the matching element. If there are multiple matches, then any
@@ -2399,7 +2400,6 @@ impl<T> [T] {
     ///
     /// See also [`binary_search_by`], [`binary_search_by_key`], and [`partition_point`].
     ///
-    /// [`contains`]: slice::contains
     /// [`binary_search_by`]: slice::binary_search_by
     /// [`binary_search_by_key`]: slice::binary_search_by_key
     /// [`partition_point`]: slice::partition_point
@@ -2462,12 +2462,13 @@ impl<T> [T] {
     }
 
     /// Binary searches this slice with a comparator function.
-    /// This behaves similarly to [`contains`] if this slice is sorted.
     ///
-    /// The comparator function should implement an order consistent
-    /// with the sort order of the underlying slice, returning an
-    /// order code that indicates whether its argument is `Less`,
-    /// `Equal` or `Greater` the desired target.
+    /// The comparator function should return an order code that indicates
+    /// whether its argument is `Less`, `Equal` or `Greater` the desired
+    /// target.
+    /// If the slice is not sorted or if the comparator function does not
+    /// implement an order consistent with the sort order of the underlying
+    /// slice, the returned result is unspecified and meaningless.
     ///
     /// If the value is found then [`Result::Ok`] is returned, containing the
     /// index of the matching element. If there are multiple matches, then any
@@ -2479,7 +2480,6 @@ impl<T> [T] {
     ///
     /// See also [`binary_search`], [`binary_search_by_key`], and [`partition_point`].
     ///
-    /// [`contains`]: slice::contains
     /// [`binary_search`]: slice::binary_search
     /// [`binary_search_by_key`]: slice::binary_search_by_key
     /// [`partition_point`]: slice::partition_point
@@ -2548,10 +2548,11 @@ impl<T> [T] {
     }
 
     /// Binary searches this slice with a key extraction function.
-    /// This behaves similarly to [`contains`] if this slice is sorted.
     ///
     /// Assumes that the slice is sorted by the key, for instance with
     /// [`sort_by_key`] using the same key extraction function.
+    /// If the slice is not sorted by the key, the returned result is
+    /// unspecified and meaningless.
     ///
     /// If the value is found then [`Result::Ok`] is returned, containing the
     /// index of the matching element. If there are multiple matches, then any
@@ -2563,7 +2564,6 @@ impl<T> [T] {
     ///
     /// See also [`binary_search`], [`binary_search_by`], and [`partition_point`].
     ///
-    /// [`contains`]: slice::contains
     /// [`sort_by_key`]: slice::sort_by_key
     /// [`binary_search`]: slice::binary_search
     /// [`binary_search_by`]: slice::binary_search_by
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 2b23f64732b..04169429949 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -2655,5 +2655,6 @@ impl_fn_for_zst! {
     };
 }
 
+// This is required to make `impl From<&str> for Box<dyn Error>` and `impl<E> From<E> for Box<dyn Error>` not overlap.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl !crate::error::Error for &str {}
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 108210b6573..344f0b61754 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -94,7 +94,7 @@
 #![feature(pointer_is_aligned)]
 #![feature(portable_simd)]
 #![feature(ptr_metadata)]
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![feature(unsized_tuple_coercion)]
 #![feature(const_option)]
 #![feature(const_option_ext)]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index baad6de707b..8c118b95b0a 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -339,7 +339,7 @@
 #![feature(edition_panic)]
 #![feature(format_args_nl)]
 #![feature(log_syntax)]
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![feature(saturating_int_impl)]
 #![feature(stdsimd)]
 #![feature(test)]
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index e12a3e378a6..bf8339335dd 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -1,7 +1,8 @@
 // `library/{std,core}/src/primitive_docs.rs` should have the same contents.
 // These are different files so that relative links work properly without
 // having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same.
-#[doc(primitive = "bool")]
+#[cfg_attr(bootstrap, doc(primitive = "bool"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "bool")]
 #[doc(alias = "true")]
 #[doc(alias = "false")]
 /// The boolean type.
@@ -63,7 +64,8 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_bool {}
 
-#[doc(primitive = "never")]
+#[cfg_attr(bootstrap, doc(primitive = "never"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "never")]
 #[doc(alias = "!")]
 //
 /// The `!` type, also called "never".
@@ -274,7 +276,8 @@ mod prim_bool {}
 #[unstable(feature = "never_type", issue = "35121")]
 mod prim_never {}
 
-#[doc(primitive = "char")]
+#[cfg_attr(bootstrap, doc(primitive = "char"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "char")]
 #[allow(rustdoc::invalid_rust_codeblocks)]
 /// A character type.
 ///
@@ -398,7 +401,8 @@ mod prim_never {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_char {}
 
-#[doc(primitive = "unit")]
+#[cfg_attr(bootstrap, doc(primitive = "unit"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "unit")]
 #[doc(alias = "(")]
 #[doc(alias = ")")]
 #[doc(alias = "()")]
@@ -460,7 +464,8 @@ impl Copy for () {
     // empty
 }
 
-#[doc(primitive = "pointer")]
+#[cfg_attr(bootstrap, doc(primitive = "pointer"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "pointer")]
 #[doc(alias = "ptr")]
 #[doc(alias = "*")]
 #[doc(alias = "*const")]
@@ -577,7 +582,8 @@ impl Copy for () {
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_pointer {}
 
-#[doc(primitive = "array")]
+#[cfg_attr(bootstrap, doc(primitive = "array"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "array")]
 #[doc(alias = "[]")]
 #[doc(alias = "[T;N]")] // unfortunately, rustdoc doesn't have fuzzy search for aliases
 #[doc(alias = "[T; N]")]
@@ -778,7 +784,8 @@ mod prim_pointer {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_array {}
 
-#[doc(primitive = "slice")]
+#[cfg_attr(bootstrap, doc(primitive = "slice"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "slice")]
 #[doc(alias = "[")]
 #[doc(alias = "]")]
 #[doc(alias = "[]")]
@@ -870,7 +877,8 @@ mod prim_array {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_slice {}
 
-#[doc(primitive = "str")]
+#[cfg_attr(bootstrap, doc(primitive = "str"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "str")]
 /// String slices.
 ///
 /// *[See also the `std::str` module](crate::str).*
@@ -937,7 +945,8 @@ mod prim_slice {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_str {}
 
-#[doc(primitive = "tuple")]
+#[cfg_attr(bootstrap, doc(primitive = "tuple"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "tuple")]
 #[doc(alias = "(")]
 #[doc(alias = ")")]
 #[doc(alias = "()")]
@@ -1081,7 +1090,8 @@ impl<T: Copy> Copy for (T,) {
     // empty
 }
 
-#[doc(primitive = "f32")]
+#[cfg_attr(bootstrap, doc(primitive = "f32"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "f32")]
 /// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
 ///
 /// This type can represent a wide range of decimal numbers, like `3.5`, `27`,
@@ -1147,7 +1157,8 @@ impl<T: Copy> Copy for (T,) {
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_f32 {}
 
-#[doc(primitive = "f64")]
+#[cfg_attr(bootstrap, doc(primitive = "f64"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "f64")]
 /// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008).
 ///
 /// This type is very similar to [`f32`], but has increased
@@ -1162,67 +1173,78 @@ mod prim_f32 {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_f64 {}
 
-#[doc(primitive = "i8")]
+#[cfg_attr(bootstrap, doc(primitive = "i8"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i8")]
 //
 /// The 8-bit signed integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i8 {}
 
-#[doc(primitive = "i16")]
+#[cfg_attr(bootstrap, doc(primitive = "i16"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i16")]
 //
 /// The 16-bit signed integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i16 {}
 
-#[doc(primitive = "i32")]
+#[cfg_attr(bootstrap, doc(primitive = "i32"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i32")]
 //
 /// The 32-bit signed integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i32 {}
 
-#[doc(primitive = "i64")]
+#[cfg_attr(bootstrap, doc(primitive = "i64"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i64")]
 //
 /// The 64-bit signed integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i64 {}
 
-#[doc(primitive = "i128")]
+#[cfg_attr(bootstrap, doc(primitive = "i128"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i128")]
 //
 /// The 128-bit signed integer type.
 #[stable(feature = "i128", since = "1.26.0")]
 mod prim_i128 {}
 
-#[doc(primitive = "u8")]
+#[cfg_attr(bootstrap, doc(primitive = "u8"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u8")]
 //
 /// The 8-bit unsigned integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u8 {}
 
-#[doc(primitive = "u16")]
+#[cfg_attr(bootstrap, doc(primitive = "u16"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u16")]
 //
 /// The 16-bit unsigned integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u16 {}
 
-#[doc(primitive = "u32")]
+#[cfg_attr(bootstrap, doc(primitive = "u32"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u32")]
 //
 /// The 32-bit unsigned integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u32 {}
 
-#[doc(primitive = "u64")]
+#[cfg_attr(bootstrap, doc(primitive = "u64"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u64")]
 //
 /// The 64-bit unsigned integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u64 {}
 
-#[doc(primitive = "u128")]
+#[cfg_attr(bootstrap, doc(primitive = "u128"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u128")]
 //
 /// The 128-bit unsigned integer type.
 #[stable(feature = "i128", since = "1.26.0")]
 mod prim_u128 {}
 
-#[doc(primitive = "isize")]
+#[cfg_attr(bootstrap, doc(primitive = "isize"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "isize")]
 //
 /// The pointer-sized signed integer type.
 ///
@@ -1232,7 +1254,8 @@ mod prim_u128 {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_isize {}
 
-#[doc(primitive = "usize")]
+#[cfg_attr(bootstrap, doc(primitive = "usize"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "usize")]
 //
 /// The pointer-sized unsigned integer type.
 ///
@@ -1242,7 +1265,8 @@ mod prim_isize {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_usize {}
 
-#[doc(primitive = "reference")]
+#[cfg_attr(bootstrap, doc(primitive = "reference"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "reference")]
 #[doc(alias = "&")]
 #[doc(alias = "&mut")]
 //
@@ -1373,7 +1397,8 @@ mod prim_usize {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_ref {}
 
-#[doc(primitive = "fn")]
+#[cfg_attr(bootstrap, doc(primitive = "fn"))]
+#[cfg_attr(not(bootstrap), rustc_doc_primitive = "fn")]
 //
 /// Function pointers, like `fn(usize) -> bool`.
 ///
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index 7e85d6a063a..8e9ea293ce4 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -26,7 +26,7 @@ union Data<T, F> {
 /// # Examples
 ///
 /// ```
-/// #![feature(once_cell)]
+/// #![feature(lazy_cell)]
 ///
 /// use std::collections::HashMap;
 ///
@@ -54,7 +54,7 @@ union Data<T, F> {
 ///     //   Some("Hoyten")
 /// }
 /// ```
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
 pub struct LazyLock<T, F = fn() -> T> {
     once: Once,
     data: UnsafeCell<Data<T, F>>,
@@ -64,7 +64,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
     /// Creates a new lazy value with the given initializing
     /// function.
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[unstable(feature = "lazy_cell", issue = "109736")]
     pub const fn new(f: F) -> LazyLock<T, F> {
         LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) }
     }
@@ -76,7 +76,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_cell)]
+    /// #![feature(lazy_cell)]
     ///
     /// use std::sync::LazyLock;
     ///
@@ -86,7 +86,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
     /// assert_eq!(&*lazy, &92);
     /// ```
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[unstable(feature = "lazy_cell", issue = "109736")]
     pub fn force(this: &LazyLock<T, F>) -> &T {
         this.once.call_once(|| {
             // SAFETY: `call_once` only runs this closure once, ever.
@@ -122,7 +122,7 @@ impl<T, F> LazyLock<T, F> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
 impl<T, F> Drop for LazyLock<T, F> {
     fn drop(&mut self) {
         match self.once.state() {
@@ -135,7 +135,7 @@ impl<T, F> Drop for LazyLock<T, F> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
 impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
     type Target = T;
 
@@ -145,7 +145,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
 impl<T: Default> Default for LazyLock<T> {
     /// Creates a new lazy value using `Default` as the initializing function.
     #[inline]
@@ -154,7 +154,7 @@ impl<T: Default> Default for LazyLock<T> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
 impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.get() {
@@ -166,13 +166,13 @@ impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
 
 // We never create a `&F` from a `&LazyLock<T, F>` so it is fine
 // to not impl `Sync` for `F`
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
 unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {}
 // auto-derived `Send` impl is OK.
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
 impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {}
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
 impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {}
 
 #[cfg(test)]
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index 4edc956173b..19641753ffe 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -133,7 +133,9 @@
 //! - [`Mutex`]: Mutual Exclusion mechanism, which ensures that at
 //!   most one thread at a time is able to access some data.
 //!
-//! - [`Once`]: Used for thread-safe, one-time initialization of a
+//! - [`Once`]: Used for a thread-safe, one-time global initialization routine
+//!
+//! - [`OnceLock`]: Used for thread-safe, one-time initialization of a
 //!   global variable.
 //!
 //! - [`RwLock`]: Provides a mutual exclusion mechanism which allows
@@ -147,6 +149,7 @@
 //! [`mpsc`]: crate::sync::mpsc
 //! [`Mutex`]: crate::sync::Mutex
 //! [`Once`]: crate::sync::Once
+//! [`OnceLock`]: crate::sync::OnceLock
 //! [`RwLock`]: crate::sync::RwLock
 
 #![stable(feature = "rust1", since = "1.0.0")]
@@ -172,9 +175,9 @@ pub use self::poison::{LockResult, PoisonError, TryLockError, TryLockResult};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
 pub use self::lazy_lock::LazyLock;
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 pub use self::once_lock::OnceLock;
 
 pub(crate) use self::remutex::{ReentrantMutex, ReentrantMutexGuard};
diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs
index ed339ca5df6..8c34375ea07 100644
--- a/library/std/src/sync/once_lock.rs
+++ b/library/std/src/sync/once_lock.rs
@@ -14,8 +14,6 @@ use crate::sync::Once;
 /// # Examples
 ///
 /// ```
-/// #![feature(once_cell)]
-///
 /// use std::sync::OnceLock;
 ///
 /// static CELL: OnceLock<String> = OnceLock::new();
@@ -32,7 +30,7 @@ use crate::sync::Once;
 /// assert!(value.is_some());
 /// assert_eq!(value.unwrap().as_str(), "Hello, World!");
 /// ```
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 pub struct OnceLock<T> {
     once: Once,
     // Whether or not the value is initialized is tracked by `once.is_completed()`.
@@ -40,8 +38,6 @@ pub struct OnceLock<T> {
     /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl.
     ///
     /// ```compile_fail,E0597
-    /// #![feature(once_cell)]
-    ///
     /// use std::sync::OnceLock;
     ///
     /// struct A<'a>(&'a str);
@@ -63,7 +59,8 @@ impl<T> OnceLock<T> {
     /// Creates a new empty cell.
     #[inline]
     #[must_use]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
     pub const fn new() -> OnceLock<T> {
         OnceLock {
             once: Once::new(),
@@ -77,7 +74,7 @@ impl<T> OnceLock<T> {
     /// Returns `None` if the cell is empty, or being initialized. This
     /// method never blocks.
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
     pub fn get(&self) -> Option<&T> {
         if self.is_initialized() {
             // Safe b/c checked is_initialized
@@ -91,7 +88,7 @@ impl<T> OnceLock<T> {
     ///
     /// Returns `None` if the cell is empty. This method never blocks.
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
     pub fn get_mut(&mut self) -> Option<&mut T> {
         if self.is_initialized() {
             // Safe b/c checked is_initialized and we have a unique access
@@ -111,8 +108,6 @@ impl<T> OnceLock<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_cell)]
-    ///
     /// use std::sync::OnceLock;
     ///
     /// static CELL: OnceLock<i32> = OnceLock::new();
@@ -129,7 +124,7 @@ impl<T> OnceLock<T> {
     /// }
     /// ```
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
     pub fn set(&self, value: T) -> Result<(), T> {
         let mut value = Some(value);
         self.get_or_init(|| value.take().unwrap());
@@ -158,8 +153,6 @@ impl<T> OnceLock<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_cell)]
-    ///
     /// use std::sync::OnceLock;
     ///
     /// let cell = OnceLock::new();
@@ -169,7 +162,7 @@ impl<T> OnceLock<T> {
     /// assert_eq!(value, &92);
     /// ```
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
     pub fn get_or_init<F>(&self, f: F) -> &T
     where
         F: FnOnce() -> T,
@@ -195,7 +188,7 @@ impl<T> OnceLock<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_cell)]
+    /// #![feature(once_cell_try)]
     ///
     /// use std::sync::OnceLock;
     ///
@@ -209,7 +202,7 @@ impl<T> OnceLock<T> {
     /// assert_eq!(cell.get(), Some(&92))
     /// ```
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[unstable(feature = "once_cell_try", issue = "109737")]
     pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
     where
         F: FnOnce() -> Result<T, E>,
@@ -236,8 +229,6 @@ impl<T> OnceLock<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_cell)]
-    ///
     /// use std::sync::OnceLock;
     ///
     /// let cell: OnceLock<String> = OnceLock::new();
@@ -248,7 +239,7 @@ impl<T> OnceLock<T> {
     /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
     /// ```
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
     pub fn into_inner(mut self) -> Option<T> {
         self.take()
     }
@@ -262,8 +253,6 @@ impl<T> OnceLock<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_cell)]
-    ///
     /// use std::sync::OnceLock;
     ///
     /// let mut cell: OnceLock<String> = OnceLock::new();
@@ -275,7 +264,7 @@ impl<T> OnceLock<T> {
     /// assert_eq!(cell.get(), None);
     /// ```
     #[inline]
-    #[unstable(feature = "once_cell", issue = "74465")]
+    #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
     pub fn take(&mut self) -> Option<T> {
         if self.is_initialized() {
             self.once = Once::new();
@@ -344,17 +333,17 @@ impl<T> OnceLock<T> {
 // scoped thread B, which fills the cell, which is
 // then destroyed by A. That is, destructor observes
 // a sent value.
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 unsafe impl<T: Send> Send for OnceLock<T> {}
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
 impl<T> const Default for OnceLock<T> {
     /// Creates a new empty cell.
@@ -362,8 +351,6 @@ impl<T> const Default for OnceLock<T> {
     /// # Example
     ///
     /// ```
-    /// #![feature(once_cell)]
-    ///
     /// use std::sync::OnceLock;
     ///
     /// fn main() {
@@ -376,7 +363,7 @@ impl<T> const Default for OnceLock<T> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: fmt::Debug> fmt::Debug for OnceLock<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.get() {
@@ -386,7 +373,7 @@ impl<T: fmt::Debug> fmt::Debug for OnceLock<T> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: Clone> Clone for OnceLock<T> {
     #[inline]
     fn clone(&self) -> OnceLock<T> {
@@ -401,15 +388,13 @@ impl<T: Clone> Clone for OnceLock<T> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T> From<T> for OnceLock<T> {
     /// Create a new cell with its contents set to `value`.
     ///
     /// # Example
     ///
     /// ```
-    /// #![feature(once_cell)]
-    ///
     /// use std::sync::OnceLock;
     ///
     /// # fn main() -> Result<(), i32> {
@@ -430,7 +415,7 @@ impl<T> From<T> for OnceLock<T> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: PartialEq> PartialEq for OnceLock<T> {
     #[inline]
     fn eq(&self, other: &OnceLock<T>) -> bool {
@@ -438,10 +423,10 @@ impl<T: PartialEq> PartialEq for OnceLock<T> {
     }
 }
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: Eq> Eq for OnceLock<T> {}
 
-#[unstable(feature = "once_cell", issue = "74465")]
+#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
 unsafe impl<#[may_dangle] T> Drop for OnceLock<T> {
     #[inline]
     fn drop(&mut self) {
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index 0f11de8f5b8..6f53583409d 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -174,6 +174,34 @@ impl From<libc::timespec> for Timespec {
     }
 }
 
+#[cfg(all(
+    target_os = "linux",
+    target_env = "gnu",
+    target_pointer_width = "32",
+    not(target_arch = "riscv32")
+))]
+#[repr(C)]
+pub(in crate::sys::unix) struct __timespec64 {
+    pub(in crate::sys::unix) tv_sec: i64,
+    #[cfg(target_endian = "big")]
+    _padding: i32,
+    pub(in crate::sys::unix) tv_nsec: i32,
+    #[cfg(target_endian = "little")]
+    _padding: i32,
+}
+
+#[cfg(all(
+    target_os = "linux",
+    target_env = "gnu",
+    target_pointer_width = "32",
+    not(target_arch = "riscv32")
+))]
+impl From<__timespec64> for Timespec {
+    fn from(t: __timespec64) -> Timespec {
+        Timespec::new(t.tv_sec, t.tv_nsec.into())
+    }
+}
+
 #[cfg(any(
     all(target_os = "macos", any(not(target_arch = "aarch64"))),
     target_os = "ios",
@@ -352,29 +380,23 @@ mod inner {
     impl Timespec {
         pub fn now(clock: libc::clockid_t) -> Timespec {
             // Try to use 64-bit time in preparation for Y2038.
-            #[cfg(all(target_os = "linux", target_env = "gnu", target_pointer_width = "32"))]
+            #[cfg(all(
+                target_os = "linux",
+                target_env = "gnu",
+                target_pointer_width = "32",
+                not(target_arch = "riscv32")
+            ))]
             {
                 use crate::sys::weak::weak;
 
                 // __clock_gettime64 was added to 32-bit arches in glibc 2.34,
                 // and it handles both vDSO calls and ENOSYS fallbacks itself.
-                weak!(fn __clock_gettime64(libc::clockid_t, *mut __timespec64) -> libc::c_int);
-
-                #[repr(C)]
-                struct __timespec64 {
-                    tv_sec: i64,
-                    #[cfg(target_endian = "big")]
-                    _padding: i32,
-                    tv_nsec: i32,
-                    #[cfg(target_endian = "little")]
-                    _padding: i32,
-                }
+                weak!(fn __clock_gettime64(libc::clockid_t, *mut super::__timespec64) -> libc::c_int);
 
                 if let Some(clock_gettime64) = __clock_gettime64.get() {
                     let mut t = MaybeUninit::uninit();
                     cvt(unsafe { clock_gettime64(clock, t.as_mut_ptr()) }).unwrap();
-                    let t = unsafe { t.assume_init() };
-                    return Timespec::new(t.tv_sec, t.tv_nsec as i64);
+                    return Timespec::from(unsafe { t.assume_init() });
                 }
             }
 
diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs
index a22f0f04b2e..cc2b45a9bdb 100644
--- a/src/bootstrap/llvm.rs
+++ b/src/bootstrap/llvm.rs
@@ -434,11 +434,6 @@ impl Step for Llvm {
             }
         }
 
-        // Workaround for ppc32 lld limitation
-        if target == "powerpc-unknown-freebsd" {
-            ldflags.exe.push(" -fuse-ld=bfd");
-        }
-
         // https://llvm.org/docs/HowToCrossCompileLLVM.html
         if target != builder.config.build {
             let LlvmResult { llvm_config, .. } =
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index 6fd113fcfd8..66fb941ea37 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.14.5
\ No newline at end of file
+0.14.6
\ No newline at end of file
diff --git a/src/doc/rustc/src/platform-support/openharmony.md b/src/doc/rustc/src/platform-support/openharmony.md
index aa4debfd45a..a8dcc644346 100644
--- a/src/doc/rustc/src/platform-support/openharmony.md
+++ b/src/doc/rustc/src/platform-support/openharmony.md
@@ -1,4 +1,4 @@
-# `*-linux-ohos*`
+# `*-unknown-linux-ohos`
 
 **Tier: 3**
 
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index b8b5014ab42..960c1de1782 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -177,9 +177,9 @@ Book][unstable-masked] and [its tracking issue][issue-masked].
 This is for Rust compiler internal use only.
 
 Since primitive types are defined in the compiler, there's no place to attach documentation
-attributes. The `#[doc(primitive)]` attribute is used by the standard library to provide a way
-to generate documentation for primitive types, and requires `#![feature(rustdoc_internals)]` to
-enable.
+attributes. The `#[rustc_doc_primitive = "..."]` attribute is used by the standard library to
+provide a way to generate documentation for primitive types, and requires `#![feature(rustc_attrs)]`
+to enable.
 
 ### Document keywords
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 2d247bd537b..1c57cd7a946 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2002,7 +2002,8 @@ fn clean_generic_args<'tcx>(
     generic_args: &hir::GenericArgs<'tcx>,
     cx: &mut DocContext<'tcx>,
 ) -> GenericArgs {
-    if generic_args.parenthesized {
+    // FIXME(return_type_notation): Fix RTN parens rendering
+    if generic_args.parenthesized == hir::GenericArgsParentheses::ParenSugar {
         let output = clean_ty(generic_args.bindings[0].ty(), cx);
         let output = if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None };
         let inputs =
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 909e0a07e4c..ffa13ebb77c 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -249,38 +249,24 @@ impl ExternalCrate {
         //
         // Note that this loop only searches the top-level items of the crate,
         // and this is intentional. If we were to search the entire crate for an
-        // item tagged with `#[doc(primitive)]` then we would also have to
+        // item tagged with `#[rustc_doc_primitive]` then we would also have to
         // search the entirety of external modules for items tagged
-        // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
+        // `#[rustc_doc_primitive]`, which is a pretty inefficient process (decoding
         // all that metadata unconditionally).
         //
         // In order to keep the metadata load under control, the
-        // `#[doc(primitive)]` feature is explicitly designed to only allow the
+        // `#[rustc_doc_primitive]` feature is explicitly designed to only allow the
         // primitive tags to show up as the top level items in a crate.
         //
         // Also note that this does not attempt to deal with modules tagged
         // duplicately for the same primitive. This is handled later on when
         // rendering by delegating everything to a hash map.
         let as_primitive = |res: Res<!>| {
-            if let Res::Def(DefKind::Mod, def_id) = res {
-                let mut prim = None;
-                let meta_items = tcx
-                    .get_attrs(def_id, sym::doc)
-                    .flat_map(|attr| attr.meta_item_list().unwrap_or_default());
-                for meta in meta_items {
-                    if let Some(v) = meta.value_str() {
-                        if meta.has_name(sym::primitive) {
-                            prim = PrimitiveType::from_symbol(v);
-                            if prim.is_some() {
-                                break;
-                            }
-                            // FIXME: should warn on unknown primitives?
-                        }
-                    }
-                }
-                return prim.map(|p| (def_id, p));
-            }
-            None
+            let Res::Def(DefKind::Mod, def_id) = res else { return None };
+            tcx.get_attrs(def_id, sym::rustc_doc_primitive).find_map(|attr| {
+                // FIXME: should warn on unknown primitives?
+                Some((def_id, PrimitiveType::from_symbol(attr.value_str()?)?))
+            })
         };
 
         if root.is_local() {
@@ -1829,13 +1815,17 @@ impl PrimitiveType {
         }
     }
 
-    /// Returns the DefId of the module with `doc(primitive)` for this primitive type.
+    /// Returns the DefId of the module with `rustc_doc_primitive` for this primitive type.
     /// Panics if there is no such module.
     ///
-    /// This gives precedence to primitives defined in the current crate, and deprioritizes primitives defined in `core`,
-    /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which will be picked.
-    /// In particular, if a crate depends on both `std` and another crate that also defines `doc(primitive)`, then
-    /// it's entirely random whether `std` or the other crate is picked. (no_std crates are usually fine unless multiple dependencies define a primitive.)
+    /// This gives precedence to primitives defined in the current crate, and deprioritizes
+    /// primitives defined in `core`,
+    /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which
+    /// will be picked.
+    ///
+    /// In particular, if a crate depends on both `std` and another crate that also defines
+    /// `rustc_doc_primitive`, then it's entirely random whether `std` or the other crate is picked.
+    /// (no_std crates are usually fine unless multiple dependencies define a primitive.)
     pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxHashMap<PrimitiveType, DefId> {
         static PRIMITIVE_LOCATIONS: OnceCell<FxHashMap<PrimitiveType, DefId>> = OnceCell::new();
         PRIMITIVE_LOCATIONS.get_or_init(|| {
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 28458f32903..b392ba05836 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -303,6 +303,9 @@ pub(crate) fn run_global_ctxt(
 
     // HACK(jynelson) this calls an _extremely_ limited subset of `typeck`
     // and might break if queries change their assumptions in the future.
+    tcx.sess.time("type_collecting", || {
+        tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
+    });
 
     // NOTE: This is copy/pasted from typeck/lib.rs and should be kept in sync with those changes.
     tcx.sess.time("item_types_checking", || {
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 1487ebf9b0a..45c0360a49e 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -1016,9 +1016,7 @@ function preLoadCss(cssUrl) {
              <code>enum</code>, <code>trait</code>, <code>type</code>, <code>macro</code>, \
              and <code>const</code>.",
             "Search functions by type signature (e.g., <code>vec -&gt; usize</code> or \
-             <code>-&gt; vec</code>)",
-            "Search multiple things at once by splitting your query with comma (e.g., \
-             <code>str,u8</code> or <code>String,struct:Vec,test</code>)",
+             <code>-&gt; vec</code> or <code>String, enum:Cow -&gt; bool</code>)",
             "You can look for items with an exact name by putting double quotes around \
              your request: <code>\"string\"</code>",
             "Look for items inside another one by searching for a path: <code>vec::Vec</code>",
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 59d67f27b30..c39caf73a93 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -249,9 +249,7 @@ pub(crate) fn id_from_item_inner(
                     // instead, we directly get the primitive symbol and convert it to u32 to
                     // generate the ID.
                     if matches!(tcx.def_kind(def_id), DefKind::Mod) &&
-                        let Some(prim) = tcx.get_attrs(*def_id, sym::doc)
-                            .flat_map(|attr| attr.meta_item_list().unwrap_or_default())
-                            .filter(|attr| attr.has_name(sym::primitive))
+                        let Some(prim) = tcx.get_attrs(*def_id, sym::rustc_doc_primitive)
                             .find_map(|attr| attr.value_str()) {
                         format!(":{}", prim.as_u32())
                     } else {
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 08bceb59cfd..d6da6e09938 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -78,7 +78,7 @@ impl<'tcx> JsonRenderer<'tcx> {
                         // HACK(hkmatsumoto): For impls of primitive types, we index them
                         // regardless of whether they're local. This is because users can
                         // document primitive items in an arbitrary crate by using
-                        // `doc(primitive)`.
+                        // `rustc_doc_primitive`.
                         let mut is_primitive_impl = false;
                         if let clean::types::ItemKind::ImplItem(ref impl_) = *item.kind &&
                             impl_.trait_.is_none() &&
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 4fcf0873600..4c4dbc9864f 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -11,7 +11,7 @@
 #![feature(let_chains)]
 #![feature(test)]
 #![feature(never_type)]
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![feature(type_ascription)]
 #![feature(iter_intersperse)]
 #![feature(type_alias_impl_trait)]
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index d98cf251e97..4188aa1037f 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -47,7 +47,18 @@ fn collect_intra_doc_links(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
     krate
 }
 
-#[derive(Copy, Clone, Debug, Hash)]
+fn filter_assoc_items_by_name_and_namespace<'a>(
+    tcx: TyCtxt<'a>,
+    assoc_items_of: DefId,
+    ident: Ident,
+    ns: Namespace,
+) -> impl Iterator<Item = &ty::AssocItem> + 'a {
+    tcx.associated_items(assoc_items_of).filter_by_name_unhygienic(ident.name).filter(move |item| {
+        item.kind.namespace() == ns && tcx.hygienic_eq(ident, item.ident(tcx), assoc_items_of)
+    })
+}
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq)]
 enum Res {
     Def(DefKind, DefId),
     Primitive(PrimitiveType),
@@ -59,7 +70,7 @@ impl Res {
     fn descr(self) -> &'static str {
         match self {
             Res::Def(kind, id) => ResolveRes::Def(kind, id).descr(),
-            Res::Primitive(_) => "builtin type",
+            Res::Primitive(_) => "primitive type",
         }
     }
 
@@ -317,14 +328,21 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
         prim_ty: PrimitiveType,
         ns: Namespace,
         item_name: Symbol,
-    ) -> Option<(Res, DefId)> {
+    ) -> Vec<(Res, DefId)> {
         let tcx = self.cx.tcx;
 
-        prim_ty.impls(tcx).find_map(|impl_| {
-            tcx.associated_items(impl_)
-                .find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, impl_)
+        prim_ty
+            .impls(tcx)
+            .flat_map(|impl_| {
+                filter_assoc_items_by_name_and_namespace(
+                    tcx,
+                    impl_,
+                    Ident::with_dummy_span(item_name),
+                    ns,
+                )
                 .map(|item| (Res::Primitive(prim_ty), item.def_id))
-        })
+            })
+            .collect::<Vec<_>>()
     }
 
     fn resolve_self_ty(&self, path_str: &str, ns: Namespace, item_id: DefId) -> Option<Res> {
@@ -394,14 +412,16 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
         ns: Namespace,
         item_id: DefId,
         module_id: DefId,
-    ) -> Result<(Res, Option<DefId>), UnresolvedPath<'path>> {
+    ) -> Result<Vec<(Res, Option<DefId>)>, UnresolvedPath<'path>> {
         if let Some(res) = self.resolve_path(path_str, ns, item_id, module_id) {
             return Ok(match res {
                 Res::Def(
                     DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Variant,
                     def_id,
-                ) => (Res::from_def_id(self.cx.tcx, self.cx.tcx.parent(def_id)), Some(def_id)),
-                _ => (res, None),
+                ) => {
+                    vec![(Res::from_def_id(self.cx.tcx, self.cx.tcx.parent(def_id)), Some(def_id))]
+                }
+                _ => vec![(res, None)],
             });
         } else if ns == MacroNS {
             return Err(UnresolvedPath {
@@ -433,17 +453,24 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             })?;
 
         // FIXME(#83862): this arbitrarily gives precedence to primitives over modules to support
-        // links to primitives when `#[doc(primitive)]` is present. It should give an ambiguity
-        // error instead and special case *only* modules with `#[doc(primitive)]`, not all
+        // links to primitives when `#[rustc_doc_primitive]` is present. It should give an ambiguity
+        // error instead and special case *only* modules with `#[rustc_doc_primitive]`, not all
         // primitives.
-        resolve_primitive(&path_root, TypeNS)
+        match resolve_primitive(&path_root, TypeNS)
             .or_else(|| self.resolve_path(&path_root, TypeNS, item_id, module_id))
             .and_then(|ty_res| {
-                self.resolve_associated_item(ty_res, item_name, ns, module_id).map(Ok)
-            })
-            .unwrap_or_else(|| {
+                let candidates = self
+                    .resolve_associated_item(ty_res, item_name, ns, module_id)
+                    .into_iter()
+                    .map(|(res, def_id)| (res, Some(def_id)))
+                    .collect::<Vec<_>>();
+                if !candidates.is_empty() { Some(candidates) } else { None }
+            }) {
+            Some(r) => Ok(r),
+            None => {
                 if ns == Namespace::ValueNS {
                     self.variant_field(path_str, item_id, module_id)
+                        .map(|(res, def_id)| vec![(res, Some(def_id))])
                 } else {
                     Err(UnresolvedPath {
                         item_id,
@@ -452,8 +479,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                         unresolved: path_root.into(),
                     })
                 }
-            })
-            .map(|(res, def_id)| (res, Some(def_id)))
+            }
+        }
     }
 
     /// Convert a DefId to a Res, where possible.
@@ -535,24 +562,31 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
         item_name: Symbol,
         ns: Namespace,
         module_id: DefId,
-    ) -> Option<(Res, DefId)> {
+    ) -> Vec<(Res, DefId)> {
         let tcx = self.cx.tcx;
 
         match root_res {
             Res::Primitive(prim) => {
-                self.resolve_primitive_associated_item(prim, ns, item_name).or_else(|| {
+                let items = self.resolve_primitive_associated_item(prim, ns, item_name);
+                if !items.is_empty() {
+                    items
+                // Inherent associated items take precedence over items that come from trait impls.
+                } else {
                     self.primitive_type_to_ty(prim)
-                        .and_then(|ty| {
+                        .map(|ty| {
                             resolve_associated_trait_item(ty, module_id, item_name, ns, self.cx)
+                                .iter()
+                                .map(|item| (root_res, item.def_id))
+                                .collect::<Vec<_>>()
                         })
-                        .map(|item| (root_res, item.def_id))
-                })
+                        .unwrap_or(Vec::new())
+                }
             }
             Res::Def(DefKind::TyAlias, did) => {
                 // Resolve the link on the type the alias points to.
                 // FIXME: if the associated item is defined directly on the type alias,
                 // it will show up on its documentation page, we should link there instead.
-                let res = self.def_id_to_res(did)?;
+                let Some(res) = self.def_id_to_res(did) else { return Vec::new() };
                 self.resolve_associated_item(res, item_name, ns, module_id)
             }
             Res::Def(
@@ -566,7 +600,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                         ty::Adt(adt_def, _) => {
                             for variant in adt_def.variants() {
                                 if variant.name == item_name {
-                                    return Some((root_res, variant.def_id));
+                                    return vec![(root_res, variant.def_id)];
                                 }
                             }
                         }
@@ -575,43 +609,46 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 }
 
                 // Checks if item_name belongs to `impl SomeItem`
-                let assoc_item = tcx
+                let mut assoc_items: Vec<_> = tcx
                     .inherent_impls(did)
                     .iter()
                     .flat_map(|&imp| {
-                        tcx.associated_items(imp).find_by_name_and_namespace(
+                        filter_assoc_items_by_name_and_namespace(
                             tcx,
+                            imp,
                             Ident::with_dummy_span(item_name),
                             ns,
-                            imp,
                         )
                     })
-                    .copied()
-                    // There should only ever be one associated item that matches from any inherent impl
-                    .next()
+                    .map(|item| (root_res, item.def_id))
+                    .collect();
+
+                if assoc_items.is_empty() {
                     // Check if item_name belongs to `impl SomeTrait for SomeItem`
                     // FIXME(#74563): This gives precedence to `impl SomeItem`:
                     // Although having both would be ambiguous, use impl version for compatibility's sake.
                     // To handle that properly resolve() would have to support
                     // something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
-                    .or_else(|| {
-                        resolve_associated_trait_item(
-                            tcx.type_of(did).subst_identity(),
-                            module_id,
-                            item_name,
-                            ns,
-                            self.cx,
-                        )
-                    });
+                    assoc_items = resolve_associated_trait_item(
+                        tcx.type_of(did).subst_identity(),
+                        module_id,
+                        item_name,
+                        ns,
+                        self.cx,
+                    )
+                    .into_iter()
+                    .map(|item| (root_res, item.def_id))
+                    .collect::<Vec<_>>();
+                }
 
-                debug!("got associated item {:?}", assoc_item);
+                debug!("got associated item {:?}", assoc_items);
 
-                if let Some(item) = assoc_item {
-                    return Some((root_res, item.def_id));
+                if !assoc_items.is_empty() {
+                    return assoc_items;
                 }
 
                 if ns != Namespace::ValueNS {
-                    return None;
+                    return Vec::new();
                 }
                 debug!("looking for fields named {} for {:?}", item_name, did);
                 // FIXME: this doesn't really belong in `associated_item` (maybe `variant_field` is better?)
@@ -631,20 +668,27 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 // field syntax) and are handled by the compiler's resolver.
                 let def = match tcx.type_of(did).subst_identity().kind() {
                     ty::Adt(def, _) if !def.is_enum() => def,
-                    _ => return None,
+                    _ => return Vec::new(),
                 };
-                let field =
-                    def.non_enum_variant().fields.iter().find(|item| item.name == item_name)?;
-                Some((root_res, field.did))
+                def.non_enum_variant()
+                    .fields
+                    .iter()
+                    .filter(|field| field.name == item_name)
+                    .map(|field| (root_res, field.did))
+                    .collect::<Vec<_>>()
             }
-            Res::Def(DefKind::Trait, did) => tcx
-                .associated_items(did)
-                .find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, did)
-                .map(|item| {
-                    let res = Res::Def(item.kind.as_def_kind(), item.def_id);
-                    (res, item.def_id)
-                }),
-            _ => None,
+            Res::Def(DefKind::Trait, did) => filter_assoc_items_by_name_and_namespace(
+                tcx,
+                did,
+                Ident::with_dummy_span(item_name),
+                ns,
+            )
+            .map(|item| {
+                let res = Res::Def(item.kind.as_def_kind(), item.def_id);
+                (res, item.def_id)
+            })
+            .collect::<Vec<_>>(),
+            _ => Vec::new(),
         }
     }
 }
@@ -664,7 +708,7 @@ fn resolve_associated_trait_item<'a>(
     item_name: Symbol,
     ns: Namespace,
     cx: &mut DocContext<'a>,
-) -> Option<ty::AssocItem> {
+) -> Vec<ty::AssocItem> {
     // FIXME: this should also consider blanket impls (`impl<T> X for T`). Unfortunately
     // `get_auto_trait_and_blanket_impls` is broken because the caching behavior is wrong. In the
     // meantime, just don't look for these blanket impls.
@@ -672,19 +716,26 @@ fn resolve_associated_trait_item<'a>(
     // Next consider explicit impls: `impl MyTrait for MyType`
     // Give precedence to inherent impls.
     let traits = trait_impls_for(cx, ty, module);
+    let tcx = cx.tcx;
     debug!("considering traits {:?}", traits);
-    let mut candidates = traits.iter().filter_map(|&(impl_, trait_)| {
-        cx.tcx
-            .associated_items(trait_)
-            .find_by_name_and_namespace(cx.tcx, Ident::with_dummy_span(item_name), ns, trait_)
-            .map(|trait_assoc| {
-                trait_assoc_to_impl_assoc_item(cx.tcx, impl_, trait_assoc.def_id)
+    let candidates = traits
+        .iter()
+        .flat_map(|&(impl_, trait_)| {
+            filter_assoc_items_by_name_and_namespace(
+                cx.tcx,
+                trait_,
+                Ident::with_dummy_span(item_name),
+                ns,
+            )
+            .map(move |trait_assoc| {
+                trait_assoc_to_impl_assoc_item(tcx, impl_, trait_assoc.def_id)
                     .unwrap_or(*trait_assoc)
             })
-    });
+        })
+        .collect::<Vec<_>>();
     // FIXME(#74563): warn about ambiguity
-    debug!("the candidates were {:?}", candidates.clone().collect::<Vec<_>>());
-    candidates.next()
+    debug!("the candidates were {:?}", candidates);
+    candidates
 }
 
 /// Find the associated item in the impl `impl_id` that corresponds to the
@@ -758,15 +809,15 @@ fn trait_impls_for<'a>(
 /// Check for resolve collisions between a trait and its derive.
 ///
 /// These are common and we should just resolve to the trait in that case.
-fn is_derive_trait_collision<T>(ns: &PerNS<Result<(Res, T), ResolutionFailure<'_>>>) -> bool {
-    matches!(
-        *ns,
-        PerNS {
-            type_ns: Ok((Res::Def(DefKind::Trait, _), _)),
-            macro_ns: Ok((Res::Def(DefKind::Macro(MacroKind::Derive), _), _)),
-            ..
-        }
-    )
+fn is_derive_trait_collision<T>(ns: &PerNS<Result<Vec<(Res, T)>, ResolutionFailure<'_>>>) -> bool {
+    if let (&Ok(ref type_ns), &Ok(ref macro_ns)) = (&ns.type_ns, &ns.macro_ns) {
+        type_ns.iter().any(|(res, _)| matches!(res, Res::Def(DefKind::Trait, _)))
+            && macro_ns
+                .iter()
+                .any(|(res, _)| matches!(res, Res::Def(DefKind::Macro(MacroKind::Derive), _)))
+    } else {
+        false
+    }
 }
 
 impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
@@ -987,15 +1038,15 @@ impl LinkCollector<'_, '_> {
                     res = prim;
                 } else {
                     // `[char]` when a `char` module is in scope
-                    let candidates = vec![res, prim];
-                    ambiguity_error(self.cx, diag_info, path_str, candidates);
+                    let candidates = &[(res, res.def_id(self.cx.tcx)), (prim, None)];
+                    ambiguity_error(self.cx, &diag_info, path_str, candidates);
                     return None;
                 }
             }
         }
 
         match res {
-            Res::Primitive(prim) => {
+            Res::Primitive(_) => {
                 if let Some(UrlFragment::Item(id)) = fragment {
                     // We're actually resolving an associated item of a primitive, so we need to
                     // verify the disambiguator (if any) matches the type of the associated item.
@@ -1015,15 +1066,6 @@ impl LinkCollector<'_, '_> {
                         item,
                         &diag_info,
                     )?;
-
-                    // FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
-                    // However I'm not sure how to check that across crates.
-                    if prim == PrimitiveType::RawPointer
-                        && item.item_id.is_local()
-                        && !self.cx.tcx.features().intra_doc_pointers
-                    {
-                        self.report_rawptr_assoc_feature_gate(dox, ori_link, item);
-                    }
                 } else {
                     match disambiguator {
                         Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {}
@@ -1102,7 +1144,7 @@ impl LinkCollector<'_, '_> {
                 }
             }
 
-        // item can be non-local e.g. when using #[doc(primitive = "pointer")]
+        // item can be non-local e.g. when using `#[rustc_doc_primitive = "pointer"]`
         if let Some((src_id, dst_id)) = id.as_local().and_then(|dst_id| {
             item.item_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
         }) {
@@ -1144,10 +1186,9 @@ impl LinkCollector<'_, '_> {
         report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, diag_info, callback);
     }
 
-    fn report_rawptr_assoc_feature_gate(&self, dox: &str, ori_link: &MarkdownLink, item: &Item) {
-        let span =
-            super::source_span_for_markdown_range(self.cx.tcx, dox, &ori_link.range, &item.attrs)
-                .unwrap_or_else(|| item.attr_span(self.cx.tcx));
+    fn report_rawptr_assoc_feature_gate(&self, dox: &str, ori_link: &Range<usize>, item: &Item) {
+        let span = super::source_span_for_markdown_range(self.cx.tcx, dox, ori_link, &item.attrs)
+            .unwrap_or_else(|| item.attr_span(self.cx.tcx));
         rustc_session::parse::feature_err(
             &self.cx.tcx.sess.parse_sess,
             sym::intra_doc_pointers,
@@ -1172,7 +1213,31 @@ impl LinkCollector<'_, '_> {
             }
         }
 
-        let res = self.resolve_with_disambiguator(&key, diag.clone()).and_then(|(res, def_id)| {
+        let mut candidates = self.resolve_with_disambiguator(&key, diag.clone());
+
+        // FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
+        // However I'm not sure how to check that across crates.
+        if let Some(candidate) = candidates.get(0) &&
+            candidate.0 == Res::Primitive(PrimitiveType::RawPointer) &&
+            key.path_str.contains("::") // We only want to check this if this is an associated item.
+        {
+            if key.item_id.is_local() && !self.cx.tcx.features().intra_doc_pointers {
+                self.report_rawptr_assoc_feature_gate(diag.dox, &diag.link_range, diag.item);
+                return None;
+            } else {
+                candidates = vec![candidates[0]];
+            }
+        }
+
+        // If there are multiple items with the same "kind" (for example, both "associated types")
+        // and after removing duplicated kinds, only one remains, the `ambiguity_error` function
+        // won't emit an error. So at this point, we can just take the first candidate as it was
+        // the first retrieved and use it to generate the link.
+        if candidates.len() > 1 && !ambiguity_error(self.cx, &diag, &key.path_str, &candidates) {
+            candidates = vec![candidates[0]];
+        }
+
+        if let &[(res, def_id)] = candidates.as_slice() {
             let fragment = match (&key.extra_fragment, def_id) {
                 (Some(_), Some(def_id)) => {
                     report_anchor_conflict(self.cx, diag, def_id);
@@ -1182,13 +1247,15 @@ impl LinkCollector<'_, '_> {
                 (None, Some(def_id)) => Some(UrlFragment::Item(def_id)),
                 (None, None) => None,
             };
-            Some((res, fragment))
-        });
+            let r = Some((res, fragment));
+            self.visited_links.insert(key, r.clone());
+            return r;
+        }
 
-        if res.is_some() || cache_errors {
-            self.visited_links.insert(key, res.clone());
+        if cache_errors {
+            self.visited_links.insert(key, None);
         }
-        res
+        None
     }
 
     /// After parsing the disambiguator, resolve the main part of the link.
@@ -1197,7 +1264,7 @@ impl LinkCollector<'_, '_> {
         &mut self,
         key: &ResolutionInfo,
         diag: DiagnosticInfo<'_>,
-    ) -> Option<(Res, Option<DefId>)> {
+    ) -> Vec<(Res, Option<DefId>)> {
         let disambiguator = key.dis;
         let path_str = &key.path_str;
         let item_id = key.item_id;
@@ -1206,7 +1273,7 @@ impl LinkCollector<'_, '_> {
         match disambiguator.map(Disambiguator::ns) {
             Some(expected_ns) => {
                 match self.resolve(path_str, expected_ns, item_id, module_id) {
-                    Ok(res) => Some(res),
+                    Ok(candidates) => candidates,
                     Err(err) => {
                         // We only looked in one namespace. Try to give a better error if possible.
                         // FIXME: really it should be `resolution_failure` that does this, not `resolve_with_disambiguator`.
@@ -1215,10 +1282,11 @@ impl LinkCollector<'_, '_> {
                         for other_ns in [TypeNS, ValueNS, MacroNS] {
                             if other_ns != expected_ns {
                                 if let Ok(res) =
-                                    self.resolve(path_str, other_ns, item_id, module_id)
+                                    self.resolve(path_str, other_ns, item_id, module_id) &&
+                                    !res.is_empty()
                                 {
                                     err = ResolutionFailure::WrongNamespace {
-                                        res: full_res(self.cx.tcx, res),
+                                        res: full_res(self.cx.tcx, res[0]),
                                         expected_ns,
                                     };
                                     break;
@@ -1239,18 +1307,26 @@ impl LinkCollector<'_, '_> {
                 let candidates = PerNS {
                     macro_ns: candidate(MacroNS),
                     type_ns: candidate(TypeNS),
-                    value_ns: candidate(ValueNS).and_then(|(res, def_id)| {
-                        match res {
-                            // Constructors are picked up in the type namespace.
-                            Res::Def(DefKind::Ctor(..), _) => {
-                                Err(ResolutionFailure::WrongNamespace { res, expected_ns: TypeNS })
+                    value_ns: candidate(ValueNS).and_then(|v_res| {
+                        for (res, _) in v_res.iter() {
+                            match res {
+                                // Constructors are picked up in the type namespace.
+                                Res::Def(DefKind::Ctor(..), _) => {
+                                    return Err(ResolutionFailure::WrongNamespace {
+                                        res: *res,
+                                        expected_ns: TypeNS,
+                                    });
+                                }
+                                _ => {}
                             }
-                            _ => Ok((res, def_id)),
                         }
+                        Ok(v_res)
                     }),
                 };
 
-                let len = candidates.iter().filter(|res| res.is_ok()).count();
+                let len = candidates
+                    .iter()
+                    .fold(0, |acc, res| if let Ok(res) = res { acc + res.len() } else { acc });
 
                 if len == 0 {
                     return resolution_failure(
@@ -1260,22 +1336,21 @@ impl LinkCollector<'_, '_> {
                         disambiguator,
                         candidates.into_iter().filter_map(|res| res.err()).collect(),
                     );
-                }
-
-                if len == 1 {
-                    Some(candidates.into_iter().find_map(|res| res.ok()).unwrap())
-                } else if len == 2 && is_derive_trait_collision(&candidates) {
-                    Some(candidates.type_ns.unwrap())
+                } else if len == 1 {
+                    candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::<Vec<_>>()
                 } else {
-                    let ignore_macro = is_derive_trait_collision(&candidates);
-                    // If we're reporting an ambiguity, don't mention the namespaces that failed
-                    let mut candidates =
-                        candidates.map(|candidate| candidate.ok().map(|(res, _)| res));
-                    if ignore_macro {
-                        candidates.macro_ns = None;
+                    let has_derive_trait_collision = is_derive_trait_collision(&candidates);
+                    if len == 2 && has_derive_trait_collision {
+                        candidates.type_ns.unwrap()
+                    } else {
+                        // If we're reporting an ambiguity, don't mention the namespaces that failed
+                        let mut candidates = candidates.map(|candidate| candidate.ok());
+                        // If there a collision between a trait and a derive, we ignore the derive.
+                        if has_derive_trait_collision {
+                            candidates.macro_ns = None;
+                        }
+                        candidates.into_iter().filter_map(|res| res).flatten().collect::<Vec<_>>()
                     }
-                    ambiguity_error(self.cx, diag, path_str, candidates.present_items().collect());
-                    None
                 }
             }
         }
@@ -1563,7 +1638,7 @@ fn resolution_failure(
     path_str: &str,
     disambiguator: Option<Disambiguator>,
     kinds: SmallVec<[ResolutionFailure<'_>; 3]>,
-) -> Option<(Res, Option<DefId>)> {
+) -> Vec<(Res, Option<DefId>)> {
     let tcx = collector.cx.tcx;
     let mut recovered_res = None;
     report_diagnostic(
@@ -1622,11 +1697,13 @@ fn resolution_failure(
                         };
                         name = start;
                         for ns in [TypeNS, ValueNS, MacroNS] {
-                            if let Ok(res) = collector.resolve(start, ns, item_id, module_id) {
-                                debug!("found partial_res={:?}", res);
-                                *partial_res = Some(full_res(collector.cx.tcx, res));
-                                *unresolved = end.into();
-                                break 'outer;
+                            if let Ok(v_res) = collector.resolve(start, ns, item_id, module_id) {
+                                debug!("found partial_res={:?}", v_res);
+                                if !v_res.is_empty() {
+                                    *partial_res = Some(full_res(collector.cx.tcx, v_res[0]));
+                                    *unresolved = end.into();
+                                    break 'outer;
+                                }
                             }
                         }
                         *unresolved = end.into();
@@ -1774,7 +1851,10 @@ fn resolution_failure(
         },
     );
 
-    recovered_res
+    match recovered_res {
+        Some(r) => vec![r],
+        None => Vec::new(),
+    }
 }
 
 fn report_multiple_anchors(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>) {
@@ -1859,28 +1939,47 @@ fn report_malformed_generics(
 }
 
 /// Report an ambiguity error, where there were multiple possible resolutions.
+///
+/// If all `candidates` have the same kind, it's not possible to disambiguate so in this case,
+/// the function won't emit an error and will return `false`. Otherwise, it'll emit the error and
+/// return `true`.
 fn ambiguity_error(
     cx: &DocContext<'_>,
-    diag_info: DiagnosticInfo<'_>,
+    diag_info: &DiagnosticInfo<'_>,
     path_str: &str,
-    candidates: Vec<Res>,
-) {
-    let mut msg = format!("`{}` is ", path_str);
+    candidates: &[(Res, Option<DefId>)],
+) -> bool {
+    let mut descrs = FxHashSet::default();
+    let kinds = candidates
+        .iter()
+        .map(
+            |(res, def_id)| {
+                if let Some(def_id) = def_id { Res::from_def_id(cx.tcx, *def_id) } else { *res }
+            },
+        )
+        .filter(|res| descrs.insert(res.descr()))
+        .collect::<Vec<_>>();
+    if descrs.len() == 1 {
+        // There is no way for users to disambiguate at this point, so better return the first
+        // candidate and not show a warning.
+        return false;
+    }
 
-    match candidates.as_slice() {
-        [first_def, second_def] => {
+    let mut msg = format!("`{}` is ", path_str);
+    match kinds.as_slice() {
+        [res1, res2] => {
             msg += &format!(
                 "both {} {} and {} {}",
-                first_def.article(),
-                first_def.descr(),
-                second_def.article(),
-                second_def.descr(),
+                res1.article(),
+                res1.descr(),
+                res2.article(),
+                res2.descr()
             );
         }
         _ => {
-            let mut candidates = candidates.iter().peekable();
-            while let Some(res) = candidates.next() {
-                if candidates.peek().is_some() {
+            let mut kinds = kinds.iter().peekable();
+            while let Some(res) = kinds.next() {
+                if kinds.peek().is_some() {
                     msg += &format!("{} {}, ", res.article(), res.descr());
                 } else {
                     msg += &format!("and {} {}", res.article(), res.descr());
@@ -1889,17 +1988,18 @@ fn ambiguity_error(
         }
     }
 
-    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, &diag_info, |diag, sp| {
+    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, diag_info, |diag, sp| {
         if let Some(sp) = sp {
             diag.span_label(sp, "ambiguous link");
         } else {
             diag.note("ambiguous link");
         }
 
-        for res in candidates {
+        for res in kinds {
             suggest_disambiguator(res, diag, path_str, diag_info.ori_link, sp);
         }
     });
+    true
 }
 
 /// In case of an ambiguity or mismatched disambiguator, suggest the correct
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index e70488165b9..8871873c661 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -1,5 +1,4 @@
 #![feature(let_chains)]
-#![feature(once_cell)]
 #![feature(rustc_private)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 // warn on lints, that are included in `rust-lang/rust`s bootstrap
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index c9210bf73f8..3da7f95c1b9 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -7,7 +7,6 @@
 #![feature(let_chains)]
 #![feature(lint_reasons)]
 #![feature(never_type)]
-#![feature(once_cell)]
 #![feature(rustc_private)]
 #![feature(stmt_expr_attributes)]
 #![recursion_limit = "512"]
diff --git a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs
index 448a32b77c0..c984a8286eb 100644
--- a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs
@@ -3,7 +3,7 @@ use clippy_utils::last_path_segment;
 use clippy_utils::source::snippet;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::{GenericArg, Mutability, Ty, TyKind};
+use rustc_hir::{GenericArg, GenericArgsParentheses, Mutability, Ty, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::sym;
@@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for RefOptionRef {
 
             if cx.tcx.is_diagnostic_item(sym::Option, def_id);
             if let Some(params) = last_path_segment(qpath).args ;
-            if !params.parenthesized;
+            if params.parenthesized == GenericArgsParentheses::No;
             if let Some(inner_ty) = params.args.iter().find_map(|arg| match arg {
                 GenericArg::Type(inner_ty) => Some(inner_ty),
                 _ => None,
diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
index 65dfe7637ea..acdf5471069 100644
--- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
@@ -20,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
                 if let QPath::Resolved(None, path) = *qpath;
                 if let [ref bx] = *path.segments;
                 if let Some(params) = bx.args;
-                if !params.parenthesized;
+                if params.parenthesized == hir::GenericArgsParentheses::No;
                 if let Some(inner) = params.args.iter().find_map(|arg| match arg {
                     GenericArg::Type(ty) => Some(ty),
                     _ => None,
diff --git a/src/tools/clippy/clippy_lints/src/types/utils.rs b/src/tools/clippy/clippy_lints/src/types/utils.rs
index 7f43b7841ff..a30748db88f 100644
--- a/src/tools/clippy/clippy_lints/src/types/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/types/utils.rs
@@ -1,6 +1,6 @@
 use clippy_utils::last_path_segment;
 use if_chain::if_chain;
-use rustc_hir::{GenericArg, QPath, TyKind};
+use rustc_hir::{GenericArg, GenericArgsParentheses, QPath, TyKind};
 use rustc_lint::LateContext;
 use rustc_span::source_map::Span;
 
@@ -8,7 +8,7 @@ pub(super) fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>)
     let last = last_path_segment(qpath);
     if_chain! {
         if let Some(params) = last.args;
-        if !params.parenthesized;
+        if params.parenthesized == GenericArgsParentheses::No;
         if let Some(ty) = params.args.iter().find_map(|arg| match arg {
             GenericArg::Type(ty) => Some(ty),
             _ => None,
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index 8ea5475fb25..7dfb0956077 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -10,7 +10,7 @@ use rustc_hir::{
     def::{CtorOf, DefKind, Res},
     def_id::LocalDefId,
     intravisit::{walk_inf, walk_ty, Visitor},
-    Expr, ExprKind, FnRetTy, FnSig, GenericArg, GenericParam, GenericParamKind, HirId, Impl, ImplItemKind, Item,
+    Expr, ExprKind, FnRetTy, FnSig, GenericArg, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl, ImplItemKind, Item,
     ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind,
 };
 use rustc_hir_analysis::hir_ty_to_ty;
@@ -100,7 +100,8 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
             if let TyKind::Path(QPath::Resolved(_, item_path)) = self_ty.kind;
             let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args;
             if parameters.as_ref().map_or(true, |params| {
-                !params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
+                params.parenthesized  == GenericArgsParentheses::No
+                    && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
             });
             if !item.span.from_expansion();
             if !is_from_proc_macro(cx, item); // expensive, should be last check
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 3a6d23ca5c1..3ee7147828b 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -401,14 +401,9 @@ impl HirEqInterExpr<'_, '_, '_> {
     }
 
     fn eq_path_parameters(&mut self, left: &GenericArgs<'_>, right: &GenericArgs<'_>) -> bool {
-        if !(left.parenthesized || right.parenthesized) {
+        if left.parenthesized == right.parenthesized {
             over(left.args, right.args, |l, r| self.eq_generic_arg(l, r)) // FIXME(flip1995): may not work
                 && over(left.bindings, right.bindings, |l, r| self.eq_type_binding(l, r))
-        } else if left.parenthesized && right.parenthesized {
-            over(left.inputs(), right.inputs(), |l, r| self.eq_ty(l, r))
-                && both(&Some(&left.bindings[0].ty()), &Some(&right.bindings[0].ty()), |l, r| {
-                    self.eq_ty(l, r)
-                })
         } else {
             false
         }
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index fd06c0b8677..619aa9f4bf6 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -3,7 +3,6 @@
 #![feature(let_chains)]
 #![feature(lint_reasons)]
 #![feature(never_type)]
-#![feature(once_cell)]
 #![feature(rustc_private)]
 #![recursion_limit = "512"]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index f08393c303e..9e0822404b6 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -1,6 +1,6 @@
 #![feature(rustc_private)]
 #![feature(let_chains)]
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![feature(lint_reasons)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 // warn on lints, that are included in `rust-lang/rust`s bootstrap
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index c10ee969c01..57890ff3173 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -1,5 +1,5 @@
 #![feature(test)] // compiletest_rs requires this attribute
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![feature(is_sorted)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![warn(rust_2018_idioms, unused_lifetimes)]
diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs
index 3a5d478fa31..68a878e9a3d 100644
--- a/src/tools/clippy/tests/dogfood.rs
+++ b/src/tools/clippy/tests/dogfood.rs
@@ -3,7 +3,7 @@
 //!
 //! See [Eating your own dog food](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) for context
 
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
diff --git a/src/tools/clippy/tests/lint_message_convention.rs b/src/tools/clippy/tests/lint_message_convention.rs
index abd0d1bc593..8feea800fdb 100644
--- a/src/tools/clippy/tests/lint_message_convention.rs
+++ b/src/tools/clippy/tests/lint_message_convention.rs
@@ -1,4 +1,4 @@
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
diff --git a/src/tools/clippy/tests/workspace.rs b/src/tools/clippy/tests/workspace.rs
index 95325e06037..c9cbc50546c 100644
--- a/src/tools/clippy/tests/workspace.rs
+++ b/src/tools/clippy/tests/workspace.rs
@@ -1,4 +1,4 @@
-#![feature(once_cell)]
+#![feature(lazy_cell)]
 
 use std::path::PathBuf;
 use std::process::Command;
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index bce61c55c3d..7048b0e08bb 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -12,6 +12,7 @@ use build_helper::git::{get_git_modified_files, get_git_untracked_files};
 use core::panic;
 use getopts::Options;
 use lazycell::LazyCell;
+use std::collections::BTreeSet;
 use std::ffi::OsString;
 use std::fs;
 use std::io::{self, ErrorKind};
@@ -409,7 +410,9 @@ pub fn run_tests(config: Config) {
 
     let mut tests = Vec::new();
     for c in &configs {
-        make_tests(c, &mut tests);
+        let mut found_paths = BTreeSet::new();
+        make_tests(c, &mut tests, &mut found_paths);
+        check_overlapping_tests(&found_paths);
     }
 
     tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice()));
@@ -535,7 +538,11 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
     }
 }
 
-pub fn make_tests(config: &Config, tests: &mut Vec<test::TestDescAndFn>) {
+pub fn make_tests(
+    config: &Config,
+    tests: &mut Vec<test::TestDescAndFn>,
+    found_paths: &mut BTreeSet<PathBuf>,
+) {
     debug!("making tests from {:?}", config.src_base.display());
     let inputs = common_inputs_stamp(config);
     let modified_tests = modified_tests(config, &config.src_base).unwrap_or_else(|err| {
@@ -547,6 +554,7 @@ pub fn make_tests(config: &Config, tests: &mut Vec<test::TestDescAndFn>) {
         &PathBuf::new(),
         &inputs,
         tests,
+        found_paths,
         &modified_tests,
     )
     .unwrap_or_else(|_| panic!("Could not read tests from {}", config.src_base.display()));
@@ -617,6 +625,7 @@ fn collect_tests_from_dir(
     relative_dir_path: &Path,
     inputs: &Stamp,
     tests: &mut Vec<test::TestDescAndFn>,
+    found_paths: &mut BTreeSet<PathBuf>,
     modified_tests: &Vec<PathBuf>,
 ) -> io::Result<()> {
     // Ignore directories that contain a file named `compiletest-ignore-dir`.
@@ -650,6 +659,8 @@ fn collect_tests_from_dir(
         let file_name = file.file_name();
         if is_test(&file_name) && (!config.only_modified || modified_tests.contains(&file_path)) {
             debug!("found test file: {:?}", file_path.display());
+            let rel_test_path = relative_dir_path.join(file_path.file_stem().unwrap());
+            found_paths.insert(rel_test_path);
             let paths =
                 TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() };
 
@@ -664,6 +675,7 @@ fn collect_tests_from_dir(
                     &relative_file_path,
                     inputs,
                     tests,
+                    found_paths,
                     modified_tests,
                 )?;
             }
@@ -1079,3 +1091,24 @@ fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> {
 fn not_a_digit(c: char) -> bool {
     !c.is_digit(10)
 }
+
+fn check_overlapping_tests(found_paths: &BTreeSet<PathBuf>) {
+    let mut collisions = Vec::new();
+    for path in found_paths {
+        for ancestor in path.ancestors().skip(1) {
+            if found_paths.contains(ancestor) {
+                collisions.push((path, ancestor.clone()));
+            }
+        }
+    }
+    if !collisions.is_empty() {
+        let collisions: String = collisions
+            .into_iter()
+            .map(|(path, check_parent)| format!("test {path:?} clashes with {check_parent:?}\n"))
+            .collect();
+        panic!(
+            "{collisions}\n\
+            Tests cannot have overlapping names. Make sure they use unique prefixes."
+        );
+    }
+}
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index 0ea1137200b..acc97c4b8a0 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -220,6 +220,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     },
                 )?;
             }
+            MisalignedPointerDereference { required, found } => {
+                // Forward to `panic_misaligned_pointer_dereference` lang item.
+
+                // First arg: required.
+                let required = this.read_scalar(&this.eval_operand(required, None)?)?;
+                // Second arg: found.
+                let found = this.read_scalar(&this.eval_operand(found, None)?)?;
+
+                // Call the lang item.
+                let panic_misaligned_pointer_dereference =
+                    this.tcx.lang_items().panic_misaligned_pointer_dereference_fn().unwrap();
+                let panic_misaligned_pointer_dereference =
+                    ty::Instance::mono(this.tcx.tcx, panic_misaligned_pointer_dereference);
+                this.call_function(
+                    panic_misaligned_pointer_dereference,
+                    Abi::Rust,
+                    &[required.into(), found.into()],
+                    None,
+                    StackPopCleanup::Goto {
+                        ret: None,
+                        unwind: match unwind {
+                            Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
+                            None => StackPopUnwind::Skip,
+                        },
+                    },
+                )?;
+            }
+
             _ => {
                 // Forward everything else to `panic` lang item.
                 this.start_panic(
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/alignment.rs b/src/tools/miri/tests/fail/unaligned_pointers/alignment.rs
index 438e74e5b8d..6bb95ae4bcb 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/alignment.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/alignment.rs
@@ -1,4 +1,5 @@
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
+//@compile-flags: -Cdebug-assertions=no
 
 fn main() {
     // No retry needed, this fails reliably.
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.rs b/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.rs
index 9dd652fd821..29976836b0b 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.rs
@@ -1,4 +1,4 @@
-//@compile-flags: -Zmiri-symbolic-alignment-check
+//@compile-flags: -Zmiri-symbolic-alignment-check -Cdebug-assertions=no
 #![feature(core_intrinsics)]
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
index cf3a558bb99..8a40e527f0e 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
@@ -1,3 +1,5 @@
+//@compile-flags: -Cdebug-assertions=no
+
 #[repr(transparent)]
 struct HasDrop(u8);
 
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs
index ca8590cc6b3..6d31ded75c6 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs
@@ -1,5 +1,5 @@
 // should find the bug even without validation and stacked borrows, but gets masked by optimizations
-//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Zmir-opt-level=0
+//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Zmir-opt-level=0 -Cdebug-assertions=no
 
 #[repr(align(256))]
 #[derive(Debug)]
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/intptrcast_alignment_check.rs b/src/tools/miri/tests/fail/unaligned_pointers/intptrcast_alignment_check.rs
index da4cadc1c87..c1041ee32a4 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/intptrcast_alignment_check.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/intptrcast_alignment_check.rs
@@ -1,4 +1,4 @@
-//@compile-flags: -Zmiri-symbolic-alignment-check -Zmiri-permissive-provenance
+//@compile-flags: -Zmiri-symbolic-alignment-check -Zmiri-permissive-provenance -Cdebug-assertions=no
 // With the symbolic alignment check, even with intptrcast and without
 // validation, we want to be *sure* to catch bugs that arise from pointers being
 // insufficiently aligned. The only way to achieve that is not not let programs
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.rs b/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.rs
index 4a43db0aac5..4a8cf405ae2 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.rs
@@ -1,5 +1,5 @@
 // This should fail even without validation/SB
-//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
+//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
 
 #![allow(dead_code, unused_variables)]
 
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr1.rs b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr1.rs
index 47d1f782cb6..921bcd6ce24 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr1.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr1.rs
@@ -1,5 +1,5 @@
 // This should fail even without validation or Stacked Borrows.
-//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
+//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
 
 fn main() {
     // Try many times as this might work by chance.
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr2.rs b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr2.rs
index c252944ffb7..8f597659f73 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr2.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr2.rs
@@ -1,5 +1,5 @@
 // This should fail even without validation or Stacked Borrows.
-//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
+//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
 
 fn main() {
     // No retry needed, this fails reliably.
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr3.rs b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr3.rs
index 3aa8cb492a1..a7fcf30c6ea 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr3.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr3.rs
@@ -1,5 +1,5 @@
 // This should fail even without validation or Stacked Borrows.
-//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
+//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
 
 fn main() {
     // Try many times as this might work by chance.
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr4.rs b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr4.rs
index 606316120d6..b8b01e113c9 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr4.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr4.rs
@@ -1,5 +1,5 @@
 // This should fail even without validation or Stacked Borrows.
-//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
+//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
 
 fn main() {
     // Make sure we notice when a u16 is loaded at offset 1 into a u8 allocation.
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr_addr_of.rs b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr_addr_of.rs
index f1032ab52bc..b414b905472 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr_addr_of.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr_addr_of.rs
@@ -1,5 +1,5 @@
 // This should fail even without validation or Stacked Borrows.
-//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
+//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
 use std::ptr;
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr_zst.rs b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr_zst.rs
index eff42375956..04dbe3fd8d4 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr_zst.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr_zst.rs
@@ -1,6 +1,6 @@
 // This should fail even without validation
 // Some optimizations remove ZST accesses, thus masking this UB.
-//@compile-flags: -Zmir-opt-level=0 -Zmiri-disable-validation
+//@compile-flags: -Zmir-opt-level=0 -Zmiri-disable-validation -Cdebug-assertions=no
 
 fn main() {
     // Try many times as this might work by chance.
diff --git a/src/tools/miri/tests/panic/alignment-assertion.rs b/src/tools/miri/tests/panic/alignment-assertion.rs
new file mode 100644
index 00000000000..68aa19a88db
--- /dev/null
+++ b/src/tools/miri/tests/panic/alignment-assertion.rs
@@ -0,0 +1,9 @@
+//@compile-flags: -Zmiri-disable-alignment-check -Cdebug-assertions=yes
+
+fn main() {
+    let mut x = [0u32; 2];
+    let ptr: *mut u8 = x.as_mut_ptr().cast::<u8>();
+    unsafe {
+        *(ptr.add(1).cast::<u32>()) = 42;
+    }
+}
diff --git a/src/tools/miri/tests/panic/alignment-assertion.stderr b/src/tools/miri/tests/panic/alignment-assertion.stderr
new file mode 100644
index 00000000000..26cf51b0cd2
--- /dev/null
+++ b/src/tools/miri/tests/panic/alignment-assertion.stderr
@@ -0,0 +1,2 @@
+thread 'main' panicked at 'misaligned pointer dereference: address must be a multiple of 0x4 but is $HEX', $DIR/alignment-assertion.rs:LL:CC
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/tools/miri/tests/pass/disable-alignment-check.rs b/src/tools/miri/tests/pass/disable-alignment-check.rs
index fdcacc6cea4..e8c0e027673 100644
--- a/src/tools/miri/tests/pass/disable-alignment-check.rs
+++ b/src/tools/miri/tests/pass/disable-alignment-check.rs
@@ -1,6 +1,6 @@
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
-//@compile-flags: -Zmiri-disable-alignment-check
+//@compile-flags: -Zmiri-disable-alignment-check -Cdebug-assertions=no
 
 fn main() {
     let mut x = [0u8; 20];
diff --git a/tests/assembly/static-relocation-model.rs b/tests/assembly/static-relocation-model.rs
index faa2e395209..41aa9a46103 100644
--- a/tests/assembly/static-relocation-model.rs
+++ b/tests/assembly/static-relocation-model.rs
@@ -6,6 +6,7 @@
 // [A64] needs-llvm-components: aarch64
 // [ppc64le] compile-flags: --target powerpc64le-unknown-linux-gnu -Crelocation-model=static
 // [ppc64le] needs-llvm-components: powerpc
+// ignore-debug: alignment checks insert panics that we don't have a lang item for
 
 #![feature(no_core, lang_items)]
 #![no_core]
diff --git a/tests/codegen/issues/issue-37945.rs b/tests/codegen/issues/issue-37945.rs
index fe54375bbf6..19e7e8b1f6e 100644
--- a/tests/codegen/issues/issue-37945.rs
+++ b/tests/codegen/issues/issue-37945.rs
@@ -4,6 +4,7 @@
 // ignore-emscripten
 // ignore-gnux32
 // ignore 32-bit platforms (LLVM has a bug with them)
+// ignore-debug
 
 // Check that LLVM understands that `Iter` pointer is not null. Issue #37945.
 
diff --git a/tests/codegen/virtual-function-elimination.rs b/tests/codegen/virtual-function-elimination.rs
index 4cf7e12fee2..30e5cd0584d 100644
--- a/tests/codegen/virtual-function-elimination.rs
+++ b/tests/codegen/virtual-function-elimination.rs
@@ -1,5 +1,6 @@
 // compile-flags: -Zvirtual-function-elimination -Clto -O -Csymbol-mangling-version=v0
 // ignore-32bit
+// ignore-debug
 
 // CHECK: @vtable.0 = {{.*}}, !type ![[TYPE0:[0-9]+]], !vcall_visibility ![[VCALL_VIS0:[0-9]+]]
 // CHECK: @vtable.1 = {{.*}}, !type ![[TYPE1:[0-9]+]], !vcall_visibility ![[VCALL_VIS0:[0-9]+]]
diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
index bc1c913c00e..a4f0ad465e2 100644
--- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
+++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
@@ -8,10 +8,10 @@
       scope 1 {
           debug _x => _1;                  // in scope 1 at $DIR/inline_into_box_place.rs:+1:9: +1:11
       }
-+     scope 2 (inlined Vec::<u32>::new) {  // at $DIR/inline_into_box_place.rs:7:38: 7:48
++     scope 2 (inlined Vec::<u32>::new) {  // at $DIR/inline_into_box_place.rs:8:38: 8:48
 +         let mut _3: alloc::raw_vec::RawVec<u32>; // in scope 2 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 +     }
-+     scope 3 (inlined Box::<Vec<u32>>::new) { // at $DIR/inline_into_box_place.rs:7:29: 7:49
++     scope 3 (inlined Box::<Vec<u32>>::new) { // at $DIR/inline_into_box_place.rs:8:29: 8:49
 +         debug x => _2;                   // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
 +         let mut _4: usize;               // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
 +         let mut _5: usize;               // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
@@ -28,7 +28,7 @@
 +         StorageLive(_3);                 // scope 2 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 +         _3 = const _;                    // scope 2 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
                                            // mir::Constant
--                                          // + span: $DIR/inline_into_box_place.rs:7:38: 7:46
+-                                          // + span: $DIR/inline_into_box_place.rs:8:38: 8:46
 -                                          // + user_ty: UserType(2)
 -                                          // + literal: Const { ty: fn() -> Vec<u32> {Vec::<u32>::new}, val: Value(<ZST>) }
 +                                          // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
@@ -47,7 +47,7 @@
       bb1: {
 -         _1 = Box::<Vec<u32>>::new(move _2) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:49
 -                                          // mir::Constant
--                                          // + span: $DIR/inline_into_box_place.rs:7:29: 7:37
+-                                          // + span: $DIR/inline_into_box_place.rs:8:29: 8:37
 -                                          // + user_ty: UserType(1)
 -                                          // + literal: Const { ty: fn(Vec<u32>) -> Box<Vec<u32>> {Box::<Vec<u32>>::new}, val: Value(<ZST>) }
 +         StorageDead(_1);                 // scope 0 at $DIR/inline_into_box_place.rs:+2:1: +2:2
diff --git a/tests/mir-opt/inline/inline_into_box_place.rs b/tests/mir-opt/inline/inline_into_box_place.rs
index b8b73f0c44c..02823e4e1b7 100644
--- a/tests/mir-opt/inline/inline_into_box_place.rs
+++ b/tests/mir-opt/inline/inline_into_box_place.rs
@@ -1,5 +1,6 @@
 // ignore-endian-big
 // ignore-wasm32-bare compiled with panic=abort by default
+// ignore-debug MIR alignment checks in std alter the diff, breaking the test
 // compile-flags: -Z mir-opt-level=4
 
 // EMIT_MIR inline_into_box_place.main.Inline.diff
diff --git a/tests/run-make/fmt-write-bloat/Makefile b/tests/run-make/fmt-write-bloat/Makefile
index 07e6e025e08..53615775486 100644
--- a/tests/run-make/fmt-write-bloat/Makefile
+++ b/tests/run-make/fmt-write-bloat/Makefile
@@ -11,11 +11,11 @@ else
 
 NM = nm
 
-PANIC_SYMS = panic_bounds_check pad_integral Display Debug
+PANIC_SYMS = panic_bounds_check Debug
 
 # Allow for debug_assert!() in debug builds of std.
 ifdef NO_DEBUG_ASSERTIONS
-PANIC_SYMS += panicking panic_fmt
+PANIC_SYMS += panicking panic_fmt pad_integral Display Debug
 endif
 
 all: main.rs
diff --git a/tests/run-make/libtest-thread-limit/test.rs b/tests/run-make/libtest-thread-limit/test.rs
index 26bc29216cf..88e8a498ae9 100644
--- a/tests/run-make/libtest-thread-limit/test.rs
+++ b/tests/run-make/libtest-thread-limit/test.rs
@@ -1,5 +1,3 @@
-#![feature(once_cell)]
-
 use std::{
     io::ErrorKind,
     sync::OnceLock,
diff --git a/tests/rustdoc-gui/go-to-collapsed-elem.goml b/tests/rustdoc-gui/go-to-collapsed-elem.goml
new file mode 100644
index 00000000000..279048e37c1
--- /dev/null
+++ b/tests/rustdoc-gui/go-to-collapsed-elem.goml
@@ -0,0 +1,21 @@
+// This test ensures that when clicking on a link which leads to an item inside a collapsed element,
+// the collapsed element will be expanded.
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+// We check that the implementors block is expanded.
+assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
+// We now collapse the implementors block.
+property: ("#implementations-list .implementors-toggle", {"open": "false"})
+// And now we click on the link to the method to ensure it'll expand the implementors block.
+click: "//*[@class='sidebar']//a[@href='#method.must_use']"
+assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
+
+// Now we do the same through search result.
+// First we reload the page without the anchor in the URL.
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+// Then we collapse the section again...
+property: ("#implementations-list .implementors-toggle", {"open": "false"})
+// Then we run the search.
+write: (".search-input", "foo::must_use")
+wait-for: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
+click: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
+assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
diff --git a/tests/rustdoc-json/impls/local_for_local_primitive.rs b/tests/rustdoc-json/impls/local_for_local_primitive.rs
index 38e7e2658df..8383dcc0482 100644
--- a/tests/rustdoc-json/impls/local_for_local_primitive.rs
+++ b/tests/rustdoc-json/impls/local_for_local_primitive.rs
@@ -1,5 +1,5 @@
 #![feature(no_core)]
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 #![no_core]
 
 // @set Local = "$.index[*][?(@.name=='Local')].id"
@@ -16,6 +16,6 @@ impl Local for bool {}
 
 // FIXME(#101695): Test bool's `impls` include "Local for bool"
 // @has "$.index[*][?(@.name=='bool')]"
-#[doc(primitive = "bool")]
+#[rustc_doc_primitive = "bool"]
 /// Boolean docs
 mod prim_bool {}
diff --git a/tests/rustdoc-json/primitives/local_primitive.rs b/tests/rustdoc-json/primitives/local_primitive.rs
index f27e6a2adec..0cf479faf29 100644
--- a/tests/rustdoc-json/primitives/local_primitive.rs
+++ b/tests/rustdoc-json/primitives/local_primitive.rs
@@ -8,7 +8,7 @@
 
 //! Link to [i32][prim@i32] [i64][prim@i64]
 
-#[doc(primitive = "i32")]
+#[rustc_doc_primitive = "i32"]
 mod prim_i32 {}
 
 // @set local_i32 = "$.index[*][?(@.name=='i32')].id"
diff --git a/tests/rustdoc-json/primitives/primitive_impls.rs b/tests/rustdoc-json/primitives/primitive_impls.rs
index 1fc9374065f..85d179ee45f 100644
--- a/tests/rustdoc-json/primitives/primitive_impls.rs
+++ b/tests/rustdoc-json/primitives/primitive_impls.rs
@@ -25,7 +25,7 @@ pub trait Trait {}
 impl Trait for i32 {}
 
 /// i32
-#[doc(primitive = "i32")]
+#[rustc_doc_primitive = "i32"]
 mod prim_i32 {}
 
 // @set i32 = "$.index[*][?(@.docs=='i32')].id"
diff --git a/tests/rustdoc-json/primitives/primitive_overloading.rs b/tests/rustdoc-json/primitives/primitive_overloading.rs
index 56b35cd14c0..81e0acdc6e9 100644
--- a/tests/rustdoc-json/primitives/primitive_overloading.rs
+++ b/tests/rustdoc-json/primitives/primitive_overloading.rs
@@ -2,7 +2,7 @@
 
 // Regression test for <https://github.com/rust-lang/rust/issues/98006>.
 
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 #![feature(no_core)]
 
 #![no_core]
@@ -10,7 +10,7 @@
 // @has "$.index[*][?(@.name=='usize')]"
 // @has "$.index[*][?(@.name=='prim')]"
 
-#[doc(primitive = "usize")]
+#[rustc_doc_primitive = "usize"]
 /// This is the built-in type `usize`.
 mod prim {
 }
diff --git a/tests/rustdoc-json/primitives/use_primitive.rs b/tests/rustdoc-json/primitives/use_primitive.rs
index e2292737462..5180a804f07 100644
--- a/tests/rustdoc-json/primitives/use_primitive.rs
+++ b/tests/rustdoc-json/primitives/use_primitive.rs
@@ -1,8 +1,8 @@
 // edition:2018
 
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 
-#[doc(primitive = "usize")]
+#[rustc_doc_primitive = "usize"]
 mod usize {}
 
 // @set local_crate_id = "$.index[*][?(@.name=='use_primitive')].crate_id"
diff --git a/tests/rustdoc-ui/const_arg_in_type_position.rs b/tests/rustdoc-ui/const_arg_in_type_position.rs
new file mode 100644
index 00000000000..4969e8d195f
--- /dev/null
+++ b/tests/rustdoc-ui/const_arg_in_type_position.rs
@@ -0,0 +1,6 @@
+type Array<T, const N: usize> = [T; N];
+
+fn foo<const N: usize>() -> Array<N, ()> {
+    //~^ ERROR constant provided when a type was expected
+    unimplemented!()
+}
diff --git a/tests/rustdoc-ui/const_arg_in_type_position.stderr b/tests/rustdoc-ui/const_arg_in_type_position.stderr
new file mode 100644
index 00000000000..ea05920dea7
--- /dev/null
+++ b/tests/rustdoc-ui/const_arg_in_type_position.stderr
@@ -0,0 +1,9 @@
+error[E0747]: constant provided when a type was expected
+  --> $DIR/const_arg_in_type_position.rs:3:35
+   |
+LL | fn foo<const N: usize>() -> Array<N, ()> {
+   |                                   ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0747`.
diff --git a/tests/rustdoc-ui/coverage/exotic.rs b/tests/rustdoc-ui/coverage/exotic.rs
index 72b70d6980b..f45405fbf5d 100644
--- a/tests/rustdoc-ui/coverage/exotic.rs
+++ b/tests/rustdoc-ui/coverage/exotic.rs
@@ -2,12 +2,13 @@
 // check-pass
 
 #![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 
 //! the features only used in std also have entries in the table, so make sure those get pulled out
 //! properly as well
 
 /// woo, check it out, we can write our own primitive docs lol
-#[doc(primitive="unit")]
+#[rustc_doc_primitive = "unit"]
 mod prim_unit {}
 
 /// keywords? sure, pile them on
diff --git a/tests/rustdoc-ui/intra-doc/ambiguity.rs b/tests/rustdoc-ui/intra-doc/ambiguity.rs
index 1f3dc722eff..0290b858204 100644
--- a/tests/rustdoc-ui/intra-doc/ambiguity.rs
+++ b/tests/rustdoc-ui/intra-doc/ambiguity.rs
@@ -35,6 +35,6 @@ pub mod foo {
 /// Ambiguous non-implied shortcut link [`foo::bar`]. //~ERROR `foo::bar`
 pub struct Docs {}
 
-/// [true] //~ ERROR `true` is both a module and a builtin type
+/// [true] //~ ERROR `true` is both a module and a primitive type
 /// [primitive@true]
 pub mod r#true {}
diff --git a/tests/rustdoc-ui/intra-doc/ambiguity.stderr b/tests/rustdoc-ui/intra-doc/ambiguity.stderr
index 7974796e47b..47853e0b589 100644
--- a/tests/rustdoc-ui/intra-doc/ambiguity.stderr
+++ b/tests/rustdoc-ui/intra-doc/ambiguity.stderr
@@ -1,4 +1,4 @@
-error: `true` is both a module and a builtin type
+error: `true` is both a module and a primitive type
   --> $DIR/ambiguity.rs:38:6
    |
 LL | /// [true]
@@ -13,89 +13,89 @@ help: to link to the module, prefix with `mod@`
    |
 LL | /// [mod@true]
    |      ++++
-help: to link to the builtin type, prefix with `prim@`
+help: to link to the primitive type, prefix with `prim@`
    |
 LL | /// [prim@true]
    |      +++++
 
-error: `ambiguous` is both a struct and a function
+error: `ambiguous` is both a function and a struct
   --> $DIR/ambiguity.rs:27:7
    |
 LL | /// [`ambiguous`] is ambiguous.
    |       ^^^^^^^^^ ambiguous link
    |
-help: to link to the struct, prefix with `struct@`
-   |
-LL | /// [`struct@ambiguous`] is ambiguous.
-   |       +++++++
 help: to link to the function, add parentheses
    |
 LL | /// [`ambiguous()`] is ambiguous.
    |                ++
+help: to link to the struct, prefix with `struct@`
+   |
+LL | /// [`struct@ambiguous`] is ambiguous.
+   |       +++++++
 
-error: `ambiguous` is both a struct and a function
+error: `ambiguous` is both a function and a struct
   --> $DIR/ambiguity.rs:29:6
    |
 LL | /// [ambiguous] is ambiguous.
    |      ^^^^^^^^^ ambiguous link
    |
-help: to link to the struct, prefix with `struct@`
-   |
-LL | /// [struct@ambiguous] is ambiguous.
-   |      +++++++
 help: to link to the function, add parentheses
    |
 LL | /// [ambiguous()] is ambiguous.
    |               ++
+help: to link to the struct, prefix with `struct@`
+   |
+LL | /// [struct@ambiguous] is ambiguous.
+   |      +++++++
 
-error: `multi_conflict` is a struct, a function, and a macro
+error: `multi_conflict` is a function, a struct, and a macro
   --> $DIR/ambiguity.rs:31:7
    |
 LL | /// [`multi_conflict`] is a three-way conflict.
    |       ^^^^^^^^^^^^^^ ambiguous link
    |
-help: to link to the struct, prefix with `struct@`
-   |
-LL | /// [`struct@multi_conflict`] is a three-way conflict.
-   |       +++++++
 help: to link to the function, add parentheses
    |
 LL | /// [`multi_conflict()`] is a three-way conflict.
    |                     ++
+help: to link to the struct, prefix with `struct@`
+   |
+LL | /// [`struct@multi_conflict`] is a three-way conflict.
+   |       +++++++
 help: to link to the macro, add an exclamation mark
    |
 LL | /// [`multi_conflict!`] is a three-way conflict.
    |                     +
 
-error: `type_and_value` is both a module and a constant
+error: `type_and_value` is both a constant and a module
   --> $DIR/ambiguity.rs:33:16
    |
 LL | /// Ambiguous [type_and_value].
    |                ^^^^^^^^^^^^^^ ambiguous link
    |
-help: to link to the module, prefix with `mod@`
-   |
-LL | /// Ambiguous [mod@type_and_value].
-   |                ++++
 help: to link to the constant, prefix with `const@`
    |
 LL | /// Ambiguous [const@type_and_value].
    |                ++++++
+help: to link to the module, prefix with `mod@`
+   |
+LL | /// Ambiguous [mod@type_and_value].
+   |                ++++
 
-error: `foo::bar` is both an enum and a function
+error: `foo::bar` is both a function and an enum
   --> $DIR/ambiguity.rs:35:43
    |
 LL | /// Ambiguous non-implied shortcut link [`foo::bar`].
    |                                           ^^^^^^^^ ambiguous link
    |
-help: to link to the enum, prefix with `enum@`
-   |
-LL | /// Ambiguous non-implied shortcut link [`enum@foo::bar`].
-   |                                           +++++
 help: to link to the function, add parentheses
    |
 LL | /// Ambiguous non-implied shortcut link [`foo::bar()`].
    |                                                   ++
+help: to link to the enum, prefix with `enum@`
+   |
+LL | /// Ambiguous non-implied shortcut link [`enum@foo::bar`].
+   |                                           +++++
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/rustdoc-ui/intra-doc/errors.rs b/tests/rustdoc-ui/intra-doc/errors.rs
index 95dd2b98e03..f37f49c24cc 100644
--- a/tests/rustdoc-ui/intra-doc/errors.rs
+++ b/tests/rustdoc-ui/intra-doc/errors.rs
@@ -54,11 +54,11 @@
 
 /// [u8::not_found]
 //~^ ERROR unresolved link
-//~| NOTE the builtin type `u8` has no associated item named `not_found`
+//~| NOTE the primitive type `u8` has no associated item named `not_found`
 
 /// [std::primitive::u8::not_found]
 //~^ ERROR unresolved link
-//~| NOTE the builtin type `u8` has no associated item named `not_found`
+//~| NOTE the primitive type `u8` has no associated item named `not_found`
 
 /// [type@Vec::into_iter]
 //~^ ERROR unresolved link
diff --git a/tests/rustdoc-ui/intra-doc/errors.stderr b/tests/rustdoc-ui/intra-doc/errors.stderr
index 1b2416d7da7..a982bba0095 100644
--- a/tests/rustdoc-ui/intra-doc/errors.stderr
+++ b/tests/rustdoc-ui/intra-doc/errors.stderr
@@ -80,13 +80,13 @@ error: unresolved link to `u8::not_found`
   --> $DIR/errors.rs:55:6
    |
 LL | /// [u8::not_found]
-   |      ^^^^^^^^^^^^^ the builtin type `u8` has no associated item named `not_found`
+   |      ^^^^^^^^^^^^^ the primitive type `u8` has no associated item named `not_found`
 
 error: unresolved link to `std::primitive::u8::not_found`
   --> $DIR/errors.rs:59:6
    |
 LL | /// [std::primitive::u8::not_found]
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the builtin type `u8` has no associated item named `not_found`
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the primitive type `u8` has no associated item named `not_found`
 
 error: unresolved link to `Vec::into_iter`
   --> $DIR/errors.rs:63:6
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-10.rs b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-10.rs
new file mode 100644
index 00000000000..464c5f0d543
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-10.rs
@@ -0,0 +1,22 @@
+// This test ensures that this warning doesn't show up:
+// warning: `PartialEq` is both a trait and a derive macro
+//  --> tests/rustdoc-ui/intra-doc/issue-108653-associated-items-10.rs:1:7
+//   |
+// 1 | //! [`PartialEq`]
+//   |       ^^^^^^^^^ ambiguous link
+//   |
+//   = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
+// help: to link to the trait, prefix with `trait@`
+//   |
+// 1 | //! [`trait@PartialEq`]
+//   |       ++++++
+// help: to link to the derive macro, prefix with `derive@`
+//   |
+// 1 | //! [`derive@PartialEq`]
+//   |       +++++++
+
+// check-pass
+
+#![deny(rustdoc::broken_intra_doc_links)]
+
+//! [`PartialEq`]
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-2.rs b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-2.rs
new file mode 100644
index 00000000000..cbe60f746b6
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-2.rs
@@ -0,0 +1,17 @@
+// This is ensuring that the UI output for associated items is as expected.
+
+#![deny(rustdoc::broken_intra_doc_links)]
+
+/// [`Trait::IDENT`]
+//~^ ERROR both an associated constant and an associated type
+pub trait Trait {
+    type IDENT;
+    const IDENT: usize;
+}
+
+/// [`Trait2::IDENT`]
+//~^ ERROR both an associated function and an associated type
+pub trait Trait2 {
+    type IDENT;
+    fn IDENT() {}
+}
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-2.stderr b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-2.stderr
new file mode 100644
index 00000000000..952392548da
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-2.stderr
@@ -0,0 +1,37 @@
+error: `Trait::IDENT` is both an associated constant and an associated type
+  --> $DIR/issue-108653-associated-items-2.rs:5:7
+   |
+LL | /// [`Trait::IDENT`]
+   |       ^^^^^^^^^^^^ ambiguous link
+   |
+note: the lint level is defined here
+  --> $DIR/issue-108653-associated-items-2.rs:3:9
+   |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the associated constant, prefix with `const@`
+   |
+LL | /// [`const@Trait::IDENT`]
+   |       ++++++
+help: to link to the associated type, prefix with `type@`
+   |
+LL | /// [`type@Trait::IDENT`]
+   |       +++++
+
+error: `Trait2::IDENT` is both an associated function and an associated type
+  --> $DIR/issue-108653-associated-items-2.rs:12:7
+   |
+LL | /// [`Trait2::IDENT`]
+   |       ^^^^^^^^^^^^^ ambiguous link
+   |
+help: to link to the associated function, add parentheses
+   |
+LL | /// [`Trait2::IDENT()`]
+   |                    ++
+help: to link to the associated type, prefix with `type@`
+   |
+LL | /// [`type@Trait2::IDENT`]
+   |       +++++
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-3.rs b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-3.rs
new file mode 100644
index 00000000000..7ffd0a40e7c
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-3.rs
@@ -0,0 +1,16 @@
+// This is ensuring that the UI output for associated items works when it's being documented
+// from another item.
+
+#![deny(rustdoc::broken_intra_doc_links)]
+#![allow(nonstandard_style)]
+
+pub trait Trait {
+    type Trait;
+    const Trait: usize;
+}
+
+/// [`Trait`]
+//~^ ERROR both a constant and a trait
+/// [`Trait::Trait`]
+//~^ ERROR both an associated constant and an associated type
+pub const Trait: usize = 0;
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-3.stderr b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-3.stderr
new file mode 100644
index 00000000000..6401dacb57a
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-3.stderr
@@ -0,0 +1,37 @@
+error: `Trait` is both a constant and a trait
+  --> $DIR/issue-108653-associated-items-3.rs:12:7
+   |
+LL | /// [`Trait`]
+   |       ^^^^^ ambiguous link
+   |
+note: the lint level is defined here
+  --> $DIR/issue-108653-associated-items-3.rs:4:9
+   |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the constant, prefix with `const@`
+   |
+LL | /// [`const@Trait`]
+   |       ++++++
+help: to link to the trait, prefix with `trait@`
+   |
+LL | /// [`trait@Trait`]
+   |       ++++++
+
+error: `Trait::Trait` is both an associated constant and an associated type
+  --> $DIR/issue-108653-associated-items-3.rs:14:7
+   |
+LL | /// [`Trait::Trait`]
+   |       ^^^^^^^^^^^^ ambiguous link
+   |
+help: to link to the associated constant, prefix with `const@`
+   |
+LL | /// [`const@Trait::Trait`]
+   |       ++++++
+help: to link to the associated type, prefix with `type@`
+   |
+LL | /// [`type@Trait::Trait`]
+   |       +++++
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-4.rs b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-4.rs
new file mode 100644
index 00000000000..537d61364bb
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-4.rs
@@ -0,0 +1,21 @@
+// This is ensuring that the UI output for associated items works when it's being documented
+// from another item.
+
+#![deny(rustdoc::broken_intra_doc_links)]
+#![allow(nonstandard_style)]
+
+pub trait Trait {
+    type Trait;
+}
+
+/// [`Struct::Trait`]
+//~^ ERROR both an associated constant and an associated type
+pub struct Struct;
+
+impl Trait for Struct {
+    type Trait = Struct;
+}
+
+impl Struct {
+    pub const Trait: usize = 0;
+}
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-4.stderr b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-4.stderr
new file mode 100644
index 00000000000..a8dc91204c0
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-4.stderr
@@ -0,0 +1,22 @@
+error: `Struct::Trait` is both an associated constant and an associated type
+  --> $DIR/issue-108653-associated-items-4.rs:11:7
+   |
+LL | /// [`Struct::Trait`]
+   |       ^^^^^^^^^^^^^ ambiguous link
+   |
+note: the lint level is defined here
+  --> $DIR/issue-108653-associated-items-4.rs:4:9
+   |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the associated constant, prefix with `const@`
+   |
+LL | /// [`const@Struct::Trait`]
+   |       ++++++
+help: to link to the associated type, prefix with `type@`
+   |
+LL | /// [`type@Struct::Trait`]
+   |       +++++
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-5.rs b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-5.rs
new file mode 100644
index 00000000000..bc28bc54421
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-5.rs
@@ -0,0 +1,8 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+#![allow(nonstandard_style)]
+
+/// [`u32::MAX`]
+//~^ ERROR both an associated constant and a trait
+pub mod u32 {
+    pub trait MAX {}
+}
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-5.stderr b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-5.stderr
new file mode 100644
index 00000000000..7430044ac3f
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-5.stderr
@@ -0,0 +1,22 @@
+error: `u32::MAX` is both an associated constant and a trait
+  --> $DIR/issue-108653-associated-items-5.rs:4:7
+   |
+LL | /// [`u32::MAX`]
+   |       ^^^^^^^^ ambiguous link
+   |
+note: the lint level is defined here
+  --> $DIR/issue-108653-associated-items-5.rs:1:9
+   |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the associated constant, prefix with `const@`
+   |
+LL | /// [`const@u32::MAX`]
+   |       ++++++
+help: to link to the trait, prefix with `trait@`
+   |
+LL | /// [`trait@u32::MAX`]
+   |       ++++++
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-6.rs b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-6.rs
new file mode 100644
index 00000000000..8fde74d0ddb
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-6.rs
@@ -0,0 +1,8 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+#![allow(nonstandard_style)]
+
+/// [`u32::MAX`]
+//~^ ERROR both an associated constant and a primitive type
+pub mod u32 {
+    pub use std::primitive::u32 as MAX;
+}
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-6.stderr b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-6.stderr
new file mode 100644
index 00000000000..fe2d8cafa30
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-6.stderr
@@ -0,0 +1,22 @@
+error: `u32::MAX` is both an associated constant and a primitive type
+  --> $DIR/issue-108653-associated-items-6.rs:4:7
+   |
+LL | /// [`u32::MAX`]
+   |       ^^^^^^^^ ambiguous link
+   |
+note: the lint level is defined here
+  --> $DIR/issue-108653-associated-items-6.rs:1:9
+   |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the associated constant, prefix with `const@`
+   |
+LL | /// [`const@u32::MAX`]
+   |       ++++++
+help: to link to the primitive type, prefix with `prim@`
+   |
+LL | /// [`prim@u32::MAX`]
+   |       +++++
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-7.rs b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-7.rs
new file mode 100644
index 00000000000..6e99f4365a7
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-7.rs
@@ -0,0 +1,12 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+#![allow(nonstandard_style)]
+
+pub trait Trait {
+    type MAX;
+}
+
+/// [`u32::MAX`]
+//~^ ERROR both an associated constant and an associated type
+impl Trait for u32 {
+    type MAX = u32;
+}
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-7.stderr b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-7.stderr
new file mode 100644
index 00000000000..1d302ff42e8
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-7.stderr
@@ -0,0 +1,22 @@
+error: `u32::MAX` is both an associated constant and an associated type
+  --> $DIR/issue-108653-associated-items-7.rs:8:7
+   |
+LL | /// [`u32::MAX`]
+   |       ^^^^^^^^ ambiguous link
+   |
+note: the lint level is defined here
+  --> $DIR/issue-108653-associated-items-7.rs:1:9
+   |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the associated constant, prefix with `const@`
+   |
+LL | /// [`const@u32::MAX`]
+   |       ++++++
+help: to link to the associated type, prefix with `type@`
+   |
+LL | /// [`type@u32::MAX`]
+   |       +++++
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-8.rs b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-8.rs
new file mode 100644
index 00000000000..2f8ee1566bd
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-8.rs
@@ -0,0 +1,12 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+#![allow(nonstandard_style)]
+
+/// [`u32::MAX`]
+//~^ ERROR both an associated constant and an associated type
+pub trait T {
+    type MAX;
+}
+
+impl T for u32 {
+    type MAX = ();
+}
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-8.stderr b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-8.stderr
new file mode 100644
index 00000000000..efed0e2ce0f
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-8.stderr
@@ -0,0 +1,22 @@
+error: `u32::MAX` is both an associated constant and an associated type
+  --> $DIR/issue-108653-associated-items-8.rs:4:7
+   |
+LL | /// [`u32::MAX`]
+   |       ^^^^^^^^ ambiguous link
+   |
+note: the lint level is defined here
+  --> $DIR/issue-108653-associated-items-8.rs:1:9
+   |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the associated constant, prefix with `const@`
+   |
+LL | /// [`const@u32::MAX`]
+   |       ++++++
+help: to link to the associated type, prefix with `type@`
+   |
+LL | /// [`type@u32::MAX`]
+   |       +++++
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-9.rs b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-9.rs
new file mode 100644
index 00000000000..3357ccf2460
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-9.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+#![deny(warnings)]
+
+//! [usize::Item]
+
+pub trait Foo { type Item; }
+pub trait Bar { type Item; }
+
+impl Foo for usize { type Item = u32; }
+impl Bar for usize { type Item = i32; }
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items.rs b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items.rs
new file mode 100644
index 00000000000..0a393e26d6a
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items.rs
@@ -0,0 +1,35 @@
+// This is ensuring that the UI output for associated items is as expected.
+
+#![deny(rustdoc::broken_intra_doc_links)]
+
+pub enum Enum {
+    IDENT,
+}
+
+/// [`Self::IDENT`]
+//~^ ERROR both an associated function and an associated type
+pub trait Trait {
+    type IDENT;
+    fn IDENT();
+}
+
+/// [`Self::IDENT`]
+//~^ ERROR both an associated function and a variant
+impl Trait for Enum {
+    type IDENT = usize;
+    fn IDENT() {}
+}
+
+/// [`Self::IDENT2`]
+//~^ ERROR both an associated constant and an associated type
+pub trait Trait2 {
+    type IDENT2;
+    const IDENT2: usize;
+}
+
+/// [`Self::IDENT2`]
+//~^ ERROR both an associated constant and an associated type
+impl Trait2 for Enum {
+    type IDENT2 = usize;
+    const IDENT2: usize = 0;
+}
diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items.stderr b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items.stderr
new file mode 100644
index 00000000000..084aefc97c8
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items.stderr
@@ -0,0 +1,67 @@
+error: `Self::IDENT` is both an associated function and an associated type
+  --> $DIR/issue-108653-associated-items.rs:9:7
+   |
+LL | /// [`Self::IDENT`]
+   |       ^^^^^^^^^^^ ambiguous link
+   |
+note: the lint level is defined here
+  --> $DIR/issue-108653-associated-items.rs:3:9
+   |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the associated function, add parentheses
+   |
+LL | /// [`Self::IDENT()`]
+   |                  ++
+help: to link to the associated type, prefix with `type@`
+   |
+LL | /// [`type@Self::IDENT`]
+   |       +++++
+
+error: `Self::IDENT2` is both an associated constant and an associated type
+  --> $DIR/issue-108653-associated-items.rs:23:7
+   |
+LL | /// [`Self::IDENT2`]
+   |       ^^^^^^^^^^^^ ambiguous link
+   |
+help: to link to the associated constant, prefix with `const@`
+   |
+LL | /// [`const@Self::IDENT2`]
+   |       ++++++
+help: to link to the associated type, prefix with `type@`
+   |
+LL | /// [`type@Self::IDENT2`]
+   |       +++++
+
+error: `Self::IDENT2` is both an associated constant and an associated type
+  --> $DIR/issue-108653-associated-items.rs:30:7
+   |
+LL | /// [`Self::IDENT2`]
+   |       ^^^^^^^^^^^^ ambiguous link
+   |
+help: to link to the associated constant, prefix with `const@`
+   |
+LL | /// [`const@Self::IDENT2`]
+   |       ++++++
+help: to link to the associated type, prefix with `type@`
+   |
+LL | /// [`type@Self::IDENT2`]
+   |       +++++
+
+error: `Self::IDENT` is both an associated function and a variant
+  --> $DIR/issue-108653-associated-items.rs:16:7
+   |
+LL | /// [`Self::IDENT`]
+   |       ^^^^^^^^^^^ ambiguous link
+   |
+help: to link to the associated function, add parentheses
+   |
+LL | /// [`Self::IDENT()`]
+   |                  ++
+help: to link to the variant, prefix with `type@`
+   |
+LL | /// [`type@Self::IDENT`]
+   |       +++++
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/rustdoc-ui/intra-doc/non-path-primitives.stderr b/tests/rustdoc-ui/intra-doc/non-path-primitives.stderr
index 8ec894d101b..6e08a923963 100644
--- a/tests/rustdoc-ui/intra-doc/non-path-primitives.stderr
+++ b/tests/rustdoc-ui/intra-doc/non-path-primitives.stderr
@@ -39,25 +39,25 @@ error: unresolved link to `unit::eq`
   --> $DIR/non-path-primitives.rs:28:6
    |
 LL | //! [unit::eq]
-   |      ^^^^^^^^ the builtin type `unit` has no associated item named `eq`
+   |      ^^^^^^^^ the primitive type `unit` has no associated item named `eq`
 
 error: unresolved link to `tuple::eq`
   --> $DIR/non-path-primitives.rs:29:6
    |
 LL | //! [tuple::eq]
-   |      ^^^^^^^^^ the builtin type `tuple` has no associated item named `eq`
+   |      ^^^^^^^^^ the primitive type `tuple` has no associated item named `eq`
 
 error: unresolved link to `fn::eq`
   --> $DIR/non-path-primitives.rs:30:6
    |
 LL | //! [fn::eq]
-   |      ^^^^^^ the builtin type `fn` has no associated item named `eq`
+   |      ^^^^^^ the primitive type `fn` has no associated item named `eq`
 
 error: unresolved link to `reference::deref`
   --> $DIR/non-path-primitives.rs:34:6
    |
 LL | //! [reference::deref]
-   |      ^^^^^^^^^^^^^^^^ the builtin type `reference` has no associated item named `deref`
+   |      ^^^^^^^^^^^^^^^^ the primitive type `reference` has no associated item named `deref`
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/rustdoc-ui/intra-doc/prim-conflict.rs b/tests/rustdoc-ui/intra-doc/prim-conflict.rs
index 2c1a8b5357a..e87ce095cd4 100644
--- a/tests/rustdoc-ui/intra-doc/prim-conflict.rs
+++ b/tests/rustdoc-ui/intra-doc/prim-conflict.rs
@@ -2,16 +2,16 @@
 //~^ NOTE lint level is defined
 
 /// [char]
-//~^ ERROR both a module and a builtin type
+//~^ ERROR both a module and a primitive type
 //~| NOTE ambiguous link
 //~| HELP to link to the module
-//~| HELP to link to the builtin type
+//~| HELP to link to the primitive type
 
 /// [type@char]
-//~^ ERROR both a module and a builtin type
+//~^ ERROR both a module and a primitive type
 //~| NOTE ambiguous link
 //~| HELP to link to the module
-//~| HELP to link to the builtin type
+//~| HELP to link to the primitive type
 
 /// [mod@char] // ok
 /// [prim@char] // ok
@@ -26,5 +26,5 @@ pub mod inner {
     //! [struct@char]
     //~^ ERROR incompatible link
     //~| HELP prefix with `prim@`
-    //~| NOTE resolved to a builtin type
+    //~| NOTE resolved to a primitive type
 }
diff --git a/tests/rustdoc-ui/intra-doc/prim-conflict.stderr b/tests/rustdoc-ui/intra-doc/prim-conflict.stderr
index 6ef3b7eab3b..03ce8f15f0a 100644
--- a/tests/rustdoc-ui/intra-doc/prim-conflict.stderr
+++ b/tests/rustdoc-ui/intra-doc/prim-conflict.stderr
@@ -1,4 +1,4 @@
-error: `char` is both a module and a builtin type
+error: `char` is both a module and a primitive type
   --> $DIR/prim-conflict.rs:4:6
    |
 LL | /// [char]
@@ -13,12 +13,12 @@ help: to link to the module, prefix with `mod@`
    |
 LL | /// [mod@char]
    |      ++++
-help: to link to the builtin type, prefix with `prim@`
+help: to link to the primitive type, prefix with `prim@`
    |
 LL | /// [prim@char]
    |      +++++
 
-error: `char` is both a module and a builtin type
+error: `char` is both a module and a primitive type
   --> $DIR/prim-conflict.rs:10:6
    |
 LL | /// [type@char]
@@ -28,7 +28,7 @@ help: to link to the module, prefix with `mod@`
    |
 LL | /// [mod@char]
    |      ~~~~
-help: to link to the builtin type, prefix with `prim@`
+help: to link to the primitive type, prefix with `prim@`
    |
 LL | /// [prim@char]
    |      ~~~~~
@@ -48,9 +48,9 @@ error: incompatible link kind for `char`
   --> $DIR/prim-conflict.rs:26:10
    |
 LL |     //! [struct@char]
-   |          ^^^^^^^^^^^ this link resolved to a builtin type, which is not a struct
+   |          ^^^^^^^^^^^ this link resolved to a primitive type, which is not a struct
    |
-help: to link to the builtin type, prefix with `prim@`
+help: to link to the primitive type, prefix with `prim@`
    |
 LL |     //! [prim@char]
    |          ~~~~~
diff --git a/tests/rustdoc-ui/invalid_associated_const.rs b/tests/rustdoc-ui/invalid_associated_const.rs
new file mode 100644
index 00000000000..6ab8c36f740
--- /dev/null
+++ b/tests/rustdoc-ui/invalid_associated_const.rs
@@ -0,0 +1,10 @@
+#![feature(associated_const_equality)]
+
+trait T {
+    type A: S<C<X = 0i32> = 34>;
+    //~^ ERROR associated type bindings are not allowed here
+}
+
+trait S {
+    const C: i32;
+}
diff --git a/tests/rustdoc-ui/invalid_associated_const.stderr b/tests/rustdoc-ui/invalid_associated_const.stderr
new file mode 100644
index 00000000000..1a8863fb18f
--- /dev/null
+++ b/tests/rustdoc-ui/invalid_associated_const.stderr
@@ -0,0 +1,9 @@
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/invalid_associated_const.rs:4:17
+   |
+LL |     type A: S<C<X = 0i32> = 34>;
+   |                 ^^^^^^^^ associated type not allowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0229`.
diff --git a/tests/rustdoc-ui/invalid_const_in_lifetime_position.rs b/tests/rustdoc-ui/invalid_const_in_lifetime_position.rs
new file mode 100644
index 00000000000..c3f4fd63bac
--- /dev/null
+++ b/tests/rustdoc-ui/invalid_const_in_lifetime_position.rs
@@ -0,0 +1,6 @@
+trait X {
+    type Y<'a>;
+}
+fn f<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
+//~^ ERROR associated type takes 1 lifetime argument but 0 lifetime arguments
+//~| ERROR associated type takes 0 generic arguments but 1 generic argument
diff --git a/tests/rustdoc-ui/invalid_const_in_lifetime_position.stderr b/tests/rustdoc-ui/invalid_const_in_lifetime_position.stderr
new file mode 100644
index 00000000000..527729a8228
--- /dev/null
+++ b/tests/rustdoc-ui/invalid_const_in_lifetime_position.stderr
@@ -0,0 +1,33 @@
+error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+  --> $DIR/invalid_const_in_lifetime_position.rs:4:26
+   |
+LL | fn f<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
+   |                          ^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/invalid_const_in_lifetime_position.rs:2:10
+   |
+LL |     type Y<'a>;
+   |          ^ --
+help: add missing lifetime argument
+   |
+LL | fn f<'a>(arg : Box<dyn X<Y<'_, 1> = &'a ()>>) {}
+   |                            +++
+
+error[E0107]: associated type takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/invalid_const_in_lifetime_position.rs:4:26
+   |
+LL | fn f<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
+   |                          ^--- help: remove these generics
+   |                          |
+   |                          expected 0 generic arguments
+   |
+note: associated type defined here, with 0 generic parameters
+  --> $DIR/invalid_const_in_lifetime_position.rs:2:10
+   |
+LL |     type Y<'a>;
+   |          ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/rustdoc-ui/invalid_infered_static_and_const.rs b/tests/rustdoc-ui/invalid_infered_static_and_const.rs
new file mode 100644
index 00000000000..3f8e68dc020
--- /dev/null
+++ b/tests/rustdoc-ui/invalid_infered_static_and_const.rs
@@ -0,0 +1,2 @@
+const FOO: dyn Fn() -> _ = ""; //~ ERROR E0121
+static BOO: dyn Fn() -> _ = ""; //~ ERROR E0121
diff --git a/tests/rustdoc-ui/invalid_infered_static_and_const.stderr b/tests/rustdoc-ui/invalid_infered_static_and_const.stderr
new file mode 100644
index 00000000000..401020224d6
--- /dev/null
+++ b/tests/rustdoc-ui/invalid_infered_static_and_const.stderr
@@ -0,0 +1,15 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for constant items
+  --> $DIR/invalid_infered_static_and_const.rs:1:24
+   |
+LL | const FOO: dyn Fn() -> _ = "";
+   |                        ^ not allowed in type signatures
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for static items
+  --> $DIR/invalid_infered_static_and_const.rs:2:25
+   |
+LL | static BOO: dyn Fn() -> _ = "";
+   |                         ^ not allowed in type signatures
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/rustdoc-ui/issue-105742.rs b/tests/rustdoc-ui/issue-105742.rs
index 9f36e5315ec..8f4172c0cbb 100644
--- a/tests/rustdoc-ui/issue-105742.rs
+++ b/tests/rustdoc-ui/issue-105742.rs
@@ -1,19 +1,50 @@
 // compile-flags: -Znormalize-docs
-
 use std::ops::Index;
 
 pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
+    //~^ expected 1 lifetime argument
+    //~| expected 1 generic argument
+    //~| the trait `SVec` cannot be made into an object
+    //~| `SVec` cannot be made into an object
+    //~| missing generics for associated type `SVec::Item`
+    //~| missing generics for associated type `SVec::Item`
     let _ = s;
 }
 
 pub trait SVec: Index<
     <Self as SVec>::Item,
+    //~^ expected 1 lifetime argument
+    //~| expected 1 generic argument
+    //~| missing generics for associated type `SVec::Item`
+    //~| missing generics for associated type `SVec::Item`
+    //~| missing generics for associated type `SVec::Item`
+    //~| missing generics for associated type `SVec::Item`
     Output = <Index<<Self as SVec>::Item,
+    //~^ expected 1 lifetime argument
+    //~| expected 1 generic argument
+    //~| missing generics for associated type `SVec::Item`
+    //~| missing generics for associated type `SVec::Item`
+    //~| missing generics for associated type `SVec::Item`
+    //~| missing generics for associated type `SVec::Item`
     Output = <Self as SVec>::Item> as SVec>::Item,
+    //~^ expected 1 lifetime argument
+    //~| expected 1 generic argument
+    //~| expected 1 lifetime argument
+    //~| missing generics for associated type `SVec::Item`
+    //~| missing generics for associated type `SVec::Item`
+    //~| missing generics for associated type `SVec::Item`
+    //~| missing generics for associated type `SVec::Item`
+    //~| expected 1 generic argument
+    //~| missing generics for associated type `SVec::Item`
+    //~| missing generics for associated type `SVec::Item`
+    //~| missing generics for associated type `SVec::Item`
+    //~| missing generics for associated type `SVec::Item`
 > {
     type Item<'a, T>;
 
     fn len(&self) -> <Self as SVec>::Item;
-    //~^ ERROR
-    //~^^ ERROR
+    //~^ expected 1 lifetime argument
+    //~| missing generics for associated type `SVec::Item`
+    //~| expected 1 generic argument
+    //~| missing generics for associated type `SVec::Item`
 }
diff --git a/tests/rustdoc-ui/issue-105742.stderr b/tests/rustdoc-ui/issue-105742.stderr
index 4d2ee972689..cd53762ef9b 100644
--- a/tests/rustdoc-ui/issue-105742.stderr
+++ b/tests/rustdoc-ui/issue-105742.stderr
@@ -1,11 +1,329 @@
 error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:16:38
+  --> $DIR/issue-105742.rs:15:21
+   |
+LL |     <Self as SVec>::Item,
+   |                     ^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^ --
+help: add missing lifetime argument
+   |
+LL |     <Self as SVec>::Item<'a>,
+   |                         ++++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:15:21
+   |
+LL |     <Self as SVec>::Item,
+   |                     ^^^^ expected 1 generic argument
+   |
+note: associated type defined here, with 1 generic parameter: `T`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^     -
+help: add missing generic argument
+   |
+LL |     <Self as SVec>::Item<T>,
+   |                         +++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:22:37
+   |
+LL |     Output = <Index<<Self as SVec>::Item,
+   |                                     ^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^ --
+help: add missing lifetime argument
+   |
+LL |     Output = <Index<<Self as SVec>::Item<'a>,
+   |                                         ++++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:22:37
+   |
+LL |     Output = <Index<<Self as SVec>::Item,
+   |                                     ^^^^ expected 1 generic argument
+   |
+note: associated type defined here, with 1 generic parameter: `T`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^     -
+help: add missing generic argument
+   |
+LL |     Output = <Index<<Self as SVec>::Item<T>,
+   |                                         +++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:29:30
+   |
+LL |     Output = <Self as SVec>::Item> as SVec>::Item,
+   |                              ^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^ --
+help: add missing lifetime argument
+   |
+LL |     Output = <Self as SVec>::Item<'a>> as SVec>::Item,
+   |                                  ++++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:29:30
+   |
+LL |     Output = <Self as SVec>::Item> as SVec>::Item,
+   |                              ^^^^ expected 1 generic argument
+   |
+note: associated type defined here, with 1 generic parameter: `T`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^     -
+help: add missing generic argument
+   |
+LL |     Output = <Self as SVec>::Item<T>> as SVec>::Item,
+   |                                  +++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:29:46
+   |
+LL |     Output = <Self as SVec>::Item> as SVec>::Item,
+   |                                              ^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^ --
+help: add missing lifetime argument
+   |
+LL |     Output = <Self as SVec>::Item> as SVec>::Item<'a>,
+   |                                                  ++++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:29:46
+   |
+LL |     Output = <Self as SVec>::Item> as SVec>::Item,
+   |                                              ^^^^ expected 1 generic argument
+   |
+note: associated type defined here, with 1 generic parameter: `T`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^     -
+help: add missing generic argument
+   |
+LL |     Output = <Self as SVec>::Item> as SVec>::Item<T>,
+   |                                                  +++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:4:40
+   |
+LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
+   |                                        ^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^ --
+help: add missing lifetime argument
+   |
+LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item<'_> = T, Output = T>) {
+   |                                            ++++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:4:40
+   |
+LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
+   |                                        ^^^^ expected 1 generic argument
+   |
+note: associated type defined here, with 1 generic parameter: `T`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^     -
+help: add missing generic argument
+   |
+LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item<T> = T, Output = T>) {
+   |                                            +++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:15:21
+   |
+LL |     <Self as SVec>::Item,
+   |                     ^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^ --
+help: add missing lifetime argument
+   |
+LL |     <Self as SVec>::Item<'a>,
+   |                         ++++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:15:21
+   |
+LL |     <Self as SVec>::Item,
+   |                     ^^^^ expected 1 generic argument
+   |
+note: associated type defined here, with 1 generic parameter: `T`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^     -
+help: add missing generic argument
+   |
+LL |     <Self as SVec>::Item<T>,
+   |                         +++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:22:37
+   |
+LL |     Output = <Index<<Self as SVec>::Item,
+   |                                     ^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^ --
+help: add missing lifetime argument
+   |
+LL |     Output = <Index<<Self as SVec>::Item<'a>,
+   |                                         ++++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:22:37
+   |
+LL |     Output = <Index<<Self as SVec>::Item,
+   |                                     ^^^^ expected 1 generic argument
+   |
+note: associated type defined here, with 1 generic parameter: `T`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^     -
+help: add missing generic argument
+   |
+LL |     Output = <Index<<Self as SVec>::Item<T>,
+   |                                         +++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:29:30
+   |
+LL |     Output = <Self as SVec>::Item> as SVec>::Item,
+   |                              ^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^ --
+help: add missing lifetime argument
+   |
+LL |     Output = <Self as SVec>::Item<'a>> as SVec>::Item,
+   |                                  ++++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:29:30
+   |
+LL |     Output = <Self as SVec>::Item> as SVec>::Item,
+   |                              ^^^^ expected 1 generic argument
+   |
+note: associated type defined here, with 1 generic parameter: `T`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^     -
+help: add missing generic argument
+   |
+LL |     Output = <Self as SVec>::Item<T>> as SVec>::Item,
+   |                                  +++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:29:46
+   |
+LL |     Output = <Self as SVec>::Item> as SVec>::Item,
+   |                                              ^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^ --
+help: add missing lifetime argument
+   |
+LL |     Output = <Self as SVec>::Item> as SVec>::Item<'a>,
+   |                                                  ++++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:29:46
+   |
+LL |     Output = <Self as SVec>::Item> as SVec>::Item,
+   |                                              ^^^^ expected 1 generic argument
+   |
+note: associated type defined here, with 1 generic parameter: `T`
+  --> $DIR/issue-105742.rs:43:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^     -
+help: add missing generic argument
+   |
+LL |     Output = <Self as SVec>::Item> as SVec>::Item<T>,
+   |                                                  +++
+
+error[E0038]: the trait `SVec` cannot be made into an object
+  --> $DIR/issue-105742.rs:4:31
+   |
+LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SVec` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-105742.rs:14:17
+   |
+LL |    pub trait SVec: Index<
+   |  ____________----__^
+   | |            |
+   | |            this trait cannot be made into an object...
+LL | |      <Self as SVec>::Item,
+LL | |
+LL | |
+...  |
+LL | |/     Output = <Index<<Self as SVec>::Item,
+LL | ||
+LL | ||
+LL | ||
+...  ||
+LL | ||
+LL | ||     Output = <Self as SVec>::Item> as SVec>::Item,
+   | ||_________________________________________________^ ...because it uses `Self` as a type parameter
+...  |
+LL | |
+LL | |  > {
+   | |__^ ...because it uses `Self` as a type parameter
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:45:38
    |
 LL |     fn len(&self) -> <Self as SVec>::Item;
    |                                      ^^^^ expected 1 lifetime argument
    |
 note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-105742.rs:14:10
+  --> $DIR/issue-105742.rs:43:10
    |
 LL |     type Item<'a, T>;
    |          ^^^^ --
@@ -15,13 +333,13 @@ LL |     fn len(&self) -> <Self as SVec>::Item<'_>;
    |                                          ++++
 
 error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:16:38
+  --> $DIR/issue-105742.rs:45:38
    |
 LL |     fn len(&self) -> <Self as SVec>::Item;
    |                                      ^^^^ expected 1 generic argument
    |
 note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-105742.rs:14:10
+  --> $DIR/issue-105742.rs:43:10
    |
 LL |     type Item<'a, T>;
    |          ^^^^     -
@@ -30,6 +348,7 @@ help: add missing generic argument
 LL |     fn len(&self) -> <Self as SVec>::Item<T>;
    |                                          +++
 
-error: aborting due to 2 previous errors
+error: aborting due to 21 previous errors
 
-For more information about this error, try `rustc --explain E0107`.
+Some errors have detailed explanations: E0038, E0107.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/rustdoc-ui/issue-106226.stderr b/tests/rustdoc-ui/issue-106226.stderr
index 2beffbc125b..1c973dab61d 100644
--- a/tests/rustdoc-ui/issue-106226.stderr
+++ b/tests/rustdoc-ui/issue-106226.stderr
@@ -1,9 +1,9 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-106226.rs:2:14
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases
+  --> $DIR/issue-106226.rs:2:11
    |
 LL | type F = [_; ()];
-   |              ^^ expected `usize`, found `()`
+   |           ^ not allowed in type signatures
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/rustdoc-ui/issue-79465.rs b/tests/rustdoc-ui/issue-79465.rs
index f1a77982fb5..e50f3995b83 100644
--- a/tests/rustdoc-ui/issue-79465.rs
+++ b/tests/rustdoc-ui/issue-79465.rs
@@ -1,3 +1,2 @@
 pub fn f1<T>(x: T::A) {}
 //~^ ERROR
-//~^^ ERROR
diff --git a/tests/rustdoc-ui/issue-79465.stderr b/tests/rustdoc-ui/issue-79465.stderr
index 489cc14420a..d187a2e664a 100644
--- a/tests/rustdoc-ui/issue-79465.stderr
+++ b/tests/rustdoc-ui/issue-79465.stderr
@@ -4,12 +4,6 @@ error[E0220]: associated type `A` not found for `T`
 LL | pub fn f1<T>(x: T::A) {}
    |                    ^ associated type `A` not found
 
-error[E0220]: associated type `A` not found for `T`
-  --> $DIR/issue-79465.rs:1:20
-   |
-LL | pub fn f1<T>(x: T::A) {}
-   |                    ^ associated type `A` not found
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/rustdoc-ui/issue-96287.rs b/tests/rustdoc-ui/issue-96287.rs
index 8d8b4456e63..08cc7ef4c90 100644
--- a/tests/rustdoc-ui/issue-96287.rs
+++ b/tests/rustdoc-ui/issue-96287.rs
@@ -6,7 +6,6 @@ pub trait TraitWithAssoc {
 
 pub type Foo<V> = impl Trait<V::Assoc>;
 //~^ ERROR
-//~^^ ERROR
 
 pub trait Trait<U> {}
 
diff --git a/tests/rustdoc-ui/issue-96287.stderr b/tests/rustdoc-ui/issue-96287.stderr
index 0236b9fe647..7722eb96028 100644
--- a/tests/rustdoc-ui/issue-96287.stderr
+++ b/tests/rustdoc-ui/issue-96287.stderr
@@ -4,12 +4,6 @@ error[E0220]: associated type `Assoc` not found for `V`
 LL | pub type Foo<V> = impl Trait<V::Assoc>;
    |                                 ^^^^^ there is a similarly named associated type `Assoc` in the trait `TraitWithAssoc`
 
-error[E0220]: associated type `Assoc` not found for `V`
-  --> $DIR/issue-96287.rs:7:33
-   |
-LL | pub type Foo<V> = impl Trait<V::Assoc>;
-   |                                 ^^^^^ there is a similarly named associated type `Assoc` in the trait `TraitWithAssoc`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/rustdoc-ui/mismatched_arg_count.rs b/tests/rustdoc-ui/mismatched_arg_count.rs
new file mode 100644
index 00000000000..7841442987b
--- /dev/null
+++ b/tests/rustdoc-ui/mismatched_arg_count.rs
@@ -0,0 +1,8 @@
+trait Trait<'a> {
+    type Assoc;
+}
+
+type Alias<'a, T> = <T as Trait<'a>>::Assoc;
+
+fn bar<'a, T: Trait<'a>>(_: Alias<'a, 'a, T>) {}
+//~^ error: type alias takes 1 lifetime argument but 2 lifetime arguments were supplied
diff --git a/tests/rustdoc-ui/mismatched_arg_count.stderr b/tests/rustdoc-ui/mismatched_arg_count.stderr
new file mode 100644
index 00000000000..7e88ce954ac
--- /dev/null
+++ b/tests/rustdoc-ui/mismatched_arg_count.stderr
@@ -0,0 +1,17 @@
+error[E0107]: type alias takes 1 lifetime argument but 2 lifetime arguments were supplied
+  --> $DIR/mismatched_arg_count.rs:7:29
+   |
+LL | fn bar<'a, T: Trait<'a>>(_: Alias<'a, 'a, T>) {}
+   |                             ^^^^^     -- help: remove this lifetime argument
+   |                             |
+   |                             expected 1 lifetime argument
+   |
+note: type alias defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/mismatched_arg_count.rs:5:6
+   |
+LL | type Alias<'a, T> = <T as Trait<'a>>::Assoc;
+   |      ^^^^^ --
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/rustdoc/auto-impl-primitive.rs b/tests/rustdoc/auto-impl-primitive.rs
index 172333d445d..a6db93dbc33 100644
--- a/tests/rustdoc/auto-impl-primitive.rs
+++ b/tests/rustdoc/auto-impl-primitive.rs
@@ -1,10 +1,10 @@
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 
 #![crate_name = "foo"]
 
 pub use std::fs::File;
 
 // @has 'foo/primitive.i16.html' '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementation'
-#[doc(primitive = "i16")]
+#[rustc_doc_primitive = "i16"]
 /// I love poneys!
 mod prim {}
diff --git a/tests/rustdoc/auxiliary/issue-15318.rs b/tests/rustdoc/auxiliary/issue-15318.rs
index 695fa58ef1d..a2f426c6352 100644
--- a/tests/rustdoc/auxiliary/issue-15318.rs
+++ b/tests/rustdoc/auxiliary/issue-15318.rs
@@ -2,6 +2,7 @@
 // compile-flags: -Cmetadata=aux
 #![crate_type = "rlib"]
 #![doc(html_root_url = "http://example.com/")]
+#![feature(rustc_attrs)]
 #![feature(lang_items)]
 #![no_std]
 
@@ -12,5 +13,5 @@ fn foo() {}
 fn bar(_: &core::panic::PanicInfo) -> ! { loop {} }
 
 /// dox
-#[doc(primitive = "pointer")]
+#[rustc_doc_primitive = "pointer"]
 pub mod ptr {}
diff --git a/tests/rustdoc/auxiliary/primitive-doc.rs b/tests/rustdoc/auxiliary/primitive-doc.rs
index e8da852a57e..d1785e42391 100644
--- a/tests/rustdoc/auxiliary/primitive-doc.rs
+++ b/tests/rustdoc/auxiliary/primitive-doc.rs
@@ -1,9 +1,10 @@
 // compile-flags: --crate-type lib --edition 2018
 
+#![feature(rustc_attrs)]
 #![feature(no_core)]
 #![no_core]
 
-#[doc(primitive = "usize")]
+#[rustc_doc_primitive = "usize"]
 /// This is the built-in type `usize`.
 mod usize {
 }
diff --git a/tests/rustdoc/check-source-code-urls-to-def.rs b/tests/rustdoc/check-source-code-urls-to-def.rs
index 5959f9c7c59..41b9d41fa44 100644
--- a/tests/rustdoc/check-source-code-urls-to-def.rs
+++ b/tests/rustdoc/check-source-code-urls-to-def.rs
@@ -2,7 +2,7 @@
 // aux-build:source_code.rs
 // build-aux-docs
 
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 
 #![crate_name = "foo"]
 
@@ -65,5 +65,5 @@ pub fn foo4() {
 }
 
 // @has - '//pre[@class="rust"]//a[@href="../../foo/primitive.bool.html"]' 'bool'
-#[doc(primitive = "bool")]
+#[rustc_doc_primitive = "bool"]
 mod whatever {}
diff --git a/tests/rustdoc/intra-doc/auxiliary/my-core.rs b/tests/rustdoc/intra-doc/auxiliary/my-core.rs
index e22feb03ae6..c050929db96 100644
--- a/tests/rustdoc/intra-doc/auxiliary/my-core.rs
+++ b/tests/rustdoc/intra-doc/auxiliary/my-core.rs
@@ -3,7 +3,7 @@
 #![rustc_coherence_is_core]
 #![crate_type="rlib"]
 
-#[doc(primitive = "char")]
+#[rustc_doc_primitive = "char"]
 /// Some char docs
 mod char {}
 
diff --git a/tests/rustdoc/intra-doc/no-doc-primitive.rs b/tests/rustdoc/intra-doc/no-doc-primitive.rs
index e5eba1d8d48..711ac09ba9a 100644
--- a/tests/rustdoc/intra-doc/no-doc-primitive.rs
+++ b/tests/rustdoc/intra-doc/no-doc-primitive.rs
@@ -1,4 +1,4 @@
-// Crate tree without a `doc(primitive)` module for primitive type linked to by a doc link.
+// Crate tree without a `rustc_doc_primitive` module for primitive type linked to by a doc link.
 
 #![deny(rustdoc::broken_intra_doc_links)]
 #![feature(no_core, lang_items, rustc_attrs)]
diff --git a/tests/rustdoc/intra-doc/prim-methods-local.rs b/tests/rustdoc/intra-doc/prim-methods-local.rs
index 79d8df04515..6de4ec1802f 100644
--- a/tests/rustdoc/intra-doc/prim-methods-local.rs
+++ b/tests/rustdoc/intra-doc/prim-methods-local.rs
@@ -10,7 +10,7 @@
 
 //! A [prim@`char`] and its [`char::len_utf8`].
 
-#[doc(primitive = "char")]
+#[rustc_doc_primitive = "char"]
 mod char {}
 
 impl char {
diff --git a/tests/rustdoc/intra-doc/prim-self.rs b/tests/rustdoc/intra-doc/prim-self.rs
index c7ce71b15f3..d13858a53cf 100644
--- a/tests/rustdoc/intra-doc/prim-self.rs
+++ b/tests/rustdoc/intra-doc/prim-self.rs
@@ -25,7 +25,7 @@ impl usize {
     pub type ME = usize;
 }
 
-#[doc(primitive = "usize")]
+#[rustc_doc_primitive = "usize"]
 /// This has some docs.
 mod usize {}
 
diff --git a/tests/rustdoc/issue-15318-3.rs b/tests/rustdoc/issue-15318-3.rs
index 2fadc26b006..2dab8f94883 100644
--- a/tests/rustdoc/issue-15318-3.rs
+++ b/tests/rustdoc/issue-15318-3.rs
@@ -1,7 +1,7 @@
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 
 // @has issue_15318_3/primitive.pointer.html
 
 /// dox
-#[doc(primitive = "pointer")]
+#[rustc_doc_primitive = "pointer"]
 pub mod ptr {}
diff --git a/tests/rustdoc/issue-23511.rs b/tests/rustdoc/issue-23511.rs
index 7576ebb0305..21d02842431 100644
--- a/tests/rustdoc/issue-23511.rs
+++ b/tests/rustdoc/issue-23511.rs
@@ -3,7 +3,7 @@
 #![no_std]
 
 pub mod str {
-    #![doc(primitive = "str")]
+    #![rustc_doc_primitive = "str"]
 
     impl str {
         // @hasraw search-index.js foo
diff --git a/tests/rustdoc/notable-trait/doc-notable_trait-mut_t_is_not_an_iterator.rs b/tests/rustdoc/notable-trait/doc-notable_trait-mut_t_is_not_an_iterator.rs
index bfce46cf444..5af5f7616b5 100644
--- a/tests/rustdoc/notable-trait/doc-notable_trait-mut_t_is_not_an_iterator.rs
+++ b/tests/rustdoc/notable-trait/doc-notable_trait-mut_t_is_not_an_iterator.rs
@@ -6,10 +6,10 @@
 //!
 //! [#80737]: https://github.com/rust-lang/rust/issues/80737
 
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 #![no_std]
 
-#[doc(primitive = "reference")]
+#[rustc_doc_primitive = "reference"]
 /// Some useless docs, wouhou!
 ///
 /// We need to put this in here, because notable traits
diff --git a/tests/rustdoc/notable-trait/doc-notable_trait-mut_t_is_not_ref_t.rs b/tests/rustdoc/notable-trait/doc-notable_trait-mut_t_is_not_ref_t.rs
index b359dcea0ff..6c980aaa2b1 100644
--- a/tests/rustdoc/notable-trait/doc-notable_trait-mut_t_is_not_ref_t.rs
+++ b/tests/rustdoc/notable-trait/doc-notable_trait-mut_t_is_not_ref_t.rs
@@ -5,9 +5,9 @@
 //!
 //! [#78160]: https://github.com/rust-lang/rust/issues/78160
 
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 
-#[doc(primitive = "reference")]
+#[rustc_doc_primitive = "reference"]
 /// Some useless docs, wouhou!
 ///
 /// We need to put this in here, because notable traits
diff --git a/tests/rustdoc/primitive-reference.rs b/tests/rustdoc/primitive-reference.rs
index 10efbefd2b1..6f034224df5 100644
--- a/tests/rustdoc/primitive-reference.rs
+++ b/tests/rustdoc/primitive-reference.rs
@@ -1,6 +1,6 @@
 #![crate_name = "foo"]
 
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 
 // @has foo/index.html
 // @has - '//h2[@id="primitives"]' 'Primitive Types'
@@ -16,7 +16,7 @@
 // @count - '//*[@class="impl"]' 1
 // @has - '//*[@id="impl-Foo%3C%26A%3E-for-%26B"]/*[@class="code-header"]' \
 //        'impl<A, B> Foo<&A> for &B'
-#[doc(primitive = "reference")]
+#[rustc_doc_primitive = "reference"]
 /// this is a test!
 mod reference {}
 
diff --git a/tests/rustdoc/primitive-slice-auto-trait.rs b/tests/rustdoc/primitive-slice-auto-trait.rs
index 77922414676..ba15a73ca1d 100644
--- a/tests/rustdoc/primitive-slice-auto-trait.rs
+++ b/tests/rustdoc/primitive-slice-auto-trait.rs
@@ -1,7 +1,7 @@
 // compile-flags: --crate-type lib --edition 2018
 
 #![crate_name = "foo"]
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 
 // @has foo/primitive.slice.html '//a[@class="primitive"]' 'slice'
 // @has - '//h1' 'Primitive Type slice'
@@ -9,6 +9,6 @@
 // @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
 // @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Send for [T]where T: Send'
 // @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Sync for [T]where T: Sync'
-#[doc(primitive = "slice")]
+#[rustc_doc_primitive = "slice"]
 /// this is a test!
 mod slice_prim {}
diff --git a/tests/rustdoc/primitive-tuple-auto-trait.rs b/tests/rustdoc/primitive-tuple-auto-trait.rs
index 4344d24f986..2b407b586a3 100644
--- a/tests/rustdoc/primitive-tuple-auto-trait.rs
+++ b/tests/rustdoc/primitive-tuple-auto-trait.rs
@@ -1,7 +1,7 @@
 // compile-flags: --crate-type lib --edition 2018
 
 #![crate_name = "foo"]
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 
 // @has foo/primitive.tuple.html '//a[@class="primitive"]' 'tuple'
 // @has - '//h1' 'Primitive Type tuple'
@@ -9,7 +9,7 @@
 // @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
 // @has - '//div[@id="synthetic-implementations-list"]//h3' 'Send'
 // @has - '//div[@id="synthetic-implementations-list"]//h3' 'Sync'
-#[doc(primitive = "tuple")]
+#[rustc_doc_primitive = "tuple"]
 /// this is a test!
 ///
 // Hardcoded anchor to header written in library/core/src/primitive_docs.rs
diff --git a/tests/rustdoc/primitive-unit-auto-trait.rs b/tests/rustdoc/primitive-unit-auto-trait.rs
index 61850e2462d..5a56f1fd83b 100644
--- a/tests/rustdoc/primitive-unit-auto-trait.rs
+++ b/tests/rustdoc/primitive-unit-auto-trait.rs
@@ -1,7 +1,7 @@
 // compile-flags: --crate-type lib --edition 2018
 
 #![crate_name = "foo"]
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 
 // @has foo/primitive.unit.html '//a[@class="primitive"]' 'unit'
 // @has - '//h1' 'Primitive Type unit'
@@ -9,6 +9,6 @@
 // @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
 // @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Send for ()'
 // @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Sync for ()'
-#[doc(primitive = "unit")]
+#[rustc_doc_primitive = "unit"]
 /// this is a test!
 mod unit_prim {}
diff --git a/tests/rustdoc/primitive/primitive-generic-impl.rs b/tests/rustdoc/primitive/primitive-generic-impl.rs
index 7b336b39810..2da8ae6ff38 100644
--- a/tests/rustdoc/primitive/primitive-generic-impl.rs
+++ b/tests/rustdoc/primitive/primitive-generic-impl.rs
@@ -1,8 +1,8 @@
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 #![crate_name = "foo"]
 
 // @has foo/primitive.i32.html '//*[@id="impl-ToString-for-i32"]//h3[@class="code-header"]' 'impl<T> ToString for T'
 
-#[doc(primitive = "i32")]
+#[rustc_doc_primitive = "i32"]
 /// Some useless docs, wouhou!
 mod i32 {}
diff --git a/tests/rustdoc/primitive.rs b/tests/rustdoc/primitive/primitive.rs
index 516c7c0c6fe..32af2636c18 100644
--- a/tests/rustdoc/primitive.rs
+++ b/tests/rustdoc/primitive/primitive.rs
@@ -1,6 +1,6 @@
 #![crate_name = "foo"]
 
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 
 // @has foo/index.html '//h2[@id="primitives"]' 'Primitive Types'
 // @has foo/index.html '//a[@href="primitive.i32.html"]' 'i32'
@@ -11,11 +11,11 @@
 // @has foo/primitive.i32.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
 // @has foo/index.html '//a/@href' '../foo/index.html'
 // @!has foo/index.html '//span' '🔒'
-#[doc(primitive = "i32")]
+#[rustc_doc_primitive = "i32"]
 /// this is a test!
 mod i32{}
 
 // @has foo/primitive.bool.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'hello'
-#[doc(primitive = "bool")]
+#[rustc_doc_primitive = "bool"]
 /// hello
 mod bool {}
diff --git a/tests/rustdoc/sidebar-all-page.rs b/tests/rustdoc/sidebar-all-page.rs
index e74b981de64..45a6ba8ed2e 100644
--- a/tests/rustdoc/sidebar-all-page.rs
+++ b/tests/rustdoc/sidebar-all-page.rs
@@ -1,6 +1,6 @@
 #![crate_name = "foo"]
 
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 
 // @has 'foo/all.html'
 // @has - '//*[@class="sidebar-elems"]//li' 'Structs'
@@ -31,5 +31,5 @@ macro_rules! foo {
 pub type Type = u8;
 pub const FOO: u8 = 0;
 pub static BAR: u8 = 0;
-#[doc(primitive = "u8")]
+#[rustc_doc_primitive = "u8"]
 mod u8 {}
diff --git a/tests/rustdoc/tab_title.rs b/tests/rustdoc/tab_title.rs
index 0cc4f147e1c..8d781b40e46 100644
--- a/tests/rustdoc/tab_title.rs
+++ b/tests/rustdoc/tab_title.rs
@@ -1,4 +1,5 @@
 #![crate_name = "foo"]
+#![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
 
 // tests for the html <title> element
@@ -39,6 +40,6 @@ mod continue_keyword {}
 
 // @has foo/primitive.u8.html '//head/title' 'u8 - Rust'
 // @!has - '//head/title' 'foo'
-#[doc(primitive = "u8")]
+#[rustc_doc_primitive = "u8"]
 /// `u8` docs
 mod u8 {}
diff --git a/tests/rustdoc/titles.rs b/tests/rustdoc/titles.rs
index 69e8b856b0a..e1feb1cd64f 100644
--- a/tests/rustdoc/titles.rs
+++ b/tests/rustdoc/titles.rs
@@ -1,5 +1,5 @@
 #![crate_name = "foo"]
-#![feature(rustdoc_internals)]
+#![feature(rustc_attrs)]
 
 // @matches 'foo/index.html' '//h1' 'Crate foo'
 // @matches 'foo/index.html' '//h2[@class="location"]' 'Crate foo'
@@ -41,7 +41,7 @@ macro_rules! foo_macro {
 }
 
 // @matches 'foo/primitive.bool.html' '//h1' 'Primitive Type bool'
-#[doc(primitive = "bool")]
+#[rustc_doc_primitive = "bool"]
 mod bool {}
 
 // @matches 'foo/static.FOO_STATIC.html' '//h1' 'Static foo::FOO_STATIC'
diff --git a/tests/ui-fulldeps/fluent-messages/test.rs b/tests/ui-fulldeps/fluent-messages/test.rs
index 1ee7227a8e9..6ba13387b04 100644
--- a/tests/ui-fulldeps/fluent-messages/test.rs
+++ b/tests/ui-fulldeps/fluent-messages/test.rs
@@ -1,4 +1,4 @@
-// normalize-stderr-test "note.*" -> "note: os-specific message"
+// normalize-stderr-test "could not open Fluent resource:.*" -> "could not open Fluent resource: os-specific message"
 
 #![feature(rustc_private)]
 #![crate_type = "lib"]
diff --git a/tests/ui-fulldeps/fluent-messages/test.stderr b/tests/ui-fulldeps/fluent-messages/test.stderr
index 8a6a4a91cc2..2affe621c11 100644
--- a/tests/ui-fulldeps/fluent-messages/test.stderr
+++ b/tests/ui-fulldeps/fluent-messages/test.stderr
@@ -1,18 +1,14 @@
-error: could not open Fluent resource
+error: could not open Fluent resource: os-specific message
   --> $DIR/test.rs:24:24
    |
 LL |     fluent_messages! { "/definitely_does_not_exist.ftl" }
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: os-specific message
 
-error: could not open Fluent resource
+error: could not open Fluent resource: os-specific message
   --> $DIR/test.rs:31:24
    |
 LL |     fluent_messages! { "../definitely_does_not_exist.ftl" }
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: os-specific message
 
 error: could not parse Fluent resource
   --> $DIR/test.rs:38:24
@@ -89,7 +85,7 @@ error: invalid escape `\n` in Fluent resource
 LL |     fluent_messages! { "./invalid-escape.ftl" }
    |                        ^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: os-specific message
+   = note: Fluent does not interpret these escape sequences (<https://projectfluent.org/fluent/guide/special.html>)
 
 error: invalid escape `\"` in Fluent resource
   --> $DIR/test.rs:99:24
@@ -97,7 +93,7 @@ error: invalid escape `\"` in Fluent resource
 LL |     fluent_messages! { "./invalid-escape.ftl" }
    |                        ^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: os-specific message
+   = note: Fluent does not interpret these escape sequences (<https://projectfluent.org/fluent/guide/special.html>)
 
 error: invalid escape `\'` in Fluent resource
   --> $DIR/test.rs:99:24
@@ -105,7 +101,7 @@ error: invalid escape `\'` in Fluent resource
 LL |     fluent_messages! { "./invalid-escape.ftl" }
    |                        ^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: os-specific message
+   = note: Fluent does not interpret these escape sequences (<https://projectfluent.org/fluent/guide/special.html>)
 
 error: aborting due to 13 previous errors
 
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
new file mode 100644
index 00000000000..75aa25906aa
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs
@@ -0,0 +1,20 @@
+// edition: 2021
+
+#![feature(return_type_notation, async_fn_in_trait)]
+//~^ WARN the feature `return_type_notation` is incomplete
+//~| WARN the feature `async_fn_in_trait` is incomplete
+
+trait Trait {
+    async fn method() {}
+}
+
+fn foo<T: Trait<method(i32): Send>>() {}
+//~^ ERROR argument types not allowed with return type notation
+
+fn bar<T: Trait<method(..) -> (): Send>>() {}
+//~^ ERROR return type not allowed with return type notation
+
+fn baz<T: Trait<method(): Send>>() {}
+//~^ ERROR return type notation arguments must be elided with `..`
+
+fn main() {}
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.stderr
new file mode 100644
index 00000000000..5b075a0fa29
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr
@@ -0,0 +1,37 @@
+error: return type not allowed with return type notation
+  --> $DIR/bad-inputs-and-output.rs:14:28
+   |
+LL | fn bar<T: Trait<method(..) -> (): Send>>() {}
+   |                            ^^^^^ help: remove the return type
+
+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
+   |
+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: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/bad-inputs-and-output.rs:3:34
+   |
+LL | #![feature(return_type_notation, async_fn_in_trait)]
+   |                                  ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+
+error: argument types not allowed with return type notation
+  --> $DIR/bad-inputs-and-output.rs:11:23
+   |
+LL | fn foo<T: Trait<method(i32): Send>>() {}
+   |                       ^^^^^ help: remove the input types: `(..)`
+
+error: return type notation arguments must be elided with `..`
+  --> $DIR/bad-inputs-and-output.rs:17:23
+   |
+LL | fn baz<T: Trait<method(): Send>>() {}
+   |                       ^^ help: add `..`: `(..)`
+
+error: aborting due to 3 previous errors; 2 warnings 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
new file mode 100644
index 00000000000..75d1dc745d1
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/basic.rs
@@ -0,0 +1,28 @@
+// revisions: with without
+// edition: 2021
+//[with] check-pass
+
+#![feature(return_type_notation, async_fn_in_trait)]
+//~^ WARN the feature `return_type_notation` is incomplete
+//~| WARN the feature `async_fn_in_trait` is incomplete
+
+trait Foo {
+    async fn method() -> Result<(), ()>;
+}
+
+async fn foo<T: Foo>() -> Result<(), ()> {
+    T::method().await?;
+    Ok(())
+}
+
+fn is_send(_: impl Send) {}
+
+fn test<
+    #[cfg(with)] T: Foo<method(..): Send>,
+    #[cfg(without)] T: Foo,
+>() {
+    is_send(foo::<T>());
+    //[without]~^ ERROR future cannot be sent between threads safely
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.with.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.with.stderr
new file mode 100644
index 00000000000..722c774cb33
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/basic.with.stderr
@@ -0,0 +1,19 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/basic.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
+
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/basic.rs:5:34
+   |
+LL | #![feature(return_type_notation, async_fn_in_trait)]
+   |                                  ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr
new file mode 100644
index 00000000000..1645d8c2650
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/basic.without.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/basic.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
+
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/basic.rs:5:34
+   |
+LL | #![feature(return_type_notation, async_fn_in_trait)]
+   |                                  ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+
+error: future cannot be sent between threads safely
+  --> $DIR/basic.rs:24: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:14: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:18:20
+   |
+LL | fn is_send(_: impl Send) {}
+   |                    ^^^^ required by this bound in `is_send`
+
+error: aborting due to previous error; 2 warnings 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
new file mode 100644
index 00000000000..c8fc980974e
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/equality.rs
@@ -0,0 +1,16 @@
+// edition: 2021
+
+#![feature(return_type_notation, async_fn_in_trait)]
+//~^ WARN the feature `return_type_notation` is incomplete
+//~| WARN the feature `async_fn_in_trait` is incomplete
+
+use std::future::Future;
+
+trait Trait {
+    async fn method() {}
+}
+
+fn test<T: Trait<method(..) = Box<dyn Future<Output = ()>>>>() {}
+//~^ ERROR return type notation is not allowed to use type equality
+
+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.stderr
new file mode 100644
index 00000000000..cd50ff38694
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/equality.stderr
@@ -0,0 +1,25 @@
+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
+   |
+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: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/equality.rs:3:34
+   |
+LL | #![feature(return_type_notation, async_fn_in_trait)]
+   |                                  ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+
+error: return type notation is not allowed to use type equality
+  --> $DIR/equality.rs:13:18
+   |
+LL | fn test<T: Trait<method(..) = Box<dyn Future<Output = ()>>>>() {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 2 warnings emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/missing.rs b/tests/ui/associated-type-bounds/return-type-notation/missing.rs
new file mode 100644
index 00000000000..1263cae4477
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/missing.rs
@@ -0,0 +1,14 @@
+// edition: 2021
+
+#![feature(return_type_notation, async_fn_in_trait)]
+//~^ WARN the feature `return_type_notation` is incomplete
+//~| WARN the feature `async_fn_in_trait` is incomplete
+
+trait Trait {
+    async fn method() {}
+}
+
+fn bar<T: Trait<methid(..): Send>>() {}
+//~^ ERROR cannot find associated function `methid` in trait `Trait`
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/missing.stderr b/tests/ui/associated-type-bounds/return-type-notation/missing.stderr
new file mode 100644
index 00000000000..93111b5c36b
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/missing.stderr
@@ -0,0 +1,25 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/missing.rs:3: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: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/missing.rs:3:34
+   |
+LL | #![feature(return_type_notation, async_fn_in_trait)]
+   |                                  ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+
+error: cannot find associated function `methid` in trait `Trait`
+  --> $DIR/missing.rs:11:17
+   |
+LL | fn bar<T: Trait<methid(..): Send>>() {}
+   |                 ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 2 warnings emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs
new file mode 100644
index 00000000000..d283c6eab37
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs
@@ -0,0 +1,11 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Trait {
+    fn method() {}
+}
+
+fn test<T: Trait<method(..): Send>>() {}
+//~^ ERROR  return type notation used on function that is not `async` and does not return `impl Trait`
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr
new file mode 100644
index 00000000000..38c498bc2fb
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr
@@ -0,0 +1,22 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/non-rpitit.rs:1: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: return type notation used on function that is not `async` and does not return `impl Trait`
+  --> $DIR/non-rpitit.rs:8:18
+   |
+LL |     fn method() {}
+   |     ----------- this function must be `async` or return `impl Trait`
+...
+LL | fn test<T: Trait<method(..): Send>>() {}
+   |                  ^^^^^^^^^^^^^^^^
+   |
+   = note: function returns `()`, which is not compatible with associated type return bounds
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/attributes/no-mangle-closure.rs b/tests/ui/attributes/no-mangle-closure.rs
new file mode 100644
index 00000000000..c76baa27f38
--- /dev/null
+++ b/tests/ui/attributes/no-mangle-closure.rs
@@ -0,0 +1,11 @@
+// Check that we do not ICE when `no_mangle` is applied to something that has no name.
+
+#![crate_type = "lib"]
+#![feature(stmt_expr_attributes)]
+
+pub struct S([usize; 8]);
+
+pub fn outer_function(x: S, y: S) -> usize {
+    (#[no_mangle] || y.0[0])()
+    //~^ ERROR `#[no_mangle]` cannot be used on a closure as it has no name
+}
diff --git a/tests/ui/attributes/no-mangle-closure.stderr b/tests/ui/attributes/no-mangle-closure.stderr
new file mode 100644
index 00000000000..949eb70510e
--- /dev/null
+++ b/tests/ui/attributes/no-mangle-closure.stderr
@@ -0,0 +1,8 @@
+error: `#[no_mangle]` cannot be used on a closure as it has no name
+  --> $DIR/no-mangle-closure.rs:9:6
+   |
+LL |     (#[no_mangle] || y.0[0])()
+   |      ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/closures/2229_closure_analysis/array_subslice.rs b/tests/ui/closures/2229_closure_analysis/array_subslice.rs
new file mode 100644
index 00000000000..5f244ea8936
--- /dev/null
+++ b/tests/ui/closures/2229_closure_analysis/array_subslice.rs
@@ -0,0 +1,13 @@
+// regression test for #109298
+// edition: 2021
+
+pub fn subslice_array(x: [u8; 3]) {
+    let f = || {
+        let [_x @ ..] = x;
+        let [ref y, ref mut z @ ..] = x; //~ ERROR cannot borrow `x[..]` as mutable
+    };
+
+    f(); //~ ERROR cannot borrow `f` as mutable
+}
+
+fn main() {}
diff --git a/tests/ui/closures/2229_closure_analysis/array_subslice.stderr b/tests/ui/closures/2229_closure_analysis/array_subslice.stderr
new file mode 100644
index 00000000000..888c60d5e91
--- /dev/null
+++ b/tests/ui/closures/2229_closure_analysis/array_subslice.stderr
@@ -0,0 +1,26 @@
+error[E0596]: cannot borrow `x[..]` as mutable, as `x` is not declared as mutable
+  --> $DIR/array_subslice.rs:7:21
+   |
+LL | pub fn subslice_array(x: [u8; 3]) {
+   |                       - help: consider changing this to be mutable: `mut x`
+...
+LL |         let [ref y, ref mut z @ ..] = x;
+   |                     ^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable
+  --> $DIR/array_subslice.rs:10:5
+   |
+LL |         let [ref y, ref mut z @ ..] = x;
+   |                                       - calling `f` requires mutable binding due to mutable borrow of `x`
+...
+LL |     f();
+   |     ^ cannot borrow as mutable
+   |
+help: consider changing this to be mutable
+   |
+LL |     let mut f = || {
+   |         +++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr
new file mode 100644
index 00000000000..85728f8e1ad
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr
@@ -0,0 +1,21 @@
+error[E0658]: return type notation is experimental
+  --> $DIR/feature-gate-return_type_notation.rs:12:18
+   |
+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: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/feature-gate-return_type_notation.rs:4:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr
new file mode 100644
index 00000000000..85728f8e1ad
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr
@@ -0,0 +1,21 @@
+error[E0658]: return type notation is experimental
+  --> $DIR/feature-gate-return_type_notation.rs:12:18
+   |
+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: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/feature-gate-return_type_notation.rs:4:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.rs b/tests/ui/feature-gates/feature-gate-return_type_notation.rs
new file mode 100644
index 00000000000..b75feb130a6
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.rs
@@ -0,0 +1,15 @@
+// edition: 2021
+// revisions: cfg no
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete
+
+trait Trait {
+    async fn m();
+}
+
+#[cfg(cfg)]
+fn foo<T: Trait<m(..): Send>>() {}
+//~^ ERROR return type notation is experimental
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs
index 74f7bc603aa..ffeabe5c2ed 100644
--- a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs
+++ b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs
@@ -2,12 +2,13 @@
 
 #![feature(return_position_impl_trait_in_trait)]
 
+use std::ops::Deref;
+
 pub trait Foo {
-    fn bar() -> impl Sized;
+    fn bar() -> impl Deref<Target = impl Sized>;
 }
 
 pub struct Foreign;
-
 impl Foo for Foreign {
-    fn bar() {}
+    fn bar() -> &'static () { &() }
 }
diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.next.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.next.stderr
index bbfa089ceef..f0cd43bcf92 100644
--- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.next.stderr
+++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.next.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `Foo::{opaque#0}`
   --> $DIR/doesnt-satisfy.rs:8:22
    |
 LL |     fn bar() -> impl std::fmt::Display;
-   |                      ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::`
+   |                      ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/impl-trait/in-trait/foreign.rs b/tests/ui/impl-trait/in-trait/foreign.rs
index df77372aabd..f4972d948b2 100644
--- a/tests/ui/impl-trait/in-trait/foreign.rs
+++ b/tests/ui/impl-trait/in-trait/foreign.rs
@@ -5,7 +5,17 @@
 
 extern crate rpitit;
 
+use std::sync::Arc;
+
+// Implement an RPITIT from another crate.
+struct Local;
+impl rpitit::Foo for Local {
+    fn bar() -> Arc<String> { Arc::new(String::new()) }
+}
+
 fn main() {
-    // Witness an RPITIT from another crate
-    let () = <rpitit::Foreign as rpitit::Foo>::bar();
+    // Witness an RPITIT from another crate.
+    let &() = <rpitit::Foreign as rpitit::Foo>::bar();
+
+    let x: Arc<String> = <Local as rpitit::Foo>::bar();
 }
diff --git a/tests/ui/impl-trait/in-trait/nested-rpitit.rs b/tests/ui/impl-trait/in-trait/nested-rpitit.rs
index 65285e3a3cc..36020753726 100644
--- a/tests/ui/impl-trait/in-trait/nested-rpitit.rs
+++ b/tests/ui/impl-trait/in-trait/nested-rpitit.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)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/multiple-lifetimes.rs b/tests/ui/impl-trait/multiple-lifetimes/multiple-lifetimes.rs
index 5407fb6dd28..5407fb6dd28 100644
--- a/tests/ui/impl-trait/multiple-lifetimes.rs
+++ b/tests/ui/impl-trait/multiple-lifetimes/multiple-lifetimes.rs
diff --git a/tests/ui/mir/mir_alignment_check.rs b/tests/ui/mir/mir_alignment_check.rs
new file mode 100644
index 00000000000..68a5384b30d
--- /dev/null
+++ b/tests/ui/mir/mir_alignment_check.rs
@@ -0,0 +1,12 @@
+// run-fail
+// ignore-wasm32-bare: No panic messages
+// compile-flags: -C debug-assertions
+// error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
+
+fn main() {
+    let mut x = [0u32; 2];
+    let ptr: *mut u8 = x.as_mut_ptr().cast::<u8>();
+    unsafe {
+        *(ptr.add(1).cast::<u32>()) = 42;
+    }
+}
diff --git a/tests/ui/modules_and_files_visibility/mod_file_disambig_aux/compiletest-ignore-dir b/tests/ui/modules_and_files_visibility/mod_file_disambig_aux/compiletest-ignore-dir
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/ui/modules_and_files_visibility/mod_file_disambig_aux/compiletest-ignore-dir
diff --git a/tests/ui/non_modrs_mods_and_inline_mods/x/y/z/compiletest-ignore-dir b/tests/ui/non_modrs_mods_and_inline_mods/x/y/z/compiletest-ignore-dir
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/ui/non_modrs_mods_and_inline_mods/x/y/z/compiletest-ignore-dir
diff --git a/tests/ui/privacy/effective_visibilities.rs b/tests/ui/privacy/effective_visibilities.rs
index ff20e20d332..3e9eef46230 100644
--- a/tests/ui/privacy/effective_visibilities.rs
+++ b/tests/ui/privacy/effective_visibilities.rs
@@ -1,3 +1,4 @@
+#![rustc_effective_visibility] //~ ERROR Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
 #![feature(rustc_attrs)]
 
 #[rustc_effective_visibility]
diff --git a/tests/ui/privacy/effective_visibilities.stderr b/tests/ui/privacy/effective_visibilities.stderr
index 046b6095f4e..2618fc427e9 100644
--- a/tests/ui/privacy/effective_visibilities.stderr
+++ b/tests/ui/privacy/effective_visibilities.stderr
@@ -1,140 +1,152 @@
+error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+  --> $DIR/effective_visibilities.rs:1:1
+   |
+LL | / #![rustc_effective_visibility]
+LL | | #![feature(rustc_attrs)]
+LL | |
+LL | | #[rustc_effective_visibility]
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
 error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
-  --> $DIR/effective_visibilities.rs:4:1
+  --> $DIR/effective_visibilities.rs:5:1
    |
 LL | mod outer {
    | ^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:6:5
+  --> $DIR/effective_visibilities.rs:7:5
    |
 LL |     pub mod inner1 {
    |     ^^^^^^^^^^^^^^
 
 error: not in the table
-  --> $DIR/effective_visibilities.rs:9:9
+  --> $DIR/effective_visibilities.rs:10:9
    |
 LL |         extern "C" {}
    |         ^^^^^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:12:9
+  --> $DIR/effective_visibilities.rs:13:9
    |
 LL |         pub trait PubTrait {
    |         ^^^^^^^^^^^^^^^^^^
 
 error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
-  --> $DIR/effective_visibilities.rs:20:9
+  --> $DIR/effective_visibilities.rs:21:9
    |
 LL |         struct PrivStruct;
    |         ^^^^^^^^^^^^^^^^^
 
 error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
-  --> $DIR/effective_visibilities.rs:20:9
+  --> $DIR/effective_visibilities.rs:21:9
    |
 LL |         struct PrivStruct;
    |         ^^^^^^^^^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:24:9
+  --> $DIR/effective_visibilities.rs:25:9
    |
 LL |         pub union PubUnion {
    |         ^^^^^^^^^^^^^^^^^^
 
 error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
-  --> $DIR/effective_visibilities.rs:26:13
+  --> $DIR/effective_visibilities.rs:27:13
    |
 LL |             a: u8,
    |             ^^^^^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:28:13
+  --> $DIR/effective_visibilities.rs:29:13
    |
 LL |             pub b: u8,
    |             ^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:32:9
+  --> $DIR/effective_visibilities.rs:33:9
    |
 LL |         pub enum Enum {
    |         ^^^^^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:34:13
+  --> $DIR/effective_visibilities.rs:35:13
    |
 LL |             A(
    |             ^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:34:13
+  --> $DIR/effective_visibilities.rs:35:13
    |
 LL |             A(
    |             ^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:37:17
+  --> $DIR/effective_visibilities.rs:38:17
    |
 LL |                 PubUnion,
    |                 ^^^^^^^^
 
 error: not in the table
-  --> $DIR/effective_visibilities.rs:43:5
+  --> $DIR/effective_visibilities.rs:44:5
    |
 LL |     macro_rules! none_macro {
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Direct: pub(self), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:49:5
+  --> $DIR/effective_visibilities.rs:50:5
    |
 LL |     macro_rules! public_macro {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:54:5
+  --> $DIR/effective_visibilities.rs:55:5
    |
 LL |     pub struct ReachableStruct {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:56:9
+  --> $DIR/effective_visibilities.rs:57:9
    |
 LL |         pub a: u8,
    |         ^^^^^^^^^
 
 error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:61:9
+  --> $DIR/effective_visibilities.rs:62:9
    |
 LL | pub use outer::inner1;
    |         ^^^^^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:67:5
+  --> $DIR/effective_visibilities.rs:68:5
    |
 LL |     pub type HalfPublicImport = u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
-  --> $DIR/effective_visibilities.rs:70:5
+  --> $DIR/effective_visibilities.rs:71:5
    |
 LL |     pub(crate) const HalfPublicImport: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:74:9
+  --> $DIR/effective_visibilities.rs:75:9
    |
 LL | pub use half_public_import::HalfPublicImport;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:14:13
+  --> $DIR/effective_visibilities.rs:15:13
    |
 LL |             const A: i32;
    |             ^^^^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:16:13
+  --> $DIR/effective_visibilities.rs:17:13
    |
 LL |             type B;
    |             ^^^^^^
 
-error: aborting due to 23 previous errors
+error: aborting due to 24 previous errors
 
diff --git a/tests/ui/process/signal-exit-status.rs b/tests/ui/process/signal-exit-status.rs
index 9519ed7b4c7..0f05f916cb9 100644
--- a/tests/ui/process/signal-exit-status.rs
+++ b/tests/ui/process/signal-exit-status.rs
@@ -4,14 +4,16 @@
 // ignore-windows
 // ignore-fuchsia code returned as ZX_TASK_RETCODE_EXCEPTION_KILL, FIXME (#58590)
 
+#![feature(core_intrinsics)]
+
 use std::env;
 use std::process::Command;
 
 pub fn main() {
     let args: Vec<String> = env::args().collect();
     if args.len() >= 2 && args[1] == "signal" {
-        // Raise a segfault.
-        unsafe { *(1 as *mut isize) = 0; }
+        // Raise an aborting signal without UB
+        core::intrinsics::abort();
     } else {
         let status = Command::new(&args[0]).arg("signal").status().unwrap();
         assert!(status.code().is_none());
diff --git a/tests/ui/rfc-1937-termination-trait/issue-103052-2.stderr b/tests/ui/rfc-1937-termination-trait/issue-103052-2.current.stderr
index a700c72ea68..f72b3ab0234 100644
--- a/tests/ui/rfc-1937-termination-trait/issue-103052-2.stderr
+++ b/tests/ui/rfc-1937-termination-trait/issue-103052-2.current.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `Something: Termination` is not satisfied
-  --> $DIR/issue-103052-2.rs:12:22
+  --> $DIR/issue-103052-2.rs:15:22
    |
 LL |         fn main() -> Something {
    |                      ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
    |
 note: required by a bound in `Main::main::{opaque#0}`
-  --> $DIR/issue-103052-2.rs:6:27
+  --> $DIR/issue-103052-2.rs:9:27
    |
 LL |         fn main() -> impl std::process::Termination;
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::main::{opaque#0}`
diff --git a/tests/ui/rfc-1937-termination-trait/issue-103052-2.next.stderr b/tests/ui/rfc-1937-termination-trait/issue-103052-2.next.stderr
new file mode 100644
index 00000000000..8b01941b4c6
--- /dev/null
+++ b/tests/ui/rfc-1937-termination-trait/issue-103052-2.next.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `Something: Termination` is not satisfied
+  --> $DIR/issue-103052-2.rs:15:22
+   |
+LL |         fn main() -> Something {
+   |                      ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
+   |
+note: required by a bound in `Main::{opaque#0}`
+  --> $DIR/issue-103052-2.rs:9:27
+   |
+LL |         fn main() -> impl std::process::Termination;
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{opaque#0}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-1937-termination-trait/issue-103052-2.rs b/tests/ui/rfc-1937-termination-trait/issue-103052-2.rs
index fa9182b6dee..ca5fa6df2a6 100644
--- a/tests/ui/rfc-1937-termination-trait/issue-103052-2.rs
+++ b/tests/ui/rfc-1937-termination-trait/issue-103052-2.rs
@@ -1,3 +1,6 @@
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
+
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
@@ -9,7 +12,8 @@ mod child {
     struct Something;
 
     impl Main for () {
-        fn main() -> Something { //~ ERROR the trait bound `Something: Termination` is not satisfied
+        fn main() -> Something {
+            //~^ ERROR the trait bound `Something: Termination` is not satisfied
             Something
         }
     }
diff --git a/tests/ui/rfc-2632-const-trait-impl/nested-closure.rs b/tests/ui/rfc-2632-const-trait-impl/nested-closure.rs
index a851136009c..0b423b34022 100644
--- a/tests/ui/rfc-2632-const-trait-impl/nested-closure.rs
+++ b/tests/ui/rfc-2632-const-trait-impl/nested-closure.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(const_trait_impl, once_cell)]
+#![feature(const_trait_impl, lazy_cell)]
 
 use std::sync::LazyLock;
 
diff --git a/tests/ui/rustdoc/doc-primitive.rs b/tests/ui/rustdoc/doc-primitive.rs
new file mode 100644
index 00000000000..4336961e3b5
--- /dev/null
+++ b/tests/ui/rustdoc/doc-primitive.rs
@@ -0,0 +1,8 @@
+#![deny(invalid_doc_attributes)]
+
+#[doc(primitive = "foo")]
+//~^ ERROR unknown `doc` attribute `primitive`
+//~| WARN
+mod bar {}
+
+fn main() {}
diff --git a/tests/ui/rustdoc/doc-primitive.stderr b/tests/ui/rustdoc/doc-primitive.stderr
new file mode 100644
index 00000000000..d61eb381647
--- /dev/null
+++ b/tests/ui/rustdoc/doc-primitive.stderr
@@ -0,0 +1,16 @@
+error: unknown `doc` attribute `primitive`
+  --> $DIR/doc-primitive.rs:3:7
+   |
+LL | #[doc(primitive = "foo")]
+   |       ^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+note: the lint level is defined here
+  --> $DIR/doc-primitive.rs:1:9
+   |
+LL | #![deny(invalid_doc_attributes)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rustdoc/feature-gate-doc_primitive.rs b/tests/ui/rustdoc/feature-gate-doc_primitive.rs
index 18e99e72f8b..78fcd90752e 100644
--- a/tests/ui/rustdoc/feature-gate-doc_primitive.rs
+++ b/tests/ui/rustdoc/feature-gate-doc_primitive.rs
@@ -1,7 +1,5 @@
-// check-pass
-#[doc(primitive = "usize")]
-//~^ WARNING `doc(primitive)` should never have been stable
-//~| WARNING hard error in a future release
+#[rustc_doc_primitive = "usize"]
+//~^ ERROR `rustc_doc_primitive` is a rustc internal attribute
 /// Some docs
 mod usize {}
 
diff --git a/tests/ui/rustdoc/feature-gate-doc_primitive.stderr b/tests/ui/rustdoc/feature-gate-doc_primitive.stderr
index 194b2d87db2..5920880675d 100644
--- a/tests/ui/rustdoc/feature-gate-doc_primitive.stderr
+++ b/tests/ui/rustdoc/feature-gate-doc_primitive.stderr
@@ -1,12 +1,11 @@
-warning: `doc(primitive)` should never have been stable
-  --> $DIR/feature-gate-doc_primitive.rs:2:7
+error[E0658]: `rustc_doc_primitive` is a rustc internal attribute
+  --> $DIR/feature-gate-doc_primitive.rs:1:1
    |
-LL | #[doc(primitive = "usize")]
-   |       ^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_doc_primitive = "usize"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
-   = note: `#[warn(invalid_doc_attributes)]` on by default
+   = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
-warning: 1 warning emitted
+error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/sync/suggest-once-cell.rs b/tests/ui/sync/suggest-once-cell.rs
index 82fca45b1a4..14f40ad87a3 100644
--- a/tests/ui/sync/suggest-once-cell.rs
+++ b/tests/ui/sync/suggest-once-cell.rs
@@ -1,5 +1,3 @@
-#![feature(once_cell)]
-
 fn require_sync<T: Sync>() {}
 //~^ NOTE required by this bound in `require_sync`
 //~| NOTE required by a bound in `require_sync`
diff --git a/tests/ui/sync/suggest-once-cell.stderr b/tests/ui/sync/suggest-once-cell.stderr
index fadf05374d8..20242f4b61c 100644
--- a/tests/ui/sync/suggest-once-cell.stderr
+++ b/tests/ui/sync/suggest-once-cell.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `OnceCell<()>` cannot be shared between threads safely
-  --> $DIR/suggest-once-cell.rs:8:20
+  --> $DIR/suggest-once-cell.rs:6:20
    |
 LL |     require_sync::<std::cell::OnceCell<()>>();
    |                    ^^^^^^^^^^^^^^^^^^^^^^^ `OnceCell<()>` cannot be shared between threads safely
@@ -7,7 +7,7 @@ LL |     require_sync::<std::cell::OnceCell<()>>();
    = help: the trait `Sync` is not implemented for `OnceCell<()>`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::OnceLock` instead
 note: required by a bound in `require_sync`
-  --> $DIR/suggest-once-cell.rs:3:20
+  --> $DIR/suggest-once-cell.rs:1:20
    |
 LL | fn require_sync<T: Sync>() {}
    |                    ^^^^ required by this bound in `require_sync`
diff --git a/tests/ui/sync/suggest-ref-cell.rs b/tests/ui/sync/suggest-ref-cell.rs
index 6b972ae0962..093a4999c65 100644
--- a/tests/ui/sync/suggest-ref-cell.rs
+++ b/tests/ui/sync/suggest-ref-cell.rs
@@ -1,5 +1,3 @@
-#![feature(once_cell)]
-
 fn require_sync<T: Sync>() {}
 //~^ NOTE required by this bound in `require_sync`
 //~| NOTE required by a bound in `require_sync`
diff --git a/tests/ui/sync/suggest-ref-cell.stderr b/tests/ui/sync/suggest-ref-cell.stderr
index 9e8b8fcb42e..ca3ae77b1a0 100644
--- a/tests/ui/sync/suggest-ref-cell.stderr
+++ b/tests/ui/sync/suggest-ref-cell.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `RefCell<()>` cannot be shared between threads safely
-  --> $DIR/suggest-ref-cell.rs:8:20
+  --> $DIR/suggest-ref-cell.rs:6:20
    |
 LL |     require_sync::<std::cell::RefCell<()>>();
    |                    ^^^^^^^^^^^^^^^^^^^^^^ `RefCell<()>` cannot be shared between threads safely
@@ -7,7 +7,7 @@ LL |     require_sync::<std::cell::RefCell<()>>();
    = help: the trait `Sync` is not implemented for `RefCell<()>`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
 note: required by a bound in `require_sync`
-  --> $DIR/suggest-ref-cell.rs:3:20
+  --> $DIR/suggest-ref-cell.rs:1:20
    |
 LL | fn require_sync<T: Sync>() {}
    |                    ^^^^ required by this bound in `require_sync`
diff --git a/tests/ui/traits/new-solver/closure-inference-guidance.rs b/tests/ui/traits/new-solver/closure-inference-guidance.rs
new file mode 100644
index 00000000000..d2ad0cc0316
--- /dev/null
+++ b/tests/ui/traits/new-solver/closure-inference-guidance.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+fn foo(i: isize) -> isize { i + 1 }
+
+fn apply<A, F>(f: F, v: A) -> A where F: FnOnce(A) -> A { f(v) }
+
+pub fn main() {
+    let f = |i| foo(i);
+    assert_eq!(apply(f, 2), 3);
+}
diff --git a/tests/ui/traits/new-solver/const-param-placeholder.fail.stderr b/tests/ui/traits/new-solver/const-param-placeholder.fail.stderr
new file mode 100644
index 00000000000..4db6e22e57f
--- /dev/null
+++ b/tests/ui/traits/new-solver/const-param-placeholder.fail.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `[T; N]: Foo` is not satisfied
+  --> $DIR/const-param-placeholder.rs:17:17
+   |
+LL |     needs_foo::<[T; N]>();
+   |                 ^^^^^^ the trait `Foo` is not implemented for `[T; N]`
+   |
+   = help: the trait `Foo` is implemented for `[T; 1]`
+note: required by a bound in `needs_foo`
+  --> $DIR/const-param-placeholder.rs:8:17
+   |
+LL | fn needs_foo<F: Foo>() {}
+   |                 ^^^ required by this bound in `needs_foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/new-solver/const-param-placeholder.rs b/tests/ui/traits/new-solver/const-param-placeholder.rs
new file mode 100644
index 00000000000..a83102a4cdd
--- /dev/null
+++ b/tests/ui/traits/new-solver/const-param-placeholder.rs
@@ -0,0 +1,21 @@
+// compile-flags: -Ztrait-solver=next
+// revisions: pass fail
+//[pass] check-pass
+
+struct Wrapper<T, const N: usize>([T; N]);
+
+trait Foo {}
+fn needs_foo<F: Foo>() {}
+
+#[cfg(fail)]
+impl<T> Foo for [T; 1] {}
+
+#[cfg(pass)]
+impl<T, const N: usize> Foo for [T; N] {}
+
+fn test<T, const N: usize>() {
+    needs_foo::<[T; N]>();
+    //[fail]~^ ERROR the trait bound `[T; N]: Foo` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/float-canonical.rs b/tests/ui/traits/new-solver/float-canonical.rs
new file mode 100644
index 00000000000..b8748cd433b
--- /dev/null
+++ b/tests/ui/traits/new-solver/float-canonical.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+fn foo(x: f64) {
+    let y = x + 1.0;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/param-discr-kind.rs b/tests/ui/traits/new-solver/param-discr-kind.rs
new file mode 100644
index 00000000000..e319ddea106
--- /dev/null
+++ b/tests/ui/traits/new-solver/param-discr-kind.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+fn foo<T>(x: T) {
+    std::mem::discriminant(&x);
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/pointee.rs b/tests/ui/traits/new-solver/pointee.rs
index fa6ee2e2daf..93c0542ace4 100644
--- a/tests/ui/traits/new-solver/pointee.rs
+++ b/tests/ui/traits/new-solver/pointee.rs
@@ -7,17 +7,15 @@ use std::ptr::{DynMetadata, Pointee};
 trait Trait<U> {}
 struct MyDst<T: ?Sized>(T);
 
-fn works<T>() {
-    let _: <T as Pointee>::Metadata = ();
-    let _: <[T] as Pointee>::Metadata = 1_usize;
-    let _: <str as Pointee>::Metadata = 1_usize;
-    let _: <dyn Trait<T> as Pointee>::Metadata = give::<DynMetadata<dyn Trait<T>>>();
-    let _: <MyDst<T> as Pointee>::Metadata = ();
-    let _: <((((([u8],),),),),) as Pointee>::Metadata = 1_usize;
-}
+fn meta_is<T: Pointee<Metadata = U> + ?Sized, U>() {}
 
-fn give<U>() -> U {
-    loop {}
+fn works<T>() {
+    meta_is::<T, ()>();
+    meta_is::<[T], usize>();
+    meta_is::<str, usize>();
+    meta_is::<dyn Trait<T>, DynMetadata<dyn Trait<T>>>();
+    meta_is::<MyDst<T>, ()>();
+    meta_is::<((((([u8],),),),),), usize>();
 }
 
 fn main() {}
diff --git a/tests/ui/traits/new-solver/projection-discr-kind.rs b/tests/ui/traits/new-solver/projection-discr-kind.rs
new file mode 100644
index 00000000000..20296b287b1
--- /dev/null
+++ b/tests/ui/traits/new-solver/projection-discr-kind.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Ztrait-solver=next
+
+// Check that `<T::Assoc as DiscriminantKind>::Discriminant` doesn't normalize
+// to itself and cause overflow/ambiguity.
+
+trait Foo {
+    type Assoc;
+}
+
+trait Bar {}
+fn needs_bar(_: impl Bar) {}
+
+fn foo<T: Foo>(x: T::Assoc) {
+    needs_bar(std::mem::discriminant(&x));
+    //~^ ERROR the trait bound `Discriminant<<T as Foo>::Assoc>: Bar` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/projection-discr-kind.stderr b/tests/ui/traits/new-solver/projection-discr-kind.stderr
new file mode 100644
index 00000000000..03e28f993e2
--- /dev/null
+++ b/tests/ui/traits/new-solver/projection-discr-kind.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `Discriminant<<T as Foo>::Assoc>: Bar` is not satisfied
+  --> $DIR/projection-discr-kind.rs:14:15
+   |
+LL |     needs_bar(std::mem::discriminant(&x));
+   |     --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `Discriminant<<T as Foo>::Assoc>`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `needs_bar`
+  --> $DIR/projection-discr-kind.rs:11:22
+   |
+LL | fn needs_bar(_: impl Bar) {}
+   |                      ^^^ required by this bound in `needs_bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/use/use-mod.rs b/tests/ui/use/use-mod/use-mod.rs
index 87064c6a42b..87064c6a42b 100644
--- a/tests/ui/use/use-mod.rs
+++ b/tests/ui/use/use-mod/use-mod.rs
diff --git a/tests/ui/use/use-mod.stderr b/tests/ui/use/use-mod/use-mod.stderr
index 0cae5eb14ae..0cae5eb14ae 100644
--- a/tests/ui/use/use-mod.stderr
+++ b/tests/ui/use/use-mod/use-mod.stderr
diff --git a/tests/ui/use.rs b/tests/ui/use/use.rs
index 1beee4a5143..1beee4a5143 100644
--- a/tests/ui/use.rs
+++ b/tests/ui/use/use.rs