about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock30
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs102
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs58
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs54
-rw-r--r--compiler/rustc_attr/src/session_diagnostics.rs90
-rw-r--r--compiler/rustc_borrowck/src/session_diagnostics.rs38
-rw-r--r--compiler/rustc_builtin_macros/src/cfg.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs37
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs15
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/main.yml99
-rw-r--r--compiler/rustc_codegen_cranelift/.gitignore6
-rw-r--r--compiler/rustc_codegen_cranelift/.vscode/settings.json6
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.lock62
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.toml14
-rw-r--r--compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock38
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs52
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/abi_checker.rs60
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/build_backend.rs16
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs13
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/config.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/mod.rs21
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/prepare.rs186
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/tests.rs179
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/utils.rs46
-rwxr-xr-xcompiler/rustc_codegen_cranelift/clean_all.sh6
-rw-r--r--compiler/rustc_codegen_cranelift/config.txt2
-rw-r--r--compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch29
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0001-abi-checker-Disable-failing-tests.patch36
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch96
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch47
-rw-r--r--compiler/rustc_codegen_cranelift/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh6
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh8
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs53
-rw-r--r--compiler/rustc_codegen_cranelift/src/allocator.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/archive.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs12
-rw-r--r--compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs17
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs87
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs51
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs22
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs62
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs128
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs14
-rw-r--r--compiler/rustc_codegen_cranelift/src/main_shim.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/num.rs61
-rw-r--r--compiler/rustc_codegen_cranelift/src/unsize.rs40
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs48
-rw-r--r--compiler/rustc_codegen_cranelift/src/vtable.rs26
-rw-r--r--compiler/rustc_codegen_gcc/src/errors.rs46
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs31
-rw-r--r--compiler/rustc_codegen_llvm/src/callee.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs27
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs13
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs127
-rw-r--r--compiler/rustc_const_eval/src/errors.rs60
-rw-r--r--compiler/rustc_data_structures/src/sso/set.rs2
-rw-r--r--compiler/rustc_driver/src/session_diagnostics.rs14
-rw-r--r--compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl2
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs14
-rw-r--r--compiler/rustc_errors/src/lib.rs3
-rw-r--r--compiler/rustc_expand/src/errors.rs12
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs4
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_method.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs58
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs31
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs35
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs24
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs68
-rw-r--r--compiler/rustc_infer/src/errors/note_and_explain.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs26
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs23
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs19
-rw-r--r--compiler/rustc_interface/src/errors.rs28
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_lint/src/array_into_iter.rs8
-rw-r--r--compiler/rustc_lint/src/builtin.rs211
-rw-r--r--compiler/rustc_lint/src/enum_intrinsics_non_enums.rs8
-rw-r--r--compiler/rustc_lint/src/errors.rs34
-rw-r--r--compiler/rustc_lint/src/expect.rs4
-rw-r--r--compiler/rustc_lint/src/hidden_unicode_codepoints.rs14
-rw-r--r--compiler/rustc_lint/src/internal.rs36
-rw-r--r--compiler/rustc_lint/src/levels.rs2
-rw-r--r--compiler/rustc_lint/src/methods.rs10
-rw-r--r--compiler/rustc_lint/src/non_ascii_idents.rs14
-rw-r--r--compiler/rustc_lint/src/non_fmt_panic.rs65
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs26
-rw-r--r--compiler/rustc_lint/src/noop_method_call.rs6
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs18
-rw-r--r--compiler/rustc_lint/src/pass_by_value.rs4
-rw-r--r--compiler/rustc_lint/src/redundant_semicolon.rs4
-rw-r--r--compiler/rustc_lint/src/traits.rs4
-rw-r--r--compiler/rustc_lint/src/types.rs198
-rw-r--r--compiler/rustc_lint/src/unused.rs36
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs1
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic.rs4
-rw-r--r--compiler/rustc_macros/src/diagnostics/fluent.rs65
-rw-r--r--compiler/rustc_macros/src/diagnostics/mod.rs14
-rw-r--r--compiler/rustc_metadata/src/errors.rs186
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs17
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs17
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs3
-rw-r--r--compiler/rustc_middle/src/error.rs12
-rw-r--r--compiler/rustc_middle/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs28
-rw-r--r--compiler/rustc_middle/src/query/mod.rs30
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs1
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs4
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs15
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs2
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs18
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs21
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs145
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs204
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs258
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs6
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs1
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs17
-rw-r--r--compiler/rustc_middle/src/ty/query.rs1
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs25
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs31
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs22
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs16
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs12
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs10
-rw-r--r--compiler/rustc_mir_dataflow/src/errors.rs20
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs249
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs21
-rw-r--r--compiler/rustc_parse/src/errors.rs354
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs9
-rw-r--r--compiler/rustc_parse/src/lexer/unescape_error_reporting.rs19
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs28
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs2
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs80
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs20
-rw-r--r--compiler/rustc_passes/src/check_attr.rs12
-rw-r--r--compiler/rustc_passes/src/errors.rs401
-rw-r--r--compiler/rustc_plugin_impl/src/errors.rs4
-rw-r--r--compiler/rustc_privacy/src/errors.rs24
-rw-r--r--compiler/rustc_privacy/src/lib.rs35
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs1
-rw-r--r--compiler/rustc_query_system/src/error.rs30
-rw-r--r--compiler/rustc_resolve/src/access_levels.rs26
-rw-r--r--compiler/rustc_resolve/src/imports.rs27
-rw-r--r--compiler/rustc_resolve/src/late.rs8
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs96
-rw-r--r--compiler/rustc_resolve/src/macros.rs16
-rw-r--r--compiler/rustc_save_analysis/src/errors.rs2
-rw-r--r--compiler/rustc_session/src/errors.rs56
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--compiler/rustc_session/src/utils.rs11
-rw-r--r--compiler/rustc_span/src/lib.rs5
-rw-r--r--compiler/rustc_span/src/source_map.rs20
-rw-r--r--compiler/rustc_symbol_mangling/src/errors.rs2
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs22
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs35
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs19
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs21
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs17
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs43
-rw-r--r--compiler/rustc_ty_utils/src/errors.rs48
-rw-r--r--config.toml.example5
-rw-r--r--library/alloc/src/borrow.rs1
-rw-r--r--library/alloc/src/rc.rs2
-rw-r--r--library/alloc/src/string.rs31
-rw-r--r--library/alloc/src/sync.rs2
-rw-r--r--library/alloc/src/vec/mod.rs4
-rw-r--r--library/core/src/array/mod.rs4
-rw-r--r--library/core/src/error.rs4
-rw-r--r--library/core/src/mem/maybe_uninit.rs3
-rw-r--r--library/core/src/ptr/metadata.rs14
-rw-r--r--library/core/src/ptr/mod.rs1
-rw-r--r--library/core/src/ptr/mut_ptr.rs6
-rw-r--r--library/core/src/ptr/non_null.rs6
-rw-r--r--library/core/src/slice/mod.rs11
-rw-r--r--library/core/src/time.rs37
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/fs.rs67
-rw-r--r--library/std/src/io/mod.rs4
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/sys/solid/fs.rs20
-rw-r--r--library/std/src/sys/unix/fs.rs85
-rw-r--r--library/std/src/sys/unix/mod.rs4
-rw-r--r--library/std/src/sys/windows/c.rs3
-rw-r--r--library/std/src/sys/windows/io.rs11
-rw-r--r--library/std/src/time.rs4
-rw-r--r--library/test/src/console.rs2
-rw-r--r--library/test/src/lib.rs17
-rw-r--r--library/test/src/term.rs2
-rw-r--r--library/test/src/term/win.rs7
-rw-r--r--library/test/src/tests.rs27
-rw-r--r--src/bootstrap/compile.rs38
-rw-r--r--src/bootstrap/config.rs30
-rw-r--r--src/ci/docker/README.md86
-rw-r--r--src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile43
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-mips-linux/build-mips-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.config740
-rw-r--r--src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0001-MIPS-SPARC-fix-wrong-vfork-aliases-in-libpthread.so.patch44
-rw-r--r--src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0002-MIPS-SPARC-more-fixes-to-the-vfork-aliases-in-libpth.patch63
-rw-r--r--src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile44
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.config741
-rw-r--r--src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile43
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config741
-rw-r--r--src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile44
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config740
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile3
-rw-r--r--src/doc/unstable-book/src/compiler-flags/dylib-lto.md4
-rw-r--r--src/librustdoc/clean/blanket_impl.rs196
-rw-r--r--src/librustdoc/clean/mod.rs85
-rw-r--r--src/librustdoc/core.rs17
-rw-r--r--src/librustdoc/doctest.rs3
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css22
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links/early.rs32
m---------src/llvm-project0
-rw-r--r--src/test/codegen/deduced-param-attrs.rs60
-rw-r--r--src/test/codegen/function-arguments.rs2
-rw-r--r--src/test/pretty/tests-are-sorted.pp69
-rw-r--r--src/test/pretty/tests-are-sorted.rs13
-rw-r--r--src/test/rustdoc-gui/docblock-details.goml11
-rw-r--r--src/test/rustdoc-gui/headings.goml176
-rw-r--r--src/test/rustdoc-gui/jump-to-def-background.goml55
-rw-r--r--src/test/rustdoc-gui/src/test_docs/lib.rs12
-rw-r--r--src/test/rustdoc-ui/z-help.stdout1
-rw-r--r--src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html1
-rw-r--r--src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html1
-rw-r--r--src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html (renamed from src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out9.html)0
-rw-r--r--src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs (renamed from src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.rs)15
-rw-r--r--src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out0.html1
-rw-r--r--src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs (renamed from src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds_with_bindings.rs)1
-rw-r--r--src/test/rustdoc/inline_cross/auxiliary/issue-24183.rs14
-rw-r--r--src/test/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html1
-rw-r--r--src/test/rustdoc/inline_cross/issue-24183.rs18
-rw-r--r--src/test/rustdoc/not-wf-ambiguous-normalization.rs24
-rw-r--r--src/test/ui-fulldeps/fluent-messages/test.rs5
-rw-r--r--src/test/ui-fulldeps/fluent-messages/test.stderr29
-rw-r--r--src/test/ui-fulldeps/internal-lints/diagnostics.rs10
-rw-r--r--src/test/ui-fulldeps/internal-lints/diagnostics.stderr2
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs272
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr202
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs106
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr72
-rw-r--r--src/test/ui/associated-type-bounds/inside-adt.rs4
-rw-r--r--src/test/ui/associated-type-bounds/inside-adt.stderr10
-rw-r--r--src/test/ui/associated-types/issue-87261.rs6
-rw-r--r--src/test/ui/associated-types/issue-87261.stderr18
-rw-r--r--src/test/ui/borrowck/issue-23338-params-outlive-temps-of-body.rs (renamed from src/test/ui/issues/issue-23338-params-outlive-temps-of-body.rs)0
-rw-r--r--src/test/ui/closures/issue-97607.rs12
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr8
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr8
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs1
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/function-call.rs1
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/function-call.stderr2
-rw-r--r--src/test/ui/const-generics/min_const_generics/complex-expression.rs1
-rw-r--r--src/test/ui/const-generics/min_const_generics/complex-expression.stderr16
-rw-r--r--src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs1
-rw-r--r--src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr6
-rw-r--r--src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr20
-rw-r--r--src/test/ui/consts/issue-25826.stderr4
-rw-r--r--src/test/ui/consts/issue-94675.stderr4
-rw-r--r--src/test/ui/drop/issue-23338-ensure-param-drop-order.rs (renamed from src/test/ui/issues/issue-23338-ensure-param-drop-order.rs)0
-rw-r--r--src/test/ui/dropck/issue-24805-dropck-itemless.rs (renamed from src/test/ui/issues/issue-24805-dropck-itemless.rs)0
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-89008.stderr19
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-91762.rs2
-rw-r--r--src/test/ui/generic-associated-types/issue-89008.rs (renamed from src/test/ui/generic-associated-types/bugs/issue-89008.rs)28
-rw-r--r--src/test/ui/impl-trait/hidden-lifetimes.stderr4
-rw-r--r--src/test/ui/impl-trait/in-trait/default-body-type-err-2.rs13
-rw-r--r--src/test/ui/impl-trait/in-trait/default-body-type-err-2.stderr11
-rw-r--r--src/test/ui/impl-trait/in-trait/default-body-type-err.rs13
-rw-r--r--src/test/ui/impl-trait/in-trait/default-body-type-err.stderr12
-rw-r--r--src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs2
-rw-r--r--src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr12
-rw-r--r--src/test/ui/impl-trait/issue-103181-1.rs85
-rw-r--r--src/test/ui/impl-trait/issue-103181-1.stderr12
-rw-r--r--src/test/ui/impl-trait/issue-103181-2.rs29
-rw-r--r--src/test/ui/impl-trait/issue-103181-2.stderr9
-rw-r--r--src/test/ui/inference/char-as-str-single.fixed1
-rw-r--r--src/test/ui/inference/char-as-str-single.rs1
-rw-r--r--src/test/ui/inference/char-as-str-single.stderr15
-rw-r--r--src/test/ui/inference/issue-36053.rs (renamed from src/test/ui/issues/issue-36053.rs)0
-rw-r--r--src/test/ui/inference/str-as-char.fixed4
-rw-r--r--src/test/ui/inference/str-as-char.rs4
-rw-r--r--src/test/ui/inference/str-as-char.stderr24
-rw-r--r--src/test/ui/let-else/let-else-non-diverging.rs2
-rw-r--r--src/test/ui/lint/invalid_value.rs7
-rw-r--r--src/test/ui/lint/invalid_value.stderr113
-rw-r--r--src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr42
-rw-r--r--src/test/ui/parser/issues/issue-93282.rs1
-rw-r--r--src/test/ui/parser/issues/issue-93282.stderr27
-rw-r--r--src/test/ui/parser/label-is-actually-char.rs16
-rw-r--r--src/test/ui/parser/label-is-actually-char.stderr46
-rw-r--r--src/test/ui/parser/numeric-lifetime.stderr16
-rw-r--r--src/test/ui/parser/require-parens-for-chained-comparison.rs2
-rw-r--r--src/test/ui/parser/require-parens-for-chained-comparison.stderr16
-rw-r--r--src/test/ui/parser/semi-after-closure-in-macro.rs14
-rw-r--r--src/test/ui/privacy/access_levels.rs1
-rw-r--r--src/test/ui/privacy/access_levels.stderr8
-rw-r--r--src/test/ui/return/issue-64620.rs (renamed from src/test/ui/issues/issue-64620.rs)0
-rw-r--r--src/test/ui/return/issue-64620.stderr (renamed from src/test/ui/issues/issue-64620.stderr)0
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr1
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr65
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs12
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr65
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop.rs2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs17
-rw-r--r--src/test/ui/structs-enums/issue-2718-a.rs (renamed from src/test/ui/issues/issue-2718-a.rs)0
-rw-r--r--src/test/ui/structs-enums/issue-2718-a.stderr (renamed from src/test/ui/issues/issue-2718-a.stderr)0
-rw-r--r--src/test/ui/suggestions/issue-103112.rs4
-rw-r--r--src/test/ui/suggestions/issue-103112.stderr15
-rw-r--r--src/test/ui/suggestions/suggest-let-for-assignment.fixed17
-rw-r--r--src/test/ui/suggestions/suggest-let-for-assignment.rs17
-rw-r--r--src/test/ui/suggestions/suggest-let-for-assignment.stderr60
-rw-r--r--src/test/ui/traits/issue-33140-hack-boundaries.stderr17
-rw-r--r--src/test/ui/traits/object/issue-33140-traitobject-crate.stderr53
-rw-r--r--src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs (renamed from src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.rs)0
-rw-r--r--src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr (renamed from src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.stderr)2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs16
-rw-r--r--src/tools/compiletest/src/main.rs2
-rw-r--r--src/tools/tidy/src/deps.rs2
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
353 files changed, 9084 insertions, 4060 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 34d7f606645..0e23c118349 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1843,9 +1843,9 @@ dependencies = [
 
 [[package]]
 name = "itertools"
-version = "0.10.1"
+version = "0.10.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
 dependencies = [
  "either",
 ]
@@ -1935,9 +1935,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 [[package]]
 name = "libc"
-version = "0.2.131"
+version = "0.2.135"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40"
+checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -4475,9 +4475,9 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.143"
+version = "1.0.147"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"
+checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
 dependencies = [
  "serde_derive",
 ]
@@ -4494,9 +4494,9 @@ dependencies = [
 
 [[package]]
 name = "serde_derive"
-version = "1.0.143"
+version = "1.0.147"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"
+checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4980,16 +4980,26 @@ dependencies = [
 ]
 
 [[package]]
+name = "toml_datetime"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "808b51e57d0ef8f71115d8f3a01e7d3750d01c79cac4b3eda910f4389fdf92fd"
+dependencies = [
+ "serde",
+]
+
+[[package]]
 name = "toml_edit"
-version = "0.14.3"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba98375fd631b83696f87c64e4ed8e29e6a1f3404d6aed95fa95163bad38e705"
+checksum = "b1541ba70885967e662f69d31ab3aeca7b1aaecfcd58679590b893e9239c3646"
 dependencies = [
  "combine",
  "indexmap",
  "itertools",
  "kstring",
  "serde",
+ "toml_datetime",
 ]
 
 [[package]]
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 17ca1aa7fe1..157f46501e1 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -3,7 +3,7 @@ use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::generic_type_with_parentheses, code = "E0214")]
+#[diag(ast_lowering_generic_type_with_parentheses, code = "E0214")]
 pub struct GenericTypeWithParentheses {
     #[primary_span]
     #[label]
@@ -13,7 +13,7 @@ pub struct GenericTypeWithParentheses {
 }
 
 #[derive(Clone, Copy, Subdiagnostic)]
-#[multipart_suggestion(ast_lowering::use_angle_brackets, applicability = "maybe-incorrect")]
+#[multipart_suggestion(ast_lowering_use_angle_brackets, applicability = "maybe-incorrect")]
 pub struct UseAngleBrackets {
     #[suggestion_part(code = "<")]
     pub open_param: Span,
@@ -22,7 +22,7 @@ pub struct UseAngleBrackets {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_lowering::invalid_abi, code = "E0703")]
+#[diag(ast_lowering_invalid_abi, code = "E0703")]
 #[note]
 pub struct InvalidAbi {
     #[primary_span]
@@ -36,7 +36,7 @@ pub struct InvalidAbi {
 
 #[derive(Subdiagnostic)]
 #[suggestion(
-    ast_lowering::invalid_abi_suggestion,
+    ast_lowering_invalid_abi_suggestion,
     code = "{suggestion}",
     applicability = "maybe-incorrect"
 )]
@@ -47,7 +47,7 @@ pub struct InvalidAbiSuggestion {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::assoc_ty_parentheses)]
+#[diag(ast_lowering_assoc_ty_parentheses)]
 pub struct AssocTyParentheses {
     #[primary_span]
     pub span: Span,
@@ -57,12 +57,12 @@ pub struct AssocTyParentheses {
 
 #[derive(Clone, Copy, Subdiagnostic)]
 pub enum AssocTyParenthesesSub {
-    #[multipart_suggestion(ast_lowering::remove_parentheses)]
+    #[multipart_suggestion(ast_lowering_remove_parentheses)]
     Empty {
         #[suggestion_part(code = "")]
         parentheses_span: Span,
     },
-    #[multipart_suggestion(ast_lowering::use_angle_brackets)]
+    #[multipart_suggestion(ast_lowering_use_angle_brackets)]
     NotEmpty {
         #[suggestion_part(code = "<")]
         open_param: Span,
@@ -72,7 +72,7 @@ pub enum AssocTyParenthesesSub {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_lowering::misplaced_impl_trait, code = "E0562")]
+#[diag(ast_lowering_misplaced_impl_trait, code = "E0562")]
 pub struct MisplacedImplTrait<'a> {
     #[primary_span]
     pub span: Span,
@@ -80,14 +80,14 @@ pub struct MisplacedImplTrait<'a> {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::rustc_box_attribute_error)]
+#[diag(ast_lowering_rustc_box_attribute_error)]
 pub struct RustcBoxAttributeError {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::underscore_expr_lhs_assign)]
+#[diag(ast_lowering_underscore_expr_lhs_assign)]
 pub struct UnderscoreExprLhsAssign {
     #[primary_span]
     #[label]
@@ -95,7 +95,7 @@ pub struct UnderscoreExprLhsAssign {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::base_expression_double_dot)]
+#[diag(ast_lowering_base_expression_double_dot)]
 pub struct BaseExpressionDoubleDot {
     #[primary_span]
     #[label]
@@ -103,24 +103,24 @@ pub struct BaseExpressionDoubleDot {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::await_only_in_async_fn_and_blocks, code = "E0728")]
+#[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = "E0728")]
 pub struct AwaitOnlyInAsyncFnAndBlocks {
     #[primary_span]
     #[label]
     pub dot_await_span: Span,
-    #[label(ast_lowering::this_not_async)]
+    #[label(ast_lowering_this_not_async)]
     pub item_span: Option<Span>,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::generator_too_many_parameters, code = "E0628")]
+#[diag(ast_lowering_generator_too_many_parameters, code = "E0628")]
 pub struct GeneratorTooManyParameters {
     #[primary_span]
     pub fn_decl_span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::closure_cannot_be_static, code = "E0697")]
+#[diag(ast_lowering_closure_cannot_be_static, code = "E0697")]
 pub struct ClosureCannotBeStatic {
     #[primary_span]
     pub fn_decl_span: Span,
@@ -128,14 +128,14 @@ pub struct ClosureCannotBeStatic {
 
 #[derive(Diagnostic, Clone, Copy)]
 #[help]
-#[diag(ast_lowering::async_non_move_closure_not_supported, code = "E0708")]
+#[diag(ast_lowering_async_non_move_closure_not_supported, code = "E0708")]
 pub struct AsyncNonMoveClosureNotSupported {
     #[primary_span]
     pub fn_decl_span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::functional_record_update_destructuring_assignment)]
+#[diag(ast_lowering_functional_record_update_destructuring_assignment)]
 pub struct FunctionalRecordUpdateDestructuringAssignemnt {
     #[primary_span]
     #[suggestion(code = "", applicability = "machine-applicable")]
@@ -143,28 +143,28 @@ pub struct FunctionalRecordUpdateDestructuringAssignemnt {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::async_generators_not_supported, code = "E0727")]
+#[diag(ast_lowering_async_generators_not_supported, code = "E0727")]
 pub struct AsyncGeneratorsNotSupported {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::inline_asm_unsupported_target, code = "E0472")]
+#[diag(ast_lowering_inline_asm_unsupported_target, code = "E0472")]
 pub struct InlineAsmUnsupportedTarget {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::att_syntax_only_x86)]
+#[diag(ast_lowering_att_syntax_only_x86)]
 pub struct AttSyntaxOnlyX86 {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::abi_specified_multiple_times)]
+#[diag(ast_lowering_abi_specified_multiple_times)]
 pub struct AbiSpecifiedMultipleTimes {
     #[primary_span]
     pub abi_span: Span,
@@ -176,7 +176,7 @@ pub struct AbiSpecifiedMultipleTimes {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::clobber_abi_not_supported)]
+#[diag(ast_lowering_clobber_abi_not_supported)]
 pub struct ClobberAbiNotSupported {
     #[primary_span]
     pub abi_span: Span,
@@ -184,7 +184,7 @@ pub struct ClobberAbiNotSupported {
 
 #[derive(Diagnostic)]
 #[note]
-#[diag(ast_lowering::invalid_abi_clobber_abi)]
+#[diag(ast_lowering_invalid_abi_clobber_abi)]
 pub struct InvalidAbiClobberAbi {
     #[primary_span]
     pub abi_span: Span,
@@ -192,7 +192,7 @@ pub struct InvalidAbiClobberAbi {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::invalid_register)]
+#[diag(ast_lowering_invalid_register)]
 pub struct InvalidRegister<'a> {
     #[primary_span]
     pub op_span: Span,
@@ -201,7 +201,7 @@ pub struct InvalidRegister<'a> {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::invalid_register_class)]
+#[diag(ast_lowering_invalid_register_class)]
 pub struct InvalidRegisterClass<'a> {
     #[primary_span]
     pub op_span: Span,
@@ -210,12 +210,12 @@ pub struct InvalidRegisterClass<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_lowering::invalid_asm_template_modifier_reg_class)]
+#[diag(ast_lowering_invalid_asm_template_modifier_reg_class)]
 pub struct InvalidAsmTemplateModifierRegClass {
     #[primary_span]
-    #[label(ast_lowering::template_modifier)]
+    #[label(ast_lowering_template_modifier)]
     pub placeholder_span: Span,
-    #[label(ast_lowering::argument)]
+    #[label(ast_lowering_argument)]
     pub op_span: Span,
     #[subdiagnostic]
     pub sub: InvalidAsmTemplateModifierRegClassSub,
@@ -223,34 +223,34 @@ pub struct InvalidAsmTemplateModifierRegClass {
 
 #[derive(Subdiagnostic)]
 pub enum InvalidAsmTemplateModifierRegClassSub {
-    #[note(ast_lowering::support_modifiers)]
+    #[note(ast_lowering_support_modifiers)]
     SupportModifier { class_name: Symbol, modifiers: String },
-    #[note(ast_lowering::does_not_support_modifiers)]
+    #[note(ast_lowering_does_not_support_modifiers)]
     DoesNotSupportModifier { class_name: Symbol },
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::invalid_asm_template_modifier_const)]
+#[diag(ast_lowering_invalid_asm_template_modifier_const)]
 pub struct InvalidAsmTemplateModifierConst {
     #[primary_span]
-    #[label(ast_lowering::template_modifier)]
+    #[label(ast_lowering_template_modifier)]
     pub placeholder_span: Span,
-    #[label(ast_lowering::argument)]
+    #[label(ast_lowering_argument)]
     pub op_span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::invalid_asm_template_modifier_sym)]
+#[diag(ast_lowering_invalid_asm_template_modifier_sym)]
 pub struct InvalidAsmTemplateModifierSym {
     #[primary_span]
-    #[label(ast_lowering::template_modifier)]
+    #[label(ast_lowering_template_modifier)]
     pub placeholder_span: Span,
-    #[label(ast_lowering::argument)]
+    #[label(ast_lowering_argument)]
     pub op_span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::register_class_only_clobber)]
+#[diag(ast_lowering_register_class_only_clobber)]
 pub struct RegisterClassOnlyClobber {
     #[primary_span]
     pub op_span: Span,
@@ -258,12 +258,12 @@ pub struct RegisterClassOnlyClobber {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::register_conflict)]
+#[diag(ast_lowering_register_conflict)]
 pub struct RegisterConflict<'a> {
     #[primary_span]
-    #[label(ast_lowering::register1)]
+    #[label(ast_lowering_register1)]
     pub op_span1: Span,
-    #[label(ast_lowering::register2)]
+    #[label(ast_lowering_register2)]
     pub op_span2: Span,
     pub reg1_name: &'a str,
     pub reg2_name: &'a str,
@@ -273,12 +273,12 @@ pub struct RegisterConflict<'a> {
 
 #[derive(Diagnostic, Clone, Copy)]
 #[help]
-#[diag(ast_lowering::sub_tuple_binding)]
+#[diag(ast_lowering_sub_tuple_binding)]
 pub struct SubTupleBinding<'a> {
     #[primary_span]
     #[label]
     #[suggestion_verbose(
-        ast_lowering::sub_tuple_binding_suggestion,
+        ast_lowering_sub_tuple_binding_suggestion,
         code = "..",
         applicability = "maybe-incorrect"
     )]
@@ -289,56 +289,56 @@ pub struct SubTupleBinding<'a> {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::extra_double_dot)]
+#[diag(ast_lowering_extra_double_dot)]
 pub struct ExtraDoubleDot<'a> {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label(ast_lowering::previously_used_here)]
+    #[label(ast_lowering_previously_used_here)]
     pub prev_span: Span,
     pub ctx: &'a str,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
 #[note]
-#[diag(ast_lowering::misplaced_double_dot)]
+#[diag(ast_lowering_misplaced_double_dot)]
 pub struct MisplacedDoubleDot {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::misplaced_relax_trait_bound)]
+#[diag(ast_lowering_misplaced_relax_trait_bound)]
 pub struct MisplacedRelaxTraitBound {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::not_supported_for_lifetime_binder_async_closure)]
+#[diag(ast_lowering_not_supported_for_lifetime_binder_async_closure)]
 pub struct NotSupportedForLifetimeBinderAsyncClosure {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::arbitrary_expression_in_pattern)]
+#[diag(ast_lowering_arbitrary_expression_in_pattern)]
 pub struct ArbitraryExpressionInPattern {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::inclusive_range_with_no_end)]
+#[diag(ast_lowering_inclusive_range_with_no_end)]
 pub struct InclusiveRangeWithNoEnd {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering::trait_fn_async, code = "E0706")]
+#[diag(ast_lowering_trait_fn_async, code = "E0706")]
 #[note]
-#[note(ast_lowering::note2)]
+#[note(note2)]
 pub struct TraitFnAsync {
     #[primary_span]
     pub fn_span: Span,
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 7865c523f75..03664324404 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -170,7 +170,7 @@ impl<'a> AstValidator<'a> {
                 DEPRECATED_WHERE_CLAUSE_LOCATION,
                 id,
                 where_clauses.0.1,
-                fluent::ast_passes::deprecated_where_clause_location,
+                fluent::ast_passes_deprecated_where_clause_location,
                 BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
                     where_clauses.1.1.shrink_to_hi(),
                     suggestion,
@@ -252,20 +252,6 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    fn visit_struct_field_def(&mut self, field: &'a FieldDef) {
-        if let Some(ident) = field.ident {
-            if ident.name == kw::Underscore {
-                self.visit_vis(&field.vis);
-                self.visit_ident(ident);
-                self.visit_ty_common(&field.ty);
-                self.walk_ty(&field.ty);
-                walk_list!(self, visit_attribute, &field.attrs);
-                return;
-            }
-        }
-        self.visit_field_def(field);
-    }
-
     fn err_handler(&self) -> &rustc_errors::Handler {
         &self.session.diagnostic()
     }
@@ -1006,8 +992,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         visit::walk_lifetime(self, lifetime);
     }
 
-    fn visit_field_def(&mut self, s: &'a FieldDef) {
-        visit::walk_field_def(self, s)
+    fn visit_field_def(&mut self, field: &'a FieldDef) {
+        visit::walk_field_def(self, field)
     }
 
     fn visit_item(&mut self, item: &'a Item) {
@@ -1195,42 +1181,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     self.check_mod_file_item_asciionly(item.ident);
                 }
             }
-            ItemKind::Struct(ref vdata, ref generics) => match vdata {
-                // Duplicating the `Visitor` logic allows catching all cases
-                // of `Anonymous(Struct, Union)` outside of a field struct or union.
-                //
-                // Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it
-                // encounters, and only on `ItemKind::Struct` and `ItemKind::Union`
-                // it uses `visit_ty_common`, which doesn't contain that specific check.
-                VariantData::Struct(ref fields, ..) => {
-                    self.visit_vis(&item.vis);
-                    self.visit_ident(item.ident);
-                    self.visit_generics(generics);
-                    self.with_banned_assoc_ty_bound(|this| {
-                        walk_list!(this, visit_struct_field_def, fields);
-                    });
-                    walk_list!(self, visit_attribute, &item.attrs);
-                    return;
-                }
-                _ => {}
-            },
-            ItemKind::Union(ref vdata, ref generics) => {
+            ItemKind::Union(ref vdata, ..) => {
                 if vdata.fields().is_empty() {
                     self.err_handler().span_err(item.span, "unions cannot have zero fields");
                 }
-                match vdata {
-                    VariantData::Struct(ref fields, ..) => {
-                        self.visit_vis(&item.vis);
-                        self.visit_ident(item.ident);
-                        self.visit_generics(generics);
-                        self.with_banned_assoc_ty_bound(|this| {
-                            walk_list!(this, visit_struct_field_def, fields);
-                        });
-                        walk_list!(self, visit_attribute, &item.attrs);
-                        return;
-                    }
-                    _ => {}
-                }
             }
             ItemKind::Const(def, .., None) => {
                 self.check_defaultness(item.span, def);
@@ -1811,12 +1765,12 @@ pub(crate) enum ForbiddenLetReason {
     /// `let` is not valid and the source environment is not important
     GenericForbidden,
     /// A let chain with the `||` operator
-    #[note(ast_passes::not_supported_or)]
+    #[note(not_supported_or)]
     NotSupportedOr(#[primary_span] Span),
     /// A let chain with invalid parentheses
     ///
     /// For example, `let 1 = 1 && (expr && expr)` is allowed
     /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
-    #[note(ast_passes::not_supported_parentheses)]
+    #[note(not_supported_parentheses)]
     NotSupportedParentheses(#[primary_span] Span),
 }
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 8319352bd24..59f582f10d9 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -7,7 +7,7 @@ use rustc_span::{Span, Symbol};
 use crate::ast_validation::ForbiddenLetReason;
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::forbidden_let)]
+#[diag(ast_passes_forbidden_let)]
 #[note]
 pub struct ForbiddenLet {
     #[primary_span]
@@ -17,7 +17,7 @@ pub struct ForbiddenLet {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::forbidden_let_stable)]
+#[diag(ast_passes_forbidden_let_stable)]
 #[note]
 pub struct ForbiddenLetStable {
     #[primary_span]
@@ -25,21 +25,21 @@ pub struct ForbiddenLetStable {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::forbidden_assoc_constraint)]
+#[diag(ast_passes_forbidden_assoc_constraint)]
 pub struct ForbiddenAssocConstraint {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::keyword_lifetime)]
+#[diag(ast_passes_keyword_lifetime)]
 pub struct KeywordLifetime {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::invalid_label)]
+#[diag(ast_passes_invalid_label)]
 pub struct InvalidLabel {
     #[primary_span]
     pub span: Span,
@@ -47,11 +47,11 @@ pub struct InvalidLabel {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::invalid_visibility, code = "E0449")]
+#[diag(ast_passes_invalid_visibility, code = "E0449")]
 pub struct InvalidVisibility {
     #[primary_span]
     pub span: Span,
-    #[label(ast_passes::implied)]
+    #[label(implied)]
     pub implied: Option<Span>,
     #[subdiagnostic]
     pub note: Option<InvalidVisibilityNote>,
@@ -59,14 +59,14 @@ pub struct InvalidVisibility {
 
 #[derive(Subdiagnostic)]
 pub enum InvalidVisibilityNote {
-    #[note(ast_passes::individual_impl_items)]
+    #[note(individual_impl_items)]
     IndividualImplItems,
-    #[note(ast_passes::individual_foreign_items)]
+    #[note(individual_foreign_items)]
     IndividualForeignItems,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::trait_fn_const, code = "E0379")]
+#[diag(ast_passes_trait_fn_const, code = "E0379")]
 pub struct TraitFnConst {
     #[primary_span]
     #[label]
@@ -74,21 +74,21 @@ pub struct TraitFnConst {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::forbidden_lifetime_bound)]
+#[diag(ast_passes_forbidden_lifetime_bound)]
 pub struct ForbiddenLifetimeBound {
     #[primary_span]
     pub spans: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::forbidden_non_lifetime_param)]
+#[diag(ast_passes_forbidden_non_lifetime_param)]
 pub struct ForbiddenNonLifetimeParam {
     #[primary_span]
     pub spans: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::fn_param_too_many)]
+#[diag(ast_passes_fn_param_too_many)]
 pub struct FnParamTooMany {
     #[primary_span]
     pub span: Span,
@@ -96,21 +96,21 @@ pub struct FnParamTooMany {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::fn_param_c_var_args_only)]
+#[diag(ast_passes_fn_param_c_var_args_only)]
 pub struct FnParamCVarArgsOnly {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::fn_param_c_var_args_not_last)]
+#[diag(ast_passes_fn_param_c_var_args_not_last)]
 pub struct FnParamCVarArgsNotLast {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::fn_param_doc_comment)]
+#[diag(ast_passes_fn_param_doc_comment)]
 pub struct FnParamDocComment {
     #[primary_span]
     #[label]
@@ -118,14 +118,14 @@ pub struct FnParamDocComment {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::fn_param_forbidden_attr)]
+#[diag(ast_passes_fn_param_forbidden_attr)]
 pub struct FnParamForbiddenAttr {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::fn_param_forbidden_self)]
+#[diag(ast_passes_fn_param_forbidden_self)]
 #[note]
 pub struct FnParamForbiddenSelf {
     #[primary_span]
@@ -134,7 +134,7 @@ pub struct FnParamForbiddenSelf {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::forbidden_default)]
+#[diag(ast_passes_forbidden_default)]
 pub struct ForbiddenDefault {
     #[primary_span]
     pub span: Span,
@@ -143,7 +143,7 @@ pub struct ForbiddenDefault {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::assoc_const_without_body)]
+#[diag(ast_passes_assoc_const_without_body)]
 pub struct AssocConstWithoutBody {
     #[primary_span]
     pub span: Span,
@@ -152,7 +152,7 @@ pub struct AssocConstWithoutBody {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::assoc_fn_without_body)]
+#[diag(ast_passes_assoc_fn_without_body)]
 pub struct AssocFnWithoutBody {
     #[primary_span]
     pub span: Span,
@@ -161,7 +161,7 @@ pub struct AssocFnWithoutBody {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::assoc_type_without_body)]
+#[diag(ast_passes_assoc_type_without_body)]
 pub struct AssocTypeWithoutBody {
     #[primary_span]
     pub span: Span,
@@ -170,7 +170,7 @@ pub struct AssocTypeWithoutBody {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::const_without_body)]
+#[diag(ast_passes_const_without_body)]
 pub struct ConstWithoutBody {
     #[primary_span]
     pub span: Span,
@@ -179,7 +179,7 @@ pub struct ConstWithoutBody {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::static_without_body)]
+#[diag(ast_passes_static_without_body)]
 pub struct StaticWithoutBody {
     #[primary_span]
     pub span: Span,
@@ -188,7 +188,7 @@ pub struct StaticWithoutBody {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::ty_alias_without_body)]
+#[diag(ast_passes_ty_alias_without_body)]
 pub struct TyAliasWithoutBody {
     #[primary_span]
     pub span: Span,
@@ -197,7 +197,7 @@ pub struct TyAliasWithoutBody {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes::fn_without_body)]
+#[diag(ast_passes_fn_without_body)]
 pub struct FnWithoutBody {
     #[primary_span]
     pub span: Span,
@@ -226,7 +226,7 @@ impl AddToDiagnostic for ExternBlockSuggestion {
         let end_suggestion = " }".to_owned();
 
         diag.multipart_suggestion(
-            fluent::ast_passes::extern_block_suggestion,
+            fluent::extern_block_suggestion,
             vec![(self.start_span, start_suggestion), (self.end_span, end_suggestion)],
             Applicability::MaybeIncorrect,
         );
diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs
index d3e9a16a9a8..edccfa1c8ff 100644
--- a/compiler/rustc_attr/src/session_diagnostics.rs
+++ b/compiler/rustc_attr/src/session_diagnostics.rs
@@ -10,14 +10,14 @@ use rustc_span::{Span, Symbol};
 use crate::UnsupportedLiteralReason;
 
 #[derive(Diagnostic)]
-#[diag(attr::expected_one_cfg_pattern, code = "E0536")]
+#[diag(attr_expected_one_cfg_pattern, code = "E0536")]
 pub(crate) struct ExpectedOneCfgPattern {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::invalid_predicate, code = "E0537")]
+#[diag(attr_invalid_predicate, code = "E0537")]
 pub(crate) struct InvalidPredicate {
     #[primary_span]
     pub span: Span,
@@ -26,7 +26,7 @@ pub(crate) struct InvalidPredicate {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::multiple_item, code = "E0538")]
+#[diag(attr_multiple_item, code = "E0538")]
 pub(crate) struct MultipleItem {
     #[primary_span]
     pub span: Span,
@@ -35,7 +35,7 @@ pub(crate) struct MultipleItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::incorrect_meta_item, code = "E0539")]
+#[diag(attr_incorrect_meta_item, code = "E0539")]
 pub(crate) struct IncorrectMetaItem {
     #[primary_span]
     pub span: Span,
@@ -54,39 +54,39 @@ impl<'a> IntoDiagnostic<'a> for UnknownMetaItem<'_> {
         let expected = self.expected.iter().map(|name| format!("`{}`", name)).collect::<Vec<_>>();
         let mut diag = handler.struct_span_err_with_code(
             self.span,
-            fluent::attr::unknown_meta_item,
+            fluent::attr_unknown_meta_item,
             error_code!(E0541),
         );
         diag.set_arg("item", self.item);
         diag.set_arg("expected", expected.join(", "));
-        diag.span_label(self.span, fluent::attr::label);
+        diag.span_label(self.span, fluent::label);
         diag
     }
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::missing_since, code = "E0542")]
+#[diag(attr_missing_since, code = "E0542")]
 pub(crate) struct MissingSince {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::missing_note, code = "E0543")]
+#[diag(attr_missing_note, code = "E0543")]
 pub(crate) struct MissingNote {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::multiple_stability_levels, code = "E0544")]
+#[diag(attr_multiple_stability_levels, code = "E0544")]
 pub(crate) struct MultipleStabilityLevels {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::invalid_issue_string, code = "E0545")]
+#[diag(attr_invalid_issue_string, code = "E0545")]
 pub(crate) struct InvalidIssueString {
     #[primary_span]
     pub span: Span,
@@ -99,31 +99,31 @@ pub(crate) struct InvalidIssueString {
 // translatable.
 #[derive(Subdiagnostic)]
 pub(crate) enum InvalidIssueStringCause {
-    #[label(attr::must_not_be_zero)]
+    #[label(must_not_be_zero)]
     MustNotBeZero {
         #[primary_span]
         span: Span,
     },
 
-    #[label(attr::empty)]
+    #[label(empty)]
     Empty {
         #[primary_span]
         span: Span,
     },
 
-    #[label(attr::invalid_digit)]
+    #[label(invalid_digit)]
     InvalidDigit {
         #[primary_span]
         span: Span,
     },
 
-    #[label(attr::pos_overflow)]
+    #[label(pos_overflow)]
     PosOverflow {
         #[primary_span]
         span: Span,
     },
 
-    #[label(attr::neg_overflow)]
+    #[label(neg_overflow)]
     NegOverflow {
         #[primary_span]
         span: Span,
@@ -144,21 +144,21 @@ impl InvalidIssueStringCause {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::missing_feature, code = "E0546")]
+#[diag(attr_missing_feature, code = "E0546")]
 pub(crate) struct MissingFeature {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::non_ident_feature, code = "E0546")]
+#[diag(attr_non_ident_feature, code = "E0546")]
 pub(crate) struct NonIdentFeature {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::missing_issue, code = "E0547")]
+#[diag(attr_missing_issue, code = "E0547")]
 pub(crate) struct MissingIssue {
     #[primary_span]
     pub span: Span,
@@ -167,7 +167,7 @@ pub(crate) struct MissingIssue {
 // FIXME: This diagnostic is identical to `IncorrectMetaItem`, barring the error code. Consider
 // changing this to `IncorrectMetaItem`. See #51489.
 #[derive(Diagnostic)]
-#[diag(attr::incorrect_meta_item, code = "E0551")]
+#[diag(attr_incorrect_meta_item, code = "E0551")]
 pub(crate) struct IncorrectMetaItem2 {
     #[primary_span]
     pub span: Span,
@@ -176,14 +176,14 @@ pub(crate) struct IncorrectMetaItem2 {
 // FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
 // It is more similar to `IncorrectReprFormatGeneric`.
 #[derive(Diagnostic)]
-#[diag(attr::incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")]
+#[diag(attr_incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")]
 pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::invalid_repr_hint_no_paren, code = "E0552")]
+#[diag(attr_invalid_repr_hint_no_paren, code = "E0552")]
 pub(crate) struct InvalidReprHintNoParen {
     #[primary_span]
     pub span: Span,
@@ -192,7 +192,7 @@ pub(crate) struct InvalidReprHintNoParen {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::invalid_repr_hint_no_value, code = "E0552")]
+#[diag(attr_invalid_repr_hint_no_value, code = "E0552")]
 pub(crate) struct InvalidReprHintNoValue {
     #[primary_span]
     pub span: Span,
@@ -213,13 +213,13 @@ impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral {
         let mut diag = handler.struct_span_err_with_code(
             self.span,
             match self.reason {
-                UnsupportedLiteralReason::Generic => fluent::attr::unsupported_literal_generic,
-                UnsupportedLiteralReason::CfgString => fluent::attr::unsupported_literal_cfg_string,
+                UnsupportedLiteralReason::Generic => fluent::attr_unsupported_literal_generic,
+                UnsupportedLiteralReason::CfgString => fluent::attr_unsupported_literal_cfg_string,
                 UnsupportedLiteralReason::DeprecatedString => {
-                    fluent::attr::unsupported_literal_deprecated_string
+                    fluent::attr_unsupported_literal_deprecated_string
                 }
                 UnsupportedLiteralReason::DeprecatedKvPair => {
-                    fluent::attr::unsupported_literal_deprecated_kv_pair
+                    fluent::attr_unsupported_literal_deprecated_kv_pair
                 }
             },
             error_code!(E0565),
@@ -227,7 +227,7 @@ impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral {
         if self.is_bytestr {
             diag.span_suggestion(
                 self.start_point_span,
-                fluent::attr::unsupported_literal_suggestion,
+                fluent::attr_unsupported_literal_suggestion,
                 "",
                 Applicability::MaybeIncorrect,
             );
@@ -237,7 +237,7 @@ impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::invalid_repr_align_need_arg, code = "E0589")]
+#[diag(attr_invalid_repr_align_need_arg, code = "E0589")]
 pub(crate) struct InvalidReprAlignNeedArg {
     #[primary_span]
     #[suggestion(code = "align(...)", applicability = "has-placeholders")]
@@ -245,7 +245,7 @@ pub(crate) struct InvalidReprAlignNeedArg {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::invalid_repr_generic, code = "E0589")]
+#[diag(attr_invalid_repr_generic, code = "E0589")]
 pub(crate) struct InvalidReprGeneric<'a> {
     #[primary_span]
     pub span: Span,
@@ -255,14 +255,14 @@ pub(crate) struct InvalidReprGeneric<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::incorrect_repr_format_align_one_arg, code = "E0693")]
+#[diag(attr_incorrect_repr_format_align_one_arg, code = "E0693")]
 pub(crate) struct IncorrectReprFormatAlignOneArg {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::incorrect_repr_format_generic, code = "E0693")]
+#[diag(attr_incorrect_repr_format_generic, code = "E0693")]
 pub(crate) struct IncorrectReprFormatGeneric<'a> {
     #[primary_span]
     pub span: Span,
@@ -275,7 +275,7 @@ pub(crate) struct IncorrectReprFormatGeneric<'a> {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum IncorrectReprFormatGenericCause<'a> {
-    #[suggestion(attr::suggestion, code = "{name}({int})", applicability = "machine-applicable")]
+    #[suggestion(suggestion, code = "{name}({int})", applicability = "machine-applicable")]
     Int {
         #[primary_span]
         span: Span,
@@ -287,11 +287,7 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> {
         int: u128,
     },
 
-    #[suggestion(
-        attr::suggestion,
-        code = "{name}({symbol})",
-        applicability = "machine-applicable"
-    )]
+    #[suggestion(suggestion, code = "{name}({symbol})", applicability = "machine-applicable")]
     Symbol {
         #[primary_span]
         span: Span,
@@ -317,28 +313,28 @@ impl<'a> IncorrectReprFormatGenericCause<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::rustc_promotable_pairing, code = "E0717")]
+#[diag(attr_rustc_promotable_pairing, code = "E0717")]
 pub(crate) struct RustcPromotablePairing {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::rustc_allowed_unstable_pairing, code = "E0789")]
+#[diag(attr_rustc_allowed_unstable_pairing, code = "E0789")]
 pub(crate) struct RustcAllowedUnstablePairing {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::cfg_predicate_identifier)]
+#[diag(attr_cfg_predicate_identifier)]
 pub(crate) struct CfgPredicateIdentifier {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::deprecated_item_suggestion)]
+#[diag(attr_deprecated_item_suggestion)]
 pub(crate) struct DeprecatedItemSuggestion {
     #[primary_span]
     pub span: Span,
@@ -351,21 +347,21 @@ pub(crate) struct DeprecatedItemSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::expected_single_version_literal)]
+#[diag(attr_expected_single_version_literal)]
 pub(crate) struct ExpectedSingleVersionLiteral {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::expected_version_literal)]
+#[diag(attr_expected_version_literal)]
 pub(crate) struct ExpectedVersionLiteral {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::expects_feature_list)]
+#[diag(attr_expects_feature_list)]
 pub(crate) struct ExpectsFeatureList {
     #[primary_span]
     pub span: Span,
@@ -374,7 +370,7 @@ pub(crate) struct ExpectsFeatureList {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::expects_features)]
+#[diag(attr_expects_features)]
 pub(crate) struct ExpectsFeatures {
     #[primary_span]
     pub span: Span,
@@ -383,14 +379,14 @@ pub(crate) struct ExpectsFeatures {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::soft_no_args)]
+#[diag(attr_soft_no_args)]
 pub(crate) struct SoftNoArgs {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr::unknown_version_literal)]
+#[diag(attr_unknown_version_literal)]
 pub(crate) struct UnknownVersionLiteral {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index ff667896eb1..cff3089c397 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -6,7 +6,7 @@ use rustc_span::Span;
 use crate::diagnostics::RegionName;
 
 #[derive(Diagnostic)]
-#[diag(borrowck::move_unsized, code = "E0161")]
+#[diag(borrowck_move_unsized, code = "E0161")]
 pub(crate) struct MoveUnsized<'tcx> {
     pub ty: Ty<'tcx>,
     #[primary_span]
@@ -15,7 +15,7 @@ pub(crate) struct MoveUnsized<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(borrowck::higher_ranked_lifetime_error)]
+#[diag(borrowck_higher_ranked_lifetime_error)]
 pub(crate) struct HigherRankedLifetimeError {
     #[subdiagnostic]
     pub cause: Option<HigherRankedErrorCause>,
@@ -25,21 +25,21 @@ pub(crate) struct HigherRankedLifetimeError {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum HigherRankedErrorCause {
-    #[note(borrowck::could_not_prove)]
+    #[note(borrowck_could_not_prove)]
     CouldNotProve { predicate: String },
-    #[note(borrowck::could_not_normalize)]
+    #[note(borrowck_could_not_normalize)]
     CouldNotNormalize { value: String },
 }
 
 #[derive(Diagnostic)]
-#[diag(borrowck::higher_ranked_subtype_error)]
+#[diag(borrowck_higher_ranked_subtype_error)]
 pub(crate) struct HigherRankedSubtypeError {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(borrowck::generic_does_not_live_long_enough)]
+#[diag(borrowck_generic_does_not_live_long_enough)]
 pub(crate) struct GenericDoesNotLiveLongEnough {
     pub kind: String,
     #[primary_span]
@@ -47,15 +47,15 @@ pub(crate) struct GenericDoesNotLiveLongEnough {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(borrowck::var_does_not_need_mut)]
+#[diag(borrowck_var_does_not_need_mut)]
 pub(crate) struct VarNeedNotMut {
     #[suggestion_short(applicability = "machine-applicable", code = "")]
     pub span: Span,
 }
 #[derive(Diagnostic)]
-#[diag(borrowck::var_cannot_escape_closure)]
+#[diag(borrowck_var_cannot_escape_closure)]
 #[note]
-#[note(borrowck::cannot_escape)]
+#[note(cannot_escape)]
 pub(crate) struct FnMutError {
     #[primary_span]
     pub span: Span,
@@ -65,17 +65,17 @@ pub(crate) struct FnMutError {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum VarHereDenote {
-    #[label(borrowck::var_here_captured)]
+    #[label(borrowck_var_here_captured)]
     Captured {
         #[primary_span]
         span: Span,
     },
-    #[label(borrowck::var_here_defined)]
+    #[label(borrowck_var_here_defined)]
     Defined {
         #[primary_span]
         span: Span,
     },
-    #[label(borrowck::closure_inferred_mut)]
+    #[label(borrowck_closure_inferred_mut)]
     FnMutInferred {
         #[primary_span]
         span: Span,
@@ -84,17 +84,17 @@ pub(crate) enum VarHereDenote {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum FnMutReturnTypeErr {
-    #[label(borrowck::returned_closure_escaped)]
+    #[label(borrowck_returned_closure_escaped)]
     ReturnClosure {
         #[primary_span]
         span: Span,
     },
-    #[label(borrowck::returned_async_block_escaped)]
+    #[label(borrowck_returned_async_block_escaped)]
     ReturnAsyncBlock {
         #[primary_span]
         span: Span,
     },
-    #[label(borrowck::returned_ref_escaped)]
+    #[label(borrowck_returned_ref_escaped)]
     ReturnRef {
         #[primary_span]
         span: Span,
@@ -102,7 +102,7 @@ pub(crate) enum FnMutReturnTypeErr {
 }
 
 #[derive(Diagnostic)]
-#[diag(borrowck::lifetime_constraints_error)]
+#[diag(borrowck_lifetime_constraints_error)]
 pub(crate) struct LifetimeOutliveErr {
     #[primary_span]
     pub span: Span,
@@ -110,7 +110,7 @@ pub(crate) struct LifetimeOutliveErr {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum LifetimeReturnCategoryErr<'a> {
-    #[label(borrowck::returned_lifetime_wrong)]
+    #[label(borrowck_returned_lifetime_wrong)]
     WrongReturn {
         #[primary_span]
         span: Span,
@@ -118,7 +118,7 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> {
         outlived_fr_name: RegionName,
         fr_name: &'a RegionName,
     },
-    #[label(borrowck::returned_lifetime_short)]
+    #[label(borrowck_returned_lifetime_short)]
     ShortReturn {
         #[primary_span]
         span: Span,
@@ -142,7 +142,7 @@ impl IntoDiagnosticArg for RegionName {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum RequireStaticErr {
-    #[note(borrowck::used_impl_require_static)]
+    #[note(borrowck_used_impl_require_static)]
     UsedImpl {
         #[primary_span]
         multi_span: MultiSpan,
diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs
index 46b54eae384..5638c2f6180 100644
--- a/compiler/rustc_builtin_macros/src/cfg.rs
+++ b/compiler/rustc_builtin_macros/src/cfg.rs
@@ -36,7 +36,7 @@ pub fn expand_cfg(
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros::requires_cfg_pattern)]
+#[diag(builtin_macros_requires_cfg_pattern)]
 struct RequiresCfgPattern {
     #[primary_span]
     #[label]
@@ -44,7 +44,7 @@ struct RequiresCfgPattern {
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros::expected_one_cfg_pattern)]
+#[diag(builtin_macros_expected_one_cfg_pattern)]
 struct OneCfgPattern {
     #[primary_span]
     span: Span,
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index 705141614e2..fee5d04cdae 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -36,13 +36,22 @@ pub fn expand_test_case(
     let sp = ecx.with_def_site_ctxt(attr_sp);
     let mut item = anno_item.expect_item();
     item = item.map(|mut item| {
+        let test_path_symbol = Symbol::intern(&item_path(
+            // skip the name of the root module
+            &ecx.current_expansion.module.mod_path[1..],
+            &item.ident,
+        ));
         item.vis = ast::Visibility {
             span: item.vis.span,
             kind: ast::VisibilityKind::Public,
             tokens: None,
         };
         item.ident.span = item.ident.span.with_ctxt(sp.ctxt());
-        item.attrs.push(ecx.attribute(ecx.meta_word(sp, sym::rustc_test_marker)));
+        item.attrs.push(ecx.attribute(attr::mk_name_value_item_str(
+            Ident::new(sym::rustc_test_marker, sp),
+            test_path_symbol,
+            sp,
+        )));
         item
     });
 
@@ -215,6 +224,12 @@ pub fn expand_test_or_bench(
         )
     };
 
+    let test_path_symbol = Symbol::intern(&item_path(
+        // skip the name of the root module
+        &cx.current_expansion.module.mod_path[1..],
+        &item.ident,
+    ));
+
     let mut test_const = cx.item(
         sp,
         Ident::new(item.ident.name, sp),
@@ -224,9 +239,14 @@ pub fn expand_test_or_bench(
                 Ident::new(sym::cfg, attr_sp),
                 vec![attr::mk_nested_word_item(Ident::new(sym::test, attr_sp))],
             )),
-            // #[rustc_test_marker]
-            cx.attribute(cx.meta_word(attr_sp, sym::rustc_test_marker)),
-        ],
+            // #[rustc_test_marker = "test_case_sort_key"]
+            cx.attribute(attr::mk_name_value_item_str(
+                Ident::new(sym::rustc_test_marker, attr_sp),
+                test_path_symbol,
+                attr_sp,
+            )),
+        ]
+        .into(),
         // const $ident: test::TestDescAndFn =
         ast::ItemKind::Const(
             ast::Defaultness::Final,
@@ -250,14 +270,7 @@ pub fn expand_test_or_bench(
                                         cx.expr_call(
                                             sp,
                                             cx.expr_path(test_path("StaticTestName")),
-                                            vec![cx.expr_str(
-                                                sp,
-                                                Symbol::intern(&item_path(
-                                                    // skip the name of the root module
-                                                    &cx.current_expansion.module.mod_path[1..],
-                                                    &item.ident,
-                                                )),
-                                            )],
+                                            vec![cx.expr_str(sp, test_path_symbol)],
                                         ),
                                     ),
                                     // ignore: true | false
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 561ca00c719..b8b8351a36f 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -18,9 +18,11 @@ use thin_vec::thin_vec;
 
 use std::{iter, mem};
 
+#[derive(Clone)]
 struct Test {
     span: Span,
     ident: Ident,
+    name: Symbol,
 }
 
 struct TestCtxt<'a> {
@@ -120,10 +122,10 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
 
     fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
         let mut item = i.into_inner();
-        if is_test_case(&self.cx.ext_cx.sess, &item) {
+        if let Some(name) = get_test_name(&self.cx.ext_cx.sess, &item) {
             debug!("this is a test item");
 
-            let test = Test { span: item.span, ident: item.ident };
+            let test = Test { span: item.span, ident: item.ident, name };
             self.tests.push(test);
         }
 
@@ -357,9 +359,12 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P<ast::Expr> {
     debug!("building test vector from {} tests", cx.test_cases.len());
     let ecx = &cx.ext_cx;
 
+    let mut tests = cx.test_cases.clone();
+    tests.sort_by(|a, b| a.name.as_str().cmp(&b.name.as_str()));
+
     ecx.expr_array_ref(
         sp,
-        cx.test_cases
+        tests
             .iter()
             .map(|test| {
                 ecx.expr_addr_of(test.span, ecx.expr_path(ecx.path(test.span, vec![test.ident])))
@@ -368,8 +373,8 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P<ast::Expr> {
     )
 }
 
-fn is_test_case(sess: &Session, i: &ast::Item) -> bool {
-    sess.contains_name(&i.attrs, sym::rustc_test_marker)
+fn get_test_name(sess: &Session, i: &ast::Item) -> Option<Symbol> {
+    sess.first_attr_value_str_by_name(&i.attrs, sym::rustc_test_marker)
 }
 
 fn get_test_runner(
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
index e8897e9ae81..5061010c86c 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
@@ -29,7 +29,11 @@ jobs:
       matrix:
         include:
           - os: ubuntu-latest
+            env:
+              TARGET_TRIPLE: x86_64-unknown-linux-gnu
           - os: macos-latest
+            env:
+              TARGET_TRIPLE: x86_64-apple-darwin
           # cross-compile from Linux to Windows using mingw
           - os: ubuntu-latest
             env:
@@ -112,7 +116,7 @@ jobs:
       if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
       uses: actions/upload-artifact@v2
       with:
-        name: cg_clif-${{ runner.os }}
+        name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
         path: cg_clif.tar.xz
 
     - name: Upload prebuilt cg_clif (cross compile)
@@ -122,56 +126,89 @@ jobs:
         name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
         path: cg_clif.tar.xz
 
-  build_windows:
-    runs-on: windows-latest
+  windows:
+    runs-on: ${{ matrix.os }}
     timeout-minutes: 60
 
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          # Native Windows build with MSVC
+          - os: windows-latest
+            env:
+              TARGET_TRIPLE: x86_64-pc-windows-msvc
+          # cross-compile from Windows to Windows MinGW
+          - os: windows-latest
+            env:
+              TARGET_TRIPLE: x86_64-pc-windows-gnu
+
     steps:
     - uses: actions/checkout@v3
 
-    #- name: Cache cargo installed crates
-    #  uses: actions/cache@v2
-    #  with:
-    #    path: ~/.cargo/bin
-    #    key: ${{ runner.os }}-cargo-installed-crates
-
-    #- name: Cache cargo registry and index
-    #  uses: actions/cache@v2
-    #  with:
-    #    path: |
-    #        ~/.cargo/registry
-    #        ~/.cargo/git
-    #    key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
-
-    #- name: Cache cargo target dir
-    #  uses: actions/cache@v2
-    #  with:
-    #    path: target
-    #    key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
+    - name: Cache cargo installed crates
+      uses: actions/cache@v2
+      with:
+        path: ~/.cargo/bin
+        key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-installed-crates
+
+    - name: Cache cargo registry and index
+      uses: actions/cache@v2
+      with:
+        path: |
+            ~/.cargo/registry
+            ~/.cargo/git
+        key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
+
+    - name: Cache cargo target dir
+      uses: actions/cache@v2
+      with:
+        path: target
+        key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
+
+    - name: Set MinGW as the default toolchain
+      if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
+      run: rustup set default-host x86_64-pc-windows-gnu
 
     - name: Prepare dependencies
       run: |
         git config --global user.email "user@example.com"
         git config --global user.name "User"
         git config --global core.autocrlf false
-        rustup set default-host x86_64-pc-windows-gnu
         rustc y.rs -o y.exe -g
         ./y.exe prepare
 
+    - name: Build without unstable features
+      env:
+        TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
+      # This is the config rust-lang/rust uses for builds
+      run: ./y.rs build --no-unstable-features
+
     - name: Build
-      #name: Test
+      run: ./y.rs build --sysroot none
+
+    - name: Test
       run: |
         # Enable backtraces for easier debugging
-        #$Env:RUST_BACKTRACE=1
+        $Env:RUST_BACKTRACE=1
 
         # Reduce amount of benchmark runs as they are slow
-        #$Env:COMPILE_RUNS=2
-        #$Env:RUN_RUNS=2
+        $Env:COMPILE_RUNS=2
+        $Env:RUN_RUNS=2
 
         # Enable extra checks
-        #$Env:CG_CLIF_ENABLE_VERIFIER=1
-
-        ./y.exe build
+        $Env:CG_CLIF_ENABLE_VERIFIER=1
+        
+        # WIP Disable some tests
+        
+        # This fails due to some weird argument handling by hyperfine, not an actual regression
+        # more of a build system issue
+        (Get-Content config.txt) -replace '(bench.simple-raytracer)', '# $1' |  Out-File config.txt
+        
+        # This fails with a different output than expected 
+        (Get-Content config.txt) -replace '(test.regex-shootout-regex-dna)', '# $1' |  Out-File config.txt
+
+        ./y.exe test
 
     - name: Package prebuilt cg_clif
       # don't use compression as xzip isn't supported by tar on windows and bzip2 hangs
@@ -180,5 +217,5 @@ jobs:
     - name: Upload prebuilt cg_clif
       uses: actions/upload-artifact@v2
       with:
-        name: cg_clif-${{ runner.os }}
+        name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
         path: cg_clif.tar
diff --git a/compiler/rustc_codegen_cranelift/.gitignore b/compiler/rustc_codegen_cranelift/.gitignore
index 6fd3e4443de..fae09592c6a 100644
--- a/compiler/rustc_codegen_cranelift/.gitignore
+++ b/compiler/rustc_codegen_cranelift/.gitignore
@@ -15,8 +15,4 @@ perf.data.old
 /build_sysroot/compiler-builtins
 /build_sysroot/rustc_version
 /rust
-/rand
-/regex
-/simple-raytracer
-/portable-simd
-/abi-checker
+/download
diff --git a/compiler/rustc_codegen_cranelift/.vscode/settings.json b/compiler/rustc_codegen_cranelift/.vscode/settings.json
index d88309e412e..13301bf20a5 100644
--- a/compiler/rustc_codegen_cranelift/.vscode/settings.json
+++ b/compiler/rustc_codegen_cranelift/.vscode/settings.json
@@ -7,7 +7,7 @@
     "rust-analyzer.cargo.features": ["unstable-features"],
     "rust-analyzer.linkedProjects": [
         "./Cargo.toml",
-        //"./build_sysroot/sysroot_src/src/libstd/Cargo.toml",
+        //"./build_sysroot/sysroot_src/library/std/Cargo.toml",
         {
             "roots": [
                 "./example/mini_core.rs",
@@ -36,10 +36,10 @@
             ]
         },
         {
-            "roots": ["./scripts/filter_profile.rs"],
+            "roots": ["./example/std_example.rs"],
             "crates": [
                 {
-                    "root_module": "./scripts/filter_profile.rs",
+                    "root_module": "./example/std_example.rs",
                     "edition": "2018",
                     "deps": [{ "crate": 1, "name": "std" }],
                     "cfg": [],
diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock
index edae7e47157..3fa9d56cd01 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/Cargo.lock
@@ -25,6 +25,12 @@ version = "0.8.0"
 source = "git+https://github.com/bjorn3/rust-ar.git?branch=do_not_remove_cg_clif_ranlib#de9ab0e56bf3a208381d342aa5b60f9ff2891648"
 
 [[package]]
+name = "arrayvec"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
+
+[[package]]
 name = "autocfg"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -37,6 +43,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
+name = "bumpalo"
+version = "3.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+
+[[package]]
 name = "byteorder"
 version = "1.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -50,19 +62,21 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.87.0"
+version = "0.88.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93945adbccc8d731503d3038814a51e8317497c9e205411820348132fa01a358"
+checksum = "44409ccf2d0f663920cab563d2b79fcd6b2e9a2bcc6e929fef76c8f82ad6c17a"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.87.0"
+version = "0.88.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b482acc9d0d0d1ad3288a90a8150ee648be3dce8dc8c8669ff026f72debdc31"
+checksum = "98de2018ad96eb97f621f7d6b900a0cc661aec8d02ea4a50e56ecb48e5a2fcaf"
 dependencies = [
+ "arrayvec",
+ "bumpalo",
  "cranelift-bforest",
  "cranelift-codegen-meta",
  "cranelift-codegen-shared",
@@ -77,30 +91,30 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.87.0"
+version = "0.88.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9ec188d71e663192ef9048f204e410a7283b609942efc9fcc77da6d496edbb8"
+checksum = "5287ce36e6c4758fbaf298bd1a8697ad97a4f2375a3d1b61142ea538db4877e5"
 dependencies = [
  "cranelift-codegen-shared",
 ]
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.87.0"
+version = "0.88.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ad794b1b1c2c7bd9f7b76cfe0f084eaf7753e55d56191c3f7d89e8fa4978b99"
+checksum = "2855c24219e2f08827f3f4ffb2da92e134ae8d8ecc185b11ec8f9878cf5f588e"
 
 [[package]]
 name = "cranelift-entity"
-version = "0.87.0"
+version = "0.88.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "342da0d5056f4119d3c311c4aab2460ceb6ee6e127bb395b76dd2279a09ea7a5"
+checksum = "0b65673279d75d34bf11af9660ae2dbd1c22e6d28f163f5c72f4e1dc56d56103"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.87.0"
+version = "0.88.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfff792f775b07d4d9cfe9f1c767ce755c6cbadda1bbd6db18a1c75ff9f7376a"
+checksum = "3ed2b3d7a4751163f6c4a349205ab1b7d9c00eecf19dcea48592ef1f7688eefc"
 dependencies = [
  "cranelift-codegen",
  "log",
@@ -110,15 +124,15 @@ dependencies = [
 
 [[package]]
 name = "cranelift-isle"
-version = "0.87.0"
+version = "0.88.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d51089478849f2ac8ef60a8a2d5346c8d4abfec0e45ac5b24530ef9f9499e1e"
+checksum = "3be64cecea9d90105fc6a2ba2d003e98c867c1d6c4c86cc878f97ad9fb916293"
 
 [[package]]
 name = "cranelift-jit"
-version = "0.87.0"
+version = "0.88.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "095936e41720f86004b4c57ce88e6a13af28646bb3a6fb4afbebd5ae90c50029"
+checksum = "f98ed42a70a0c9c388e34ec9477f57fc7300f541b1e5136a0e2ea02b1fac6015"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -134,9 +148,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-module"
-version = "0.87.0"
+version = "0.88.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "704a1aea4723d97eafe0fb7af110f6f6868b1ac95f5380bbc9adb2a3b8cf97e8"
+checksum = "d658ac7f156708bfccb647216cc8b9387469f50d352ba4ad80150541e4ae2d49"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -144,9 +158,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-native"
-version = "0.87.0"
+version = "0.88.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "885debe62f2078638d6585f54c9f05f5c2008f22ce5a2a9100ada785fc065dbd"
+checksum = "c4a03a6ac1b063e416ca4b93f6247978c991475e8271465340caa6f92f3c16a4"
 dependencies = [
  "cranelift-codegen",
  "libc",
@@ -155,9 +169,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-object"
-version = "0.87.0"
+version = "0.88.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aac1310cf1081ae8eca916c92cd163b977c77cab6e831fa812273c26ff921816"
+checksum = "eef0b4119b645b870a43a036d76c0ada3a076b1f82e8b8487659304c8b09049b"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -232,9 +246,9 @@ checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"
 
 [[package]]
 name = "libloading"
-version = "0.6.7"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883"
+checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
 dependencies = [
  "cfg-if",
  "winapi",
diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml
index e7c34274854..09cf5b4a1ed 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/Cargo.toml
@@ -8,19 +8,19 @@ crate-type = ["dylib"]
 
 [dependencies]
 # These have to be in sync with each other
-cranelift-codegen = { version = "0.87.0", features = ["unwind", "all-arch"] }
-cranelift-frontend = "0.87.0"
-cranelift-module = "0.87.0"
-cranelift-native = "0.87.0"
-cranelift-jit = { version = "0.87.0", optional = true }
-cranelift-object = "0.87.0"
+cranelift-codegen = { version = "0.88.1", features = ["unwind", "all-arch"] }
+cranelift-frontend = "0.88.1"
+cranelift-module = "0.88.1"
+cranelift-native = "0.88.1"
+cranelift-jit = { version = "0.88.1", optional = true }
+cranelift-object = "0.88.1"
 target-lexicon = "0.12.0"
 gimli = { version = "0.26.0", default-features = false, features = ["write"]}
 object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
 
 ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
 indexmap = "1.9.1"
-libloading = { version = "0.6.0", optional = true }
+libloading = { version = "0.7.3", optional = true }
 once_cell = "1.10.0"
 smallvec = "1.8.1"
 
diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
index 6c5043bb6f8..f6a9cb67290 100644
--- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
@@ -55,10 +55,20 @@ dependencies = [
 ]
 
 [[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+dependencies = [
+ "compiler_builtins",
+ "rustc-std-workspace-core",
+]
+
+[[package]]
 name = "compiler_builtins"
-version = "0.1.79"
+version = "0.1.82"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f873ce2bd3550b0b565f878b3d04ea8253f4259dc3d20223af2e1ba86f5ecca"
+checksum = "18cd7635fea7bb481ea543b392789844c1ad581299da70184c7175ce3af76603"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -123,9 +133,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.2.5"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "897cd85af6387be149f55acf168e41be176a02de7872403aaab184afc2f327e6"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
 dependencies = [
  "compiler_builtins",
  "libc",
@@ -135,9 +145,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.132"
+version = "0.2.135"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
+checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -182,7 +192,7 @@ name = "panic_abort"
 version = "0.0.0"
 dependencies = [
  "alloc",
- "cfg-if",
+ "cfg-if 0.1.10",
  "compiler_builtins",
  "core",
  "libc",
@@ -193,7 +203,7 @@ name = "panic_unwind"
 version = "0.0.0"
 dependencies = [
  "alloc",
- "cfg-if",
+ "cfg-if 0.1.10",
  "compiler_builtins",
  "core",
  "libc",
@@ -245,7 +255,7 @@ version = "0.0.0"
 dependencies = [
  "addr2line",
  "alloc",
- "cfg-if",
+ "cfg-if 1.0.0",
  "compiler_builtins",
  "core",
  "dlmalloc",
@@ -267,7 +277,7 @@ dependencies = [
 name = "std_detect"
 version = "0.1.5"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "compiler_builtins",
  "libc",
  "rustc-std-workspace-alloc",
@@ -289,7 +299,7 @@ dependencies = [
 name = "test"
 version = "0.0.0"
 dependencies = [
- "cfg-if",
+ "cfg-if 0.1.10",
  "core",
  "getopts",
  "libc",
@@ -301,9 +311,9 @@ dependencies = [
 
 [[package]]
 name = "unicode-width"
-version = "0.1.9"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
@@ -315,7 +325,7 @@ name = "unwind"
 version = "0.0.0"
 dependencies = [
  "cc",
- "cfg-if",
+ "cfg-if 0.1.10",
  "compiler_builtins",
  "core",
  "libc",
diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
new file mode 100644
index 00000000000..fae5b271636
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
@@ -0,0 +1,52 @@
+use std::env;
+use std::path::Path;
+
+use super::build_sysroot;
+use super::config;
+use super::prepare;
+use super::utils::{cargo_command, spawn_and_wait};
+use super::SysrootKind;
+
+pub(crate) fn run(
+    channel: &str,
+    sysroot_kind: SysrootKind,
+    target_dir: &Path,
+    cg_clif_dylib: &Path,
+    host_triple: &str,
+    target_triple: &str,
+) {
+    if !config::get_bool("testsuite.abi-cafe") {
+        eprintln!("[SKIP] abi-cafe");
+        return;
+    }
+
+    if host_triple != target_triple {
+        eprintln!("[SKIP] abi-cafe (cross-compilation not supported)");
+        return;
+    }
+
+    eprintln!("Building sysroot for abi-cafe");
+    build_sysroot::build_sysroot(
+        channel,
+        sysroot_kind,
+        target_dir,
+        cg_clif_dylib,
+        host_triple,
+        target_triple,
+    );
+
+    eprintln!("Running abi-cafe");
+    let abi_cafe_path = prepare::ABI_CAFE.source_dir();
+    env::set_current_dir(abi_cafe_path.clone()).unwrap();
+
+    let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
+
+    let mut cmd = cargo_command("cargo", "run", Some(target_triple), &abi_cafe_path);
+    cmd.arg("--");
+    cmd.arg("--pairs");
+    cmd.args(pairs);
+    cmd.arg("--add-rustc-codegen-backend");
+    cmd.arg(format!("cgclif:{}", cg_clif_dylib.display()));
+
+    spawn_and_wait(cmd);
+}
diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_checker.rs b/compiler/rustc_codegen_cranelift/build_system/abi_checker.rs
deleted file mode 100644
index 67dbd0a38a4..00000000000
--- a/compiler/rustc_codegen_cranelift/build_system/abi_checker.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-use super::build_sysroot;
-use super::config;
-use super::utils::spawn_and_wait;
-use build_system::SysrootKind;
-use std::env;
-use std::path::Path;
-use std::process::Command;
-
-pub(crate) fn run(
-    channel: &str,
-    sysroot_kind: SysrootKind,
-    target_dir: &Path,
-    cg_clif_build_dir: &Path,
-    host_triple: &str,
-    target_triple: &str,
-) {
-    if !config::get_bool("testsuite.abi-checker") {
-        eprintln!("[SKIP] abi-checker");
-        return;
-    }
-
-    if host_triple != target_triple {
-        eprintln!("[SKIP] abi-checker (cross-compilation not supported)");
-        return;
-    }
-
-    eprintln!("Building sysroot for abi-checker");
-    build_sysroot::build_sysroot(
-        channel,
-        sysroot_kind,
-        target_dir,
-        cg_clif_build_dir,
-        host_triple,
-        target_triple,
-    );
-
-    eprintln!("Running abi-checker");
-    let mut abi_checker_path = env::current_dir().unwrap();
-    abi_checker_path.push("abi-checker");
-    env::set_current_dir(abi_checker_path.clone()).unwrap();
-
-    let build_dir = abi_checker_path.parent().unwrap().join("build");
-    let cg_clif_dylib_path = build_dir.join(if cfg!(windows) { "bin" } else { "lib" }).join(
-        env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX,
-    );
-
-    let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
-
-    let mut cmd = Command::new("cargo");
-    cmd.arg("run");
-    cmd.arg("--target");
-    cmd.arg(target_triple);
-    cmd.arg("--");
-    cmd.arg("--pairs");
-    cmd.args(pairs);
-    cmd.arg("--add-rustc-codegen-backend");
-    cmd.arg(format!("cgclif:{}", cg_clif_dylib_path.display()));
-
-    spawn_and_wait(cmd);
-}
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
index 9e59b8199b4..cda468bcfa2 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
@@ -1,16 +1,16 @@
 use std::env;
-use std::path::{Path, PathBuf};
-use std::process::Command;
+use std::path::PathBuf;
 
-use super::utils::is_ci;
+use super::rustc_info::get_file_name;
+use super::utils::{cargo_command, is_ci};
 
 pub(crate) fn build_backend(
     channel: &str,
     host_triple: &str,
     use_unstable_features: bool,
 ) -> PathBuf {
-    let mut cmd = Command::new("cargo");
-    cmd.arg("build").arg("--target").arg(host_triple);
+    let source_dir = std::env::current_dir().unwrap();
+    let mut cmd = cargo_command("cargo", "build", Some(host_triple), &source_dir);
 
     cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode
 
@@ -41,5 +41,9 @@ pub(crate) fn build_backend(
     eprintln!("[BUILD] rustc_codegen_cranelift");
     super::utils::spawn_and_wait(cmd);
 
-    Path::new("target").join(host_triple).join(channel)
+    source_dir
+        .join("target")
+        .join(host_triple)
+        .join(channel)
+        .join(get_file_name("rustc_codegen_cranelift", "dylib"))
 }
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
index 7e205b0fd0b..856aecc49fd 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
@@ -3,14 +3,14 @@ use std::path::{Path, PathBuf};
 use std::process::{self, Command};
 
 use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name};
-use super::utils::{spawn_and_wait, try_hard_link};
+use super::utils::{cargo_command, spawn_and_wait, try_hard_link};
 use super::SysrootKind;
 
 pub(crate) fn build_sysroot(
     channel: &str,
     sysroot_kind: SysrootKind,
     target_dir: &Path,
-    cg_clif_build_dir: &Path,
+    cg_clif_dylib_src: &Path,
     host_triple: &str,
     target_triple: &str,
 ) {
@@ -23,7 +23,6 @@ pub(crate) fn build_sysroot(
     fs::create_dir_all(target_dir.join("lib")).unwrap();
 
     // Copy the backend
-    let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib");
     let cg_clif_dylib_path = target_dir
         .join(if cfg!(windows) {
             // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
@@ -32,8 +31,8 @@ pub(crate) fn build_sysroot(
         } else {
             "lib"
         })
-        .join(&cg_clif_dylib);
-    try_hard_link(cg_clif_build_dir.join(cg_clif_dylib), &cg_clif_dylib_path);
+        .join(get_file_name("rustc_codegen_cranelift", "dylib"));
+    try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path);
 
     // Build and copy rustc and cargo wrappers
     for wrapper in ["rustc-clif", "cargo-clif"] {
@@ -186,10 +185,10 @@ fn build_clif_sysroot_for_triple(
     }
 
     // Build sysroot
-    let mut build_cmd = Command::new("cargo");
-    build_cmd.arg("build").arg("--target").arg(triple).current_dir("build_sysroot");
+    let mut build_cmd = cargo_command("cargo", "build", Some(triple), Path::new("build_sysroot"));
     let mut rustflags = "-Zforce-unstable-if-unmarked -Cpanic=abort".to_string();
     rustflags.push_str(&format!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap()));
+    rustflags.push_str(&format!(" --sysroot={}", target_dir.to_str().unwrap()));
     if channel == "release" {
         build_cmd.arg("--release");
         rustflags.push_str(" -Zmir-opt-level=3");
diff --git a/compiler/rustc_codegen_cranelift/build_system/config.rs b/compiler/rustc_codegen_cranelift/build_system/config.rs
index ef540cf1f82..c31784e1097 100644
--- a/compiler/rustc_codegen_cranelift/build_system/config.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/config.rs
@@ -1,4 +1,5 @@
-use std::{fs, process};
+use std::fs;
+use std::process;
 
 fn load_config_file() -> Vec<(String, Option<String>)> {
     fs::read_to_string("config.txt")
diff --git a/compiler/rustc_codegen_cranelift/build_system/mod.rs b/compiler/rustc_codegen_cranelift/build_system/mod.rs
index c3706dc6f82..b25270d832c 100644
--- a/compiler/rustc_codegen_cranelift/build_system/mod.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/mod.rs
@@ -4,7 +4,7 @@ use std::process;
 
 use self::utils::is_ci;
 
-mod abi_checker;
+mod abi_cafe;
 mod build_backend;
 mod build_sysroot;
 mod config;
@@ -122,32 +122,23 @@ pub fn main() {
         host_triple.clone()
     };
 
-    if target_triple.ends_with("-msvc") {
-        eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift.");
-        eprintln!("Switch to the MinGW toolchain for Windows support.");
-        eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to");
-        eprintln!("set the global default target to MinGW");
-        process::exit(1);
-    }
-
-    let cg_clif_build_dir =
-        build_backend::build_backend(channel, &host_triple, use_unstable_features);
+    let cg_clif_dylib = build_backend::build_backend(channel, &host_triple, use_unstable_features);
     match command {
         Command::Test => {
             tests::run_tests(
                 channel,
                 sysroot_kind,
                 &target_dir,
-                &cg_clif_build_dir,
+                &cg_clif_dylib,
                 &host_triple,
                 &target_triple,
             );
 
-            abi_checker::run(
+            abi_cafe::run(
                 channel,
                 sysroot_kind,
                 &target_dir,
-                &cg_clif_build_dir,
+                &cg_clif_dylib,
                 &host_triple,
                 &target_triple,
             );
@@ -157,7 +148,7 @@ pub fn main() {
                 channel,
                 sysroot_kind,
                 &target_dir,
-                &cg_clif_build_dir,
+                &cg_clif_dylib,
                 &host_triple,
                 &target_triple,
             );
diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
index d23b7f00dcf..3111f62f6c2 100644
--- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
@@ -1,64 +1,63 @@
 use std::env;
 use std::ffi::OsStr;
-use std::ffi::OsString;
 use std::fs;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::process::Command;
 
 use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version};
-use super::utils::{copy_dir_recursively, spawn_and_wait};
+use super::utils::{cargo_command, copy_dir_recursively, spawn_and_wait};
+
+pub(crate) const ABI_CAFE: GitRepo =
+    GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
+
+pub(crate) const RAND: GitRepo =
+    GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
+
+pub(crate) const REGEX: GitRepo =
+    GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
+
+pub(crate) const PORTABLE_SIMD: GitRepo = GitRepo::github(
+    "rust-lang",
+    "portable-simd",
+    "d5cd4a8112d958bd3a252327e0d069a6363249bd",
+    "portable-simd",
+);
+
+pub(crate) const SIMPLE_RAYTRACER: GitRepo = GitRepo::github(
+    "ebobby",
+    "simple-raytracer",
+    "804a7a21b9e673a482797aa289a18ed480e4d813",
+    "<none>",
+);
 
 pub(crate) fn prepare() {
+    if Path::new("download").exists() {
+        std::fs::remove_dir_all(Path::new("download")).unwrap();
+    }
+    std::fs::create_dir_all(Path::new("download")).unwrap();
+
     prepare_sysroot();
 
+    // FIXME maybe install this only locally?
     eprintln!("[INSTALL] hyperfine");
     Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap();
 
-    clone_repo_shallow_github(
-        "abi-checker",
-        "Gankra",
-        "abi-checker",
-        "a2232d45f202846f5c02203c9f27355360f9a2ff",
-    );
-    apply_patches("abi-checker", Path::new("abi-checker"));
-
-    clone_repo_shallow_github(
-        "rand",
-        "rust-random",
-        "rand",
-        "0f933f9c7176e53b2a3c7952ded484e1783f0bf1",
-    );
-    apply_patches("rand", Path::new("rand"));
-
-    clone_repo_shallow_github(
-        "regex",
-        "rust-lang",
-        "regex",
-        "341f207c1071f7290e3f228c710817c280c8dca1",
-    );
-
-    clone_repo_shallow_github(
-        "portable-simd",
-        "rust-lang",
-        "portable-simd",
-        "b8d6b6844602f80af79cd96401339ec594d472d8",
-    );
-    apply_patches("portable-simd", Path::new("portable-simd"));
-
-    clone_repo_shallow_github(
-        "simple-raytracer",
-        "ebobby",
-        "simple-raytracer",
-        "804a7a21b9e673a482797aa289a18ed480e4d813",
-    );
+    ABI_CAFE.fetch();
+    RAND.fetch();
+    REGEX.fetch();
+    PORTABLE_SIMD.fetch();
+    SIMPLE_RAYTRACER.fetch();
 
     eprintln!("[LLVM BUILD] simple-raytracer");
-    let mut build_cmd = Command::new("cargo");
-    build_cmd.arg("build").env_remove("CARGO_TARGET_DIR").current_dir("simple-raytracer");
+    let build_cmd = cargo_command("cargo", "build", None, &SIMPLE_RAYTRACER.source_dir());
     spawn_and_wait(build_cmd);
     fs::copy(
-        Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")),
-        Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin")),
+        SIMPLE_RAYTRACER
+            .source_dir()
+            .join("target")
+            .join("debug")
+            .join(get_file_name("main", "bin")),
+        SIMPLE_RAYTRACER.source_dir().join(get_file_name("raytracer_cg_llvm", "bin")),
     )
     .unwrap();
 }
@@ -90,38 +89,78 @@ fn prepare_sysroot() {
     apply_patches("sysroot", &sysroot_src);
 }
 
+pub(crate) struct GitRepo {
+    url: GitRepoUrl,
+    rev: &'static str,
+    patch_name: &'static str,
+}
+
+enum GitRepoUrl {
+    Github { user: &'static str, repo: &'static str },
+}
+
+impl GitRepo {
+    const fn github(
+        user: &'static str,
+        repo: &'static str,
+        rev: &'static str,
+        patch_name: &'static str,
+    ) -> GitRepo {
+        GitRepo { url: GitRepoUrl::Github { user, repo }, rev, patch_name }
+    }
+
+    pub(crate) fn source_dir(&self) -> PathBuf {
+        match self.url {
+            GitRepoUrl::Github { user: _, repo } => {
+                std::env::current_dir().unwrap().join("download").join(repo)
+            }
+        }
+    }
+
+    fn fetch(&self) {
+        match self.url {
+            GitRepoUrl::Github { user, repo } => {
+                clone_repo_shallow_github(&self.source_dir(), user, repo, self.rev);
+            }
+        }
+        apply_patches(self.patch_name, &self.source_dir());
+    }
+}
+
 #[allow(dead_code)]
-fn clone_repo(target_dir: &str, repo: &str, rev: &str) {
+fn clone_repo(download_dir: &Path, repo: &str, rev: &str) {
     eprintln!("[CLONE] {}", repo);
     // Ignore exit code as the repo may already have been checked out
-    Command::new("git").arg("clone").arg(repo).arg(target_dir).spawn().unwrap().wait().unwrap();
+    Command::new("git").arg("clone").arg(repo).arg(&download_dir).spawn().unwrap().wait().unwrap();
 
     let mut clean_cmd = Command::new("git");
-    clean_cmd.arg("checkout").arg("--").arg(".").current_dir(target_dir);
+    clean_cmd.arg("checkout").arg("--").arg(".").current_dir(&download_dir);
     spawn_and_wait(clean_cmd);
 
     let mut checkout_cmd = Command::new("git");
-    checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(target_dir);
+    checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(download_dir);
     spawn_and_wait(checkout_cmd);
 }
 
-fn clone_repo_shallow_github(target_dir: &str, username: &str, repo: &str, rev: &str) {
+fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &str) {
     if cfg!(windows) {
         // Older windows doesn't have tar or curl by default. Fall back to using git.
-        clone_repo(target_dir, &format!("https://github.com/{}/{}.git", username, repo), rev);
+        clone_repo(download_dir, &format!("https://github.com/{}/{}.git", user, repo), rev);
         return;
     }
 
-    let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", username, repo, rev);
-    let archive_file = format!("{}.tar.gz", rev);
-    let archive_dir = format!("{}-{}", repo, rev);
+    let downloads_dir = std::env::current_dir().unwrap().join("download");
+
+    let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", user, repo, rev);
+    let archive_file = downloads_dir.join(format!("{}.tar.gz", rev));
+    let archive_dir = downloads_dir.join(format!("{}-{}", repo, rev));
 
-    eprintln!("[DOWNLOAD] {}/{} from {}", username, repo, archive_url);
+    eprintln!("[DOWNLOAD] {}/{} from {}", user, repo, archive_url);
 
     // Remove previous results if they exists
     let _ = std::fs::remove_file(&archive_file);
     let _ = std::fs::remove_dir_all(&archive_dir);
-    let _ = std::fs::remove_dir_all(target_dir);
+    let _ = std::fs::remove_dir_all(&download_dir);
 
     // Download zip archive
     let mut download_cmd = Command::new("curl");
@@ -130,13 +169,13 @@ fn clone_repo_shallow_github(target_dir: &str, username: &str, repo: &str, rev:
 
     // Unpack tar archive
     let mut unpack_cmd = Command::new("tar");
-    unpack_cmd.arg("xf").arg(&archive_file);
+    unpack_cmd.arg("xf").arg(&archive_file).current_dir(downloads_dir);
     spawn_and_wait(unpack_cmd);
 
     // Rename unpacked dir to the expected name
-    std::fs::rename(archive_dir, target_dir).unwrap();
+    std::fs::rename(archive_dir, &download_dir).unwrap();
 
-    init_git_repo(Path::new(target_dir));
+    init_git_repo(&download_dir);
 
     // Cleanup
     std::fs::remove_file(archive_file).unwrap();
@@ -156,14 +195,20 @@ fn init_git_repo(repo_dir: &Path) {
     spawn_and_wait(git_commit_cmd);
 }
 
-fn get_patches(crate_name: &str) -> Vec<OsString> {
-    let mut patches: Vec<_> = fs::read_dir("patches")
+fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
+    let mut patches: Vec<_> = fs::read_dir(source_dir.join("patches"))
         .unwrap()
         .map(|entry| entry.unwrap().path())
         .filter(|path| path.extension() == Some(OsStr::new("patch")))
-        .map(|path| path.file_name().unwrap().to_owned())
-        .filter(|file_name| {
-            file_name.to_str().unwrap().split_once("-").unwrap().1.starts_with(crate_name)
+        .filter(|path| {
+            path.file_name()
+                .unwrap()
+                .to_str()
+                .unwrap()
+                .split_once("-")
+                .unwrap()
+                .1
+                .starts_with(crate_name)
         })
         .collect();
     patches.sort();
@@ -171,11 +216,18 @@ fn get_patches(crate_name: &str) -> Vec<OsString> {
 }
 
 fn apply_patches(crate_name: &str, target_dir: &Path) {
-    for patch in get_patches(crate_name) {
-        eprintln!("[PATCH] {:?} <- {:?}", target_dir.file_name().unwrap(), patch);
-        let patch_arg = env::current_dir().unwrap().join("patches").join(patch);
+    if crate_name == "<none>" {
+        return;
+    }
+
+    for patch in get_patches(&std::env::current_dir().unwrap(), crate_name) {
+        eprintln!(
+            "[PATCH] {:?} <- {:?}",
+            target_dir.file_name().unwrap(),
+            patch.file_name().unwrap()
+        );
         let mut apply_patch_cmd = Command::new("git");
-        apply_patch_cmd.arg("am").arg(patch_arg).arg("-q").current_dir(target_dir);
+        apply_patch_cmd.arg("am").arg(patch).arg("-q").current_dir(target_dir);
         spawn_and_wait(apply_patch_cmd);
     }
 }
diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs
index e21397cece8..a414b60f4e0 100644
--- a/compiler/rustc_codegen_cranelift/build_system/tests.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs
@@ -1,7 +1,8 @@
 use super::build_sysroot;
 use super::config;
+use super::prepare;
 use super::rustc_info::get_wrapper_file_name;
-use super::utils::{spawn_and_wait, spawn_and_wait_with_input};
+use super::utils::{cargo_command, hyperfine_command, spawn_and_wait, spawn_and_wait_with_input};
 use build_system::SysrootKind;
 use std::env;
 use std::ffi::OsStr;
@@ -217,103 +218,95 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
 
 const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
     TestCase::new("test.rust-random/rand", &|runner| {
-        runner.in_dir(["rand"], |runner| {
-            runner.run_cargo(["clean"]);
+        runner.in_dir(prepare::RAND.source_dir(), |runner| {
+            runner.run_cargo("clean", []);
 
             if runner.host_triple == runner.target_triple {
                 eprintln!("[TEST] rust-random/rand");
-                runner.run_cargo(["test", "--workspace"]);
+                runner.run_cargo("test", ["--workspace"]);
             } else {
                 eprintln!("[AOT] rust-random/rand");
-                runner.run_cargo([
-                    "build",
-                    "--workspace",
-                    "--target",
-                    &runner.target_triple,
-                    "--tests",
-                ]);
+                runner.run_cargo("build", ["--workspace", "--tests"]);
             }
         });
     }),
     TestCase::new("bench.simple-raytracer", &|runner| {
-        runner.in_dir(["simple-raytracer"], |runner| {
-            let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string());
+        runner.in_dir(prepare::SIMPLE_RAYTRACER.source_dir(), |runner| {
+            let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
 
             if runner.host_triple == runner.target_triple {
                 eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
-                let mut bench_compile = Command::new("hyperfine");
-                bench_compile.arg("--runs");
-                bench_compile.arg(&run_runs);
-                bench_compile.arg("--warmup");
-                bench_compile.arg("1");
-                bench_compile.arg("--prepare");
-                bench_compile.arg(format!("{:?}", runner.cargo_command(["clean"])));
-
-                if cfg!(windows) {
-                    bench_compile.arg("cmd /C \"set RUSTFLAGS= && cargo build\"");
-                } else {
-                    bench_compile.arg("RUSTFLAGS='' cargo build");
-                }
+                let prepare = runner.cargo_command("clean", []);
+
+                let llvm_build_cmd = cargo_command("cargo", "build", None, Path::new("."));
+
+                let cargo_clif = runner
+                    .root_dir
+                    .clone()
+                    .join("build")
+                    .join(get_wrapper_file_name("cargo-clif", "bin"));
+                let clif_build_cmd = cargo_command(cargo_clif, "build", None, Path::new("."));
+
+                let bench_compile =
+                    hyperfine_command(1, run_runs, Some(prepare), llvm_build_cmd, clif_build_cmd);
 
-                bench_compile.arg(format!("{:?}", runner.cargo_command(["build"])));
                 spawn_and_wait(bench_compile);
 
                 eprintln!("[BENCH RUN] ebobby/simple-raytracer");
                 fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif"))
                     .unwrap();
 
-                let mut bench_run = Command::new("hyperfine");
-                bench_run.arg("--runs");
-                bench_run.arg(&run_runs);
-                bench_run.arg(PathBuf::from("./raytracer_cg_llvm"));
-                bench_run.arg(PathBuf::from("./raytracer_cg_clif"));
+                let bench_run = hyperfine_command(
+                    0,
+                    run_runs,
+                    None,
+                    Command::new("./raytracer_cg_llvm"),
+                    Command::new("./raytracer_cg_clif"),
+                );
                 spawn_and_wait(bench_run);
             } else {
-                runner.run_cargo(["clean"]);
+                runner.run_cargo("clean", []);
                 eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
                 eprintln!("[COMPILE] ebobby/simple-raytracer");
-                runner.run_cargo(["build", "--target", &runner.target_triple]);
+                runner.run_cargo("build", []);
                 eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
             }
         });
     }),
     TestCase::new("test.libcore", &|runner| {
-        runner.in_dir(["build_sysroot", "sysroot_src", "library", "core", "tests"], |runner| {
-            runner.run_cargo(["clean"]);
-
-            if runner.host_triple == runner.target_triple {
-                runner.run_cargo(["test"]);
-            } else {
-                eprintln!("Cross-Compiling: Not running tests");
-                runner.run_cargo(["build", "--target", &runner.target_triple, "--tests"]);
-            }
-        });
+        runner.in_dir(
+            std::env::current_dir()
+                .unwrap()
+                .join("build_sysroot")
+                .join("sysroot_src")
+                .join("library")
+                .join("core")
+                .join("tests"),
+            |runner| {
+                runner.run_cargo("clean", []);
+
+                if runner.host_triple == runner.target_triple {
+                    runner.run_cargo("test", []);
+                } else {
+                    eprintln!("Cross-Compiling: Not running tests");
+                    runner.run_cargo("build", ["--tests"]);
+                }
+            },
+        );
     }),
     TestCase::new("test.regex-shootout-regex-dna", &|runner| {
-        runner.in_dir(["regex"], |runner| {
-            runner.run_cargo(["clean"]);
+        runner.in_dir(prepare::REGEX.source_dir(), |runner| {
+            runner.run_cargo("clean", []);
 
             // newer aho_corasick versions throw a deprecation warning
             let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
 
-            let mut build_cmd = runner.cargo_command([
-                "build",
-                "--example",
-                "shootout-regex-dna",
-                "--target",
-                &runner.target_triple,
-            ]);
+            let mut build_cmd = runner.cargo_command("build", ["--example", "shootout-regex-dna"]);
             build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
             spawn_and_wait(build_cmd);
 
             if runner.host_triple == runner.target_triple {
-                let mut run_cmd = runner.cargo_command([
-                    "run",
-                    "--example",
-                    "shootout-regex-dna",
-                    "--target",
-                    &runner.target_triple,
-                ]);
+                let mut run_cmd = runner.cargo_command("run", ["--example", "shootout-regex-dna"]);
                 run_cmd.env("RUSTFLAGS", lint_rust_flags);
 
                 let input =
@@ -353,41 +346,43 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
         });
     }),
     TestCase::new("test.regex", &|runner| {
-        runner.in_dir(["regex"], |runner| {
-            runner.run_cargo(["clean"]);
+        runner.in_dir(prepare::REGEX.source_dir(), |runner| {
+            runner.run_cargo("clean", []);
 
             // newer aho_corasick versions throw a deprecation warning
             let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
 
             if runner.host_triple == runner.target_triple {
-                let mut run_cmd = runner.cargo_command([
+                let mut run_cmd = runner.cargo_command(
                     "test",
-                    "--tests",
-                    "--",
-                    "--exclude-should-panic",
-                    "--test-threads",
-                    "1",
-                    "-Zunstable-options",
-                    "-q",
-                ]);
+                    [
+                        "--tests",
+                        "--",
+                        "--exclude-should-panic",
+                        "--test-threads",
+                        "1",
+                        "-Zunstable-options",
+                        "-q",
+                    ],
+                );
                 run_cmd.env("RUSTFLAGS", lint_rust_flags);
                 spawn_and_wait(run_cmd);
             } else {
                 eprintln!("Cross-Compiling: Not running tests");
                 let mut build_cmd =
-                    runner.cargo_command(["build", "--tests", "--target", &runner.target_triple]);
+                    runner.cargo_command("build", ["--tests", "--target", &runner.target_triple]);
                 build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
                 spawn_and_wait(build_cmd);
             }
         });
     }),
     TestCase::new("test.portable-simd", &|runner| {
-        runner.in_dir(["portable-simd"], |runner| {
-            runner.run_cargo(["clean"]);
-            runner.run_cargo(["build", "--all-targets", "--target", &runner.target_triple]);
+        runner.in_dir(prepare::PORTABLE_SIMD.source_dir(), |runner| {
+            runner.run_cargo("clean", []);
+            runner.run_cargo("build", ["--all-targets", "--target", &runner.target_triple]);
 
             if runner.host_triple == runner.target_triple {
-                runner.run_cargo(["test", "-q"]);
+                runner.run_cargo("test", ["-q"]);
             }
         });
     }),
@@ -397,7 +392,7 @@ pub(crate) fn run_tests(
     channel: &str,
     sysroot_kind: SysrootKind,
     target_dir: &Path,
-    cg_clif_build_dir: &Path,
+    cg_clif_dylib: &Path,
     host_triple: &str,
     target_triple: &str,
 ) {
@@ -408,7 +403,7 @@ pub(crate) fn run_tests(
             channel,
             SysrootKind::None,
             &target_dir,
-            cg_clif_build_dir,
+            cg_clif_dylib,
             &host_triple,
             &target_triple,
         );
@@ -427,7 +422,7 @@ pub(crate) fn run_tests(
             channel,
             sysroot_kind,
             &target_dir,
-            cg_clif_build_dir,
+            cg_clif_dylib,
             &host_triple,
             &target_triple,
         );
@@ -521,16 +516,8 @@ impl TestRunner {
         }
     }
 
-    fn in_dir<'a, I, F>(&self, dir: I, callback: F)
-    where
-        I: IntoIterator<Item = &'a str>,
-        F: FnOnce(&TestRunner),
-    {
+    fn in_dir(&self, new: impl AsRef<Path>, callback: impl FnOnce(&TestRunner)) {
         let current = env::current_dir().unwrap();
-        let mut new = current.clone();
-        for d in dir {
-            new.push(d);
-        }
 
         env::set_current_dir(new).unwrap();
         callback(self);
@@ -595,25 +582,29 @@ impl TestRunner {
         spawn_and_wait(cmd);
     }
 
-    fn cargo_command<I, S>(&self, args: I) -> Command
+    fn cargo_command<'a, I>(&self, subcommand: &str, args: I) -> Command
     where
-        I: IntoIterator<Item = S>,
-        S: AsRef<OsStr>,
+        I: IntoIterator<Item = &'a str>,
     {
         let mut cargo_clif = self.root_dir.clone();
         cargo_clif.push("build");
         cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin"));
 
-        let mut cmd = Command::new(cargo_clif);
+        let mut cmd = cargo_command(
+            cargo_clif,
+            subcommand,
+            if subcommand == "clean" { None } else { Some(&self.target_triple) },
+            Path::new("."),
+        );
         cmd.args(args);
         cmd.env("RUSTFLAGS", &self.rust_flags);
         cmd
     }
 
-    fn run_cargo<'a, I>(&self, args: I)
+    fn run_cargo<'a, I>(&self, subcommand: &str, args: I)
     where
         I: IntoIterator<Item = &'a str>,
     {
-        spawn_and_wait(self.cargo_command(args));
+        spawn_and_wait(self.cargo_command(subcommand, args));
     }
 }
diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs
index bdf8f8ecd99..48da64906e2 100644
--- a/compiler/rustc_codegen_cranelift/build_system/utils.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs
@@ -4,6 +4,52 @@ use std::io::Write;
 use std::path::Path;
 use std::process::{self, Command, Stdio};
 
+pub(crate) fn cargo_command(
+    cargo: impl AsRef<Path>,
+    subcommand: &str,
+    triple: Option<&str>,
+    source_dir: &Path,
+) -> Command {
+    let mut cmd = Command::new(cargo.as_ref());
+    cmd.arg(subcommand)
+        .arg("--manifest-path")
+        .arg(source_dir.join("Cargo.toml"))
+        .arg("--target-dir")
+        .arg(source_dir.join("target"));
+
+    if let Some(triple) = triple {
+        cmd.arg("--target").arg(triple);
+    }
+
+    cmd
+}
+
+pub(crate) fn hyperfine_command(
+    warmup: u64,
+    runs: u64,
+    prepare: Option<Command>,
+    a: Command,
+    b: Command,
+) -> Command {
+    let mut bench = Command::new("hyperfine");
+
+    if warmup != 0 {
+        bench.arg("--warmup").arg(warmup.to_string());
+    }
+
+    if runs != 0 {
+        bench.arg("--runs").arg(runs.to_string());
+    }
+
+    if let Some(prepare) = prepare {
+        bench.arg("--prepare").arg(format!("{:?}", prepare));
+    }
+
+    bench.arg(format!("{:?}", a)).arg(format!("{:?}", b));
+
+    bench
+}
+
 #[track_caller]
 pub(crate) fn try_hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
     let src = src.as_ref();
diff --git a/compiler/rustc_codegen_cranelift/clean_all.sh b/compiler/rustc_codegen_cranelift/clean_all.sh
index 62e52bd1958..fedab2433aa 100755
--- a/compiler/rustc_codegen_cranelift/clean_all.sh
+++ b/compiler/rustc_codegen_cranelift/clean_all.sh
@@ -3,4 +3,8 @@ set -e
 
 rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
 rm -rf target/ build/ perf.data{,.old} y.bin
-rm -rf rand/ regex/ simple-raytracer/ portable-simd/ abi-checker/
+rm -rf download/
+
+# Kept for now in case someone updates their checkout of cg_clif before running clean_all.sh
+# FIXME remove at some point in the future
+rm -rf rand/ regex/ simple-raytracer/ portable-simd/ abi-checker/ abi-cafe/
diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt
index 2264d301d59..0d539191b12 100644
--- a/compiler/rustc_codegen_cranelift/config.txt
+++ b/compiler/rustc_codegen_cranelift/config.txt
@@ -49,4 +49,4 @@ test.regex-shootout-regex-dna
 test.regex
 test.portable-simd
 
-testsuite.abi-checker
+testsuite.abi-cafe
diff --git a/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs b/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs
index 2ecc8b8238b..03910069633 100644
--- a/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs
+++ b/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs
@@ -5,7 +5,6 @@
 // Test that we can handle unsized types with an extern type tail part.
 // Regression test for issue #91827.
 
-#![feature(const_ptr_offset_from)]
 #![feature(extern_types)]
 
 use std::ptr::addr_of;
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs
index 42f8aa50ba1..7f85b52f083 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs
@@ -559,16 +559,22 @@ pub union MaybeUninit<T> {
 
 pub mod intrinsics {
     extern "rust-intrinsic" {
+        #[rustc_safe_intrinsic]
         pub fn abort() -> !;
+        #[rustc_safe_intrinsic]
         pub fn size_of<T>() -> usize;
         pub fn size_of_val<T: ?::Sized>(val: *const T) -> usize;
+        #[rustc_safe_intrinsic]
         pub fn min_align_of<T>() -> usize;
         pub fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize;
         pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
         pub fn transmute<T, U>(e: T) -> U;
         pub fn ctlz_nonzero<T>(x: T) -> T;
+        #[rustc_safe_intrinsic]
         pub fn needs_drop<T: ?::Sized>() -> bool;
+        #[rustc_safe_intrinsic]
         pub fn bitreverse<T>(x: T) -> T;
+        #[rustc_safe_intrinsic]
         pub fn bswap<T>(x: T) -> T;
         pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
     }
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
index e83be3a3df5..215d3556a17 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
@@ -93,6 +93,7 @@ fn start<T: Termination + 'static>(
     main: fn() -> T,
     argc: isize,
     argv: *const *const u8,
+    _sigpipe: u8,
 ) -> isize {
     if argc == 3 {
         unsafe { puts(*argv as *const i8); }
diff --git a/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch b/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch
new file mode 100644
index 00000000000..0e5e7cdfcdf
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch
@@ -0,0 +1,29 @@
+From 2b15fee2bb5fd14e34c7e17e44d99cb34f4c555d Mon Sep 17 00:00:00 2001
+From: Afonso Bordado <afonsobordado@az8.co>
+Date: Tue, 27 Sep 2022 07:55:17 +0100
+Subject: [PATCH] Disable some test on x86_64-pc-windows-gnu
+
+---
+ src/report.rs | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/report.rs b/src/report.rs
+index eeec614..f582867 100644
+--- a/src/report.rs
++++ b/src/report.rs
+@@ -48,6 +48,12 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl
+     //
+     // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES
+ 
++    // x86_64-pc-windows-gnu has some broken i128 tests that aren't disabled by default
++    if cfg!(all(target_os = "windows", target_env = "gnu")) && test.test_name == "ui128" {
++        result.run = Link;
++        result.check = Pass(Link);
++    }
++
+     // END OF VENDOR RESERVED AREA
+     //
+     //
+-- 
+2.30.1.windows.1
+
diff --git a/compiler/rustc_codegen_cranelift/patches/0001-abi-checker-Disable-failing-tests.patch b/compiler/rustc_codegen_cranelift/patches/0001-abi-checker-Disable-failing-tests.patch
deleted file mode 100644
index 526366a7598..00000000000
--- a/compiler/rustc_codegen_cranelift/patches/0001-abi-checker-Disable-failing-tests.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From 1a315ba225577dbbd1f449d9609f16f984f68708 Mon Sep 17 00:00:00 2001
-From: Afonso Bordado <afonso360@users.noreply.github.com>
-Date: Fri, 12 Aug 2022 22:51:58 +0000
-Subject: [PATCH] Disable abi-checker tests
-
----
- src/report.rs | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
-diff --git a/src/report.rs b/src/report.rs
-index 7346f5e..8347762 100644
---- a/src/report.rs
-+++ b/src/report.rs
-@@ -45,6 +45,20 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl
-     //
-     // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES
-
-+    // Currently MSVC has some broken ABI issues. Furthermore, they cause
-+    // a STATUS_ACCESS_VIOLATION, so we can't even run them. Ensure that they compile and link.
-+    if cfg!(windows) && (test.test_name == "bool" || test.test_name == "ui128") {
-+        result.run = Link;
-+        result.check = Pass(Link);
-+    }
-+
-+    // structs is broken in the current release of cranelift for aarch64.
-+    // It has been fixed for cranelift 0.88: https://github.com/bytecodealliance/wasmtime/pull/4634
-+    if cfg!(target_arch = "aarch64") && test.test_name == "structs" {
-+        result.run = Link;
-+        result.check = Pass(Link);
-+    }
-+
-     // END OF VENDOR RESERVED AREA
-     //
-     //
---
-2.34.1
diff --git a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch
index 54e13b090ab..89e2b61c1fc 100644
--- a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch
@@ -1,80 +1,29 @@
-From 97c473937382a5b5858d9cce3c947855d23b2dc5 Mon Sep 17 00:00:00 2001
+From b742f03694b920cc14400727d54424e8e1b60928 Mon Sep 17 00:00:00 2001
 From: bjorn3 <bjorn3@users.noreply.github.com>
 Date: Thu, 18 Nov 2021 19:28:40 +0100
 Subject: [PATCH] Disable unsupported tests
 
 ---
- crates/core_simd/src/math.rs         | 6 ++++++
- crates/core_simd/src/vector.rs       | 2 ++
- crates/core_simd/tests/masks.rs      | 2 ++
- crates/core_simd/tests/ops_macros.rs | 4 ++++
- 4 files changed, 14 insertions(+)
+ crates/core_simd/src/elements/int.rs     | 8 ++++++++
+ crates/core_simd/src/elements/uint.rs    | 4 ++++
+ crates/core_simd/src/masks/full_masks.rs | 6 ++++++
+ crates/core_simd/src/vector.rs           | 2 ++
+ crates/core_simd/tests/masks.rs          | 3 ---
+ 5 files changed, 20 insertions(+), 3 deletions(-)
 
-diff --git a/crates/core_simd/src/math.rs b/crates/core_simd/src/math.rs
-index 2bae414..2f87499 100644
---- a/crates/core_simd/src/math.rs
-+++ b/crates/core_simd/src/math.rs
-@@ -5,6 +5,7 @@ macro_rules! impl_uint_arith {
-     ($($ty:ty),+) => {
-         $( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
- 
-+            /*
-             /// Lanewise saturating add.
-             ///
-             /// # Examples
-@@ -43,6 +44,7 @@ macro_rules! impl_uint_arith {
-             pub fn saturating_sub(self, second: Self) -> Self {
-                 unsafe { simd_saturating_sub(self, second) }
-             }
-+            */
-         })+
-     }
- }
-@@ -51,6 +53,7 @@ macro_rules! impl_int_arith {
-     ($($ty:ty),+) => {
-         $( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
- 
-+            /*
-             /// Lanewise saturating add.
-             ///
-             /// # Examples
-@@ -89,6 +92,7 @@ macro_rules! impl_int_arith {
-             pub fn saturating_sub(self, second: Self) -> Self {
-                 unsafe { simd_saturating_sub(self, second) }
-             }
-+            */
- 
-             /// Lanewise absolute value, implemented in Rust.
-             /// Every lane becomes its absolute value.
-@@ -109,6 +113,7 @@ macro_rules! impl_int_arith {
-                 (self^m) - m
-             }
- 
-+            /*
-             /// Lanewise saturating absolute value, implemented in Rust.
-             /// As abs(), except the MIN value becomes MAX instead of itself.
-             ///
-@@ -151,6 +156,7 @@ macro_rules! impl_int_arith {
-             pub fn saturating_neg(self) -> Self {
-                 Self::splat(0).saturating_sub(self)
-             }
-+            */
-         })+
-     }
- }
 diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs
-index 7c5ec2b..c8631e8 100644
+index e8e8f68..7173c24 100644
 --- a/crates/core_simd/src/vector.rs
 +++ b/crates/core_simd/src/vector.rs
-@@ -75,6 +75,7 @@ where
-         Self(array)
+@@ -250,6 +250,7 @@ where
+         unsafe { intrinsics::simd_cast(self) }
      }
  
 +    /*
      /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
      /// If an index is out-of-bounds, the lane is instead selected from the `or` vector.
      ///
-@@ -297,6 +298,7 @@ where
+@@ -473,6 +474,7 @@ where
              // Cleared ☢️ *mut T Zone
          }
      }
@@ -82,26 +31,5 @@ index 7c5ec2b..c8631e8 100644
  }
  
  impl<T, const LANES: usize> Copy for Simd<T, LANES>
-diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs
-index 6a8ecd3..68fcb49 100644
---- a/crates/core_simd/tests/masks.rs
-+++ b/crates/core_simd/tests/masks.rs
-@@ -68,6 +68,7 @@ macro_rules! test_mask_api {
-                 assert_eq!(core_simd::Mask::<$type, 8>::from_int(int), mask);
-             }
- 
-+            /*
-             #[cfg(feature = "generic_const_exprs")]
-             #[test]
-             fn roundtrip_bitmask_conversion() {
-@@ -80,6 +81,7 @@ macro_rules! test_mask_api {
-                 assert_eq!(bitmask, [0b01001001, 0b10000011]);
-                 assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask);
-             }
-+            */
-         }
-     }
- }
 -- 
-2.26.2.7.g19db9cfb68
-
+2.25.1
diff --git a/compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch b/compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch
new file mode 100644
index 00000000000..d8775e2d022
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch
@@ -0,0 +1,47 @@
+From eec874c889b8d24e5ad50faded24288150f057b1 Mon Sep 17 00:00:00 2001
+From: Afonso Bordado <afonsobordado@az8.co>
+Date: Tue, 27 Sep 2022 08:13:58 +0100
+Subject: [PATCH] Disable rand tests on mingw
+
+---
+ rand_distr/src/pareto.rs            | 2 ++
+ rand_distr/tests/value_stability.rs | 4 ++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/rand_distr/src/pareto.rs b/rand_distr/src/pareto.rs
+index 217899e..9cedeb7 100644
+--- a/rand_distr/src/pareto.rs
++++ b/rand_distr/src/pareto.rs
+@@ -107,6 +107,8 @@ mod tests {
+     }
+
+     #[test]
++    // This is broken on x86_64-pc-windows-gnu presumably due to a broken powf implementation
++    #[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)]
+     fn value_stability() {
+         fn test_samples<F: Float + core::fmt::Debug, D: Distribution<F>>(
+             distr: D, zero: F, expected: &[F],
+diff --git a/rand_distr/tests/value_stability.rs b/rand_distr/tests/value_stability.rs
+index 192ba74..0101ace 100644
+--- a/rand_distr/tests/value_stability.rs
++++ b/rand_distr/tests/value_stability.rs
+@@ -72,6 +72,8 @@ fn unit_disc_stability() {
+ }
+
+ #[test]
++// This is broken on x86_64-pc-windows-gnu
++#[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)]
+ fn pareto_stability() {
+     test_samples(213, Pareto::new(1.0, 1.0).unwrap(), &[
+         1.0423688f32, 2.1235929, 4.132709, 1.4679428,
+@@ -143,6 +145,8 @@ fn inverse_gaussian_stability() {
+ }
+
+ #[test]
++// This is broken on x86_64-pc-windows-gnu
++#[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)]
+ fn gamma_stability() {
+     // Gamma has 3 cases: shape == 1, shape < 1, shape > 1
+     test_samples(223, Gamma::new(1.0, 5.0).unwrap(), &[
+--
+2.25.1
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index 14f2746ecb1..c0a2e7a7883 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2022-08-24"
+channel = "nightly-2022-10-23"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
index 091bfa1e992..d6a37789599 100644
--- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
@@ -10,6 +10,8 @@ git fetch
 git checkout -- .
 git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')"
 
+git am ../patches/*-sysroot-*.patch
+
 git apply - <<EOF
 diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
 index d95b5b7f17f..00b6f0e3635 100644
@@ -66,3 +68,7 @@ popd
 
 # FIXME remove once inline asm is fully supported
 export RUSTFLAGS="$RUSTFLAGS --cfg=rustix_use_libc"
+
+# Allow the testsuite to use llvm tools
+host_triple=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
+export LLVM_BIN_DIR="$(rustc --print sysroot)/lib/rustlib/$host_triple/bin"
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
index 944787612d8..9b5db3cf81f 100755
--- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
@@ -29,10 +29,6 @@ rm src/test/incremental/change_crate_dep_kind.rs
 rm src/test/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abort instead of exit(101)
 
 # requires compiling with -Cpanic=unwind
-rm src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs # "Cannot run dynamic test fn out-of-process"
-rm src/test/ui/async-await/async-fn-size-moved-locals.rs # -Cpanic=abort shrinks some generator by one byte
-rm src/test/ui/async-await/async-fn-size-uninit-locals.rs # same
-rm src/test/ui/generator/size-moved-locals.rs # same
 rm -r src/test/ui/macros/rfc-2011-nicer-assert-messages/
 
 # vendor intrinsics
@@ -67,6 +63,7 @@ rm src/test/ui/target-feature/missing-plusminus.rs # error not implemented
 rm src/test/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment
 rm -r src/test/run-make/emit-named-files # requires full --emit support
 rm src/test/ui/abi/stack-probes.rs # stack probes not yet implemented
+rm src/test/ui/simd/intrinsic/ptr-cast.rs # simd_expose_addr intrinsic unimplemented
 
 # optimization tests
 # ==================
@@ -110,12 +107,13 @@ rm src/test/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unorde
 # bugs in the test suite
 # ======================
 rm src/test/ui/backtrace.rs # TODO warning
-rm src/test/ui/empty_global_asm.rs # TODO add needs-asm-support
 rm src/test/ui/simple_global_asm.rs # TODO add needs-asm-support
 rm src/test/ui/test-attrs/test-type.rs # TODO panic message on stderr. correct stdout
 # not sure if this is actually a bug in the test suite, but the symbol list shows the function without leading _ for some reason
 rm -r src/test/run-make/native-link-modifier-bundle
 
+rm src/test/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
+
 echo "[TEST] rustc test suite"
 RUST_TEST_NOCAPTURE=1 COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 src/test/{codegen-units,run-make,run-pass-valgrind,ui,incremental}
 popd
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 0497c2570e6..99059e788a0 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -465,7 +465,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
             let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
             let sig = fx.bcx.import_signature(sig);
 
-            (CallTarget::Indirect(sig, method), Some(ptr))
+            (CallTarget::Indirect(sig, method), Some(ptr.get_addr(fx)))
         }
 
         // Normal call
@@ -560,7 +560,19 @@ pub(crate) fn codegen_drop<'tcx>(
         // we don't actually need to drop anything
     } else {
         match ty.kind() {
-            ty::Dynamic(..) => {
+            ty::Dynamic(_, _, ty::Dyn) => {
+                // IN THIS ARM, WE HAVE:
+                // ty = *mut (dyn Trait)
+                // which is: exists<T> ( *mut T,    Vtable<T: Trait> )
+                //                       args[0]    args[1]
+                //
+                // args = ( Data, Vtable )
+                //                  |
+                //                  v
+                //                /-------\
+                //                | ...   |
+                //                \-------/
+                //
                 let (ptr, vtable) = drop_place.to_ptr_maybe_unsized();
                 let ptr = ptr.get_addr(fx);
                 let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable.unwrap());
@@ -578,6 +590,43 @@ pub(crate) fn codegen_drop<'tcx>(
                 let sig = fx.bcx.import_signature(sig);
                 fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
             }
+            ty::Dynamic(_, _, ty::DynStar) => {
+                // IN THIS ARM, WE HAVE:
+                // ty = *mut (dyn* Trait)
+                // which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
+                //
+                // args = [ * ]
+                //          |
+                //          v
+                //      ( Data, Vtable )
+                //                |
+                //                v
+                //              /-------\
+                //              | ...   |
+                //              \-------/
+                //
+                //
+                // WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
+                //
+                // data = &(*args[0]).0    // gives a pointer to Data above (really the same pointer)
+                // vtable = (*args[0]).1   // loads the vtable out
+                // (data, vtable)          // an equivalent Rust `*mut dyn Trait`
+                //
+                // SO THEN WE CAN USE THE ABOVE CODE.
+                let (data, vtable) = drop_place.to_cvalue(fx).dyn_star_force_data_on_stack(fx);
+                let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable);
+
+                let virtual_drop = Instance {
+                    def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
+                    substs: drop_instance.substs,
+                };
+                let fn_abi =
+                    RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty());
+
+                let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
+                let sig = fx.bcx.import_signature(sig);
+                fx.bcx.ins().call_indirect(sig, drop_fn, &[data]);
+            }
             _ => {
                 assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _)));
 
diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs
index 6d321c7b298..bad8a87b9be 100644
--- a/compiler/rustc_codegen_cranelift/src/allocator.rs
+++ b/compiler/rustc_codegen_cranelift/src/allocator.rs
@@ -78,7 +78,7 @@ fn codegen_inner(
         let callee_func_id = module.declare_function(&callee_name, Linkage::Import, &sig).unwrap();
 
         let mut ctx = Context::new();
-        ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig.clone());
+        ctx.func.signature = sig.clone();
         {
             let mut func_ctx = FunctionBuilderContext::new();
             let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
@@ -116,7 +116,7 @@ fn codegen_inner(
     let callee_func_id = module.declare_function(callee_name, Linkage::Import, &sig).unwrap();
 
     let mut ctx = Context::new();
-    ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig);
+    ctx.func.signature = sig;
     {
         let mut func_ctx = FunctionBuilderContext::new();
         let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs
index b4c79096170..31d3d0e0615 100644
--- a/compiler/rustc_codegen_cranelift/src/archive.rs
+++ b/compiler/rustc_codegen_cranelift/src/archive.rs
@@ -159,6 +159,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
                         let err = err.to_string();
                         if err == "Unknown file magic" {
                             // Not an object file; skip it.
+                        } else if object::read::archive::ArchiveFile::parse(&*data).is_ok() {
+                            // Nested archive file; skip it.
                         } else {
                             sess.fatal(&format!(
                                 "error parsing `{}` during archive creation: {}",
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 4303d63fe21..a41b561598f 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -6,6 +6,8 @@ use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::layout::FnAbiOf;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 
+use cranelift_codegen::ir::UserFuncName;
+
 use crate::constant::ConstantCx;
 use crate::debuginfo::FunctionDebugContext;
 use crate::prelude::*;
@@ -64,7 +66,7 @@ pub(crate) fn codegen_fn<'tcx>(
     let mut func_ctx = FunctionBuilderContext::new();
     let mut func = cached_func;
     func.clear();
-    func.name = ExternalName::user(0, func_id.as_u32());
+    func.name = UserFuncName::user(0, func_id.as_u32());
     func.signature = sig;
     func.collect_debug_info();
 
@@ -706,9 +708,9 @@ fn codegen_stmt<'tcx>(
                     let operand = codegen_operand(fx, operand);
                     operand.unsize_value(fx, lval);
                 }
-                Rvalue::Cast(CastKind::DynStar, _, _) => {
-                    // FIXME(dyn-star)
-                    unimplemented!()
+                Rvalue::Cast(CastKind::DynStar, ref operand, _) => {
+                    let operand = codegen_operand(fx, operand);
+                    operand.coerce_dyn_star(fx, lval);
                 }
                 Rvalue::Discriminant(place) => {
                     let place = codegen_place(fx, place);
@@ -922,7 +924,7 @@ pub(crate) fn codegen_operand<'tcx>(
             let cplace = codegen_place(fx, *place);
             cplace.to_cvalue(fx)
         }
-        Operand::Constant(const_) => crate::constant::codegen_constant(fx, const_),
+        Operand::Constant(const_) => crate::constant::codegen_constant_operand(fx, const_),
     }
 }
 
diff --git a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs
index dfde9792046..f855e20e0a1 100644
--- a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs
+++ b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs
@@ -10,6 +10,7 @@ pub(super) struct ConcurrencyLimiter {
     helper_thread: Option<HelperThread>,
     state: Arc<Mutex<state::ConcurrencyLimiterState>>,
     available_token_condvar: Arc<Condvar>,
+    finished: bool,
 }
 
 impl ConcurrencyLimiter {
@@ -32,6 +33,7 @@ impl ConcurrencyLimiter {
             helper_thread: Some(helper_thread),
             state,
             available_token_condvar: Arc::new(Condvar::new()),
+            finished: false,
         }
     }
 
@@ -56,16 +58,23 @@ impl ConcurrencyLimiter {
         let mut state = self.state.lock().unwrap();
         state.job_already_done();
     }
-}
 
-impl Drop for ConcurrencyLimiter {
-    fn drop(&mut self) {
-        //
+    pub(crate) fn finished(mut self) {
         self.helper_thread.take();
 
         // Assert that all jobs have finished
         let state = Mutex::get_mut(Arc::get_mut(&mut self.state).unwrap()).unwrap();
         state.assert_done();
+
+        self.finished = true;
+    }
+}
+
+impl Drop for ConcurrencyLimiter {
+    fn drop(&mut self) {
+        if !self.finished && !std::thread::panicking() {
+            panic!("Forgot to call finished() on ConcurrencyLimiter");
+        }
     }
 }
 
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index c5f44bb8479..d4bc3543b2d 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -7,7 +7,6 @@ use rustc_middle::mir::interpret::{
 };
 use rustc_span::DUMMY_SP;
 
-use cranelift_codegen::ir::GlobalValueData;
 use cranelift_module::*;
 
 use crate::prelude::*;
@@ -81,53 +80,46 @@ pub(crate) fn codegen_tls_ref<'tcx>(
     CValue::by_val(tls_ptr, layout)
 }
 
-fn codegen_static_ref<'tcx>(
-    fx: &mut FunctionCx<'_, '_, 'tcx>,
-    def_id: DefId,
-    layout: TyAndLayout<'tcx>,
-) -> CPlace<'tcx> {
-    let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false);
-    let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
-    if fx.clif_comments.enabled() {
-        fx.add_comment(local_data_id, format!("{:?}", def_id));
-    }
-    let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id);
-    assert!(!layout.is_unsized(), "unsized statics aren't supported");
-    assert!(
-        matches!(
-            fx.bcx.func.global_values[local_data_id],
-            GlobalValueData::Symbol { tls: false, .. }
-        ),
-        "tls static referenced without Rvalue::ThreadLocalRef"
-    );
-    CPlace::for_ptr(crate::pointer::Pointer::new(global_ptr), layout)
-}
-
-pub(crate) fn codegen_constant<'tcx>(
+pub(crate) fn eval_mir_constant<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     constant: &Constant<'tcx>,
-) -> CValue<'tcx> {
-    let (const_val, ty) = match fx.monomorphize(constant.literal) {
-        ConstantKind::Ty(const_) => unreachable!("{:?}", const_),
-        ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs, promoted }, ty)
+) -> (ConstValue<'tcx>, Ty<'tcx>) {
+    let constant_kind = fx.monomorphize(constant.literal);
+    let uv = match constant_kind {
+        ConstantKind::Ty(const_) => match const_.kind() {
+            ty::ConstKind::Unevaluated(uv) => uv.expand(),
+            ty::ConstKind::Value(val) => {
+                return (fx.tcx.valtree_to_const_val((const_.ty(), val)), const_.ty());
+            }
+            err => span_bug!(
+                constant.span,
+                "encountered bad ConstKind after monomorphizing: {:?}",
+                err
+            ),
+        },
+        ConstantKind::Unevaluated(mir::UnevaluatedConst { def, .. }, _)
             if fx.tcx.is_static(def.did) =>
         {
-            assert!(substs.is_empty());
-            assert!(promoted.is_none());
-
-            return codegen_static_ref(fx, def.did, fx.layout_of(ty)).to_cvalue(fx);
-        }
-        ConstantKind::Unevaluated(unevaluated, ty) => {
-            match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
-                Ok(const_val) => (const_val, ty),
-                Err(_) => {
-                    span_bug!(constant.span, "erroneous constant not captured by required_consts");
-                }
-            }
+            span_bug!(constant.span, "MIR constant refers to static");
         }
-        ConstantKind::Val(val, ty) => (val, ty),
+        ConstantKind::Unevaluated(uv, _) => uv,
+        ConstantKind::Val(val, _) => return (val, constant_kind.ty()),
     };
 
+    (
+        fx.tcx.const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).unwrap_or_else(|_err| {
+            span_bug!(constant.span, "erroneous constant not captured by required_consts");
+        }),
+        constant_kind.ty(),
+    )
+}
+
+pub(crate) fn codegen_constant_operand<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    constant: &Constant<'tcx>,
+) -> CValue<'tcx> {
+    let (const_val, ty) = eval_mir_constant(fx, constant);
+
     codegen_const_value(fx, const_val, ty)
 }
 
@@ -244,7 +236,7 @@ pub(crate) fn codegen_const_value<'tcx>(
     }
 }
 
-pub(crate) fn pointer_for_allocation<'tcx>(
+fn pointer_for_allocation<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     alloc: ConstAllocation<'tcx>,
 ) -> crate::pointer::Pointer {
@@ -467,14 +459,13 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
     operand: &Operand<'tcx>,
 ) -> Option<ConstValue<'tcx>> {
     match operand {
-        Operand::Constant(const_) => match const_.literal {
-            ConstantKind::Ty(const_) => fx
-                .monomorphize(const_)
-                .eval_for_mir(fx.tcx, ParamEnv::reveal_all())
-                .try_to_value(fx.tcx),
+        Operand::Constant(const_) => match fx.monomorphize(const_.literal) {
+            ConstantKind::Ty(const_) => Some(
+                const_.eval_for_mir(fx.tcx, ParamEnv::reveal_all()).try_to_value(fx.tcx).unwrap(),
+            ),
             ConstantKind::Val(val, _) => Some(val),
             ConstantKind::Unevaluated(uv, _) => {
-                fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), uv, None).ok()
+                Some(fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), uv, None).unwrap())
             }
         },
         // FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 8eabe1cbcb1..f873561c171 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -106,7 +106,7 @@ impl OngoingCodegen {
             }
         }
 
-        drop(self.concurrency_limiter);
+        self.concurrency_limiter.finished();
 
         (
             CodegenResults {
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 0e77e4004c0..6a430b5215e 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -67,13 +67,12 @@ fn create_jit_module(
     hotswap: bool,
 ) -> (JITModule, CodegenCx) {
     let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
-    let imported_symbols = load_imported_symbols_for_jit(tcx.sess, crate_info);
 
     let isa = crate::build_isa(tcx.sess, backend_config);
     let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
     jit_builder.hotswap(hotswap);
     crate::compiler_builtins::register_functions_for_jit(&mut jit_builder);
-    jit_builder.symbols(imported_symbols);
+    jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info));
     jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8);
     let mut jit_module = JITModule::new(jit_builder);
 
@@ -286,10 +285,10 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
     })
 }
 
-fn load_imported_symbols_for_jit(
+fn dep_symbol_lookup_fn(
     sess: &Session,
     crate_info: CrateInfo,
-) -> Vec<(String, *const u8)> {
+) -> Box<dyn Fn(&str) -> Option<*const u8>> {
     use rustc_middle::middle::dependency_format::Linkage;
 
     let mut dylib_paths = Vec::new();
@@ -316,39 +315,23 @@ fn load_imported_symbols_for_jit(
         }
     }
 
-    let mut imported_symbols = Vec::new();
-    for path in dylib_paths {
-        use object::{Object, ObjectSymbol};
-        let lib = libloading::Library::new(&path).unwrap();
-        let obj = std::fs::read(path).unwrap();
-        let obj = object::File::parse(&*obj).unwrap();
-        imported_symbols.extend(obj.dynamic_symbols().filter_map(|symbol| {
-            let name = symbol.name().unwrap().to_string();
-            if name.is_empty() || !symbol.is_global() || symbol.is_undefined() {
-                return None;
-            }
-            if name.starts_with("rust_metadata_") {
-                // The metadata is part of a section that is not loaded by the dynamic linker in
-                // case of cg_llvm.
-                return None;
-            }
-            let dlsym_name = if cfg!(target_os = "macos") {
-                // On macOS `dlsym` expects the name without leading `_`.
-                assert!(name.starts_with('_'), "{:?}", name);
-                &name[1..]
-            } else {
-                &name
-            };
-            let symbol: libloading::Symbol<'_, *const u8> =
-                unsafe { lib.get(dlsym_name.as_bytes()) }.unwrap();
-            Some((name, *symbol))
-        }));
-        std::mem::forget(lib)
-    }
+    let imported_dylibs = Box::leak(
+        dylib_paths
+            .into_iter()
+            .map(|path| unsafe { libloading::Library::new(&path).unwrap() })
+            .collect::<Box<[_]>>(),
+    );
 
     sess.abort_if_errors();
 
-    imported_symbols
+    Box::new(move |sym_name| {
+        for dylib in &*imported_dylibs {
+            if let Ok(sym) = unsafe { dylib.get::<*const u8>(sym_name.as_bytes()) } {
+                return Some(*sym);
+            }
+        }
+        None
+    })
 }
 
 fn codegen_shim<'tcx>(
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index 8b3d475cb18..3fcc84d3929 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -27,7 +27,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
         }
 
         // Used by stdarch
-        if template[0] == InlineAsmTemplatePiece::String("movq %rbx, ".to_string())
+        if template[0] == InlineAsmTemplatePiece::String("mov ".to_string())
             && matches!(
                 template[1],
                 InlineAsmTemplatePiece::Placeholder {
@@ -36,24 +36,26 @@ pub(crate) fn codegen_inline_asm<'tcx>(
                     span: _
                 }
             )
-            && template[2] == InlineAsmTemplatePiece::String("\n".to_string())
-            && template[3] == InlineAsmTemplatePiece::String("cpuid".to_string())
-            && template[4] == InlineAsmTemplatePiece::String("\n".to_string())
-            && template[5] == InlineAsmTemplatePiece::String("xchgq %rbx, ".to_string())
+            && template[2] == InlineAsmTemplatePiece::String(", rbx".to_string())
+            && template[3] == InlineAsmTemplatePiece::String("\n".to_string())
+            && template[4] == InlineAsmTemplatePiece::String("cpuid".to_string())
+            && template[5] == InlineAsmTemplatePiece::String("\n".to_string())
+            && template[6] == InlineAsmTemplatePiece::String("xchg ".to_string())
             && matches!(
-                template[6],
+                template[7],
                 InlineAsmTemplatePiece::Placeholder {
                     operand_idx: 0,
                     modifier: Some('r'),
                     span: _
                 }
             )
+            && template[8] == InlineAsmTemplatePiece::String(", rbx".to_string())
         {
             assert_eq!(operands.len(), 4);
             let (leaf, eax_place) = match operands[1] {
                 InlineAsmOperand::InOut {
                     reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
-                    late: true,
+                    late: _,
                     ref in_value,
                     out_place: Some(out_place),
                 } => (
@@ -68,7 +70,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
                         InlineAsmRegOrRegClass::RegClass(InlineAsmRegClass::X86(
                             X86InlineAsmRegClass::reg,
                         )),
-                    late: true,
+                    late: _,
                     place: Some(place),
                 } => crate::base::codegen_place(fx, place),
                 _ => unreachable!(),
@@ -76,7 +78,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
             let (sub_leaf, ecx_place) = match operands[2] {
                 InlineAsmOperand::InOut {
                     reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)),
-                    late: true,
+                    late: _,
                     ref in_value,
                     out_place: Some(out_place),
                 } => (
@@ -88,7 +90,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
             let edx_place = match operands[3] {
                 InlineAsmOperand::Out {
                     reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)),
-                    late: true,
+                    late: _,
                     place: Some(place),
                 } => crate::base::codegen_place(fx, place),
                 _ => unreachable!(),
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
index a799dca938e..783d426c30b 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
@@ -14,6 +14,10 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
     target: Option<BasicBlock>,
 ) {
     match intrinsic {
+        "llvm.x86.sse2.pause" | "llvm.aarch64.isb" => {
+            // Spin loop hint
+        }
+
         // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
         "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => {
             intrinsic_args!(fx, args => (a); intrinsic);
@@ -25,8 +29,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
             let mut res = fx.bcx.ins().iconst(types::I32, 0);
 
             for lane in (0..lane_count).rev() {
-                let a_lane =
-                    a.value_field(fx, mir::Field::new(lane.try_into().unwrap())).load_scalar(fx);
+                let a_lane = a.value_lane(fx, lane).load_scalar(fx);
 
                 // cast float to int
                 let a_lane = match lane_ty {
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 2e4ca594f91..0302b843aa2 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -84,6 +84,30 @@ fn simd_for_each_lane<'tcx>(
     }
 }
 
+fn simd_pair_for_each_lane_typed<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    x: CValue<'tcx>,
+    y: CValue<'tcx>,
+    ret: CPlace<'tcx>,
+    f: &dyn Fn(&mut FunctionCx<'_, '_, 'tcx>, CValue<'tcx>, CValue<'tcx>) -> CValue<'tcx>,
+) {
+    assert_eq!(x.layout(), y.layout());
+    let layout = x.layout();
+
+    let (lane_count, _lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
+    let (ret_lane_count, _ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
+    assert_eq!(lane_count, ret_lane_count);
+
+    for lane_idx in 0..lane_count {
+        let x_lane = x.value_lane(fx, lane_idx);
+        let y_lane = y.value_lane(fx, lane_idx);
+
+        let res_lane = f(fx, x_lane, y_lane);
+
+        ret.place_lane(fx, lane_idx).write_cvalue(fx, res_lane);
+    }
+}
+
 fn simd_pair_for_each_lane<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     x: CValue<'tcx>,
@@ -504,37 +528,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
                 _ => unreachable!(),
             };
 
-            let signed = type_sign(lhs.layout().ty);
-
-            let checked_res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs);
-
-            let (val, has_overflow) = checked_res.load_scalar_pair(fx);
-            let clif_ty = fx.clif_type(lhs.layout().ty).unwrap();
-
-            let (min, max) = type_min_max_value(&mut fx.bcx, clif_ty, signed);
-
-            let val = match (intrinsic, signed) {
-                (sym::saturating_add, false) => fx.bcx.ins().select(has_overflow, max, val),
-                (sym::saturating_sub, false) => fx.bcx.ins().select(has_overflow, min, val),
-                (sym::saturating_add, true) => {
-                    let rhs = rhs.load_scalar(fx);
-                    let rhs_ge_zero =
-                        fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
-                    let sat_val = fx.bcx.ins().select(rhs_ge_zero, max, min);
-                    fx.bcx.ins().select(has_overflow, sat_val, val)
-                }
-                (sym::saturating_sub, true) => {
-                    let rhs = rhs.load_scalar(fx);
-                    let rhs_ge_zero =
-                        fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
-                    let sat_val = fx.bcx.ins().select(rhs_ge_zero, min, max);
-                    fx.bcx.ins().select(has_overflow, sat_val, val)
-                }
-                _ => unreachable!(),
-            };
-
-            let res = CValue::by_val(val, lhs.layout());
-
+            let res = crate::num::codegen_saturating_int_binop(fx, bin_op, lhs, rhs);
             ret.write_cvalue(fx, res);
         }
         sym::rotate_left => {
@@ -819,8 +813,8 @@ fn codegen_regular_intrinsic_call<'tcx>(
         sym::ptr_guaranteed_cmp => {
             intrinsic_args!(fx, args => (a, b); intrinsic);
 
-            let val = crate::num::codegen_ptr_binop(fx, BinOp::Eq, a, b);
-            ret.write_cvalue(fx, val);
+            let val = crate::num::codegen_ptr_binop(fx, BinOp::Eq, a, b).load_scalar(fx);
+            ret.write_cvalue(fx, CValue::by_val(val, fx.layout_of(fx.tcx.types.u8)));
         }
 
         sym::caller_location => {
@@ -1206,7 +1200,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             // FIXME once unwinding is supported, change this to actually catch panics
             let f_sig = fx.bcx.func.import_signature(Signature {
                 call_conv: fx.target_config.default_call_conv,
-                params: vec![AbiParam::new(fx.bcx.func.dfg.value_type(data))],
+                params: vec![AbiParam::new(pointer_ty(fx.tcx))],
                 returns: vec![],
             });
 
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index 1f358b1bbb9..51fce8c854b 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -2,6 +2,7 @@
 
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_span::Symbol;
+use rustc_target::abi::Endian;
 
 use super::*;
 use crate::prelude::*;
@@ -26,7 +27,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
     span: Span,
 ) {
     match intrinsic {
-        sym::simd_cast => {
+        sym::simd_as | sym::simd_cast => {
             intrinsic_args!(fx, args => (a); intrinsic);
 
             if !a.layout().ty.is_simd() {
@@ -162,6 +163,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                     }
                 }
             } else {
+                // FIXME remove this case
                 intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap()
             };
 
@@ -650,8 +652,128 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
             }
         }
 
-        // simd_saturating_*
-        // simd_bitmask
+        sym::simd_select_bitmask => {
+            intrinsic_args!(fx, args => (m, a, b); intrinsic);
+
+            if !a.layout().ty.is_simd() {
+                report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty);
+                return;
+            }
+            assert_eq!(a.layout(), b.layout());
+
+            let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
+            let lane_layout = fx.layout_of(lane_ty);
+
+            let m = m.load_scalar(fx);
+
+            for lane in 0..lane_count {
+                let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(lane) as i64);
+                let m_lane = fx.bcx.ins().band_imm(m_lane, 1);
+                let a_lane = a.value_lane(fx, lane).load_scalar(fx);
+                let b_lane = b.value_lane(fx, lane).load_scalar(fx);
+
+                let m_lane = fx.bcx.ins().icmp_imm(IntCC::Equal, m_lane, 0);
+                let res_lane =
+                    CValue::by_val(fx.bcx.ins().select(m_lane, b_lane, a_lane), lane_layout);
+
+                ret.place_lane(fx, lane).write_cvalue(fx, res_lane);
+            }
+        }
+
+        sym::simd_bitmask => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
+            let lane_clif_ty = fx.clif_type(lane_ty).unwrap();
+
+            // The `fn simd_bitmask(vector) -> unsigned integer` intrinsic takes a
+            // vector mask and returns the most significant bit (MSB) of each lane in the form
+            // of either:
+            // * an unsigned integer
+            // * an array of `u8`
+            // If the vector has less than 8 lanes, a u8 is returned with zeroed trailing bits.
+            //
+            // The bit order of the result depends on the byte endianness, LSB-first for little
+            // endian and MSB-first for big endian.
+            let expected_int_bits = lane_count.max(8);
+            let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 0) as u64);
+
+            match lane_ty.kind() {
+                ty::Int(_) | ty::Uint(_) => {}
+                _ => {
+                    fx.tcx.sess.span_fatal(
+                        span,
+                        &format!(
+                            "invalid monomorphization of `simd_bitmask` intrinsic: \
+                            vector argument `{}`'s element type `{}`, expected integer element \
+                            type",
+                            a.layout().ty,
+                            lane_ty
+                        ),
+                    );
+                }
+            }
+
+            let res_type =
+                Type::int_with_byte_size(u16::try_from(expected_bytes).unwrap()).unwrap();
+            let mut res = fx.bcx.ins().iconst(res_type, 0);
+
+            let lanes = match fx.tcx.sess.target.endian {
+                Endian::Big => Box::new(0..lane_count) as Box<dyn Iterator<Item = u64>>,
+                Endian::Little => Box::new((0..lane_count).rev()) as Box<dyn Iterator<Item = u64>>,
+            };
+            for lane in lanes {
+                let a_lane = a.value_lane(fx, lane).load_scalar(fx);
+
+                // extract sign bit of an int
+                let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_clif_ty.bits() - 1));
+
+                // shift sign bit into result
+                let a_lane_sign = clif_intcast(fx, a_lane_sign, res_type, false);
+                res = fx.bcx.ins().ishl_imm(res, 1);
+                res = fx.bcx.ins().bor(res, a_lane_sign);
+            }
+
+            match ret.layout().ty.kind() {
+                ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => {}
+                ty::Array(elem, len)
+                    if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
+                        && len.try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all())
+                            == Some(expected_bytes) => {}
+                _ => {
+                    fx.tcx.sess.span_fatal(
+                        span,
+                        &format!(
+                            "invalid monomorphization of `simd_bitmask` intrinsic: \
+                            cannot return `{}`, expected `u{}` or `[u8; {}]`",
+                            ret.layout().ty,
+                            expected_int_bits,
+                            expected_bytes
+                        ),
+                    );
+                }
+            }
+
+            let res = CValue::by_val(res, ret.layout());
+            ret.write_cvalue(fx, res);
+        }
+
+        sym::simd_saturating_add | sym::simd_saturating_sub => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            let bin_op = match intrinsic {
+                sym::simd_saturating_add => BinOp::Add,
+                sym::simd_saturating_sub => BinOp::Sub,
+                _ => unreachable!(),
+            };
+
+            // FIXME use vector instructions when possible
+            simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| {
+                crate::num::codegen_saturating_int_binop(fx, bin_op, x_lane, y_lane)
+            });
+        }
+
+        // simd_arith_offset
         // simd_scatter
         // simd_gather
         _ => {
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 913414e7618..629d79d5012 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -96,8 +96,8 @@ mod prelude {
     pub(crate) use cranelift_codegen::ir::function::Function;
     pub(crate) use cranelift_codegen::ir::types;
     pub(crate) use cranelift_codegen::ir::{
-        AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc,
-        StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value,
+        AbiParam, Block, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot,
+        StackSlotData, StackSlotKind, TrapCode, Type, Value,
     };
     pub(crate) use cranelift_codegen::isa::{self, CallConv};
     pub(crate) use cranelift_codegen::Context;
@@ -251,7 +251,6 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
 
     let mut flags_builder = settings::builder();
     flags_builder.enable("is_pic").unwrap();
-    flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
     let enable_verifier = if backend_config.enable_verifier { "true" } else { "false" };
     flags_builder.set("enable_verifier", enable_verifier).unwrap();
     flags_builder.set("regalloc_checker", enable_verifier).unwrap();
@@ -279,6 +278,15 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
         }
     }
 
+    if target_triple.architecture == target_lexicon::Architecture::X86_64 {
+        // Windows depends on stack probes to grow the committed part of the stack
+        flags_builder.enable("enable_probestack").unwrap();
+        flags_builder.set("probestack_strategy", "inline").unwrap();
+    } else {
+        // __cranelift_probestack is not provided and inline stack probes are only supported on x86_64
+        flags_builder.set("enable_probestack", "false").unwrap();
+    }
+
     let flags = settings::Flags::new(flags_builder);
 
     let isa_builder = match sess.opts.cg.target_cpu.as_deref() {
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index 3c024a84d90..cae6312a607 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -75,7 +75,7 @@ pub(crate) fn maybe_create_entry_wrapper(
         let main_func_id = m.declare_function(main_name, Linkage::Import, &main_sig).unwrap();
 
         let mut ctx = Context::new();
-        ctx.func = Function::with_name_signature(ExternalName::user(0, 0), cmain_sig);
+        ctx.func.signature = cmain_sig;
         {
             let mut func_ctx = FunctionBuilderContext::new();
             let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs
index 4ce8adb182e..ecbab408ded 100644
--- a/compiler/rustc_codegen_cranelift/src/num.rs
+++ b/compiler/rustc_codegen_cranelift/src/num.rs
@@ -150,18 +150,12 @@ pub(crate) fn codegen_int_binop<'tcx>(
         BinOp::BitXor => b.bxor(lhs, rhs),
         BinOp::BitAnd => b.band(lhs, rhs),
         BinOp::BitOr => b.bor(lhs, rhs),
-        BinOp::Shl => {
-            let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
-            let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
-            fx.bcx.ins().ishl(lhs, actual_shift)
-        }
+        BinOp::Shl => b.ishl(lhs, rhs),
         BinOp::Shr => {
-            let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
-            let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
             if signed {
-                fx.bcx.ins().sshr(lhs, actual_shift)
+                b.sshr(lhs, rhs)
             } else {
-                fx.bcx.ins().ushr(lhs, actual_shift)
+                b.ushr(lhs, rhs)
             }
         }
         // Compare binops handles by `codegen_binop`.
@@ -279,22 +273,15 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
             }
         }
         BinOp::Shl => {
-            let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
-            let masked_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
-            let val = fx.bcx.ins().ishl(lhs, masked_shift);
+            let val = fx.bcx.ins().ishl(lhs, rhs);
             let ty = fx.bcx.func.dfg.value_type(val);
             let max_shift = i64::from(ty.bits()) - 1;
             let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift);
             (val, has_overflow)
         }
         BinOp::Shr => {
-            let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
-            let masked_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
-            let val = if !signed {
-                fx.bcx.ins().ushr(lhs, masked_shift)
-            } else {
-                fx.bcx.ins().sshr(lhs, masked_shift)
-            };
+            let val =
+                if !signed { fx.bcx.ins().ushr(lhs, rhs) } else { fx.bcx.ins().sshr(lhs, rhs) };
             let ty = fx.bcx.func.dfg.value_type(val);
             let max_shift = i64::from(ty.bits()) - 1;
             let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift);
@@ -309,6 +296,42 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
     CValue::by_val_pair(res, has_overflow, out_layout)
 }
 
+pub(crate) fn codegen_saturating_int_binop<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    bin_op: BinOp,
+    lhs: CValue<'tcx>,
+    rhs: CValue<'tcx>,
+) -> CValue<'tcx> {
+    assert_eq!(lhs.layout().ty, rhs.layout().ty);
+
+    let signed = type_sign(lhs.layout().ty);
+    let clif_ty = fx.clif_type(lhs.layout().ty).unwrap();
+    let (min, max) = type_min_max_value(&mut fx.bcx, clif_ty, signed);
+
+    let checked_res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs);
+    let (val, has_overflow) = checked_res.load_scalar_pair(fx);
+
+    let val = match (bin_op, signed) {
+        (BinOp::Add, false) => fx.bcx.ins().select(has_overflow, max, val),
+        (BinOp::Sub, false) => fx.bcx.ins().select(has_overflow, min, val),
+        (BinOp::Add, true) => {
+            let rhs = rhs.load_scalar(fx);
+            let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
+            let sat_val = fx.bcx.ins().select(rhs_ge_zero, max, min);
+            fx.bcx.ins().select(has_overflow, sat_val, val)
+        }
+        (BinOp::Sub, true) => {
+            let rhs = rhs.load_scalar(fx);
+            let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
+            let sat_val = fx.bcx.ins().select(rhs_ge_zero, min, max);
+            fx.bcx.ins().select(has_overflow, sat_val, val)
+        }
+        _ => unreachable!(),
+    };
+
+    CValue::by_val(val, lhs.layout())
+}
+
 pub(crate) fn codegen_float_binop<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     bin_op: BinOp,
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs
index dd9d891ddbd..9c88f7dbcda 100644
--- a/compiler/rustc_codegen_cranelift/src/unsize.rs
+++ b/compiler/rustc_codegen_cranelift/src/unsize.rs
@@ -25,7 +25,12 @@ pub(crate) fn unsized_info<'tcx>(
             .bcx
             .ins()
             .iconst(fx.pointer_type, len.eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64),
-        (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
+        (
+            &ty::Dynamic(ref data_a, _, src_dyn_kind),
+            &ty::Dynamic(ref data_b, _, target_dyn_kind),
+        ) => {
+            assert_eq!(src_dyn_kind, target_dyn_kind);
+
             let old_info =
                 old_info.expect("unsized_info: missing old info for trait upcasting coercion");
             if data_a.principal_def_id() == data_b.principal_def_id() {
@@ -101,6 +106,21 @@ fn unsize_ptr<'tcx>(
     }
 }
 
+/// Coerces `src` to `dst_ty` which is guaranteed to be a `dyn*` type.
+pub(crate) fn cast_to_dyn_star<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    src: Value,
+    src_ty_and_layout: TyAndLayout<'tcx>,
+    dst_ty: Ty<'tcx>,
+    old_info: Option<Value>,
+) -> (Value, Value) {
+    assert!(
+        matches!(dst_ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
+        "destination type must be a dyn*"
+    );
+    (src, unsized_info(fx, src_ty_and_layout.ty, dst_ty, old_info))
+}
+
 /// Coerce `src`, which is a reference to a value of type `src_ty`,
 /// to a value of type `dst_ty` and store the result in `dst`
 pub(crate) fn coerce_unsized_into<'tcx>(
@@ -147,6 +167,24 @@ pub(crate) fn coerce_unsized_into<'tcx>(
     }
 }
 
+pub(crate) fn coerce_dyn_star<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    src: CValue<'tcx>,
+    dst: CPlace<'tcx>,
+) {
+    let (data, extra) = if let ty::Dynamic(_, _, ty::DynStar) = src.layout().ty.kind() {
+        let (data, vtable) = src.load_scalar_pair(fx);
+        (data, Some(vtable))
+    } else {
+        let data = src.load_scalar(fx);
+        (data, None)
+    };
+
+    let (data, vtable) = cast_to_dyn_star(fx, data, src.layout(), dst.layout().ty, extra);
+
+    dst.write_cvalue(fx, CValue::by_val_pair(data, vtable, dst.layout()));
+}
+
 // Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/glue.rs
 
 pub(crate) fn size_and_align_of_dst<'tcx>(
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index 3fa3e3657cb..c3dfbd37279 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -107,6 +107,50 @@ impl<'tcx> CValue<'tcx> {
         }
     }
 
+    // FIXME remove
+    // Forces the data value of a dyn* value to the stack and returns a pointer to it as well as the
+    // vtable pointer.
+    pub(crate) fn dyn_star_force_data_on_stack(
+        self,
+        fx: &mut FunctionCx<'_, '_, 'tcx>,
+    ) -> (Value, Value) {
+        assert!(self.1.ty.is_dyn_star());
+
+        match self.0 {
+            CValueInner::ByRef(ptr, None) => {
+                let (a_scalar, b_scalar) = match self.1.abi {
+                    Abi::ScalarPair(a, b) => (a, b),
+                    _ => unreachable!("dyn_star_force_data_on_stack({:?})", self),
+                };
+                let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
+                let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar);
+                let mut flags = MemFlags::new();
+                flags.set_notrap();
+                let vtable = ptr.offset(fx, b_offset).load(fx, clif_ty2, flags);
+                (ptr.get_addr(fx), vtable)
+            }
+            CValueInner::ByValPair(data, vtable) => {
+                let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {
+                    kind: StackSlotKind::ExplicitSlot,
+                    // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to
+                    // specify stack slot alignment.
+                    size: (u32::try_from(fx.target_config.pointer_type().bytes()).unwrap() + 15)
+                        / 16
+                        * 16,
+                });
+                let data_ptr = Pointer::stack_slot(stack_slot);
+                let mut flags = MemFlags::new();
+                flags.set_notrap();
+                data_ptr.store(fx, data, flags);
+
+                (data_ptr.get_addr(fx), vtable)
+            }
+            CValueInner::ByRef(_, Some(_)) | CValueInner::ByVal(_) => {
+                unreachable!("dyn_star_force_data_on_stack({:?})", self)
+            }
+        }
+    }
+
     pub(crate) fn try_to_ptr(self) -> Option<(Pointer, Option<Value>)> {
         match self.0 {
             CValueInner::ByRef(ptr, meta) => Some((ptr, meta)),
@@ -236,6 +280,10 @@ impl<'tcx> CValue<'tcx> {
         crate::unsize::coerce_unsized_into(fx, self, dest);
     }
 
+    pub(crate) fn coerce_dyn_star(self, fx: &mut FunctionCx<'_, '_, 'tcx>, dest: CPlace<'tcx>) {
+        crate::unsize::coerce_dyn_star(fx, self, dest);
+    }
+
     /// If `ty` is signed, `const_val` must already be sign extended.
     pub(crate) fn const_val(
         fx: &mut FunctionCx<'_, '_, 'tcx>,
diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs
index 36b3725ef42..f04fb82de8c 100644
--- a/compiler/rustc_codegen_cranelift/src/vtable.rs
+++ b/compiler/rustc_codegen_cranelift/src/vtable.rs
@@ -45,12 +45,26 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     arg: CValue<'tcx>,
     idx: usize,
-) -> (Value, Value) {
-    let (ptr, vtable) = if let Abi::ScalarPair(_, _) = arg.layout().abi {
-        arg.load_scalar_pair(fx)
-    } else {
-        let (ptr, vtable) = arg.try_to_ptr().unwrap();
-        (ptr.get_addr(fx), vtable.unwrap())
+) -> (Pointer, Value) {
+    let (ptr, vtable) = 'block: {
+        if let ty::Ref(_, ty, _) = arg.layout().ty.kind() {
+            if ty.is_dyn_star() {
+                let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap().ty);
+                let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout);
+                let ptr = dyn_star.place_field(fx, mir::Field::new(0)).to_ptr();
+                let vtable =
+                    dyn_star.place_field(fx, mir::Field::new(1)).to_cvalue(fx).load_scalar(fx);
+                break 'block (ptr, vtable);
+            }
+        }
+
+        if let Abi::ScalarPair(_, _) = arg.layout().abi {
+            let (ptr, vtable) = arg.load_scalar_pair(fx);
+            (Pointer::new(ptr), vtable)
+        } else {
+            let (ptr, vtable) = arg.try_to_ptr().unwrap();
+            (ptr, vtable.unwrap())
+        }
     };
 
     let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs
index d7816e395c8..15ad90f9043 100644
--- a/compiler/rustc_codegen_gcc/src/errors.rs
+++ b/compiler/rustc_codegen_gcc/src/errors.rs
@@ -17,7 +17,7 @@ impl IntoDiagnosticArg for ExitCode {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::ranlib_failure)]
+#[diag(codegen_gcc_ranlib_failure)]
 pub(crate) struct RanlibFailure {
     exit_code: ExitCode,
 }
@@ -29,7 +29,7 @@ impl RanlibFailure {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_basic_integer, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_basic_integer, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationBasicInteger<'a> {
     #[primary_span]
     pub span: Span,
@@ -38,7 +38,7 @@ pub(crate) struct InvalidMonomorphizationBasicInteger<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_invalid_float_vector, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_invalid_float_vector, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationInvalidFloatVector<'a> {
     #[primary_span]
     pub span: Span,
@@ -48,7 +48,7 @@ pub(crate) struct InvalidMonomorphizationInvalidFloatVector<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_not_float, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_not_float, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationNotFloat<'a> {
     #[primary_span]
     pub span: Span,
@@ -57,7 +57,7 @@ pub(crate) struct InvalidMonomorphizationNotFloat<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_unrecognized, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_unrecognized, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationUnrecognized {
     #[primary_span]
     pub span: Span,
@@ -65,7 +65,7 @@ pub(crate) struct InvalidMonomorphizationUnrecognized {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_expected_signed_unsigned, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_expected_signed_unsigned, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationExpectedSignedUnsigned<'a> {
     #[primary_span]
     pub span: Span,
@@ -75,7 +75,7 @@ pub(crate) struct InvalidMonomorphizationExpectedSignedUnsigned<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_unsupported_element, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_unsupported_element, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationUnsupportedElement<'a> {
     #[primary_span]
     pub span: Span,
@@ -86,7 +86,7 @@ pub(crate) struct InvalidMonomorphizationUnsupportedElement<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_invalid_bitmask, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_invalid_bitmask, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationInvalidBitmask<'a> {
     #[primary_span]
     pub span: Span,
@@ -97,7 +97,7 @@ pub(crate) struct InvalidMonomorphizationInvalidBitmask<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_simd_shuffle, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_simd_shuffle, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationSimdShuffle<'a> {
     #[primary_span]
     pub span: Span,
@@ -106,7 +106,7 @@ pub(crate) struct InvalidMonomorphizationSimdShuffle<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_expected_simd, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_expected_simd, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> {
     #[primary_span]
     pub span: Span,
@@ -116,7 +116,7 @@ pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_mask_type, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_mask_type, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationMaskType<'a> {
     #[primary_span]
     pub span: Span,
@@ -125,7 +125,7 @@ pub(crate) struct InvalidMonomorphizationMaskType<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_return_length, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_return_length, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationReturnLength<'a> {
     #[primary_span]
     pub span: Span,
@@ -136,7 +136,7 @@ pub(crate) struct InvalidMonomorphizationReturnLength<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_return_length_input_type, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_return_length_input_type, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationReturnLengthInputType<'a> {
     #[primary_span]
     pub span: Span,
@@ -148,7 +148,7 @@ pub(crate) struct InvalidMonomorphizationReturnLengthInputType<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_return_element, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_return_element, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationReturnElement<'a> {
     #[primary_span]
     pub span: Span,
@@ -160,7 +160,7 @@ pub(crate) struct InvalidMonomorphizationReturnElement<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_return_type, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_return_type, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationReturnType<'a> {
     #[primary_span]
     pub span: Span,
@@ -171,7 +171,7 @@ pub(crate) struct InvalidMonomorphizationReturnType<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_inserted_type, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_inserted_type, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationInsertedType<'a> {
     #[primary_span]
     pub span: Span,
@@ -182,7 +182,7 @@ pub(crate) struct InvalidMonomorphizationInsertedType<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_return_integer_type, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_return_integer_type, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationReturnIntegerType<'a> {
     #[primary_span]
     pub span: Span,
@@ -192,7 +192,7 @@ pub(crate) struct InvalidMonomorphizationReturnIntegerType<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_mismatched_lengths, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_mismatched_lengths, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationMismatchedLengths {
     #[primary_span]
     pub span: Span,
@@ -202,7 +202,7 @@ pub(crate) struct InvalidMonomorphizationMismatchedLengths {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_unsupported_cast, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_unsupported_cast, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationUnsupportedCast<'a> {
     #[primary_span]
     pub span: Span,
@@ -214,7 +214,7 @@ pub(crate) struct InvalidMonomorphizationUnsupportedCast<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::invalid_monomorphization_unsupported_operation, code = "E0511")]
+#[diag(codegen_gcc_invalid_monomorphization_unsupported_operation, code = "E0511")]
 pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> {
     #[primary_span]
     pub span: Span,
@@ -224,18 +224,18 @@ pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::linkage_const_or_mut_type)]
+#[diag(codegen_gcc_linkage_const_or_mut_type)]
 pub(crate) struct LinkageConstOrMutType {
     #[primary_span]
     pub span: Span
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::lto_not_supported)]
+#[diag(codegen_gcc_lto_not_supported)]
 pub(crate) struct LTONotSupported;
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc::unwinding_inline_asm)]
+#[diag(codegen_gcc_unwinding_inline_asm)]
 pub(crate) struct UnwindingInlineAsm {
     #[primary_span]
     pub span: Span
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index cef7bf1e803..a49cc7f8d66 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -32,8 +32,8 @@ pub const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin";
 
 pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
     match crate_type {
-        CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => true,
-        CrateType::Dylib | CrateType::Rlib | CrateType::ProcMacro => false,
+        CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true,
+        CrateType::Rlib | CrateType::ProcMacro => false,
     }
 }
 
@@ -73,17 +73,6 @@ fn prepare_lto(
     // with either fat or thin LTO
     let mut upstream_modules = Vec::new();
     if cgcx.lto != Lto::ThinLocal {
-        if cgcx.opts.cg.prefer_dynamic {
-            diag_handler
-                .struct_err("cannot prefer dynamic linking when performing LTO")
-                .note(
-                    "only 'staticlib', 'bin', and 'cdylib' outputs are \
-                               supported with LTO",
-                )
-                .emit();
-            return Err(FatalError);
-        }
-
         // Make sure we actually can run LTO
         for crate_type in cgcx.crate_types.iter() {
             if !crate_type_allows_lto(*crate_type) {
@@ -92,9 +81,25 @@ fn prepare_lto(
                                             static library outputs",
                 );
                 return Err(e);
+            } else if *crate_type == CrateType::Dylib {
+                if !cgcx.opts.unstable_opts.dylib_lto {
+                    return Err(diag_handler
+                        .fatal("lto cannot be used for `dylib` crate type without `-Zdylib-lto`"));
+                }
             }
         }
 
+        if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto {
+            diag_handler
+                .struct_err("cannot prefer dynamic linking when performing LTO")
+                .note(
+                    "only 'staticlib', 'bin', and 'cdylib' outputs are \
+                               supported with LTO",
+                )
+                .emit();
+            return Err(FatalError);
+        }
+
         for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() {
             let exported_symbols =
                 cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs
index b83c1e8f08f..6f0d1b7ce84 100644
--- a/compiler/rustc_codegen_llvm/src/callee.rs
+++ b/compiler/rustc_codegen_llvm/src/callee.rs
@@ -179,7 +179,8 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
             // MinGW: For backward compatibility we rely on the linker to decide whether it
             // should use dllimport for functions.
             if cx.use_dll_storage_attrs
-                && tcx.is_dllimport_foreign_item(instance_def_id)
+                && let Some(library) = tcx.native_library(instance_def_id)
+                && library.kind.is_dllimport()
                 && !matches!(tcx.sess.target.env.as_ref(), "gnu" | "uclibc")
             {
                 llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index ee2fc65e37b..dd3c43ba5ca 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -332,7 +332,10 @@ impl<'ll> CodegenCx<'ll, '_> {
             }
         }
 
-        if self.use_dll_storage_attrs && self.tcx.is_dllimport_foreign_item(def_id) {
+        if self.use_dll_storage_attrs
+            && let Some(library) = self.tcx.native_library(def_id)
+            && library.kind.is_dllimport()
+        {
             // For foreign (native) libs we know the exact storage type to use.
             unsafe {
                 llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 88b584c3086..a0b5e3b6daf 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -11,7 +11,7 @@ use rustc_metadata::find_native_static_library;
 use rustc_metadata::fs::{emit_metadata, METADATA_FILENAME};
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
-use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
+use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Lto, Strip};
 use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
 use rustc_session::cstore::DllImport;
 use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
@@ -39,6 +39,7 @@ use cc::windows_registry;
 use regex::Regex;
 use tempfile::Builder as TempFileBuilder;
 
+use itertools::Itertools;
 use std::borrow::Borrow;
 use std::cell::OnceCell;
 use std::collections::BTreeSet;
@@ -208,11 +209,29 @@ pub fn link_binary<'a>(
 }
 
 pub fn each_linked_rlib(
+    sess: &Session,
     info: &CrateInfo,
     f: &mut dyn FnMut(CrateNum, &Path),
 ) -> Result<(), errors::LinkRlibError> {
     let crates = info.used_crates.iter();
     let mut fmts = None;
+
+    let lto_active = matches!(sess.lto(), Lto::Fat | Lto::Thin);
+    if lto_active {
+        for combination in info.dependency_formats.iter().combinations(2) {
+            let (ty1, list1) = &combination[0];
+            let (ty2, list2) = &combination[1];
+            if list1 != list2 {
+                return Err(errors::LinkRlibError::IncompatibleDependencyFormats {
+                    ty1: format!("{ty1:?}"),
+                    ty2: format!("{ty2:?}"),
+                    list1: format!("{list1:?}"),
+                    list2: format!("{list2:?}"),
+                });
+            }
+        }
+    }
+
     for (ty, list) in info.dependency_formats.iter() {
         match ty {
             CrateType::Executable
@@ -222,6 +241,10 @@ pub fn each_linked_rlib(
                 fmts = Some(list);
                 break;
             }
+            CrateType::Dylib if lto_active => {
+                fmts = Some(list);
+                break;
+            }
             _ => {}
         }
     }
@@ -490,7 +513,7 @@ fn link_staticlib<'a>(
     )?;
     let mut all_native_libs = vec![];
 
-    let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| {
+    let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| {
         let name = codegen_results.crate_info.crate_name[&cnum];
         let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
 
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index b92e146bee2..99ddd176478 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -117,6 +117,10 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
         "riscv32" => Architecture::Riscv32,
         "riscv64" => Architecture::Riscv64,
         "sparc64" => Architecture::Sparc64,
+        "avr" => Architecture::Avr,
+        "msp430" => Architecture::Msp430,
+        "hexagon" => Architecture::Hexagon,
+        "bpf" => Architecture::Bpf,
         // Unsupported architecture.
         _ => return None,
     };
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 8d7e2c5cf39..c2ecc41601c 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -13,7 +13,7 @@ use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::{self, SymbolName, TyCtxt};
-use rustc_session::config::CrateType;
+use rustc_session::config::{CrateType, OomStrategy};
 use rustc_target::spec::SanitizerSet;
 
 pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
@@ -76,7 +76,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
             // let it through if it's included statically.
             match tcx.hir().get_by_def_id(def_id) {
                 Node::ForeignItem(..) => {
-                    tcx.is_statically_included_foreign_item(def_id).then_some(def_id)
+                    tcx.native_library(def_id).map_or(false, |library| library.kind.is_statically_included()).then_some(def_id)
                 }
 
                 // Only consider nodes that actually have exported symbols.
@@ -206,6 +206,15 @@ fn exported_symbols_provider_local<'tcx>(
                 },
             ));
         }
+
+        symbols.push((
+            ExportedSymbol::NoDefId(SymbolName::new(tcx, OomStrategy::SYMBOL)),
+            SymbolExportInfo {
+                level: SymbolExportLevel::Rust,
+                kind: SymbolExportKind::Text,
+                used: false,
+            },
+        ));
     }
 
     if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() {
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index a292bfce31e..d0ac016b02e 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -999,6 +999,14 @@ fn start_executing_work<B: ExtraBackendMethods>(
     let coordinator_send = tx_to_llvm_workers;
     let sess = tcx.sess;
 
+    let mut each_linked_rlib_for_lto = Vec::new();
+    drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| {
+        if link::ignored_for_lto(sess, crate_info, cnum) {
+            return;
+        }
+        each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
+    }));
+
     // Compute the set of symbols we need to retain when doing LTO (if we need to)
     let exported_symbols = {
         let mut exported_symbols = FxHashMap::default();
@@ -1020,7 +1028,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
             }
             Lto::Fat | Lto::Thin => {
                 exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
-                for &cnum in tcx.crates(()).iter() {
+                for &(cnum, ref _path) in &each_linked_rlib_for_lto {
                     exported_symbols.insert(cnum, copy_symbols(cnum));
                 }
                 Some(Arc::new(exported_symbols))
@@ -1040,14 +1048,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
         })
         .expect("failed to spawn helper thread");
 
-    let mut each_linked_rlib_for_lto = Vec::new();
-    drop(link::each_linked_rlib(crate_info, &mut |cnum, path| {
-        if link::ignored_for_lto(sess, crate_info, cnum) {
-            return;
-        }
-        each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
-    }));
-
     let ol =
         if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
             // If we know that we won’t be doing codegen, create target machines without optimisation.
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 135ed680da2..e05646e1e86 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -666,10 +666,8 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
                     hcx.while_hashing_spans(false, |hcx| {
                         ct.to_valtree().hash_stable(hcx, &mut hasher)
                     });
-                    // Note: Don't use `StableHashResult` impl of `u64` here directly, since that
-                    // would lead to endianness problems.
-                    let hash: u128 = hasher.finish();
-                    (hash.to_le() as u64).to_le()
+                    let hash: u64 = hasher.finish();
+                    hash
                 });
 
                 if cpp_like_debuginfo(tcx) {
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 0ffe8872022..ebb531f1c43 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -13,43 +13,43 @@ use std::path::{Path, PathBuf};
 use std::process::ExitStatus;
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::lib_def_write_failure)]
+#[diag(codegen_ssa_lib_def_write_failure)]
 pub struct LibDefWriteFailure {
     pub error: Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::version_script_write_failure)]
+#[diag(codegen_ssa_version_script_write_failure)]
 pub struct VersionScriptWriteFailure {
     pub error: Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::symbol_file_write_failure)]
+#[diag(codegen_ssa_symbol_file_write_failure)]
 pub struct SymbolFileWriteFailure {
     pub error: Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::ld64_unimplemented_modifier)]
+#[diag(codegen_ssa_ld64_unimplemented_modifier)]
 pub struct Ld64UnimplementedModifier;
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::linker_unsupported_modifier)]
+#[diag(codegen_ssa_linker_unsupported_modifier)]
 pub struct LinkerUnsupportedModifier;
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::L4Bender_exporting_symbols_unimplemented)]
+#[diag(codegen_ssa_L4Bender_exporting_symbols_unimplemented)]
 pub struct L4BenderExportingSymbolsUnimplemented;
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::no_natvis_directory)]
+#[diag(codegen_ssa_no_natvis_directory)]
 pub struct NoNatvisDirectory {
     pub error: Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::copy_path_buf)]
+#[diag(codegen_ssa_copy_path_buf)]
 pub struct CopyPathBuf {
     pub source_file: PathBuf,
     pub output_path: PathBuf,
@@ -58,7 +58,7 @@ pub struct CopyPathBuf {
 
 // Reports Paths using `Debug` implementation rather than Path's `Display` implementation.
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::copy_path)]
+#[diag(codegen_ssa_copy_path)]
 pub struct CopyPath<'a> {
     from: DebugArgPath<'a>,
     to: DebugArgPath<'a>,
@@ -80,36 +80,36 @@ impl IntoDiagnosticArg for DebugArgPath<'_> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::ignoring_emit_path)]
+#[diag(codegen_ssa_ignoring_emit_path)]
 pub struct IgnoringEmitPath {
     pub extension: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::ignoring_output)]
+#[diag(codegen_ssa_ignoring_output)]
 pub struct IgnoringOutput {
     pub extension: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::create_temp_dir)]
+#[diag(codegen_ssa_create_temp_dir)]
 pub struct CreateTempDir {
     pub error: Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::incompatible_linking_modifiers)]
+#[diag(codegen_ssa_incompatible_linking_modifiers)]
 pub struct IncompatibleLinkingModifiers;
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::add_native_library)]
+#[diag(codegen_ssa_add_native_library)]
 pub struct AddNativeLibrary {
     pub library_path: PathBuf,
     pub error: Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa::multiple_external_func_decl)]
+#[diag(codegen_ssa_multiple_external_func_decl)]
 pub struct MultipleExternalFuncDecl<'a> {
     #[primary_span]
     pub span: Span,
@@ -119,14 +119,17 @@ pub struct MultipleExternalFuncDecl<'a> {
 
 #[derive(Diagnostic)]
 pub enum LinkRlibError {
-    #[diag(codegen_ssa::rlib_missing_format)]
+    #[diag(codegen_ssa_rlib_missing_format)]
     MissingFormat,
 
-    #[diag(codegen_ssa::rlib_only_rmeta_found)]
+    #[diag(codegen_ssa_rlib_only_rmeta_found)]
     OnlyRmetaFound { crate_name: Symbol },
 
-    #[diag(codegen_ssa::rlib_not_found)]
+    #[diag(codegen_ssa_rlib_not_found)]
     NotFound { crate_name: Symbol },
+
+    #[diag(codegen_ssa_rlib_incompatible_dependency_formats)]
+    IncompatibleDependencyFormats { ty1: String, ty2: String, list1: String, list2: String },
 }
 
 pub struct ThorinErrorWrapper(pub thorin::Error);
@@ -136,188 +139,188 @@ impl IntoDiagnostic<'_> for ThorinErrorWrapper {
         let mut diag;
         match self.0 {
             thorin::Error::ReadInput(_) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_read_input_failure);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_read_input_failure);
                 diag
             }
             thorin::Error::ParseFileKind(_) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_input_file_kind);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_input_file_kind);
                 diag
             }
             thorin::Error::ParseObjectFile(_) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_input_object_file);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_input_object_file);
                 diag
             }
             thorin::Error::ParseArchiveFile(_) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_input_archive_file);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_input_archive_file);
                 diag
             }
             thorin::Error::ParseArchiveMember(_) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_archive_member);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_archive_member);
                 diag
             }
             thorin::Error::InvalidInputKind => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_invalid_input_kind);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_invalid_input_kind);
                 diag
             }
             thorin::Error::DecompressData(_) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_decompress_data);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_decompress_data);
                 diag
             }
             thorin::Error::NamelessSection(_, offset) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_section_without_name);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_section_without_name);
                 diag.set_arg("offset", format!("0x{:08x}", offset));
                 diag
             }
             thorin::Error::RelocationWithInvalidSymbol(section, offset) => {
                 diag =
-                    handler.struct_err(fluent::codegen_ssa::thorin_relocation_with_invalid_symbol);
+                    handler.struct_err(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol);
                 diag.set_arg("section", section);
                 diag.set_arg("offset", format!("0x{:08x}", offset));
                 diag
             }
             thorin::Error::MultipleRelocations(section, offset) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_multiple_relocations);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_multiple_relocations);
                 diag.set_arg("section", section);
                 diag.set_arg("offset", format!("0x{:08x}", offset));
                 diag
             }
             thorin::Error::UnsupportedRelocation(section, offset) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_unsupported_relocation);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_unsupported_relocation);
                 diag.set_arg("section", section);
                 diag.set_arg("offset", format!("0x{:08x}", offset));
                 diag
             }
             thorin::Error::MissingDwoName(id) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_missing_dwo_name);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_missing_dwo_name);
                 diag.set_arg("id", format!("0x{:08x}", id));
                 diag
             }
             thorin::Error::NoCompilationUnits => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_no_compilation_units);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_no_compilation_units);
                 diag
             }
             thorin::Error::NoDie => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_no_die);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_no_die);
                 diag
             }
             thorin::Error::TopLevelDieNotUnit => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_top_level_die_not_unit);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_top_level_die_not_unit);
                 diag
             }
             thorin::Error::MissingRequiredSection(section) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_missing_required_section);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_missing_required_section);
                 diag.set_arg("section", section);
                 diag
             }
             thorin::Error::ParseUnitAbbreviations(_) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_unit_abbreviations);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit_abbreviations);
                 diag
             }
             thorin::Error::ParseUnitAttribute(_) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_unit_attribute);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit_attribute);
                 diag
             }
             thorin::Error::ParseUnitHeader(_) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_unit_header);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit_header);
                 diag
             }
             thorin::Error::ParseUnit(_) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_unit);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit);
                 diag
             }
             thorin::Error::IncompatibleIndexVersion(section, format, actual) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_incompatible_index_version);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_incompatible_index_version);
                 diag.set_arg("section", section);
                 diag.set_arg("actual", actual);
                 diag.set_arg("format", format);
                 diag
             }
             thorin::Error::OffsetAtIndex(_, index) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_offset_at_index);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_offset_at_index);
                 diag.set_arg("index", index);
                 diag
             }
             thorin::Error::StrAtOffset(_, offset) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_str_at_offset);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_str_at_offset);
                 diag.set_arg("offset", format!("0x{:08x}", offset));
                 diag
             }
             thorin::Error::ParseIndex(_, section) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_index);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_index);
                 diag.set_arg("section", section);
                 diag
             }
             thorin::Error::UnitNotInIndex(unit) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_unit_not_in_index);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_unit_not_in_index);
                 diag.set_arg("unit", format!("0x{:08x}", unit));
                 diag
             }
             thorin::Error::RowNotInIndex(_, row) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_row_not_in_index);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_row_not_in_index);
                 diag.set_arg("row", row);
                 diag
             }
             thorin::Error::SectionNotInRow => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_section_not_in_row);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_section_not_in_row);
                 diag
             }
             thorin::Error::EmptyUnit(unit) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_empty_unit);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_empty_unit);
                 diag.set_arg("unit", format!("0x{:08x}", unit));
                 diag
             }
             thorin::Error::MultipleDebugInfoSection => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_multiple_debug_info_section);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_multiple_debug_info_section);
                 diag
             }
             thorin::Error::MultipleDebugTypesSection => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_multiple_debug_types_section);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_multiple_debug_types_section);
                 diag
             }
             thorin::Error::NotSplitUnit => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_not_split_unit);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_not_split_unit);
                 diag
             }
             thorin::Error::DuplicateUnit(unit) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_duplicate_unit);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_duplicate_unit);
                 diag.set_arg("unit", format!("0x{:08x}", unit));
                 diag
             }
             thorin::Error::MissingReferencedUnit(unit) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_missing_referenced_unit);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_missing_referenced_unit);
                 diag.set_arg("unit", format!("0x{:08x}", unit));
                 diag
             }
             thorin::Error::NoOutputObjectCreated => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_not_output_object_created);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_not_output_object_created);
                 diag
             }
             thorin::Error::MixedInputEncodings => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_mixed_input_encodings);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_mixed_input_encodings);
                 diag
             }
             thorin::Error::Io(e) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_io);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_io);
                 diag.set_arg("error", format!("{e}"));
                 diag
             }
             thorin::Error::ObjectRead(e) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_object_read);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_object_read);
                 diag.set_arg("error", format!("{e}"));
                 diag
             }
             thorin::Error::ObjectWrite(e) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_object_write);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_object_write);
                 diag.set_arg("error", format!("{e}"));
                 diag
             }
             thorin::Error::GimliRead(e) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_gimli_read);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_gimli_read);
                 diag.set_arg("error", format!("{e}"));
                 diag
             }
             thorin::Error::GimliWrite(e) => {
-                diag = handler.struct_err(fluent::codegen_ssa::thorin_gimli_write);
+                diag = handler.struct_err(fluent::codegen_ssa_thorin_gimli_write);
                 diag.set_arg("error", format!("{e}"));
                 diag
             }
@@ -335,7 +338,7 @@ pub struct LinkingFailed<'a> {
 
 impl IntoDiagnostic<'_> for LinkingFailed<'_> {
     fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
-        let mut diag = handler.struct_err(fluent::codegen_ssa::linking_failed);
+        let mut diag = handler.struct_err(fluent::codegen_ssa_linking_failed);
         diag.set_arg("linker_path", format!("{}", self.linker_path.display()));
         diag.set_arg("exit_status", format!("{}", self.exit_status));
 
@@ -344,9 +347,9 @@ impl IntoDiagnostic<'_> for LinkingFailed<'_> {
         // Trying to match an error from OS linkers
         // which by now we have no way to translate.
         if self.escaped_output.contains("undefined reference to") {
-            diag.note(fluent::codegen_ssa::extern_funcs_not_found)
-                .note(fluent::codegen_ssa::specify_libraries_to_link)
-                .note(fluent::codegen_ssa::use_cargo_directive);
+            diag.note(fluent::codegen_ssa_extern_funcs_not_found)
+                .note(fluent::codegen_ssa_specify_libraries_to_link)
+                .note(fluent::codegen_ssa_use_cargo_directive);
         }
         diag
     }
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index c6cb7a8b961..4b055076742 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -3,18 +3,18 @@ use rustc_macros::Diagnostic;
 use rustc_span::Span;
 
 #[derive(Diagnostic)]
-#[diag(const_eval::unstable_in_stable)]
+#[diag(const_eval_unstable_in_stable)]
 pub(crate) struct UnstableInStable {
     pub gate: String,
     #[primary_span]
     pub span: Span,
     #[suggestion(
-        const_eval::unstable_sugg,
+        unstable_sugg,
         code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n",
         applicability = "has-placeholders"
     )]
     #[suggestion(
-        const_eval::bypass_sugg,
+        bypass_sugg,
         code = "#[rustc_allow_const_fn_unstable({gate})]\n",
         applicability = "has-placeholders"
     )]
@@ -22,35 +22,35 @@ pub(crate) struct UnstableInStable {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::thread_local_access, code = "E0625")]
+#[diag(const_eval_thread_local_access, code = "E0625")]
 pub(crate) struct NonConstOpErr {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::static_access, code = "E0013")]
+#[diag(const_eval_static_access, code = "E0013")]
 #[help]
 pub(crate) struct StaticAccessErr {
     #[primary_span]
     pub span: Span,
     pub kind: ConstContext,
-    #[note(const_eval::teach_note)]
-    #[help(const_eval::teach_help)]
+    #[note(teach_note)]
+    #[help(teach_help)]
     pub teach: Option<()>,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::raw_ptr_to_int)]
+#[diag(const_eval_raw_ptr_to_int)]
 #[note]
-#[note(const_eval::note2)]
+#[note(note2)]
 pub(crate) struct RawPtrToIntErr {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::raw_ptr_comparison)]
+#[diag(const_eval_raw_ptr_comparison)]
 #[note]
 pub(crate) struct RawPtrComparisonErr {
     #[primary_span]
@@ -58,14 +58,14 @@ pub(crate) struct RawPtrComparisonErr {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::panic_non_str)]
+#[diag(const_eval_panic_non_str)]
 pub(crate) struct PanicNonStrErr {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::mut_deref, code = "E0658")]
+#[diag(const_eval_mut_deref, code = "E0658")]
 pub(crate) struct MutDerefErr {
     #[primary_span]
     pub span: Span,
@@ -73,7 +73,7 @@ pub(crate) struct MutDerefErr {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::transient_mut_borrow, code = "E0658")]
+#[diag(const_eval_transient_mut_borrow, code = "E0658")]
 pub(crate) struct TransientMutBorrowErr {
     #[primary_span]
     pub span: Span,
@@ -81,7 +81,7 @@ pub(crate) struct TransientMutBorrowErr {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::transient_mut_borrow_raw, code = "E0658")]
+#[diag(const_eval_transient_mut_borrow_raw, code = "E0658")]
 pub(crate) struct TransientMutBorrowErrRaw {
     #[primary_span]
     pub span: Span,
@@ -89,7 +89,7 @@ pub(crate) struct TransientMutBorrowErrRaw {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::max_num_nodes_in_const)]
+#[diag(const_eval_max_num_nodes_in_const)]
 pub(crate) struct MaxNumNodesInConstErr {
     #[primary_span]
     pub span: Span,
@@ -97,7 +97,7 @@ pub(crate) struct MaxNumNodesInConstErr {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::unallowed_fn_pointer_call)]
+#[diag(const_eval_unallowed_fn_pointer_call)]
 pub(crate) struct UnallowedFnPointerCall {
     #[primary_span]
     pub span: Span,
@@ -105,7 +105,7 @@ pub(crate) struct UnallowedFnPointerCall {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::unstable_const_fn)]
+#[diag(const_eval_unstable_const_fn)]
 pub(crate) struct UnstableConstFn {
     #[primary_span]
     pub span: Span,
@@ -113,26 +113,26 @@ pub(crate) struct UnstableConstFn {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::unallowed_mutable_refs, code = "E0764")]
+#[diag(const_eval_unallowed_mutable_refs, code = "E0764")]
 pub(crate) struct UnallowedMutableRefs {
     #[primary_span]
     pub span: Span,
     pub kind: ConstContext,
-    #[note(const_eval::teach_note)]
+    #[note(teach_note)]
     pub teach: Option<()>,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::unallowed_mutable_refs_raw, code = "E0764")]
+#[diag(const_eval_unallowed_mutable_refs_raw, code = "E0764")]
 pub(crate) struct UnallowedMutableRefsRaw {
     #[primary_span]
     pub span: Span,
     pub kind: ConstContext,
-    #[note(const_eval::teach_note)]
+    #[note(teach_note)]
     pub teach: Option<()>,
 }
 #[derive(Diagnostic)]
-#[diag(const_eval::non_const_fmt_macro_call, code = "E0015")]
+#[diag(const_eval_non_const_fmt_macro_call, code = "E0015")]
 pub(crate) struct NonConstFmtMacroCall {
     #[primary_span]
     pub span: Span,
@@ -140,7 +140,7 @@ pub(crate) struct NonConstFmtMacroCall {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::non_const_fn_call, code = "E0015")]
+#[diag(const_eval_non_const_fn_call, code = "E0015")]
 pub(crate) struct NonConstFnCall {
     #[primary_span]
     pub span: Span,
@@ -149,7 +149,7 @@ pub(crate) struct NonConstFnCall {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::unallowed_op_in_const_context)]
+#[diag(const_eval_unallowed_op_in_const_context)]
 pub(crate) struct UnallowedOpInConstContext {
     #[primary_span]
     pub span: Span,
@@ -157,18 +157,18 @@ pub(crate) struct UnallowedOpInConstContext {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::unallowed_heap_allocations, code = "E0010")]
+#[diag(const_eval_unallowed_heap_allocations, code = "E0010")]
 pub(crate) struct UnallowedHeapAllocations {
     #[primary_span]
     #[label]
     pub span: Span,
     pub kind: ConstContext,
-    #[note(const_eval::teach_note)]
+    #[note(teach_note)]
     pub teach: Option<()>,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::unallowed_inline_asm, code = "E0015")]
+#[diag(const_eval_unallowed_inline_asm, code = "E0015")]
 pub(crate) struct UnallowedInlineAsm {
     #[primary_span]
     pub span: Span,
@@ -176,7 +176,7 @@ pub(crate) struct UnallowedInlineAsm {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::interior_mutable_data_refer, code = "E0492")]
+#[diag(const_eval_interior_mutable_data_refer, code = "E0492")]
 pub(crate) struct InteriorMutableDataRefer {
     #[primary_span]
     #[label]
@@ -184,12 +184,12 @@ pub(crate) struct InteriorMutableDataRefer {
     #[help]
     pub opt_help: Option<()>,
     pub kind: ConstContext,
-    #[note(const_eval::teach_note)]
+    #[note(teach_note)]
     pub teach: Option<()>,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval::interior_mutability_borrow)]
+#[diag(const_eval_interior_mutability_borrow)]
 pub(crate) struct InteriorMutabilityBorrow {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_data_structures/src/sso/set.rs b/compiler/rustc_data_structures/src/sso/set.rs
index 4fda3adb7b8..406f0270dcc 100644
--- a/compiler/rustc_data_structures/src/sso/set.rs
+++ b/compiler/rustc_data_structures/src/sso/set.rs
@@ -27,7 +27,7 @@ pub struct SsoHashSet<T> {
     map: SsoHashMap<T, ()>,
 }
 
-/// Adapter function used ot return
+/// Adapter function used to return
 /// result if SsoHashMap functions into
 /// result SsoHashSet should return.
 #[inline(always)]
diff --git a/compiler/rustc_driver/src/session_diagnostics.rs b/compiler/rustc_driver/src/session_diagnostics.rs
index 289baf17773..c1bc1089114 100644
--- a/compiler/rustc_driver/src/session_diagnostics.rs
+++ b/compiler/rustc_driver/src/session_diagnostics.rs
@@ -1,39 +1,39 @@
 use rustc_macros::Diagnostic;
 
 #[derive(Diagnostic)]
-#[diag(driver::rlink_unable_to_read)]
+#[diag(driver_rlink_unable_to_read)]
 pub(crate) struct RlinkUnableToRead {
     pub err: std::io::Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(driver::rlink_wrong_file_type)]
+#[diag(driver_rlink_wrong_file_type)]
 pub(crate) struct RLinkWrongFileType;
 
 #[derive(Diagnostic)]
-#[diag(driver::rlink_empty_version_number)]
+#[diag(driver_rlink_empty_version_number)]
 pub(crate) struct RLinkEmptyVersionNumber;
 
 #[derive(Diagnostic)]
-#[diag(driver::rlink_encoding_version_mismatch)]
+#[diag(driver_rlink_encoding_version_mismatch)]
 pub(crate) struct RLinkEncodingVersionMismatch {
     pub version_array: String,
     pub rlink_version: u32,
 }
 
 #[derive(Diagnostic)]
-#[diag(driver::rlink_rustc_version_mismatch)]
+#[diag(driver_rlink_rustc_version_mismatch)]
 pub(crate) struct RLinkRustcVersionMismatch<'a> {
     pub rustc_version: String,
     pub current_version: &'a str,
 }
 
 #[derive(Diagnostic)]
-#[diag(driver::rlink_no_a_file)]
+#[diag(driver_rlink_no_a_file)]
 pub(crate) struct RlinkNotAFile;
 
 #[derive(Diagnostic)]
-#[diag(driver::unpretty_dump_fail)]
+#[diag(driver_unpretty_dump_fail)]
 pub(crate) struct UnprettyDumpFail {
     pub path: String,
     pub err: String,
diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
index 0d0388a039e..966a421bcf0 100644
--- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
@@ -34,6 +34,8 @@ codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, fo
 
 codegen_ssa_rlib_not_found = could not find rlib for: `{$crate_name}`
 
+codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)
+
 codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}
 
 codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 571b7dbfd1b..7640b2919f7 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -175,14 +175,14 @@ impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
         let mut diag;
         match self {
             TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => {
-                diag = handler.struct_fatal(fluent::errors::target_invalid_address_space);
+                diag = handler.struct_fatal(fluent::errors_target_invalid_address_space);
                 diag.set_arg("addr_space", addr_space);
                 diag.set_arg("cause", cause);
                 diag.set_arg("err", err);
                 diag
             }
             TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => {
-                diag = handler.struct_fatal(fluent::errors::target_invalid_bits);
+                diag = handler.struct_fatal(fluent::errors_target_invalid_bits);
                 diag.set_arg("kind", kind);
                 diag.set_arg("bit", bit);
                 diag.set_arg("cause", cause);
@@ -190,30 +190,30 @@ impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
                 diag
             }
             TargetDataLayoutErrors::MissingAlignment { cause } => {
-                diag = handler.struct_fatal(fluent::errors::target_missing_alignment);
+                diag = handler.struct_fatal(fluent::errors_target_missing_alignment);
                 diag.set_arg("cause", cause);
                 diag
             }
             TargetDataLayoutErrors::InvalidAlignment { cause, err } => {
-                diag = handler.struct_fatal(fluent::errors::target_invalid_alignment);
+                diag = handler.struct_fatal(fluent::errors_target_invalid_alignment);
                 diag.set_arg("cause", cause);
                 diag.set_arg("err", err);
                 diag
             }
             TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => {
-                diag = handler.struct_fatal(fluent::errors::target_inconsistent_architecture);
+                diag = handler.struct_fatal(fluent::errors_target_inconsistent_architecture);
                 diag.set_arg("dl", dl);
                 diag.set_arg("target", target);
                 diag
             }
             TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => {
-                diag = handler.struct_fatal(fluent::errors::target_inconsistent_pointer_width);
+                diag = handler.struct_fatal(fluent::errors_target_inconsistent_pointer_width);
                 diag.set_arg("pointer_size", pointer_size);
                 diag.set_arg("target", target);
                 diag
             }
             TargetDataLayoutErrors::InvalidBitsSize { err } => {
-                diag = handler.struct_fatal(fluent::errors::target_invalid_bits_size);
+                diag = handler.struct_fatal(fluent::errors_target_invalid_bits_size);
                 diag.set_arg("err", err);
                 diag
             }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 9fafbe4bd40..0963ea71f80 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -463,6 +463,9 @@ pub enum StashKey {
     UnderscoreForArrayLengths,
     EarlySyntaxWarning,
     CallIntoMethod,
+    /// When an invalid lifetime e.g. `'2` should be reinterpreted
+    /// as a char literal in the parser
+    LifetimeIsChar,
 }
 
 fn default_track_diagnostic(_: &Diagnostic) {}
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index bd93f0717f5..d383f4832f6 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -3,28 +3,28 @@ use rustc_span::symbol::MacroRulesNormalizedIdent;
 use rustc_span::Span;
 
 #[derive(Diagnostic)]
-#[diag(expand::expr_repeat_no_syntax_vars)]
+#[diag(expand_expr_repeat_no_syntax_vars)]
 pub(crate) struct NoSyntaxVarsExprRepeat {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(expand::must_repeat_once)]
+#[diag(expand_must_repeat_once)]
 pub(crate) struct MustRepeatOnce {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(expand::count_repetition_misplaced)]
+#[diag(expand_count_repetition_misplaced)]
 pub(crate) struct CountRepetitionMisplaced {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(expand::meta_var_expr_unrecognized_var)]
+#[diag(expand_meta_var_expr_unrecognized_var)]
 pub(crate) struct MetaVarExprUnrecognizedVar {
     #[primary_span]
     pub span: Span,
@@ -32,7 +32,7 @@ pub(crate) struct MetaVarExprUnrecognizedVar {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand::var_still_repeating)]
+#[diag(expand_var_still_repeating)]
 pub(crate) struct VarStillRepeating {
     #[primary_span]
     pub span: Span,
@@ -40,7 +40,7 @@ pub(crate) struct VarStillRepeating {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand::meta_var_dif_seq_matchers)]
+#[diag(expand_meta_var_dif_seq_matchers)]
 pub(crate) struct MetaVarsDifSeqMatchers {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 0aa2b44a0f8..1e268542bcd 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -598,12 +598,12 @@ pub fn compile_declarative_macro(
 
 #[derive(Subdiagnostic)]
 enum ExplainDocComment {
-    #[label(expand::explain_doc_comment_inner)]
+    #[label(expand_explain_doc_comment_inner)]
     Inner {
         #[primary_span]
         span: Span,
     },
-    #[label(expand::explain_doc_comment_outer)]
+    #[label(expand_explain_doc_comment_outer)]
     Outer {
         #[primary_span]
         span: Span,
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index afa0f6fcb80..2ead3c2c8d4 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -746,7 +746,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
          for reserving for `for<T> From<!> for T` impl"
     ),
     rustc_attr!(
-        rustc_test_marker, Normal, template!(Word), WarnFollowing,
+        rustc_test_marker, Normal, template!(NameValueStr: "name"), WarnFollowing,
         "the `#[rustc_test_marker]` attribute is used internally to track tests",
     ),
     rustc_attr!(
diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs
index 60eaad9b498..3469ec4767b 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_method.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs
@@ -664,10 +664,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
             });
             self.types.insert(proj.item_def_id, (infer_ty, proj.substs));
             // Recurse into bounds
-            for pred in self.tcx().bound_explicit_item_bounds(proj.item_def_id).transpose_iter() {
-                let pred_span = pred.0.1;
-
-                let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx(), proj.substs);
+            for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.item_def_id).subst_iter_copied(self.tcx(), proj.substs) {
                 let pred = pred.fold_with(self);
                 let pred = self.ocx.normalize(
                     ObligationCause::misc(self.span, self.body_id),
@@ -1752,15 +1749,10 @@ pub fn check_type_bounds<'tcx>(
 
     let obligations = tcx
         .bound_explicit_item_bounds(trait_ty.def_id)
-        .transpose_iter()
-        .map(|e| e.map_bound(|e| *e).transpose_tuple2())
-        .map(|(bound, span)| {
-            debug!(?bound);
-            // this is where opaque type is found
-            let concrete_ty_bound = bound.subst(tcx, rebased_substs);
+        .subst_iter_copied(tcx, rebased_substs)
+        .map(|(concrete_ty_bound, span)| {
             debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
-
-            traits::Obligation::new(mk_cause(span.0), param_env, concrete_ty_bound)
+            traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
         })
         .collect();
     debug!("check_type_bounds: item_bounds={:?}", obligations);
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index e5b212eb757..a74016e220e 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -184,13 +184,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
             let p = p.kind();
             match (predicate.skip_binder(), p.skip_binder()) {
                 (ty::PredicateKind::Trait(a), ty::PredicateKind::Trait(b)) => {
-                    // Since struct predicates cannot have ~const, project the impl predicate
-                    // onto one that ignores the constness. This is equivalent to saying that
-                    // we match a `Trait` bound on the struct with a `Trait` or `~const Trait`
-                    // in the impl.
-                    let non_const_a =
-                        ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..a };
-                    relator.relate(predicate.rebind(non_const_a), p.rebind(b)).is_ok()
+                    relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
                 }
                 (ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => {
                     relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
@@ -198,7 +192,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
                 (
                     ty::PredicateKind::ConstEvaluatable(a),
                     ty::PredicateKind::ConstEvaluatable(b),
-                ) => tcx.try_unify_abstract_consts(self_param_env.and((a, b))),
+                ) => relator.relate(predicate.rebind(a), predicate.rebind(b)).is_ok(),
                 (
                     ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, lt_a)),
                     ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_b, lt_b)),
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 0a8a1bec9b8..33ed3b96aa8 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1101,8 +1101,6 @@ fn check_type_defn<'tcx, F>(
 
             // Explicit `enum` discriminant values must const-evaluate successfully.
             if let Some(discr_def_id) = variant.explicit_discr {
-                let discr_substs = InternalSubsts::identity_for_item(tcx, discr_def_id.to_def_id());
-
                 let cause = traits::ObligationCause::new(
                     tcx.def_span(discr_def_id),
                     wfcx.body_id,
@@ -1112,10 +1110,7 @@ fn check_type_defn<'tcx, F>(
                     cause,
                     wfcx.param_env,
                     ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
-                        ty::UnevaluatedConst::new(
-                            ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
-                            discr_substs,
-                        ),
+                        ty::Const::from_anon_const(tcx, discr_def_id),
                     ))
                     .to_predicate(tcx),
                 ));
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index db8f8de68f2..2e84e1d0160 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -318,10 +318,10 @@ fn const_evaluatable_predicates_of<'tcx>(
         fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
             let def_id = self.tcx.hir().local_def_id(c.hir_id);
             let ct = ty::Const::from_anon_const(self.tcx, def_id);
-            if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
+            if let ty::ConstKind::Unevaluated(_) = ct.kind() {
                 let span = self.tcx.hir().span(c.hir_id);
                 self.preds.insert((
-                    ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
+                    ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
                         .to_predicate(self.tcx),
                     span,
                 ));
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index aaebbe6398a..9457da32ce6 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -7,7 +7,7 @@ use rustc_middle::ty::Ty;
 use rustc_span::{symbol::Ident, Span, Symbol};
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::unrecognized_atomic_operation, code = "E0092")]
+#[diag(hir_analysis_unrecognized_atomic_operation, code = "E0092")]
 pub struct UnrecognizedAtomicOperation<'a> {
     #[primary_span]
     #[label]
@@ -16,7 +16,7 @@ pub struct UnrecognizedAtomicOperation<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")]
+#[diag(hir_analysis_wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")]
 pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
     #[primary_span]
     #[label]
@@ -27,7 +27,7 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::unrecognized_intrinsic_function, code = "E0093")]
+#[diag(hir_analysis_unrecognized_intrinsic_function, code = "E0093")]
 pub struct UnrecognizedIntrinsicFunction {
     #[primary_span]
     #[label]
@@ -36,19 +36,19 @@ pub struct UnrecognizedIntrinsicFunction {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::lifetimes_or_bounds_mismatch_on_trait, code = "E0195")]
+#[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_trait, code = "E0195")]
 pub struct LifetimesOrBoundsMismatchOnTrait {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label(hir_analysis::generics_label)]
+    #[label(generics_label)]
     pub generics_span: Option<Span>,
     pub item_kind: &'static str,
     pub ident: Ident,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::drop_impl_on_wrong_item, code = "E0120")]
+#[diag(hir_analysis_drop_impl_on_wrong_item, code = "E0120")]
 pub struct DropImplOnWrongItem {
     #[primary_span]
     #[label]
@@ -56,18 +56,18 @@ pub struct DropImplOnWrongItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::field_already_declared, code = "E0124")]
+#[diag(hir_analysis_field_already_declared, code = "E0124")]
 pub struct FieldAlreadyDeclared {
     pub field_name: Ident,
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label(hir_analysis::previous_decl_label)]
+    #[label(previous_decl_label)]
     pub prev_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::copy_impl_on_type_with_dtor, code = "E0184")]
+#[diag(hir_analysis_copy_impl_on_type_with_dtor, code = "E0184")]
 pub struct CopyImplOnTypeWithDtor {
     #[primary_span]
     #[label]
@@ -75,14 +75,14 @@ pub struct CopyImplOnTypeWithDtor {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::multiple_relaxed_default_bounds, code = "E0203")]
+#[diag(hir_analysis_multiple_relaxed_default_bounds, code = "E0203")]
 pub struct MultipleRelaxedDefaultBounds {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::copy_impl_on_non_adt, code = "E0206")]
+#[diag(hir_analysis_copy_impl_on_non_adt, code = "E0206")]
 pub struct CopyImplOnNonAdt {
     #[primary_span]
     #[label]
@@ -90,23 +90,23 @@ pub struct CopyImplOnNonAdt {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::trait_object_declared_with_no_traits, code = "E0224")]
+#[diag(hir_analysis_trait_object_declared_with_no_traits, code = "E0224")]
 pub struct TraitObjectDeclaredWithNoTraits {
     #[primary_span]
     pub span: Span,
-    #[label(hir_analysis::alias_span)]
+    #[label(alias_span)]
     pub trait_alias_span: Option<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::ambiguous_lifetime_bound, code = "E0227")]
+#[diag(hir_analysis_ambiguous_lifetime_bound, code = "E0227")]
 pub struct AmbiguousLifetimeBound {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::assoc_type_binding_not_allowed, code = "E0229")]
+#[diag(hir_analysis_assoc_type_binding_not_allowed, code = "E0229")]
 pub struct AssocTypeBindingNotAllowed {
     #[primary_span]
     #[label]
@@ -114,7 +114,7 @@ pub struct AssocTypeBindingNotAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::typeof_reserved_keyword_used, code = "E0516")]
+#[diag(hir_analysis_typeof_reserved_keyword_used, code = "E0516")]
 pub struct TypeofReservedKeywordUsed<'tcx> {
     pub ty: Ty<'tcx>,
     #[primary_span]
@@ -125,19 +125,19 @@ pub struct TypeofReservedKeywordUsed<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::value_of_associated_struct_already_specified, code = "E0719")]
+#[diag(hir_analysis_value_of_associated_struct_already_specified, code = "E0719")]
 pub struct ValueOfAssociatedStructAlreadySpecified {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label(hir_analysis::previous_bound_label)]
+    #[label(previous_bound_label)]
     pub prev_span: Span,
     pub item_name: Ident,
     pub def_path: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::unconstrained_opaque_type)]
+#[diag(hir_analysis_unconstrained_opaque_type)]
 #[note]
 pub struct UnconstrainedOpaqueType {
     #[primary_span]
@@ -158,7 +158,7 @@ impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
     fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
         let mut err = handler.struct_span_err_with_code(
             self.span,
-            rustc_errors::fluent::hir_analysis::missing_type_params,
+            rustc_errors::fluent::hir_analysis_missing_type_params,
             error_code!(E0393),
         );
         err.set_arg("parameterCount", self.missing_type_params.len());
@@ -171,7 +171,7 @@ impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
                 .join(", "),
         );
 
-        err.span_label(self.def_span, rustc_errors::fluent::hir_analysis::label);
+        err.span_label(self.def_span, rustc_errors::fluent::label);
 
         let mut suggested = false;
         // Don't suggest setting the type params if there are some already: the order is
@@ -186,7 +186,7 @@ impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
                 // least we can clue them to the correct syntax `Iterator<Type>`.
                 err.span_suggestion(
                     self.span,
-                    rustc_errors::fluent::hir_analysis::suggestion,
+                    rustc_errors::fluent::suggestion,
                     format!(
                         "{}<{}>",
                         snippet,
@@ -202,16 +202,16 @@ impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
             }
         }
         if !suggested {
-            err.span_label(self.span, rustc_errors::fluent::hir_analysis::no_suggestion_label);
+            err.span_label(self.span, rustc_errors::fluent::no_suggestion_label);
         }
 
-        err.note(rustc_errors::fluent::hir_analysis::note);
+        err.note(rustc_errors::fluent::note);
         err
     }
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::manual_implementation, code = "E0183")]
+#[diag(hir_analysis_manual_implementation, code = "E0183")]
 #[help]
 pub struct ManualImplementation {
     #[primary_span]
@@ -221,21 +221,21 @@ pub struct ManualImplementation {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::substs_on_overridden_impl)]
+#[diag(hir_analysis_substs_on_overridden_impl)]
 pub struct SubstsOnOverriddenImpl {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(hir_analysis::unused_extern_crate)]
+#[diag(hir_analysis_unused_extern_crate)]
 pub struct UnusedExternCrate {
     #[suggestion(applicability = "machine-applicable", code = "")]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(hir_analysis::extern_crate_not_idiomatic)]
+#[diag(hir_analysis_extern_crate_not_idiomatic)]
 pub struct ExternCrateNotIdiomatic {
     #[suggestion_short(applicability = "machine-applicable", code = "{suggestion_code}")]
     pub span: Span,
@@ -244,7 +244,7 @@ pub struct ExternCrateNotIdiomatic {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::expected_used_symbol)]
+#[diag(hir_analysis_expected_used_symbol)]
 pub struct ExpectedUsedSymbol {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index c22d828625b..2b15d4dcd08 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -514,8 +514,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
 
                 for ty in [first_ty, second_ty] {
-                    for pred in self.tcx.bound_explicit_item_bounds(rpit_def_id).transpose_iter() {
-                        let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx, substs);
+                    for (pred, _) in self
+                        .tcx
+                        .bound_explicit_item_bounds(rpit_def_id)
+                        .subst_iter_copied(self.tcx, substs)
+                    {
                         let pred = match pred.kind().skip_binder() {
                             ty::PredicateKind::Trait(mut trait_pred) => {
                                 assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index de5b4a50218..a5a45f75e0e 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -176,24 +176,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match *expected_ty.kind() {
             ty::Opaque(def_id, substs) => {
                 let bounds = self.tcx.bound_explicit_item_bounds(def_id);
-                let sig = bounds
-                    .transpose_iter()
-                    .map(|e| e.map_bound(|e| *e).transpose_tuple2())
-                    .find_map(|(pred, span)| match pred.0.kind().skip_binder() {
+                let sig =
+                    bounds.subst_iter_copied(self.tcx, substs).find_map(|(pred, span)| match pred
+                        .kind()
+                        .skip_binder()
+                    {
                         ty::PredicateKind::Projection(proj_predicate) => self
                             .deduce_sig_from_projection(
-                                Some(span.0),
-                                pred.0
-                                    .kind()
-                                    .rebind(pred.rebind(proj_predicate).subst(self.tcx, substs)),
+                                Some(span),
+                                pred.kind().rebind(proj_predicate),
                             ),
                         _ => None,
                     });
 
                 let kind = bounds
-                    .transpose_iter()
-                    .map(|e| e.map_bound(|e| *e).transpose_tuple2())
-                    .filter_map(|(pred, _)| match pred.0.kind().skip_binder() {
+                    .0
+                    .iter()
+                    .filter_map(|(pred, _)| match pred.kind().skip_binder() {
                         ty::PredicateKind::Trait(tp) => {
                             self.tcx.fn_trait_kind_from_lang_item(tp.def_id())
                         }
@@ -697,18 +696,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty::Opaque(def_id, substs) => self
                 .tcx
                 .bound_explicit_item_bounds(def_id)
-                .transpose_iter()
-                .map(|e| e.map_bound(|e| *e).transpose_tuple2())
-                .find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0))?,
+                .subst_iter_copied(self.tcx, substs)
+                .find_map(|(p, s)| get_future_output(p, s))?,
             ty::Error(_) => return None,
             ty::Projection(proj)
                 if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
             {
                 self.tcx
                     .bound_explicit_item_bounds(proj.item_def_id)
-                    .transpose_iter()
-                    .map(|e| e.map_bound(|e| *e).transpose_tuple2())
-                    .find_map(|(p, s)| get_future_output(p.subst(self.tcx, proj.substs), s.0))?
+                    .subst_iter_copied(self.tcx, proj.substs)
+                    .find_map(|(p, s)| get_future_output(p, s))?
             }
             _ => span_bug!(
                 self.tcx.def_span(expr_def_id),
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 2f8898d5ea9..175037f9b3a 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -4,36 +4,36 @@ use rustc_middle::ty::Ty;
 use rustc_span::{symbol::Ident, Span};
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::field_multiply_specified_in_initializer, code = "E0062")]
+#[diag(hir_analysis_field_multiply_specified_in_initializer, code = "E0062")]
 pub struct FieldMultiplySpecifiedInInitializer {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label(hir_analysis::previous_use_label)]
+    #[label(previous_use_label)]
     pub prev_span: Span,
     pub ident: Ident,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::return_stmt_outside_of_fn_body, code = "E0572")]
+#[diag(hir_analysis_return_stmt_outside_of_fn_body, code = "E0572")]
 pub struct ReturnStmtOutsideOfFnBody {
     #[primary_span]
     pub span: Span,
-    #[label(hir_analysis::encl_body_label)]
+    #[label(encl_body_label)]
     pub encl_body_span: Option<Span>,
-    #[label(hir_analysis::encl_fn_label)]
+    #[label(encl_fn_label)]
     pub encl_fn_span: Option<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::yield_expr_outside_of_generator, code = "E0627")]
+#[diag(hir_analysis_yield_expr_outside_of_generator, code = "E0627")]
 pub struct YieldExprOutsideOfGenerator {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::struct_expr_non_exhaustive, code = "E0639")]
+#[diag(hir_analysis_struct_expr_non_exhaustive, code = "E0639")]
 pub struct StructExprNonExhaustive {
     #[primary_span]
     pub span: Span,
@@ -41,21 +41,21 @@ pub struct StructExprNonExhaustive {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::method_call_on_unknown_type, code = "E0699")]
+#[diag(hir_analysis_method_call_on_unknown_type, code = "E0699")]
 pub struct MethodCallOnUnknownType {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::functional_record_update_on_non_struct, code = "E0436")]
+#[diag(hir_analysis_functional_record_update_on_non_struct, code = "E0436")]
 pub struct FunctionalRecordUpdateOnNonStruct {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::address_of_temporary_taken, code = "E0745")]
+#[diag(hir_analysis_address_of_temporary_taken, code = "E0745")]
 pub struct AddressOfTemporaryTaken {
     #[primary_span]
     #[label]
@@ -65,7 +65,7 @@ pub struct AddressOfTemporaryTaken {
 #[derive(Subdiagnostic)]
 pub enum AddReturnTypeSuggestion {
     #[suggestion(
-        hir_analysis::add_return_type_add,
+        hir_analysis_add_return_type_add,
         code = "-> {found} ",
         applicability = "machine-applicable"
     )]
@@ -75,7 +75,7 @@ pub enum AddReturnTypeSuggestion {
         found: String,
     },
     #[suggestion(
-        hir_analysis::add_return_type_missing_here,
+        hir_analysis_add_return_type_missing_here,
         code = "-> _ ",
         applicability = "has-placeholders"
     )]
@@ -87,12 +87,12 @@ pub enum AddReturnTypeSuggestion {
 
 #[derive(Subdiagnostic)]
 pub enum ExpectedReturnTypeLabel<'tcx> {
-    #[label(hir_analysis::expected_default_return_type)]
+    #[label(hir_analysis_expected_default_return_type)]
     Unit {
         #[primary_span]
         span: Span,
     },
-    #[label(hir_analysis::expected_return_type)]
+    #[label(hir_analysis_expected_return_type)]
     Other {
         #[primary_span]
         span: Span,
@@ -101,21 +101,20 @@ pub enum ExpectedReturnTypeLabel<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis::missing_parentheses_in_range, code = "E0689")]
+#[diag(hir_analysis_missing_parentheses_in_range, code = "E0689")]
 pub struct MissingParentheseInRange {
     #[primary_span]
-    #[label(hir_analysis::missing_parentheses_in_range)]
+    #[label(hir_analysis_missing_parentheses_in_range)]
     pub span: Span,
     pub ty_str: String,
     pub method_name: String,
-
     #[subdiagnostic]
     pub add_missing_parentheses: Option<AddMissingParenthesesInRange>,
 }
 
 #[derive(Subdiagnostic)]
 #[multipart_suggestion_verbose(
-    hir_analysis::add_missing_parentheses_in_range,
+    hir_analysis_add_missing_parentheses_in_range,
     applicability = "maybe-incorrect"
 )]
 pub struct AddMissingParenthesesInRange {
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
index 7954ddc4166..bfe95852aa7 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
@@ -6,8 +6,11 @@ use crate::{
 use hir::{def_id::DefId, Body, HirId, HirIdMap};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
-use rustc_middle::hir::place::{PlaceBase, Projection, ProjectionKind};
 use rustc_middle::ty::{ParamEnv, TyCtxt};
+use rustc_middle::{
+    hir::place::{PlaceBase, Projection, ProjectionKind},
+    ty::TypeVisitable,
+};
 
 pub(super) fn find_consumed_and_borrowed<'a, 'tcx>(
     fcx: &'a FnCtxt<'a, 'tcx>,
@@ -198,11 +201,13 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
 
         // If the type being assigned needs dropped, then the mutation counts as a borrow
         // since it is essentially doing `Drop::drop(&mut x); x = new_value;`.
-        //
-        // FIXME(drop-tracking): We need to be more responsible about inference
-        // variables here, since `needs_drop` is a "raw" type query, i.e. it
-        // basically requires types to have been fully resolved.
-        if assignee_place.place.base_ty.needs_drop(self.tcx, self.param_env) {
+        let ty = self.tcx.erase_regions(assignee_place.place.base_ty);
+        if ty.needs_infer() {
+            self.tcx.sess.delay_span_bug(
+                self.tcx.hir().span(assignee_place.hir_id),
+                &format!("inference variables in {ty}"),
+            );
+        } else if ty.needs_drop(self.tcx, self.param_env) {
             self.places
                 .borrowed
                 .insert(TrackedValue::from_place_with_projections_allowed(assignee_place));
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 898419b5b23..b7dd599cd43 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -377,15 +377,6 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
         debug!("is_borrowed_temporary: {:?}", self.drop_ranges.is_borrowed_temporary(expr));
 
         let ty = self.fcx.typeck_results.borrow().expr_ty_adjusted_opt(expr);
-        let may_need_drop = |ty: Ty<'tcx>| {
-            // Avoid ICEs in needs_drop.
-            let ty = self.fcx.resolve_vars_if_possible(ty);
-            let ty = self.fcx.tcx.erase_regions(ty);
-            if ty.needs_infer() {
-                return true;
-            }
-            ty.needs_drop(self.fcx.tcx, self.fcx.param_env)
-        };
 
         // Typically, the value produced by an expression is consumed by its parent in some way,
         // so we only have to check if the parent contains a yield (note that the parent may, for
@@ -403,9 +394,18 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
         // src/test/ui/generator/drop-tracking-parent-expression.rs.
         let scope = if self.drop_ranges.is_borrowed_temporary(expr)
             || ty.map_or(true, |ty| {
-                let needs_drop = may_need_drop(ty);
-                debug!(?needs_drop, ?ty);
-                needs_drop
+                // Avoid ICEs in needs_drop.
+                let ty = self.fcx.resolve_vars_if_possible(ty);
+                let ty = self.fcx.tcx.erase_regions(ty);
+                if ty.needs_infer() {
+                    self.fcx
+                        .tcx
+                        .sess
+                        .delay_span_bug(expr.span, &format!("inference variables in {ty}"));
+                    true
+                } else {
+                    ty.needs_drop(self.fcx.tcx, self.fcx.param_env)
+                }
             }) {
             self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id)
         } else {
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 25e8630bf6b..2131d19068e 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -18,19 +18,19 @@ use crate::infer::error_reporting::{
 pub mod note_and_explain;
 
 #[derive(Diagnostic)]
-#[diag(infer::opaque_hidden_type)]
+#[diag(infer_opaque_hidden_type)]
 pub struct OpaqueHiddenTypeDiag {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[note(infer::opaque_type)]
+    #[note(opaque_type)]
     pub opaque_type: Span,
-    #[note(infer::hidden_type)]
+    #[note(hidden_type)]
     pub hidden_type: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(infer::type_annotations_needed, code = "E0282")]
+#[diag(infer_type_annotations_needed, code = "E0282")]
 pub struct AnnotationRequired<'a> {
     #[primary_span]
     pub span: Span,
@@ -48,7 +48,7 @@ pub struct AnnotationRequired<'a> {
 
 // Copy of `AnnotationRequired` for E0283
 #[derive(Diagnostic)]
-#[diag(infer::type_annotations_needed, code = "E0283")]
+#[diag(infer_type_annotations_needed, code = "E0283")]
 pub struct AmbigousImpl<'a> {
     #[primary_span]
     pub span: Span,
@@ -66,7 +66,7 @@ pub struct AmbigousImpl<'a> {
 
 // Copy of `AnnotationRequired` for E0284
 #[derive(Diagnostic)]
-#[diag(infer::type_annotations_needed, code = "E0284")]
+#[diag(infer_type_annotations_needed, code = "E0284")]
 pub struct AmbigousReturn<'a> {
     #[primary_span]
     pub span: Span,
@@ -83,7 +83,7 @@ pub struct AmbigousReturn<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer::need_type_info_in_generator, code = "E0698")]
+#[diag(infer_need_type_info_in_generator, code = "E0698")]
 pub struct NeedTypeInfoInGenerator<'a> {
     #[primary_span]
     pub span: Span,
@@ -94,7 +94,7 @@ pub struct NeedTypeInfoInGenerator<'a> {
 
 // Used when a better one isn't available
 #[derive(Subdiagnostic)]
-#[label(infer::label_bad)]
+#[label(infer_label_bad)]
 pub struct InferenceBadError<'a> {
     #[primary_span]
     pub span: Span,
@@ -110,7 +110,7 @@ pub struct InferenceBadError<'a> {
 #[derive(Subdiagnostic)]
 pub enum SourceKindSubdiag<'a> {
     #[suggestion_verbose(
-        infer::source_kind_subdiag_let,
+        infer_source_kind_subdiag_let,
         code = ": {type_name}",
         applicability = "has-placeholders"
     )]
@@ -125,7 +125,7 @@ pub enum SourceKindSubdiag<'a> {
         prefix: &'a str,
         arg_name: String,
     },
-    #[label(infer::source_kind_subdiag_generic_label)]
+    #[label(infer_source_kind_subdiag_generic_label)]
     GenericLabel {
         #[primary_span]
         span: Span,
@@ -136,7 +136,7 @@ pub enum SourceKindSubdiag<'a> {
         parent_name: String,
     },
     #[suggestion_verbose(
-        infer::source_kind_subdiag_generic_suggestion,
+        infer_source_kind_subdiag_generic_suggestion,
         code = "::<{args}>",
         applicability = "has-placeholders"
     )]
@@ -151,7 +151,7 @@ pub enum SourceKindSubdiag<'a> {
 #[derive(Subdiagnostic)]
 pub enum SourceKindMultiSuggestion<'a> {
     #[multipart_suggestion_verbose(
-        infer::source_kind_fully_qualified,
+        infer_source_kind_fully_qualified,
         applicability = "has-placeholders"
     )]
     FullyQualified {
@@ -164,7 +164,7 @@ pub enum SourceKindMultiSuggestion<'a> {
         successor_pos: &'a str,
     },
     #[multipart_suggestion_verbose(
-        infer::source_kind_closure_return,
+        infer_source_kind_closure_return,
         applicability = "has-placeholders"
     )]
     ClosureReturn {
@@ -260,7 +260,7 @@ impl AddToDiagnostic for RegionOriginNote<'_> {
                 requirement,
                 expected_found: Some((expected, found)),
             } => {
-                label_or_note(span, fluent::infer::subtype);
+                label_or_note(span, fluent::infer_subtype);
                 diag.set_arg("requirement", requirement);
 
                 diag.note_expected_found(&"", expected, &"", found);
@@ -269,7 +269,7 @@ impl AddToDiagnostic for RegionOriginNote<'_> {
                 // FIXME: this really should be handled at some earlier stage. Our
                 // handling of region checking when type errors are present is
                 // *terrible*.
-                label_or_note(span, fluent::infer::subtype_2);
+                label_or_note(span, fluent::infer_subtype_2);
                 diag.set_arg("requirement", requirement);
             }
         };
@@ -300,9 +300,9 @@ impl AddToDiagnostic for LifetimeMismatchLabels {
     {
         match self {
             LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
-                diag.span_label(param_span, fluent::infer::declared_different);
-                diag.span_label(ret_span, fluent::infer::nothing);
-                diag.span_label(span, fluent::infer::data_returned);
+                diag.span_label(param_span, fluent::infer_declared_different);
+                diag.span_label(ret_span, fluent::infer_nothing);
+                diag.span_label(span, fluent::infer_data_returned);
                 diag.set_arg("label_var1_exists", label_var1.is_some());
                 diag.set_arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
             }
@@ -315,13 +315,13 @@ impl AddToDiagnostic for LifetimeMismatchLabels {
                 sub: label_var2,
             } => {
                 if hir_equal {
-                    diag.span_label(ty_sup, fluent::infer::declared_multiple);
-                    diag.span_label(ty_sub, fluent::infer::nothing);
-                    diag.span_label(span, fluent::infer::data_lifetime_flow);
+                    diag.span_label(ty_sup, fluent::infer_declared_multiple);
+                    diag.span_label(ty_sub, fluent::infer_nothing);
+                    diag.span_label(span, fluent::infer_data_lifetime_flow);
                 } else {
-                    diag.span_label(ty_sup, fluent::infer::types_declared_different);
-                    diag.span_label(ty_sub, fluent::infer::nothing);
-                    diag.span_label(span, fluent::infer::data_flows);
+                    diag.span_label(ty_sup, fluent::infer_types_declared_different);
+                    diag.span_label(ty_sub, fluent::infer_nothing);
+                    diag.span_label(span, fluent::infer_data_flows);
                     diag.set_arg("label_var1_exists", label_var1.is_some());
                     diag.set_arg(
                         "label_var1",
@@ -419,7 +419,7 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
             }
 
             diag.multipart_suggestion(
-                fluent::infer::lifetime_param_suggestion,
+                fluent::infer_lifetime_param_suggestion,
                 suggestions,
                 Applicability::MaybeIncorrect,
             );
@@ -427,13 +427,13 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
             true
         };
         if mk_suggestion() && self.add_note {
-            diag.note(fluent::infer::lifetime_param_suggestion_elided);
+            diag.note(fluent::infer_lifetime_param_suggestion_elided);
         }
     }
 }
 
 #[derive(Diagnostic)]
-#[diag(infer::lifetime_mismatch, code = "E0623")]
+#[diag(infer_lifetime_mismatch, code = "E0623")]
 pub struct LifetimeMismatch<'a> {
     #[primary_span]
     pub span: Span,
@@ -454,32 +454,32 @@ impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
     {
         self.unmet_requirements
-            .push_span_label(self.binding_span, fluent::infer::msl_introduces_static);
-        diag.span_note(self.unmet_requirements, fluent::infer::msl_unmet_req);
+            .push_span_label(self.binding_span, fluent::infer_msl_introduces_static);
+        diag.span_note(self.unmet_requirements, fluent::infer_msl_unmet_req);
     }
 }
 
 // FIXME(#100717): replace with a `Option<Span>` when subdiagnostic supports that
 #[derive(Subdiagnostic)]
 pub enum DoesNotOutliveStaticFromImpl {
-    #[note(infer::does_not_outlive_static_from_impl)]
+    #[note(infer_does_not_outlive_static_from_impl)]
     Spanned {
         #[primary_span]
         span: Span,
     },
-    #[note(infer::does_not_outlive_static_from_impl)]
+    #[note(infer_does_not_outlive_static_from_impl)]
     Unspanned,
 }
 
 #[derive(Subdiagnostic)]
 pub enum ImplicitStaticLifetimeSubdiag {
-    #[note(infer::implicit_static_lifetime_note)]
+    #[note(infer_implicit_static_lifetime_note)]
     Note {
         #[primary_span]
         span: Span,
     },
     #[suggestion_verbose(
-        infer::implicit_static_lifetime_suggestion,
+        infer_implicit_static_lifetime_suggestion,
         code = " + '_",
         applicability = "maybe-incorrect"
     )]
@@ -490,7 +490,7 @@ pub enum ImplicitStaticLifetimeSubdiag {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer::mismatched_static_lifetime)]
+#[diag(infer_mismatched_static_lifetime)]
 pub struct MismatchedStaticLifetime<'a> {
     #[primary_span]
     pub cause_span: Span,
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index 201a3c7100c..6a29d85627a 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -166,9 +166,9 @@ impl AddToDiagnostic for RegionExplanation<'_> {
         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
     {
         if let Some(span) = self.desc.span {
-            diag.span_note(span, fluent::infer::region_explanation);
+            diag.span_note(span, fluent::infer_region_explanation);
         } else {
-            diag.note(fluent::infer::region_explanation);
+            diag.note(fluent::infer_region_explanation);
         }
         self.desc.add_to(diag);
         diag.set_arg("pref_kind", self.prefix);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index ddeeaa9618e..9ff703e521f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -338,8 +338,7 @@ impl<'tcx> InferCtxt<'tcx> {
 
             let bounds = self.tcx.bound_explicit_item_bounds(*def_id);
 
-            for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
-                let predicate = predicate.subst(self.tcx, substs);
+            for (predicate, _) in bounds.subst_iter_copied(self.tcx, substs) {
                 let output = predicate
                     .kind()
                     .map_bound(|kind| match kind {
@@ -2272,6 +2271,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
             }
             FailureCode::Error0308(failure_str) => {
+                fn escape_literal(s: &str) -> String {
+                    let mut escaped = String::with_capacity(s.len());
+                    let mut chrs = s.chars().peekable();
+                    while let Some(first) = chrs.next() {
+                        match (first, chrs.peek()) {
+                            ('\\', Some(&delim @ '"') | Some(&delim @ '\'')) => {
+                                escaped.push('\\');
+                                escaped.push(delim);
+                                chrs.next();
+                            }
+                            ('"' | '\'', _) => {
+                                escaped.push('\\');
+                                escaped.push(first)
+                            }
+                            (c, _) => escaped.push(c),
+                        };
+                    }
+                    escaped
+                }
                 let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
                 if let Some((expected, found)) = trace.values.ty() {
                     match (expected.kind(), found.kind()) {
@@ -2293,7 +2311,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 err.span_suggestion(
                                     span,
                                     "if you meant to write a `char` literal, use single quotes",
-                                    format!("'{}'", code),
+                                    format!("'{}'", escape_literal(code)),
                                     Applicability::MachineApplicable,
                                 );
                             }
@@ -2308,7 +2326,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                     err.span_suggestion(
                                         span,
                                         "if you meant to write a `str` literal, use double quotes",
-                                        format!("\"{}\"", code),
+                                        format!("\"{}\"", escape_literal(code)),
                                         Applicability::MachineApplicable,
                                     );
                                 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index a04245a23a2..41b115f3377 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -19,26 +19,27 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 expected_found: self.values_str(trace.values),
             }
             .add_to_diagnostic(err),
-            infer::Reborrow(span) => RegionOriginNote::Plain { span, msg: fluent::infer::reborrow }
-                .add_to_diagnostic(err),
+            infer::Reborrow(span) => {
+                RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err)
+            }
             infer::ReborrowUpvar(span, ref upvar_id) => {
                 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
                 RegionOriginNote::WithName {
                     span,
-                    msg: fluent::infer::reborrow,
+                    msg: fluent::infer_reborrow,
                     name: &var_name.to_string(),
                     continues: false,
                 }
                 .add_to_diagnostic(err);
             }
             infer::RelateObjectBound(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer::relate_object_bound }
+                RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
                     .add_to_diagnostic(err);
             }
             infer::DataBorrowed(ty, span) => {
                 RegionOriginNote::WithName {
                     span,
-                    msg: fluent::infer::data_borrowed,
+                    msg: fluent::infer_data_borrowed,
                     name: &self.ty_to_string(ty),
                     continues: false,
                 }
@@ -47,7 +48,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             infer::ReferenceOutlivesReferent(ty, span) => {
                 RegionOriginNote::WithName {
                     span,
-                    msg: fluent::infer::reference_outlives_referent,
+                    msg: fluent::infer_reference_outlives_referent,
                     name: &self.ty_to_string(ty),
                     continues: false,
                 }
@@ -56,22 +57,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             infer::RelateParamBound(span, ty, opt_span) => {
                 RegionOriginNote::WithName {
                     span,
-                    msg: fluent::infer::relate_param_bound,
+                    msg: fluent::infer_relate_param_bound,
                     name: &self.ty_to_string(ty),
                     continues: opt_span.is_some(),
                 }
                 .add_to_diagnostic(err);
                 if let Some(span) = opt_span {
-                    RegionOriginNote::Plain { span, msg: fluent::infer::relate_param_bound_2 }
+                    RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
                         .add_to_diagnostic(err);
                 }
             }
             infer::RelateRegionParamBound(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer::relate_region_param_bound }
+                RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
                     .add_to_diagnostic(err);
             }
             infer::CompareImplItemObligation { span, .. } => {
-                RegionOriginNote::Plain { span, msg: fluent::infer::compare_impl_item_obligation }
+                RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
                     .add_to_diagnostic(err);
             }
             infer::CheckAssociatedTypeBounds { ref parent, .. } => {
@@ -80,7 +81,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             infer::AscribeUserTypeProvePredicate(span) => {
                 RegionOriginNote::Plain {
                     span,
-                    msg: fluent::infer::ascribe_user_type_prove_predicate,
+                    msg: fluent::infer_ascribe_user_type_prove_predicate,
                 }
                 .add_to_diagnostic(err);
             }
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 77e8f72aefa..0a4ecc4c033 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -1,6 +1,7 @@
 use crate::errors::OpaqueHiddenTypeDiag;
 use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
 use crate::traits;
+use hir::def::DefKind;
 use hir::def_id::{DefId, LocalDefId};
 use hir::{HirId, OpaqueTyOrigin};
 use rustc_data_structures::sync::Lrc;
@@ -543,16 +544,18 @@ impl<'tcx> InferCtxt<'tcx> {
 
         let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id());
 
-        for predicate in item_bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
-            debug!(?predicate);
-            let predicate = predicate.subst(tcx, substs);
-
+        for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) {
             let predicate = predicate.fold_with(&mut BottomUpFolder {
                 tcx,
                 ty_op: |ty| match *ty.kind() {
                     // We can't normalize associated types from `rustc_infer`,
                     // but we can eagerly register inference variables for them.
-                    ty::Projection(projection_ty) if !projection_ty.has_escaping_bound_vars() => {
+                    // FIXME(RPITIT): Don't replace RPITITs with inference vars.
+                    ty::Projection(projection_ty)
+                        if !projection_ty.has_escaping_bound_vars()
+                            && tcx.def_kind(projection_ty.item_def_id)
+                                != DefKind::ImplTraitPlaceholder =>
+                    {
                         self.infer_projection(
                             param_env,
                             projection_ty,
@@ -568,6 +571,12 @@ impl<'tcx> InferCtxt<'tcx> {
                     {
                         hidden_ty
                     }
+                    // FIXME(RPITIT): This can go away when we move to associated types
+                    ty::Projection(proj)
+                        if def_id.to_def_id() == proj.item_def_id && substs == proj.substs =>
+                    {
+                        hidden_ty
+                    }
                     _ => ty,
                 },
                 lt_op: |lt| lt,
diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs
index 097640f26c1..f5135c78dc8 100644
--- a/compiler/rustc_interface/src/errors.rs
+++ b/compiler/rustc_interface/src/errors.rs
@@ -5,7 +5,7 @@ use std::io;
 use std::path::Path;
 
 #[derive(Diagnostic)]
-#[diag(interface::ferris_identifier)]
+#[diag(interface_ferris_identifier)]
 pub struct FerrisIdentifier {
     #[primary_span]
     pub spans: Vec<Span>,
@@ -14,7 +14,7 @@ pub struct FerrisIdentifier {
 }
 
 #[derive(Diagnostic)]
-#[diag(interface::emoji_identifier)]
+#[diag(interface_emoji_identifier)]
 pub struct EmojiIdentifier {
     #[primary_span]
     pub spans: Vec<Span>,
@@ -22,67 +22,67 @@ pub struct EmojiIdentifier {
 }
 
 #[derive(Diagnostic)]
-#[diag(interface::mixed_bin_crate)]
+#[diag(interface_mixed_bin_crate)]
 pub struct MixedBinCrate;
 
 #[derive(Diagnostic)]
-#[diag(interface::mixed_proc_macro_crate)]
+#[diag(interface_mixed_proc_macro_crate)]
 pub struct MixedProcMacroCrate;
 
 #[derive(Diagnostic)]
-#[diag(interface::proc_macro_doc_without_arg)]
+#[diag(interface_proc_macro_doc_without_arg)]
 pub struct ProcMacroDocWithoutArg;
 
 #[derive(Diagnostic)]
-#[diag(interface::error_writing_dependencies)]
+#[diag(interface_error_writing_dependencies)]
 pub struct ErrorWritingDependencies<'a> {
     pub path: &'a Path,
     pub error: io::Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(interface::input_file_would_be_overwritten)]
+#[diag(interface_input_file_would_be_overwritten)]
 pub struct InputFileWouldBeOverWritten<'a> {
     pub path: &'a Path,
 }
 
 #[derive(Diagnostic)]
-#[diag(interface::generated_file_conflicts_with_directory)]
+#[diag(interface_generated_file_conflicts_with_directory)]
 pub struct GeneratedFileConflictsWithDirectory<'a> {
     pub input_path: &'a Path,
     pub dir_path: &'a Path,
 }
 
 #[derive(Diagnostic)]
-#[diag(interface::temps_dir_error)]
+#[diag(interface_temps_dir_error)]
 pub struct TempsDirError;
 
 #[derive(Diagnostic)]
-#[diag(interface::out_dir_error)]
+#[diag(interface_out_dir_error)]
 pub struct OutDirError;
 
 #[derive(Diagnostic)]
-#[diag(interface::cant_emit_mir)]
+#[diag(interface_cant_emit_mir)]
 pub struct CantEmitMIR {
     pub error: io::Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(interface::rustc_error_fatal)]
+#[diag(interface_rustc_error_fatal)]
 pub struct RustcErrorFatal {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(interface::rustc_error_unexpected_annotation)]
+#[diag(interface_rustc_error_unexpected_annotation)]
 pub struct RustcErrorUnexpectedAnnotation {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(interface::failed_writing_file)]
+#[diag(interface_failed_writing_file)]
 pub struct FailedWritingFile<'a> {
     pub path: &'a Path,
     pub error: io::Error,
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index da3102ba7b0..eb8e65a6d59 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -648,6 +648,7 @@ fn test_unstable_options_tracking_hash() {
     untracked!(dump_mir_dir, String::from("abc"));
     untracked!(dump_mir_exclude_pass_number, true);
     untracked!(dump_mir_graphviz, true);
+    untracked!(dylib_lto, true);
     untracked!(emit_stack_sizes, true);
     untracked!(future_incompat_test, true);
     untracked!(hir_stats, true);
diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs
index bd6b637f76f..abebc533cc1 100644
--- a/compiler/rustc_lint/src/array_into_iter.rs
+++ b/compiler/rustc_lint/src/array_into_iter.rs
@@ -121,25 +121,25 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
             cx.struct_span_lint(
                 ARRAY_INTO_ITER,
                 call.ident.span,
-                fluent::lint::array_into_iter,
+                fluent::lint_array_into_iter,
                 |diag| {
                     diag.set_arg("target", target);
                     diag.span_suggestion(
                         call.ident.span,
-                        fluent::lint::use_iter_suggestion,
+                        fluent::use_iter_suggestion,
                         "iter",
                         Applicability::MachineApplicable,
                     );
                     if self.for_expr_span == expr.span {
                         diag.span_suggestion(
                             receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
-                            fluent::lint::remove_into_iter_suggestion,
+                            fluent::remove_into_iter_suggestion,
                             "",
                             Applicability::MaybeIncorrect,
                         );
                     } else if receiver_ty.is_array() {
                         diag.multipart_suggestion(
-                            fluent::lint::use_explicit_into_iter_suggestion,
+                            fluent::use_explicit_into_iter_suggestion,
                             vec![
                                 (expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()),
                                 (
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 715ba4ca156..53c49105134 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -106,11 +106,11 @@ impl EarlyLintPass for WhileTrue {
             cx.struct_span_lint(
                             WHILE_TRUE,
                             condition_span,
-                fluent::lint::builtin_while_true,
+                fluent::lint_builtin_while_true,
                             |lint| {
                     lint.span_suggestion_short(
                         condition_span,
-                        fluent::lint::suggestion,
+                        fluent::suggestion,
                         format!(
                             "{}loop",
                             label.map_or_else(String::new, |label| format!(
@@ -160,7 +160,7 @@ impl BoxPointers {
                     cx.struct_span_lint(
                         BOX_POINTERS,
                         span,
-                        fluent::lint::builtin_box_pointers,
+                        fluent::lint_builtin_box_pointers,
                         |lint| lint.set_arg("ty", ty),
                     );
                 }
@@ -264,13 +264,13 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
                         cx.struct_span_lint(
                             NON_SHORTHAND_FIELD_PATTERNS,
                             fieldpat.span,
-                            fluent::lint::builtin_non_shorthand_field_patterns,
+                            fluent::lint_builtin_non_shorthand_field_patterns,
                             |lint| {
                                 let suggested_ident =
                                     format!("{}{}", binding_annot.prefix_str(), ident);
                                 lint.set_arg("ident", ident.clone()).span_suggestion(
                                     fieldpat.span,
-                                    fluent::lint::suggestion,
+                                    fluent::suggestion,
                                     suggested_ident,
                                     Applicability::MachineApplicable,
                                 )
@@ -335,7 +335,7 @@ impl UnsafeCode {
         msg: DiagnosticMessage,
     ) {
         self.report_unsafe(cx, span, msg, |lint| {
-            lint.note(fluent::lint::builtin_overridden_symbol_name)
+            lint.note(fluent::lint_builtin_overridden_symbol_name)
         })
     }
 
@@ -346,7 +346,7 @@ impl UnsafeCode {
         msg: DiagnosticMessage,
     ) {
         self.report_unsafe(cx, span, msg, |lint| {
-            lint.note(fluent::lint::builtin_overridden_symbol_section)
+            lint.note(fluent::lint_builtin_overridden_symbol_section)
         })
     }
 }
@@ -354,12 +354,9 @@ impl UnsafeCode {
 impl EarlyLintPass for UnsafeCode {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
         if attr.has_name(sym::allow_internal_unsafe) {
-            self.report_unsafe(
-                cx,
-                attr.span,
-                fluent::lint::builtin_allow_internal_unsafe,
-                |lint| lint,
-            );
+            self.report_unsafe(cx, attr.span, fluent::lint_builtin_allow_internal_unsafe, |lint| {
+                lint
+            });
         }
     }
 
@@ -367,7 +364,7 @@ impl EarlyLintPass for UnsafeCode {
         if let ast::ExprKind::Block(ref blk, _) = e.kind {
             // Don't warn about generated blocks; that'll just pollute the output.
             if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
-                self.report_unsafe(cx, blk.span, fluent::lint::builtin_unsafe_block, |lint| lint);
+                self.report_unsafe(cx, blk.span, fluent::lint_builtin_unsafe_block, |lint| lint);
             }
         }
     }
@@ -375,11 +372,11 @@ impl EarlyLintPass for UnsafeCode {
     fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
         match it.kind {
             ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => {
-                self.report_unsafe(cx, it.span, fluent::lint::builtin_unsafe_trait, |lint| lint)
+                self.report_unsafe(cx, it.span, fluent::lint_builtin_unsafe_trait, |lint| lint)
             }
 
             ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => {
-                self.report_unsafe(cx, it.span, fluent::lint::builtin_unsafe_impl, |lint| lint)
+                self.report_unsafe(cx, it.span, fluent::lint_builtin_unsafe_impl, |lint| lint)
             }
 
             ast::ItemKind::Fn(..) => {
@@ -387,7 +384,7 @@ impl EarlyLintPass for UnsafeCode {
                     self.report_overridden_symbol_name(
                         cx,
                         attr.span,
-                        fluent::lint::builtin_no_mangle_fn,
+                        fluent::lint_builtin_no_mangle_fn,
                     );
                 }
 
@@ -395,7 +392,7 @@ impl EarlyLintPass for UnsafeCode {
                     self.report_overridden_symbol_name(
                         cx,
                         attr.span,
-                        fluent::lint::builtin_export_name_fn,
+                        fluent::lint_builtin_export_name_fn,
                     );
                 }
 
@@ -403,7 +400,7 @@ impl EarlyLintPass for UnsafeCode {
                     self.report_overridden_symbol_section(
                         cx,
                         attr.span,
-                        fluent::lint::builtin_link_section_fn,
+                        fluent::lint_builtin_link_section_fn,
                     );
                 }
             }
@@ -413,7 +410,7 @@ impl EarlyLintPass for UnsafeCode {
                     self.report_overridden_symbol_name(
                         cx,
                         attr.span,
-                        fluent::lint::builtin_no_mangle_static,
+                        fluent::lint_builtin_no_mangle_static,
                     );
                 }
 
@@ -421,7 +418,7 @@ impl EarlyLintPass for UnsafeCode {
                     self.report_overridden_symbol_name(
                         cx,
                         attr.span,
-                        fluent::lint::builtin_export_name_static,
+                        fluent::lint_builtin_export_name_static,
                     );
                 }
 
@@ -429,7 +426,7 @@ impl EarlyLintPass for UnsafeCode {
                     self.report_overridden_symbol_section(
                         cx,
                         attr.span,
-                        fluent::lint::builtin_link_section_static,
+                        fluent::lint_builtin_link_section_static,
                     );
                 }
             }
@@ -444,14 +441,14 @@ impl EarlyLintPass for UnsafeCode {
                 self.report_overridden_symbol_name(
                     cx,
                     attr.span,
-                    fluent::lint::builtin_no_mangle_method,
+                    fluent::lint_builtin_no_mangle_method,
                 );
             }
             if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) {
                 self.report_overridden_symbol_name(
                     cx,
                     attr.span,
-                    fluent::lint::builtin_export_name_method,
+                    fluent::lint_builtin_export_name_method,
                 );
             }
         }
@@ -469,9 +466,9 @@ impl EarlyLintPass for UnsafeCode {
         {
             let msg = match ctxt {
                 FnCtxt::Foreign => return,
-                FnCtxt::Free => fluent::lint::builtin_decl_unsafe_fn,
-                FnCtxt::Assoc(_) if body.is_none() => fluent::lint::builtin_decl_unsafe_method,
-                FnCtxt::Assoc(_) => fluent::lint::builtin_impl_unsafe_method,
+                FnCtxt::Free => fluent::lint_builtin_decl_unsafe_fn,
+                FnCtxt::Assoc(_) if body.is_none() => fluent::lint_builtin_decl_unsafe_method,
+                FnCtxt::Assoc(_) => fluent::lint_builtin_impl_unsafe_method,
             };
             self.report_unsafe(cx, span, msg, |lint| lint);
         }
@@ -577,7 +574,7 @@ impl MissingDoc {
             cx.struct_span_lint(
                 MISSING_DOCS,
                 cx.tcx.def_span(def_id),
-                fluent::lint::builtin_missing_doc,
+                fluent::lint_builtin_missing_doc,
                 |lint| lint.set_arg("article", article).set_arg("desc", desc),
             );
         }
@@ -769,7 +766,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
             cx.struct_span_lint(
                 MISSING_COPY_IMPLEMENTATIONS,
                 item.span,
-                fluent::lint::builtin_missing_copy_impl,
+                fluent::lint_builtin_missing_copy_impl,
                 |lint| lint,
             )
         }
@@ -848,7 +845,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
             cx.struct_span_lint(
                 MISSING_DEBUG_IMPLEMENTATIONS,
                 item.span,
-                fluent::lint::builtin_missing_debug_impl,
+                fluent::lint_builtin_missing_debug_impl,
                 |lint| lint.set_arg("debug", cx.tcx.def_path_str(debug)),
             );
         }
@@ -928,11 +925,11 @@ impl EarlyLintPass for AnonymousParameters {
                         cx.struct_span_lint(
                             ANONYMOUS_PARAMETERS,
                             arg.pat.span,
-                            fluent::lint::builtin_anonymous_params,
+                            fluent::lint_builtin_anonymous_params,
                             |lint| {
                                 lint.span_suggestion(
                                     arg.pat.span,
-                                    fluent::lint::suggestion,
+                                    fluent::suggestion,
                                     format!("_: {}", ty_snip),
                                     appl,
                                 )
@@ -976,7 +973,7 @@ impl EarlyLintPass for DeprecatedAttr {
                     cx.struct_span_lint(
                         DEPRECATED,
                         attr.span,
-                        fluent::lint::builtin_deprecated_attr_link,
+                        fluent::lint_builtin_deprecated_attr_link,
                         |lint| {
                             lint.set_arg("name", name)
                                 .set_arg("reason", reason)
@@ -984,7 +981,7 @@ impl EarlyLintPass for DeprecatedAttr {
                                 .span_suggestion_short(
                                     attr.span,
                                     suggestion.map(|s| s.into()).unwrap_or(
-                                        fluent::lint::builtin_deprecated_attr_default_suggestion,
+                                        fluent::lint_builtin_deprecated_attr_default_suggestion,
                                     ),
                                     "",
                                     Applicability::MachineApplicable,
@@ -999,12 +996,12 @@ impl EarlyLintPass for DeprecatedAttr {
             cx.struct_span_lint(
                 DEPRECATED,
                 attr.span,
-                fluent::lint::builtin_deprecated_attr_used,
+                fluent::lint_builtin_deprecated_attr_used,
                 |lint| {
                     lint.set_arg("name", pprust::path_to_string(&attr.get_normal_item().path))
                         .span_suggestion_short(
                             attr.span,
-                            fluent::lint::builtin_deprecated_attr_default_suggestion,
+                            fluent::lint_builtin_deprecated_attr_default_suggestion,
                             "",
                             Applicability::MachineApplicable,
                         )
@@ -1039,14 +1036,14 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &
             cx.struct_span_lint(
                 UNUSED_DOC_COMMENTS,
                 span,
-                fluent::lint::builtin_unused_doc_comment,
+                fluent::lint_builtin_unused_doc_comment,
                 |lint| {
-                    lint.set_arg("kind", node_kind).span_label(node_span, fluent::lint::label).help(
+                    lint.set_arg("kind", node_kind).span_label(node_span, fluent::label).help(
                         match attr.kind {
                             AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => {
-                                fluent::lint::plain_help
+                                fluent::plain_help
                             }
-                            AttrKind::DocComment(CommentKind::Block, _) => fluent::lint::block_help,
+                            AttrKind::DocComment(CommentKind::Block, _) => fluent::block_help,
                         },
                     )
                 },
@@ -1167,11 +1164,11 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
                         cx.struct_span_lint(
                             NO_MANGLE_GENERIC_ITEMS,
                             span,
-                            fluent::lint::builtin_no_mangle_generic,
+                            fluent::lint_builtin_no_mangle_generic,
                             |lint| {
                                 lint.span_suggestion_short(
                                     no_mangle_attr.span,
-                                    fluent::lint::suggestion,
+                                    fluent::suggestion,
                                     "",
                                     // Use of `#[no_mangle]` suggests FFI intent; correct
                                     // fix may be to monomorphize source by hand
@@ -1197,7 +1194,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
                     cx.struct_span_lint(
                         NO_MANGLE_CONST_ITEMS,
                         it.span,
-                        fluent::lint::builtin_const_no_mangle,
+                        fluent::lint_builtin_const_no_mangle,
                         |lint| {
                             // account for "pub const" (#45562)
                             let start = cx
@@ -1211,7 +1208,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
                             let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5));
                             lint.span_suggestion(
                                 const_span,
-                                fluent::lint::suggestion,
+                                fluent::suggestion,
                                 "pub static",
                                 Applicability::MachineApplicable,
                             )
@@ -1279,7 +1276,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
                 cx.struct_span_lint(
                     MUTABLE_TRANSMUTES,
                     expr.span,
-                    fluent::lint::builtin_mutable_transmutes,
+                    fluent::lint_builtin_mutable_transmutes,
                     |lint| lint,
                 );
             }
@@ -1332,7 +1329,7 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
                     cx.struct_span_lint(
                         UNSTABLE_FEATURES,
                         item.span(),
-                        fluent::lint::builtin_unstable_features,
+                        fluent::lint_builtin_unstable_features,
                         |lint| lint,
                     );
                 }
@@ -1396,18 +1393,13 @@ impl UnreachablePub {
             cx.struct_span_lint(
                 UNREACHABLE_PUB,
                 def_span,
-                fluent::lint::builtin_unreachable_pub,
+                fluent::lint_builtin_unreachable_pub,
                 |lint| {
                     lint.set_arg("what", what);
 
-                    lint.span_suggestion(
-                        vis_span,
-                        fluent::lint::suggestion,
-                        "pub(crate)",
-                        applicability,
-                    );
+                    lint.span_suggestion(vis_span, fluent::suggestion, "pub(crate)", applicability);
                     if exportable {
-                        lint.help(fluent::lint::help);
+                        lint.help(fluent::help);
                     }
                     lint
                 },
@@ -1498,7 +1490,7 @@ impl TypeAliasBounds {
         impl Visitor<'_> for WalkAssocTypes<'_> {
             fn visit_qpath(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) {
                 if TypeAliasBounds::is_type_variable_assoc(qpath) {
-                    self.err.span_help(span, fluent::lint::builtin_type_alias_bounds_help);
+                    self.err.span_help(span, fluent::lint_builtin_type_alias_bounds_help);
                 }
                 intravisit::walk_qpath(self, qpath, id)
             }
@@ -1541,11 +1533,11 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
 
         let mut suggested_changing_assoc_types = false;
         if !where_spans.is_empty() {
-            cx.lint(TYPE_ALIAS_BOUNDS, fluent::lint::builtin_type_alias_where_clause, |lint| {
+            cx.lint(TYPE_ALIAS_BOUNDS, fluent::lint_builtin_type_alias_where_clause, |lint| {
                 lint.set_span(where_spans);
                 lint.span_suggestion(
                     type_alias_generics.where_clause_span,
-                    fluent::lint::suggestion,
+                    fluent::suggestion,
                     "",
                     Applicability::MachineApplicable,
                 );
@@ -1558,10 +1550,10 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
         }
 
         if !inline_spans.is_empty() {
-            cx.lint(TYPE_ALIAS_BOUNDS, fluent::lint::builtin_type_alias_generic_bounds, |lint| {
+            cx.lint(TYPE_ALIAS_BOUNDS, fluent::lint_builtin_type_alias_generic_bounds, |lint| {
                 lint.set_span(inline_spans);
                 lint.multipart_suggestion(
-                    fluent::lint::suggestion,
+                    fluent::suggestion,
                     inline_sugg,
                     Applicability::MachineApplicable,
                 );
@@ -1670,7 +1662,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
                     cx.struct_span_lint(
                         TRIVIAL_BOUNDS,
                         span,
-                        fluent::lint::builtin_trivial_bounds,
+                        fluent::lint_builtin_trivial_bounds,
                         |lint| {
                             lint.set_arg("predicate_kind_name", predicate_kind_name)
                                 .set_arg("predicate", predicate)
@@ -1775,8 +1767,8 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
         };
 
         if let Some((start, end, join)) = endpoints {
-            let msg = fluent::lint::builtin_ellipsis_inclusive_range_patterns;
-            let suggestion = fluent::lint::suggestion;
+            let msg = fluent::lint_builtin_ellipsis_inclusive_range_patterns;
+            let suggestion = fluent::suggestion;
             if parenthesise {
                 self.node_id = Some(pat.id);
                 let end = expr_to_string(&end);
@@ -1899,7 +1891,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems {
             cx.struct_span_lint(
                 UNNAMEABLE_TEST_ITEMS,
                 attr.span,
-                fluent::lint::builtin_unnameable_test_items,
+                fluent::lint_builtin_unnameable_test_items,
                 |lint| lint,
             );
         }
@@ -2020,11 +2012,11 @@ impl KeywordIdents {
         cx.struct_span_lint(
             KEYWORD_IDENTS,
             ident.span,
-            fluent::lint::builtin_keyword_idents,
+            fluent::lint_builtin_keyword_idents,
             |lint| {
                 lint.set_arg("kw", ident.clone()).set_arg("next", next_edition).span_suggestion(
                     ident.span,
-                    fluent::lint::suggestion,
+                    fluent::suggestion,
                     format!("r#{}", ident),
                     Applicability::MachineApplicable,
                 )
@@ -2283,10 +2275,10 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
                 cx.struct_span_lint(
                     EXPLICIT_OUTLIVES_REQUIREMENTS,
                     lint_spans.clone(),
-                    fluent::lint::builtin_explicit_outlives,
+                    fluent::lint_builtin_explicit_outlives,
                     |lint| {
                         lint.set_arg("count", bound_count).multipart_suggestion(
-                            fluent::lint::suggestion,
+                            fluent::suggestion,
                             lint_spans
                                 .into_iter()
                                 .map(|span| (span, String::new()))
@@ -2344,17 +2336,17 @@ impl EarlyLintPass for IncompleteFeatures {
                 cx.struct_span_lint(
                     INCOMPLETE_FEATURES,
                     span,
-                    fluent::lint::builtin_incomplete_features,
+                    fluent::lint_builtin_incomplete_features,
                     |lint| {
                         lint.set_arg("name", name);
                         if let Some(n) =
                             rustc_feature::find_feature_issue(name, GateIssue::Language)
                         {
                             lint.set_arg("n", n);
-                            lint.note(fluent::lint::note);
+                            lint.note(fluent::note);
                         }
                         if HAS_MIN_FEATURES.contains(&name) {
-                            lint.help(fluent::lint::help);
+                            lint.help(fluent::help);
                         }
                         lint
                     },
@@ -2467,42 +2459,6 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
             None
         }
 
-        /// Determines whether the given type is inhabited. `None` means that we don't know.
-        fn ty_inhabited<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<bool> {
-            use rustc_type_ir::sty::TyKind::*;
-            if !cx.tcx.type_uninhabited_from(cx.param_env.and(ty)).is_empty() {
-                // This is definitely uninhabited from some module.
-                return Some(false);
-            }
-            match ty.kind() {
-                Never => Some(false),
-                Int(_) | Uint(_) | Float(_) | Bool | Char | RawPtr(_) => Some(true),
-                // Fallback for more complicated types. (Note that `&!` might be considered
-                // uninhabited so references are "complicated", too.)
-                _ => None,
-            }
-        }
-        /// Determines whether a product type formed from a list of types is inhabited.
-        fn tys_inhabited<'tcx>(
-            cx: &LateContext<'tcx>,
-            tys: impl Iterator<Item = Ty<'tcx>>,
-        ) -> Option<bool> {
-            let mut definitely_inhabited = true; // with no fields, we are definitely inhabited.
-            for ty in tys {
-                match ty_inhabited(cx, ty) {
-                    // If any type is uninhabited, the product is uninhabited.
-                    Some(false) => return Some(false),
-                    // Otherwise go searching for a `None`.
-                    None => {
-                        // We don't know.
-                        definitely_inhabited = false;
-                    }
-                    Some(true) => {}
-                }
-            }
-            if definitely_inhabited { Some(true) } else { None }
-        }
-
         fn variant_find_init_error<'tcx>(
             cx: &LateContext<'tcx>,
             variant: &VariantDef,
@@ -2570,7 +2526,10 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                         // return `Bound::Excluded`.  (And we have tests checking that we
                         // handle the attribute correctly.)
                         // We don't add a span since users cannot declare such types anyway.
-                        (Bound::Included(lo), _) if lo > 0 => {
+                        (Bound::Included(lo), Bound::Included(hi)) if 0 < lo && lo < hi => {
+                            return Some((format!("`{}` must be non-null", ty), None));
+                        }
+                        (Bound::Included(lo), Bound::Unbounded) if 0 < lo => {
                             return Some((format!("`{}` must be non-null", ty), None));
                         }
                         (Bound::Included(_), _) | (_, Bound::Included(_))
@@ -2599,11 +2558,11 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                     // And now, enums.
                     let span = cx.tcx.def_span(adt_def.did());
                     let mut potential_variants = adt_def.variants().iter().filter_map(|variant| {
-                        let inhabited = tys_inhabited(
-                            cx,
-                            variant.fields.iter().map(|field| field.ty(cx.tcx, substs)),
-                        );
-                        let definitely_inhabited = match inhabited {
+                        let definitely_inhabited = match variant
+                            .inhabited_predicate(cx.tcx, *adt_def)
+                            .subst(cx.tcx, substs)
+                            .apply_any_module(cx.tcx, cx.param_env)
+                        {
                             // Entirely skip uninhbaited variants.
                             Some(false) => return None,
                             // Forward the others, but remember which ones are definitely inhabited.
@@ -3051,9 +3010,9 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
                     // Finally, emit the diagnostic.
 
                     let msg = if orig.get_name() == this_fi.ident.name {
-                        fluent::lint::builtin_clashing_extern_same_name
+                        fluent::lint_builtin_clashing_extern_same_name
                     } else {
-                        fluent::lint::builtin_clashing_extern_diff_name
+                        fluent::lint_builtin_clashing_extern_diff_name
                     };
                     tcx.struct_span_lint_hir(
                         CLASHING_EXTERN_DECLARATIONS,
@@ -3068,14 +3027,8 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
 
                             lint.set_arg("this_fi", this_fi.ident.name)
                                 .set_arg("orig", orig.get_name())
-                                .span_label(
-                                    get_relevant_span(orig_fi),
-                                    fluent::lint::previous_decl_label,
-                                )
-                                .span_label(
-                                    get_relevant_span(this_fi),
-                                    fluent::lint::mismatch_label,
-                                )
+                                .span_label(get_relevant_span(orig_fi), fluent::previous_decl_label)
+                                .span_label(get_relevant_span(this_fi), fluent::mismatch_label)
                                 // FIXME(davidtwco): translatable expected/found
                                 .note_expected_found(&"", expected_str, &"", found_str)
                         },
@@ -3161,8 +3114,8 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr {
                 cx.struct_span_lint(
                     DEREF_NULLPTR,
                     expr.span,
-                    fluent::lint::builtin_deref_nullptr,
-                    |lint| lint.span_label(expr.span, fluent::lint::label),
+                    fluent::lint_builtin_deref_nullptr,
+                    |lint| lint.span_label(expr.span, fluent::label),
                 );
             }
         }
@@ -3274,7 +3227,7 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
                     cx.lookup_with_diagnostics(
                             NAMED_ASM_LABELS,
                             Some(target_spans),
-                            fluent::lint::builtin_asm_labels,
+                            fluent::lint_builtin_asm_labels,
                             |lint| lint,
                             BuiltinLintDiagnostics::NamedAsmLabel(
                                 "only local labels of the form `<number>:` should be used in inline asm"
@@ -3377,8 +3330,8 @@ impl EarlyLintPass for UnexpectedCfgs {
                     cx.lookup(
                         UNEXPECTED_CFGS,
                         None::<MultiSpan>,
-                        fluent::lint::builtin_unexpected_cli_config_name,
-                        |diag| diag.help(fluent::lint::help).set_arg("name", name),
+                        fluent::lint_builtin_unexpected_cli_config_name,
+                        |diag| diag.help(fluent::help).set_arg("name", name),
                     );
                 }
             }
@@ -3388,9 +3341,9 @@ impl EarlyLintPass for UnexpectedCfgs {
                         cx.lookup(
                             UNEXPECTED_CFGS,
                             None::<MultiSpan>,
-                            fluent::lint::builtin_unexpected_cli_config_value,
+                            fluent::lint_builtin_unexpected_cli_config_value,
                             |diag| {
-                                diag.help(fluent::lint::help)
+                                diag.help(fluent::help)
                                     .set_arg("name", name)
                                     .set_arg("value", value)
                             },
diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
index e8d307814b9..f9d7466228a 100644
--- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
+++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
@@ -53,8 +53,8 @@ fn enforce_mem_discriminant(
         cx.struct_span_lint(
             ENUM_INTRINSICS_NON_ENUMS,
             expr_span,
-            fluent::lint::enum_intrinsics_mem_discriminant,
-            |lint| lint.set_arg("ty_param", ty_param).span_note(args_span, fluent::lint::note),
+            fluent::lint_enum_intrinsics_mem_discriminant,
+            |lint| lint.set_arg("ty_param", ty_param).span_note(args_span, fluent::note),
         );
     }
 }
@@ -65,8 +65,8 @@ fn enforce_mem_variant_count(cx: &LateContext<'_>, func_expr: &hir::Expr<'_>, sp
         cx.struct_span_lint(
             ENUM_INTRINSICS_NON_ENUMS,
             span,
-            fluent::lint::enum_intrinsics_mem_variant,
-            |lint| lint.set_arg("ty_param", ty_param).note(fluent::lint::note),
+            fluent::lint_enum_intrinsics_mem_variant,
+            |lint| lint.set_arg("ty_param", ty_param).note(fluent::note),
         );
     }
 }
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index 34b70030a58..a49d1bdacc2 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -7,7 +7,7 @@ use rustc_session::lint::Level;
 use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
-#[diag(lint::overruled_attribute, code = "E0453")]
+#[diag(lint_overruled_attribute, code = "E0453")]
 pub struct OverruledAttribute {
     #[primary_span]
     pub span: Span,
@@ -32,24 +32,24 @@ impl AddToDiagnostic for OverruledAttributeSub {
     {
         match self {
             OverruledAttributeSub::DefaultSource { id } => {
-                diag.note(fluent::lint::default_source);
+                diag.note(fluent::lint_default_source);
                 diag.set_arg("id", id);
             }
             OverruledAttributeSub::NodeSource { span, reason } => {
-                diag.span_label(span, fluent::lint::node_source);
+                diag.span_label(span, fluent::lint_node_source);
                 if let Some(rationale) = reason {
                     diag.note(rationale.as_str());
                 }
             }
             OverruledAttributeSub::CommandLineSource => {
-                diag.note(fluent::lint::command_line_source);
+                diag.note(fluent::lint_command_line_source);
             }
         }
     }
 }
 
 #[derive(Diagnostic)]
-#[diag(lint::malformed_attribute, code = "E0452")]
+#[diag(lint_malformed_attribute, code = "E0452")]
 pub struct MalformedAttribute {
     #[primary_span]
     pub span: Span,
@@ -59,16 +59,16 @@ pub struct MalformedAttribute {
 
 #[derive(Subdiagnostic)]
 pub enum MalformedAttributeSub {
-    #[label(lint::bad_attribute_argument)]
+    #[label(lint_bad_attribute_argument)]
     BadAttributeArgument(#[primary_span] Span),
-    #[label(lint::reason_must_be_string_literal)]
+    #[label(lint_reason_must_be_string_literal)]
     ReasonMustBeStringLiteral(#[primary_span] Span),
-    #[label(lint::reason_must_come_last)]
+    #[label(lint_reason_must_come_last)]
     ReasonMustComeLast(#[primary_span] Span),
 }
 
 #[derive(Diagnostic)]
-#[diag(lint::unknown_tool_in_scoped_lint, code = "E0710")]
+#[diag(lint_unknown_tool_in_scoped_lint, code = "E0710")]
 pub struct UnknownToolInScopedLint {
     #[primary_span]
     pub span: Option<Span>,
@@ -79,7 +79,7 @@ pub struct UnknownToolInScopedLint {
 }
 
 #[derive(Diagnostic)]
-#[diag(lint::builtin_ellipsis_inclusive_range_patterns, code = "E0783")]
+#[diag(lint_builtin_ellipsis_inclusive_range_patterns, code = "E0783")]
 pub struct BuiltinEllpisisInclusiveRangePatterns {
     #[primary_span]
     pub span: Span,
@@ -89,14 +89,14 @@ pub struct BuiltinEllpisisInclusiveRangePatterns {
 }
 
 #[derive(Subdiagnostic)]
-#[note(lint::requested_level)]
+#[note(lint_requested_level)]
 pub struct RequestedLevel {
     pub level: Level,
     pub lint_name: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(lint::unsupported_group, code = "E0602")]
+#[diag(lint_unsupported_group, code = "E0602")]
 pub struct UnsupportedGroup {
     pub lint_group: String,
 }
@@ -112,10 +112,10 @@ impl IntoDiagnostic<'_> for CheckNameUnknown {
         self,
         handler: &Handler,
     ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
-        let mut diag = handler.struct_err(fluent::lint::check_name_unknown);
+        let mut diag = handler.struct_err(fluent::lint_check_name_unknown);
         diag.code(rustc_errors::error_code!(E0602));
         if let Some(suggestion) = self.suggestion {
-            diag.help(fluent::lint::help);
+            diag.help(fluent::help);
             diag.set_arg("suggestion", suggestion);
         }
         diag.set_arg("lint_name", self.lint_name);
@@ -125,7 +125,7 @@ impl IntoDiagnostic<'_> for CheckNameUnknown {
 }
 
 #[derive(Diagnostic)]
-#[diag(lint::check_name_unknown_tool, code = "E0602")]
+#[diag(lint_check_name_unknown_tool, code = "E0602")]
 pub struct CheckNameUnknownTool {
     pub tool_name: Symbol,
     #[subdiagnostic]
@@ -133,7 +133,7 @@ pub struct CheckNameUnknownTool {
 }
 
 #[derive(Diagnostic)]
-#[diag(lint::check_name_warning)]
+#[diag(lint_check_name_warning)]
 pub struct CheckNameWarning {
     pub msg: String,
     #[subdiagnostic]
@@ -141,7 +141,7 @@ pub struct CheckNameWarning {
 }
 
 #[derive(Diagnostic)]
-#[diag(lint::check_name_deprecated)]
+#[diag(lint_check_name_deprecated)]
 pub struct CheckNameDeprecated {
     pub lint_name: String,
     pub new_name: String,
diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs
index 4c3c39734dd..cf8f31bcbd0 100644
--- a/compiler/rustc_lint/src/expect.rs
+++ b/compiler/rustc_lint/src/expect.rs
@@ -45,14 +45,14 @@ fn emit_unfulfilled_expectation_lint(
         builtin::UNFULFILLED_LINT_EXPECTATIONS,
         hir_id,
         expectation.emission_span,
-        fluent::lint::expectation,
+        fluent::lint_expectation,
         |lint| {
             if let Some(rationale) = expectation.reason {
                 lint.note(rationale.as_str());
             }
 
             if expectation.is_unfulfilled_lint_expectations {
-                lint.note(fluent::lint::note);
+                lint.note(fluent::note);
             }
 
             lint
diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
index 42557068bd3..7e884e990ce 100644
--- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
+++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
@@ -63,12 +63,12 @@ impl HiddenUnicodeCodepoints {
         cx.struct_span_lint(
             TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
             span,
-            fluent::lint::hidden_unicode_codepoints,
+            fluent::lint_hidden_unicode_codepoints,
             |lint| {
                 lint.set_arg("label", label);
                 lint.set_arg("count", spans.len());
-                lint.span_label(span, fluent::lint::label);
-                lint.note(fluent::lint::note);
+                lint.span_label(span, fluent::label);
+                lint.note(fluent::note);
                 if point_at_inner_spans {
                     for (c, span) in &spans {
                         lint.span_label(*span, format!("{:?}", c));
@@ -76,13 +76,13 @@ impl HiddenUnicodeCodepoints {
                 }
                 if point_at_inner_spans && !spans.is_empty() {
                     lint.multipart_suggestion_with_style(
-                        fluent::lint::suggestion_remove,
+                        fluent::suggestion_remove,
                         spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
                         Applicability::MachineApplicable,
                         SuggestionStyle::HideCodeAlways,
                     );
                     lint.multipart_suggestion(
-                        fluent::lint::suggestion_escape,
+                        fluent::suggestion_escape,
                         spans
                             .into_iter()
                             .map(|(c, span)| {
@@ -104,8 +104,8 @@ impl HiddenUnicodeCodepoints {
                             .collect::<Vec<String>>()
                             .join(", "),
                     );
-                    lint.note(fluent::lint::suggestion_remove);
-                    lint.note(fluent::lint::no_suggestion_note_escape);
+                    lint.note(fluent::suggestion_remove);
+                    lint.note(fluent::no_suggestion_note_escape);
                 }
                 lint
             },
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 8f5e38fdbcc..11e4650cb4b 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -37,11 +37,11 @@ impl LateLintPass<'_> for DefaultHashTypes {
         cx.struct_span_lint(
             DEFAULT_HASH_TYPES,
             path.span,
-            fluent::lint::default_hash_types,
+            fluent::lint_default_hash_types,
             |lint| {
                 lint.set_arg("preferred", replace)
                     .set_arg("used", cx.tcx.item_name(def_id))
-                    .note(fluent::lint::note)
+                    .note(fluent::note)
             },
         );
     }
@@ -86,8 +86,8 @@ impl LateLintPass<'_> for QueryStability {
                 cx.struct_span_lint(
                     POTENTIAL_QUERY_INSTABILITY,
                     span,
-                    fluent::lint::query_instability,
-                    |lint| lint.set_arg("query", cx.tcx.item_name(def_id)).note(fluent::lint::note),
+                    fluent::lint_query_instability,
+                    |lint| lint.set_arg("query", cx.tcx.item_name(def_id)).note(fluent::note),
                 )
             }
         }
@@ -126,11 +126,11 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
             let span = path.span.with_hi(
                 segment.args.map_or(segment.ident.span, |a| a.span_ext).hi()
             );
-            cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, fluent::lint::tykind_kind, |lint| {
+            cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, fluent::lint_tykind_kind, |lint| {
                 lint
                     .span_suggestion(
                         span,
-                        fluent::lint::suggestion,
+                        fluent::suggestion,
                         "ty",
                         Applicability::MaybeIncorrect, // ty maybe needs an import
                     )
@@ -193,10 +193,10 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
                             cx.struct_span_lint(
                                 USAGE_OF_TY_TYKIND,
                                 path.span,
-                                fluent::lint::tykind_kind,
+                                fluent::lint_tykind_kind,
                                 |lint| lint.span_suggestion(
                                     span,
-                                    fluent::lint::suggestion,
+                                    fluent::suggestion,
                                     "ty",
                                     Applicability::MaybeIncorrect, // ty maybe needs an import
                                 )
@@ -205,18 +205,18 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
                         None => cx.struct_span_lint(
                             USAGE_OF_TY_TYKIND,
                             path.span,
-                            fluent::lint::tykind,
-                            |lint| lint.help(fluent::lint::help)
+                            fluent::lint_tykind,
+                            |lint| lint.help(fluent::help)
                         )
                     }
                 } else if !ty.span.from_expansion() && let Some(t) = is_ty_or_ty_ctxt(cx, &path) {
                     if path.segments.len() > 1 {
-                        cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, fluent::lint::ty_qualified, |lint| {
+                        cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, fluent::lint_ty_qualified, |lint| {
                             lint
                                 .set_arg("ty", t.clone())
                                 .span_suggestion(
                                     path.span,
-                                    fluent::lint::suggestion,
+                                    fluent::suggestion,
                                     t,
                                     // The import probably needs to be changed
                                     Applicability::MaybeIncorrect,
@@ -310,8 +310,8 @@ impl EarlyLintPass for LintPassImpl {
                         cx.struct_span_lint(
                             LINT_PASS_IMPL_WITHOUT_MACRO,
                             lint_pass.path.span,
-                            fluent::lint::lintpass_by_hand,
-                            |lint| lint.help(fluent::lint::help),
+                            fluent::lint_lintpass_by_hand,
+                            |lint| lint.help(fluent::help),
                         )
                     }
                 }
@@ -351,8 +351,8 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword {
                         cx.struct_span_lint(
                             EXISTING_DOC_KEYWORD,
                             attr.span,
-                            fluent::lint::non_existant_doc_keyword,
-                            |lint| lint.set_arg("keyword", v).help(fluent::lint::help),
+                            fluent::lint_non_existant_doc_keyword,
+                            |lint| lint.set_arg("keyword", v).help(fluent::help),
                         );
                     }
                 }
@@ -414,7 +414,7 @@ impl LateLintPass<'_> for Diagnostics {
             cx.struct_span_lint(
                 DIAGNOSTIC_OUTSIDE_OF_IMPL,
                 span,
-                fluent::lint::diag_out_of_impl,
+                fluent::lint_diag_out_of_impl,
                 |lint| lint,
             )
         }
@@ -435,7 +435,7 @@ impl LateLintPass<'_> for Diagnostics {
             cx.struct_span_lint(
                 UNTRANSLATABLE_DIAGNOSTIC,
                 span,
-                fluent::lint::untranslatable_diag,
+                fluent::lint_untranslatable_diag,
                 |lint| lint,
             )
         }
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index d3879ff487d..db0a3419e6a 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -960,7 +960,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                                         sp,
                                         "did you mean",
                                         suggestion,
-                                        Applicability::MachineApplicable,
+                                        Applicability::MaybeIncorrect,
                                     );
                                 }
                                 lint
diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs
index 313119637bc..e2d7d5b49f6 100644
--- a/compiler/rustc_lint/src/methods.rs
+++ b/compiler/rustc_lint/src/methods.rs
@@ -93,12 +93,12 @@ fn lint_cstring_as_ptr(
                     cx.struct_span_lint(
                         TEMPORARY_CSTRING_AS_PTR,
                         as_ptr_span,
-                        fluent::lint::cstring_ptr,
+                        fluent::lint_cstring_ptr,
                         |diag| {
-                            diag.span_label(as_ptr_span, fluent::lint::as_ptr_label)
-                                .span_label(unwrap.span, fluent::lint::unwrap_label)
-                                .note(fluent::lint::note)
-                                .help(fluent::lint::help)
+                            diag.span_label(as_ptr_span, fluent::as_ptr_label)
+                                .span_label(unwrap.span, fluent::unwrap_label)
+                                .note(fluent::note)
+                                .help(fluent::help)
                         },
                     );
                 }
diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs
index b2626efb6d7..dea9506acb2 100644
--- a/compiler/rustc_lint/src/non_ascii_idents.rs
+++ b/compiler/rustc_lint/src/non_ascii_idents.rs
@@ -183,7 +183,7 @@ impl EarlyLintPass for NonAsciiIdents {
             cx.struct_span_lint(
                 NON_ASCII_IDENTS,
                 sp,
-                fluent::lint::identifier_non_ascii_char,
+                fluent::lint_identifier_non_ascii_char,
                 |lint| lint,
             );
             if check_uncommon_codepoints
@@ -192,7 +192,7 @@ impl EarlyLintPass for NonAsciiIdents {
                 cx.struct_span_lint(
                     UNCOMMON_CODEPOINTS,
                     sp,
-                    fluent::lint::identifier_uncommon_codepoints,
+                    fluent::lint_identifier_uncommon_codepoints,
                     |lint| lint,
                 )
             }
@@ -225,11 +225,11 @@ impl EarlyLintPass for NonAsciiIdents {
                             cx.struct_span_lint(
                                 CONFUSABLE_IDENTS,
                                 sp,
-                                fluent::lint::confusable_identifier_pair,
+                                fluent::lint_confusable_identifier_pair,
                                 |lint| {
                                     lint.set_arg("existing_sym", *existing_symbol)
                                         .set_arg("sym", symbol)
-                                        .span_label(*existing_span, fluent::lint::label)
+                                        .span_label(*existing_span, fluent::label)
                                 },
                             );
                         }
@@ -334,7 +334,7 @@ impl EarlyLintPass for NonAsciiIdents {
                     cx.struct_span_lint(
                         MIXED_SCRIPT_CONFUSABLES,
                         sp,
-                        fluent::lint::mixed_script_confusables,
+                        fluent::lint_mixed_script_confusables,
                         |lint| {
                             let mut includes = String::new();
                             for (idx, ch) in ch_list.into_iter().enumerate() {
@@ -346,8 +346,8 @@ impl EarlyLintPass for NonAsciiIdents {
                             }
                             lint.set_arg("set", script_set.to_string())
                                 .set_arg("includes", includes)
-                                .note(fluent::lint::includes_note)
-                                .note(fluent::lint::note)
+                                .note(fluent::includes_note)
+                                .note(fluent::note)
                         },
                     );
                 }
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index 886b686e5e8..6ad2e0294b9 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -119,20 +119,20 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
         arg_span = expn.call_site;
     }
 
-    cx.struct_span_lint(NON_FMT_PANICS, arg_span, fluent::lint::non_fmt_panic, |lint| {
+    cx.struct_span_lint(NON_FMT_PANICS, arg_span, fluent::lint_non_fmt_panic, |lint| {
         lint.set_arg("name", symbol);
-        lint.note(fluent::lint::note);
-        lint.note(fluent::lint::more_info_note);
+        lint.note(fluent::note);
+        lint.note(fluent::more_info_note);
         if !is_arg_inside_call(arg_span, span) {
             // No clue where this argument is coming from.
             return lint;
         }
         if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) {
             // A case of `panic!(format!(..))`.
-            lint.note(fluent::lint::supports_fmt_note);
+            lint.note(fluent::supports_fmt_note);
             if let Some((open, close, _)) = find_delimiters(cx, arg_span) {
                 lint.multipart_suggestion(
-                    fluent::lint::supports_fmt_suggestion,
+                    fluent::supports_fmt_suggestion,
                     vec![
                         (arg_span.until(open.shrink_to_hi()), "".into()),
                         (close.until(arg_span.shrink_to_hi()), "".into()),
@@ -178,7 +178,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
             if suggest_display {
                 lint.span_suggestion_verbose(
                     arg_span.shrink_to_lo(),
-                    fluent::lint::display_suggestion,
+                    fluent::display_suggestion,
                     "\"{}\", ",
                     fmt_applicability,
                 );
@@ -186,7 +186,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
                 lint.set_arg("ty", ty);
                 lint.span_suggestion_verbose(
                     arg_span.shrink_to_lo(),
-                    fluent::lint::debug_suggestion,
+                    fluent::debug_suggestion,
                     "\"{:?}\", ",
                     fmt_applicability,
                 );
@@ -196,7 +196,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
                 if let Some((open, close, del)) = find_delimiters(cx, span) {
                     lint.set_arg("already_suggested", suggest_display || suggest_debug);
                     lint.multipart_suggestion(
-                        fluent::lint::panic_suggestion,
+                        fluent::panic_suggestion,
                         if del == '(' {
                             vec![(span.until(open), "std::panic::panic_any".into())]
                         } else {
@@ -254,30 +254,25 @@ fn check_panic_str<'tcx>(
                 .map(|span| fmt_span.from_inner(InnerSpan::new(span.start, span.end)))
                 .collect(),
         };
-        cx.struct_span_lint(
-            NON_FMT_PANICS,
-            arg_spans,
-            fluent::lint::non_fmt_panic_unused,
-            |lint| {
-                lint.set_arg("count", n_arguments);
-                lint.note(fluent::lint::note);
-                if is_arg_inside_call(arg.span, span) {
-                    lint.span_suggestion(
-                        arg.span.shrink_to_hi(),
-                        fluent::lint::add_args_suggestion,
-                        ", ...",
-                        Applicability::HasPlaceholders,
-                    );
-                    lint.span_suggestion(
-                        arg.span.shrink_to_lo(),
-                        fluent::lint::add_fmt_suggestion,
-                        "\"{}\", ",
-                        Applicability::MachineApplicable,
-                    );
-                }
-                lint
-            },
-        );
+        cx.struct_span_lint(NON_FMT_PANICS, arg_spans, fluent::lint_non_fmt_panic_unused, |lint| {
+            lint.set_arg("count", n_arguments);
+            lint.note(fluent::note);
+            if is_arg_inside_call(arg.span, span) {
+                lint.span_suggestion(
+                    arg.span.shrink_to_hi(),
+                    fluent::add_args_suggestion,
+                    ", ...",
+                    Applicability::HasPlaceholders,
+                );
+                lint.span_suggestion(
+                    arg.span.shrink_to_lo(),
+                    fluent::add_fmt_suggestion,
+                    "\"{}\", ",
+                    Applicability::MachineApplicable,
+                );
+            }
+            lint
+        });
     } else {
         let brace_spans: Option<Vec<_>> =
             snippet.filter(|s| s.starts_with('"') || s.starts_with("r#")).map(|s| {
@@ -290,14 +285,14 @@ fn check_panic_str<'tcx>(
         cx.struct_span_lint(
             NON_FMT_PANICS,
             brace_spans.unwrap_or_else(|| vec![span]),
-            fluent::lint::non_fmt_panic_braces,
+            fluent::lint_non_fmt_panic_braces,
             |lint| {
                 lint.set_arg("count", count);
-                lint.note(fluent::lint::note);
+                lint.note(fluent::note);
                 if is_arg_inside_call(arg.span, span) {
                     lint.span_suggestion(
                         arg.span.shrink_to_lo(),
-                        fluent::lint::suggestion,
+                        fluent::suggestion,
                         "\"{}\", ",
                         Applicability::MachineApplicable,
                     );
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 6b32e78b910..7e50801f80c 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -139,7 +139,7 @@ impl NonCamelCaseTypes {
             cx.struct_span_lint(
                 NON_CAMEL_CASE_TYPES,
                 ident.span,
-                fluent::lint::non_camel_case_type,
+                fluent::lint_non_camel_case_type,
                 |lint| {
                     let cc = to_camel_case(name);
                     // We cannot provide meaningful suggestions
@@ -147,12 +147,12 @@ impl NonCamelCaseTypes {
                     if *name != cc {
                         lint.span_suggestion(
                             ident.span,
-                            fluent::lint::suggestion,
+                            fluent::suggestion,
                             to_camel_case(name),
                             Applicability::MaybeIncorrect,
                         );
                     } else {
-                        lint.span_label(ident.span, fluent::lint::label);
+                        lint.span_label(ident.span, fluent::label);
                     }
 
                     lint.set_arg("sort", sort);
@@ -284,7 +284,7 @@ impl NonSnakeCase {
         let name = ident.name.as_str();
 
         if !is_snake_case(name) {
-            cx.struct_span_lint(NON_SNAKE_CASE, ident.span, fluent::lint::non_snake_case, |lint| {
+            cx.struct_span_lint(NON_SNAKE_CASE, ident.span, fluent::lint_non_snake_case, |lint| {
                 let sc = NonSnakeCase::to_snake_case(name);
                 // We cannot provide meaningful suggestions
                 // if the characters are in the category of "Uppercase Letter".
@@ -298,13 +298,13 @@ impl NonSnakeCase {
                             // Instead, recommend renaming the identifier entirely or, if permitted,
                             // escaping it to create a raw identifier.
                             if sc_ident.name.can_be_raw() {
-                                (fluent::lint::rename_or_convert_suggestion, sc_ident.to_string())
+                                (fluent::rename_or_convert_suggestion, sc_ident.to_string())
                             } else {
-                                lint.note(fluent::lint::cannot_convert_note);
-                                (fluent::lint::rename_suggestion, String::new())
+                                lint.note(fluent::cannot_convert_note);
+                                (fluent::rename_suggestion, String::new())
                             }
                         } else {
-                            (fluent::lint::convert_suggestion, sc.clone())
+                            (fluent::convert_suggestion, sc.clone())
                         };
 
                         lint.span_suggestion(
@@ -314,10 +314,10 @@ impl NonSnakeCase {
                             Applicability::MaybeIncorrect,
                         );
                     } else {
-                        lint.help(fluent::lint::help);
+                        lint.help(fluent::help);
                     }
                 } else {
-                    lint.span_label(ident.span, fluent::lint::label);
+                    lint.span_label(ident.span, fluent::label);
                 }
 
                 lint.set_arg("sort", sort);
@@ -484,7 +484,7 @@ impl NonUpperCaseGlobals {
             cx.struct_span_lint(
                 NON_UPPER_CASE_GLOBALS,
                 ident.span,
-                fluent::lint::non_upper_case_global,
+                fluent::lint_non_upper_case_global,
                 |lint| {
                     let uc = NonSnakeCase::to_snake_case(&name).to_uppercase();
                     // We cannot provide meaningful suggestions
@@ -492,12 +492,12 @@ impl NonUpperCaseGlobals {
                     if *name != uc {
                         lint.span_suggestion(
                             ident.span,
-                            fluent::lint::suggestion,
+                            fluent::suggestion,
                             uc,
                             Applicability::MaybeIncorrect,
                         );
                     } else {
-                        lint.span_label(ident.span, fluent::lint::label);
+                        lint.span_label(ident.span, fluent::label);
                     }
 
                     lint.set_arg("sort", sort);
diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs
index 9a62afd3caf..2ef425a1093 100644
--- a/compiler/rustc_lint/src/noop_method_call.rs
+++ b/compiler/rustc_lint/src/noop_method_call.rs
@@ -85,11 +85,11 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
         }
         let expr_span = expr.span;
         let span = expr_span.with_lo(receiver.span.hi());
-        cx.struct_span_lint(NOOP_METHOD_CALL, span, fluent::lint::noop_method_call, |lint| {
+        cx.struct_span_lint(NOOP_METHOD_CALL, span, fluent::lint_noop_method_call, |lint| {
             lint.set_arg("method", call.ident.name)
                 .set_arg("receiver_ty", receiver_ty)
-                .span_label(span, fluent::lint::label)
-                .note(fluent::lint::note)
+                .span_label(span, fluent::label)
+                .note(fluent::note)
         });
     }
 }
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index 81b9f55e703..7f6f4a0abb4 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -91,14 +91,12 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
             // For example, in `impl Trait<Assoc = impl Send>`, for all of the bounds on `Assoc`,
             // e.g. `type Assoc: OtherTrait`, replace `<impl Trait as Trait>::Assoc: OtherTrait`
             // with `impl Send: OtherTrait`.
-            for assoc_pred_and_span in
-                cx.tcx.bound_explicit_item_bounds(proj.projection_ty.item_def_id).transpose_iter()
+            for (assoc_pred, assoc_pred_span) in cx
+                .tcx
+                .bound_explicit_item_bounds(proj.projection_ty.item_def_id)
+                .subst_iter_copied(cx.tcx, &proj.projection_ty.substs)
             {
-                let assoc_pred_span = assoc_pred_and_span.0.1;
-                let assoc_pred = assoc_pred_and_span
-                    .map_bound(|(pred, _)| *pred)
-                    .subst(cx.tcx, &proj.projection_ty.substs)
-                    .fold_with(proj_replacer);
+                let assoc_pred = assoc_pred.fold_with(proj_replacer);
                 let Ok(assoc_pred) = traits::fully_normalize(infcx, traits::ObligationCause::dummy(), cx.param_env, assoc_pred) else {
                     continue;
                 };
@@ -141,11 +139,11 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint::opaque_hidden_inferred_bound)]
+#[diag(lint_opaque_hidden_inferred_bound)]
 struct OpaqueHiddenInferredBoundLint<'tcx> {
     ty: Ty<'tcx>,
     proj_ty: Ty<'tcx>,
-    #[label(lint::specifically)]
+    #[label(specifically)]
     assoc_pred_span: Span,
     #[subdiagnostic]
     add_bound: Option<AddBound<'tcx>>,
@@ -153,7 +151,7 @@ struct OpaqueHiddenInferredBoundLint<'tcx> {
 
 #[derive(Subdiagnostic)]
 #[suggestion_verbose(
-    lint::opaque_hidden_inferred_bound_sugg,
+    lint_opaque_hidden_inferred_bound_sugg,
     applicability = "machine-applicable",
     code = " + {trait_ref}"
 )]
diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index 349399b5964..01bface718a 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -32,11 +32,11 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue {
                     cx.struct_span_lint(
                         PASS_BY_VALUE,
                         ty.span,
-                        fluent::lint::pass_by_value,
+                        fluent::lint_pass_by_value,
                         |lint| {
                             lint.set_arg("ty", t.clone()).span_suggestion(
                                 ty.span,
-                                fluent::lint::suggestion,
+                                fluent::suggestion,
                                 t,
                                 // Changing type of function argument
                                 Applicability::MaybeIncorrect,
diff --git a/compiler/rustc_lint/src/redundant_semicolon.rs b/compiler/rustc_lint/src/redundant_semicolon.rs
index 46c84550e9f..3521de7fc08 100644
--- a/compiler/rustc_lint/src/redundant_semicolon.rs
+++ b/compiler/rustc_lint/src/redundant_semicolon.rs
@@ -51,11 +51,11 @@ fn maybe_lint_redundant_semis(cx: &EarlyContext<'_>, seq: &mut Option<(Span, boo
         cx.struct_span_lint(
             REDUNDANT_SEMICOLONS,
             span,
-            fluent::lint::redundant_semicolons,
+            fluent::lint_redundant_semicolons,
             |lint| {
                 lint.set_arg("multiple", multiple).span_suggestion(
                     span,
-                    fluent::lint::suggestion,
+                    fluent::suggestion,
                     "",
                     Applicability::MaybeIncorrect,
                 )
diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs
index 078465bdce6..a118dda8b40 100644
--- a/compiler/rustc_lint/src/traits.rs
+++ b/compiler/rustc_lint/src/traits.rs
@@ -106,7 +106,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
                 cx.struct_span_lint(
                     DROP_BOUNDS,
                     span,
-                    fluent::lint::drop_trait_constraints,
+                    fluent::lint_drop_trait_constraints,
                     |lint| {
                         lint.set_arg("predicate", predicate)
                             .set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
@@ -125,7 +125,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
             if cx.tcx.lang_items().drop_trait() == def_id
                 && let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop)
             {
-                cx.struct_span_lint(DYN_DROP, bound.span, fluent::lint::drop_glue, |lint| {
+                cx.struct_span_lint(DYN_DROP, bound.span, fluent::lint_drop_glue, |lint| {
                     lint.set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
                 });
             }
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index b6009bd800a..7c99bb2790f 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -116,8 +116,8 @@ impl TypeLimits {
     }
 }
 
-/// Attempts to special-case the overflowing literal lint when it occurs as a range endpoint.
-/// Returns `true` iff the lint was overridden.
+/// Attempts to special-case the overflowing literal lint when it occurs as a range endpoint (`expr..MAX+1`).
+/// Returns `true` iff the lint was emitted.
 fn lint_overflowing_range_endpoint<'tcx>(
     cx: &LateContext<'tcx>,
     lit: &hir::Lit,
@@ -140,44 +140,46 @@ fn lint_overflowing_range_endpoint<'tcx>(
         return false;
     }
 
-    let mut overwritten = false;
     // We can suggest using an inclusive range
     // (`..=`) instead only if it is the `end` that is
     // overflowing and only by 1.
-    if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max
-        && let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span)
-    {
-        cx.struct_span_lint(
-            OVERFLOWING_LITERALS,
-            struct_expr.span,
-            fluent::lint::range_endpoint_out_of_range,
-            |lint| {
-                use ast::{LitIntType, LitKind};
-
-                lint.set_arg("ty", ty);
-
-                // We need to preserve the literal's suffix,
-                // as it may determine typing information.
-                let suffix = match lit.node {
-                    LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
-                    LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
-                    LitKind::Int(_, LitIntType::Unsuffixed) => "",
-                    _ => bug!(),
-                };
-                let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
-                lint.span_suggestion(
-                    struct_expr.span,
-                    fluent::lint::suggestion,
-                    suggestion,
-                    Applicability::MachineApplicable,
-                );
-                overwritten = true;
+    if !(eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max) {
+        return false;
+    };
+    let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false };
 
-                lint
-            },
-        );
-    }
-    overwritten
+    cx.struct_span_lint(
+        OVERFLOWING_LITERALS,
+        struct_expr.span,
+        fluent::lint_range_endpoint_out_of_range,
+        |lint| {
+            use ast::{LitIntType, LitKind};
+
+            lint.set_arg("ty", ty);
+
+            // We need to preserve the literal's suffix,
+            // as it may determine typing information.
+            let suffix = match lit.node {
+                LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
+                LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
+                LitKind::Int(_, LitIntType::Unsuffixed) => "",
+                _ => bug!(),
+            };
+            let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
+            lint.span_suggestion(
+                struct_expr.span,
+                fluent::suggestion,
+                suggestion,
+                Applicability::MachineApplicable,
+            );
+
+            lint
+        },
+    );
+
+    // We've just emitted a lint, special cased for `(...)..MAX+1` ranges,
+    // return `true` so the callers don't also emit a lint
+    true
 }
 
 // For `isize` & `usize`, be conservative with the warnings, so that the
@@ -231,7 +233,7 @@ fn report_bin_hex_error(
     cx.struct_span_lint(
         OVERFLOWING_LITERALS,
         expr.span,
-        fluent::lint::overflowing_bin_hex,
+        fluent::lint_overflowing_bin_hex,
         |lint| {
             let (t, actually) = match ty {
                 attr::IntType::SignedInt(t) => {
@@ -251,10 +253,10 @@ fn report_bin_hex_error(
             if negative {
                 // If the value is negative,
                 // emits a note about the value itself, apart from the literal.
-                lint.note(fluent::lint::negative_note);
-                lint.note(fluent::lint::negative_becomes_note);
+                lint.note(fluent::negative_note);
+                lint.note(fluent::negative_becomes_note);
             } else {
-                lint.note(fluent::lint::positive_note);
+                lint.note(fluent::positive_note);
             }
             if let Some(sugg_ty) =
                 get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative)
@@ -264,12 +266,12 @@ fn report_bin_hex_error(
                     let (sans_suffix, _) = repr_str.split_at(pos);
                     lint.span_suggestion(
                         expr.span,
-                        fluent::lint::suggestion,
+                        fluent::suggestion,
                         format!("{}{}", sans_suffix, sugg_ty),
                         Applicability::MachineApplicable,
                     );
                 } else {
-                    lint.help(fluent::lint::help);
+                    lint.help(fluent::help);
                 }
             }
             lint.set_arg("ty", t)
@@ -358,11 +360,11 @@ fn lint_int_literal<'tcx>(
         }
 
         if lint_overflowing_range_endpoint(cx, lit, v, max, e, t.name_str()) {
-            // The overflowing literal lint was overridden.
+            // The overflowing literal lint was emited by `lint_overflowing_range_endpoint`.
             return;
         }
 
-        cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, fluent::lint::overflowing_int, |lint| {
+        cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, fluent::lint_overflowing_int, |lint| {
             lint.set_arg("ty", t.name_str())
                 .set_arg(
                     "lit",
@@ -373,13 +375,13 @@ fn lint_int_literal<'tcx>(
                 )
                 .set_arg("min", min)
                 .set_arg("max", max)
-                .note(fluent::lint::note);
+                .note(fluent::note);
 
             if let Some(sugg_ty) =
                 get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative)
             {
                 lint.set_arg("suggestion_ty", sugg_ty);
-                lint.help(fluent::lint::help);
+                lint.help(fluent::help);
             }
 
             lint
@@ -410,11 +412,11 @@ fn lint_uint_literal<'tcx>(
                         cx.struct_span_lint(
                             OVERFLOWING_LITERALS,
                             par_e.span,
-                            fluent::lint::only_cast_u8_to_char,
+                            fluent::lint_only_cast_u8_to_char,
                             |lint| {
                                 lint.span_suggestion(
                                     par_e.span,
-                                    fluent::lint::suggestion,
+                                    fluent::suggestion,
                                     format!("'\\u{{{:X}}}'", lit_val),
                                     Applicability::MachineApplicable,
                                 )
@@ -427,7 +429,7 @@ fn lint_uint_literal<'tcx>(
             }
         }
         if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, t.name_str()) {
-            // The overflowing literal lint was overridden.
+            // The overflowing literal lint was emited by `lint_overflowing_range_endpoint`.
             return;
         }
         if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
@@ -441,7 +443,7 @@ fn lint_uint_literal<'tcx>(
             );
             return;
         }
-        cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, fluent::lint::overflowing_uint, |lint| {
+        cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, fluent::lint_overflowing_uint, |lint| {
             lint.set_arg("ty", t.name_str())
                 .set_arg(
                     "lit",
@@ -452,7 +454,7 @@ fn lint_uint_literal<'tcx>(
                 )
                 .set_arg("min", min)
                 .set_arg("max", max)
-                .note(fluent::lint::note)
+                .note(fluent::note)
         });
     }
 }
@@ -485,7 +487,7 @@ fn lint_literal<'tcx>(
                 cx.struct_span_lint(
                     OVERFLOWING_LITERALS,
                     e.span,
-                    fluent::lint::overflowing_literal,
+                    fluent::lint_overflowing_literal,
                     |lint| {
                         lint.set_arg("ty", t.name_str())
                             .set_arg(
@@ -495,7 +497,7 @@ fn lint_literal<'tcx>(
                                     .span_to_snippet(lit.span)
                                     .expect("must get snippet from literal"),
                             )
-                            .note(fluent::lint::note)
+                            .note(fluent::note)
                     },
                 );
             }
@@ -518,7 +520,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
                     cx.struct_span_lint(
                         UNUSED_COMPARISONS,
                         e.span,
-                        fluent::lint::unused_comparisons,
+                        fluent::lint_unused_comparisons,
                         |lint| lint,
                     );
                 }
@@ -840,8 +842,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             self.emit_ffi_unsafe_type_lint(
                 ty,
                 sp,
-                fluent::lint::improper_ctypes_array_reason,
-                Some(fluent::lint::improper_ctypes_array_help),
+                fluent::lint_improper_ctypes_array_reason,
+                Some(fluent::lint_improper_ctypes_array_help),
             );
             true
         } else {
@@ -884,7 +886,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             } else {
                 // All fields are ZSTs; this means that the type should behave
                 // like (), which is FFI-unsafe
-                FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_struct_zst, help: None }
+                FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_struct_zst, help: None }
             }
         } else {
             // We can't completely trust repr(C) markings; make sure the fields are
@@ -898,7 +900,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                     FfiPhantom(..) if def.is_enum() => {
                         return FfiUnsafe {
                             ty,
-                            reason: fluent::lint::improper_ctypes_enum_phantomdata,
+                            reason: fluent::lint_improper_ctypes_enum_phantomdata,
                             help: None,
                         };
                     }
@@ -934,7 +936,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                     } else {
                         return FfiUnsafe {
                             ty,
-                            reason: fluent::lint::improper_ctypes_box,
+                            reason: fluent::lint_improper_ctypes_box,
                             help: None,
                         };
                     }
@@ -948,14 +950,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             return FfiUnsafe {
                                 ty,
                                 reason: if def.is_struct() {
-                                    fluent::lint::improper_ctypes_struct_layout_reason
+                                    fluent::lint_improper_ctypes_struct_layout_reason
                                 } else {
-                                    fluent::lint::improper_ctypes_union_layout_reason
+                                    fluent::lint_improper_ctypes_union_layout_reason
                                 },
                                 help: if def.is_struct() {
-                                    Some(fluent::lint::improper_ctypes_struct_layout_help)
+                                    Some(fluent::lint_improper_ctypes_struct_layout_help)
                                 } else {
-                                    Some(fluent::lint::improper_ctypes_union_layout_help)
+                                    Some(fluent::lint_improper_ctypes_union_layout_help)
                                 },
                             };
                         }
@@ -966,9 +968,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             return FfiUnsafe {
                                 ty,
                                 reason: if def.is_struct() {
-                                    fluent::lint::improper_ctypes_struct_non_exhaustive
+                                    fluent::lint_improper_ctypes_struct_non_exhaustive
                                 } else {
-                                    fluent::lint::improper_ctypes_union_non_exhaustive
+                                    fluent::lint_improper_ctypes_union_non_exhaustive
                                 },
                                 help: None,
                             };
@@ -978,14 +980,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             return FfiUnsafe {
                                 ty,
                                 reason: if def.is_struct() {
-                                    fluent::lint::improper_ctypes_struct_fieldless_reason
+                                    fluent::lint_improper_ctypes_struct_fieldless_reason
                                 } else {
-                                    fluent::lint::improper_ctypes_union_fieldless_reason
+                                    fluent::lint_improper_ctypes_union_fieldless_reason
                                 },
                                 help: if def.is_struct() {
-                                    Some(fluent::lint::improper_ctypes_struct_fieldless_help)
+                                    Some(fluent::lint_improper_ctypes_struct_fieldless_help)
                                 } else {
-                                    Some(fluent::lint::improper_ctypes_union_fieldless_help)
+                                    Some(fluent::lint_improper_ctypes_union_fieldless_help)
                                 },
                             };
                         }
@@ -1006,8 +1008,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             if repr_nullable_ptr(self.cx, ty, self.mode).is_none() {
                                 return FfiUnsafe {
                                     ty,
-                                    reason: fluent::lint::improper_ctypes_enum_repr_reason,
-                                    help: Some(fluent::lint::improper_ctypes_enum_repr_help),
+                                    reason: fluent::lint_improper_ctypes_enum_repr_reason,
+                                    help: Some(fluent::lint_improper_ctypes_enum_repr_help),
                                 };
                             }
                         }
@@ -1015,7 +1017,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                         if def.is_variant_list_non_exhaustive() && !def.did().is_local() {
                             return FfiUnsafe {
                                 ty,
-                                reason: fluent::lint::improper_ctypes_non_exhaustive,
+                                reason: fluent::lint_improper_ctypes_non_exhaustive,
                                 help: None,
                             };
                         }
@@ -1026,7 +1028,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             if is_non_exhaustive && !variant.def_id.is_local() {
                                 return FfiUnsafe {
                                     ty,
-                                    reason: fluent::lint::improper_ctypes_non_exhaustive_variant,
+                                    reason: fluent::lint_improper_ctypes_non_exhaustive_variant,
                                     help: None,
                                 };
                             }
@@ -1044,12 +1046,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 
             ty::Char => FfiUnsafe {
                 ty,
-                reason: fluent::lint::improper_ctypes_char_reason,
-                help: Some(fluent::lint::improper_ctypes_char_help),
+                reason: fluent::lint_improper_ctypes_char_reason,
+                help: Some(fluent::lint_improper_ctypes_char_help),
             },
 
             ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => {
-                FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_128bit, help: None }
+                FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_128bit, help: None }
             }
 
             // Primitive types with a stable representation.
@@ -1057,24 +1059,24 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 
             ty::Slice(_) => FfiUnsafe {
                 ty,
-                reason: fluent::lint::improper_ctypes_slice_reason,
-                help: Some(fluent::lint::improper_ctypes_slice_help),
+                reason: fluent::lint_improper_ctypes_slice_reason,
+                help: Some(fluent::lint_improper_ctypes_slice_help),
             },
 
             ty::Dynamic(..) => {
-                FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_dyn, help: None }
+                FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_dyn, help: None }
             }
 
             ty::Str => FfiUnsafe {
                 ty,
-                reason: fluent::lint::improper_ctypes_str_reason,
-                help: Some(fluent::lint::improper_ctypes_str_help),
+                reason: fluent::lint_improper_ctypes_str_reason,
+                help: Some(fluent::lint_improper_ctypes_str_help),
             },
 
             ty::Tuple(..) => FfiUnsafe {
                 ty,
-                reason: fluent::lint::improper_ctypes_tuple_reason,
-                help: Some(fluent::lint::improper_ctypes_tuple_help),
+                reason: fluent::lint_improper_ctypes_tuple_reason,
+                help: Some(fluent::lint_improper_ctypes_tuple_help),
             },
 
             ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _)
@@ -1105,8 +1107,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                 if self.is_internal_abi(sig.abi()) {
                     return FfiUnsafe {
                         ty,
-                        reason: fluent::lint::improper_ctypes_fnptr_reason,
-                        help: Some(fluent::lint::improper_ctypes_fnptr_help),
+                        reason: fluent::lint_improper_ctypes_fnptr_reason,
+                        help: Some(fluent::lint_improper_ctypes_fnptr_help),
                     };
                 }
 
@@ -1137,7 +1139,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             // While opaque types are checked for earlier, if a projection in a struct field
             // normalizes to an opaque type, then it will reach this branch.
             ty::Opaque(..) => {
-                FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_opaque, help: None }
+                FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_opaque, help: None }
             }
 
             // `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe,
@@ -1171,21 +1173,21 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             CItemKind::Definition => IMPROPER_CTYPES_DEFINITIONS,
         };
 
-        self.cx.struct_span_lint(lint, sp, fluent::lint::improper_ctypes, |lint| {
+        self.cx.struct_span_lint(lint, sp, fluent::lint_improper_ctypes, |lint| {
             let item_description = match self.mode {
                 CItemKind::Declaration => "block",
                 CItemKind::Definition => "fn",
             };
             lint.set_arg("ty", ty);
             lint.set_arg("desc", item_description);
-            lint.span_label(sp, fluent::lint::label);
+            lint.span_label(sp, fluent::label);
             if let Some(help) = help {
                 lint.help(help);
             }
             lint.note(note);
             if let ty::Adt(def, _) = ty.kind() {
                 if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did()) {
-                    lint.span_note(sp, fluent::lint::note);
+                    lint.span_note(sp, fluent::note);
                 }
             }
             lint
@@ -1222,7 +1224,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         }
 
         if let Some(ty) = ty.visit_with(&mut ProhibitOpaqueTypes { cx: self.cx }).break_value() {
-            self.emit_ffi_unsafe_type_lint(ty, sp, fluent::lint::improper_ctypes_opaque, None);
+            self.emit_ffi_unsafe_type_lint(ty, sp, fluent::lint_improper_ctypes_opaque, None);
             true
         } else {
             false
@@ -1267,7 +1269,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                 self.emit_ffi_unsafe_type_lint(
                     ty,
                     sp,
-                    fluent::lint::improper_ctypes_only_phantomdata,
+                    fluent::lint_improper_ctypes_only_phantomdata,
                     None,
                 );
             }
@@ -1401,7 +1403,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
                 cx.struct_span_lint(
                     VARIANT_SIZE_DIFFERENCES,
                     enum_definition.variants[largest_index].span,
-                    fluent::lint::variant_size_differences,
+                    fluent::lint_variant_size_differences,
                     |lint| lint.set_arg("largest", largest),
                 );
             }
@@ -1511,15 +1513,15 @@ impl InvalidAtomicOrdering {
     fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) {
         if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::load, sym::store])
             && let Some((ordering_arg, invalid_ordering, msg)) = match method {
-                sym::load => Some((&args[0], sym::Release, fluent::lint::atomic_ordering_load)),
-                sym::store => Some((&args[1], sym::Acquire, fluent::lint::atomic_ordering_store)),
+                sym::load => Some((&args[0], sym::Release, fluent::lint_atomic_ordering_load)),
+                sym::store => Some((&args[1], sym::Acquire, fluent::lint_atomic_ordering_store)),
                 _ => None,
             }
             && let Some(ordering) = Self::match_ordering(cx, ordering_arg)
             && (ordering == invalid_ordering || ordering == sym::AcqRel)
         {
             cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, msg, |lint| {
-                lint.help(fluent::lint::help)
+                lint.help(fluent::help)
             });
         }
     }
@@ -1531,9 +1533,9 @@ impl InvalidAtomicOrdering {
             && matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence))
             && Self::match_ordering(cx, &args[0]) == Some(sym::Relaxed)
         {
-            cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, fluent::lint::atomic_ordering_fence, |lint| {
+            cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, fluent::lint_atomic_ordering_fence, |lint| {
                 lint
-                    .help(fluent::lint::help)
+                    .help(fluent::help)
             });
         }
     }
@@ -1552,7 +1554,7 @@ impl InvalidAtomicOrdering {
 
         if matches!(fail_ordering, sym::Release | sym::AcqRel) {
             #[derive(LintDiagnostic)]
-            #[diag(lint::atomic_ordering_invalid)]
+            #[diag(lint_atomic_ordering_invalid)]
             #[help]
             struct InvalidAtomicOrderingDiag {
                 method: Symbol,
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 36657909b19..46706e49844 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -155,12 +155,12 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
         };
 
         if let Some(must_use_op) = must_use_op {
-            cx.struct_span_lint(UNUSED_MUST_USE, expr.span, fluent::lint::unused_op, |lint| {
+            cx.struct_span_lint(UNUSED_MUST_USE, expr.span, fluent::lint_unused_op, |lint| {
                 lint.set_arg("op", must_use_op)
-                    .span_label(expr.span, fluent::lint::label)
+                    .span_label(expr.span, fluent::label)
                     .span_suggestion_verbose(
                         expr.span.shrink_to_lo(),
-                        fluent::lint::suggestion,
+                        fluent::suggestion,
                         "let _ = ",
                         Applicability::MachineApplicable,
                     )
@@ -169,7 +169,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
         }
 
         if !(type_permits_lack_of_use || fn_warned || op_warned) {
-            cx.struct_span_lint(UNUSED_RESULTS, s.span, fluent::lint::unused_result, |lint| {
+            cx.struct_span_lint(UNUSED_RESULTS, s.span, fluent::lint_unused_result, |lint| {
                 lint.set_arg("ty", ty)
             });
         }
@@ -272,14 +272,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                     cx.struct_span_lint(
                         UNUSED_MUST_USE,
                         span,
-                        fluent::lint::unused_closure,
+                        fluent::lint_unused_closure,
                         |lint| {
                             // FIXME(davidtwco): this isn't properly translatable because of the
                             // pre/post strings
                             lint.set_arg("count", plural_len)
                                 .set_arg("pre", descr_pre)
                                 .set_arg("post", descr_post)
-                                .note(fluent::lint::note)
+                                .note(fluent::note)
                         },
                     );
                     true
@@ -288,14 +288,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                     cx.struct_span_lint(
                         UNUSED_MUST_USE,
                         span,
-                        fluent::lint::unused_generator,
+                        fluent::lint_unused_generator,
                         |lint| {
                             // FIXME(davidtwco): this isn't properly translatable because of the
                             // pre/post strings
                             lint.set_arg("count", plural_len)
                                 .set_arg("pre", descr_pre)
                                 .set_arg("post", descr_post)
-                                .note(fluent::lint::note)
+                                .note(fluent::note)
                         },
                     );
                     true
@@ -317,7 +317,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
             descr_post_path: &str,
         ) -> bool {
             if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) {
-                cx.struct_span_lint(UNUSED_MUST_USE, span, fluent::lint::unused_def, |lint| {
+                cx.struct_span_lint(UNUSED_MUST_USE, span, fluent::lint_unused_def, |lint| {
                     // FIXME(davidtwco): this isn't properly translatable because of the pre/post
                     // strings
                     lint.set_arg("pre", descr_pre_path);
@@ -369,17 +369,17 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
                     cx.struct_span_lint(
                         PATH_STATEMENTS,
                         s.span,
-                        fluent::lint::path_statement_drop,
+                        fluent::lint_path_statement_drop,
                         |lint| {
                             if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) {
                                 lint.span_suggestion(
                                     s.span,
-                                    fluent::lint::suggestion,
+                                    fluent::suggestion,
                                     format!("drop({});", snippet),
                                     Applicability::MachineApplicable,
                                 );
                             } else {
-                                lint.span_help(s.span, fluent::lint::suggestion);
+                                lint.span_help(s.span, fluent::suggestion);
                             }
                             lint
                         },
@@ -388,7 +388,7 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
                     cx.struct_span_lint(
                         PATH_STATEMENTS,
                         s.span,
-                        fluent::lint::path_statement_no_effect,
+                        fluent::lint_path_statement_no_effect,
                         |lint| lint,
                     );
                 }
@@ -561,7 +561,7 @@ trait UnusedDelimLint {
         } else {
             MultiSpan::from(value_span)
         };
-        cx.struct_span_lint(self.lint(), primary_span, fluent::lint::unused_delim, |lint| {
+        cx.struct_span_lint(self.lint(), primary_span, fluent::lint_unused_delim, |lint| {
             lint.set_arg("delim", Self::DELIM_STR);
             lint.set_arg("item", msg);
             if let Some((lo, hi)) = spans {
@@ -570,7 +570,7 @@ trait UnusedDelimLint {
                     (hi, if keep_space.1 { " ".into() } else { "".into() }),
                 ];
                 lint.multipart_suggestion(
-                    fluent::lint::suggestion,
+                    fluent::suggestion,
                     replacement,
                     Applicability::MachineApplicable,
                 );
@@ -1146,7 +1146,7 @@ impl UnusedImportBraces {
             cx.struct_span_lint(
                 UNUSED_IMPORT_BRACES,
                 item.span,
-                fluent::lint::unused_import_braces,
+                fluent::lint_unused_import_braces,
                 |lint| lint.set_arg("node", node_name),
             );
         }
@@ -1201,9 +1201,9 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
                     UNUSED_ALLOCATION,
                     e.span,
                     match m {
-                        adjustment::AutoBorrowMutability::Not => fluent::lint::unused_allocation,
+                        adjustment::AutoBorrowMutability::Not => fluent::lint_unused_allocation,
                         adjustment::AutoBorrowMutability::Mut { .. } => {
-                            fluent::lint::unused_allocation_mut
+                            fluent::lint_unused_allocation_mut
                         }
                     },
                     |lint| lint,
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index d6cc31331a3..61ee467f595 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -1427,6 +1427,7 @@ declare_lint! {
     "trait-object types were treated as different depending on marker-trait order",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #56484 <https://github.com/rust-lang/rust/issues/56484>",
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
     };
 }
 
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
index 8cf307df5a5..ef1985b960e 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
@@ -40,7 +40,7 @@ impl<'a> DiagnosticDerive<'a> {
                     span_err(builder.span, "diagnostic slug not specified")
                         .help(&format!(
                             "specify the slug as the first argument to the `#[diag(...)]` \
-                            attribute, such as `#[diag(hir_analysis::example_error)]`",
+                            attribute, such as `#[diag(hir_analysis_example_error)]`",
                         ))
                         .emit();
                     return DiagnosticDeriveError::ErrorHandled.to_compile_error();
@@ -121,7 +121,7 @@ impl<'a> LintDiagnosticDerive<'a> {
                     span_err(builder.span, "diagnostic slug not specified")
                         .help(&format!(
                             "specify the slug as the first argument to the attribute, such as \
-                            `#[diag(compiletest::example)]`",
+                            `#[diag(compiletest_example)]`",
                         ))
                         .emit();
                     return DiagnosticDeriveError::ErrorHandled.to_compile_error();
diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs
index f7d8b494ee2..3e447c94ef1 100644
--- a/compiler/rustc_macros/src/diagnostics/fluent.rs
+++ b/compiler/rustc_macros/src/diagnostics/fluent.rs
@@ -25,18 +25,18 @@ use syn::{
 use unic_langid::langid;
 
 struct Resource {
-    ident: Ident,
+    krate: Ident,
     #[allow(dead_code)]
     fat_arrow_token: token::FatArrow,
-    resource: LitStr,
+    resource_path: LitStr,
 }
 
 impl Parse for Resource {
     fn parse(input: ParseStream<'_>) -> Result<Self> {
         Ok(Resource {
-            ident: input.parse()?,
+            krate: input.parse()?,
             fat_arrow_token: input.parse()?,
-            resource: input.parse()?,
+            resource_path: input.parse()?,
         })
     }
 }
@@ -94,19 +94,20 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
     // diagnostics.
     let mut previous_defns = HashMap::new();
 
+    // Set of Fluent attribute names already output, to avoid duplicate type errors - any given
+    // constant created for a given attribute is the same.
+    let mut previous_attrs = HashSet::new();
+
     let mut includes = TokenStream::new();
     let mut generated = TokenStream::new();
-    for res in resources.0 {
-        let ident_span = res.ident.span().unwrap();
-        let path_span = res.resource.span().unwrap();
 
-        // Set of Fluent attribute names already output, to avoid duplicate type errors - any given
-        // constant created for a given attribute is the same.
-        let mut previous_attrs = HashSet::new();
+    for res in resources.0 {
+        let krate_span = res.krate.span().unwrap();
+        let path_span = res.resource_path.span().unwrap();
 
-        let relative_ftl_path = res.resource.value();
+        let relative_ftl_path = res.resource_path.value();
         let absolute_ftl_path =
-            invocation_relative_path_to_absolute(ident_span, &relative_ftl_path);
+            invocation_relative_path_to_absolute(krate_span, &relative_ftl_path);
         // 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) {
@@ -185,7 +186,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
 
         let mut constants = TokenStream::new();
         for entry in resource.entries() {
-            let span = res.ident.span();
+            let span = res.krate.span();
             if let Entry::Message(Message { id: Identifier { name }, attributes, .. }) = entry {
                 let _ = previous_defns.entry(name.to_string()).or_insert(path_span);
 
@@ -199,29 +200,30 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
                     .emit();
                 }
 
-                // `typeck_foo_bar` => `foo_bar` (in `typeck.ftl`)
-                // `const_eval_baz` => `baz` (in `const_eval.ftl`)
+                // Require that the message name starts with the crate name
+                // `hir_typeck_foo_bar` (in `hir_typeck.ftl`)
+                // `const_eval_baz` (in `const_eval.ftl`)
                 // `const-eval-hyphen-having` => `hyphen_having` (in `const_eval.ftl`)
                 // The last case we error about above, but we want to fall back gracefully
                 // so that only the error is being emitted and not also one about the macro
                 // failing.
-                let crate_prefix = format!("{}_", res.ident);
+                let crate_prefix = format!("{}_", res.krate);
 
                 let snake_name = name.replace('-', "_");
-                let snake_name = match snake_name.strip_prefix(&crate_prefix) {
-                    Some(rest) => Ident::new(rest, span),
-                    None => {
-                        Diagnostic::spanned(
-                            path_span,
-                            Level::Error,
-                            format!("name `{name}` does not start with the crate name"),
-                        )
-                        .help(format!("prepend `{crate_prefix}` to the slug name: `{crate_prefix}{snake_name}`"))
-                        .emit();
-                        Ident::new(&snake_name, span)
-                    }
+                if !snake_name.starts_with(&crate_prefix) {
+                    Diagnostic::spanned(
+                        path_span,
+                        Level::Error,
+                        format!("name `{name}` does not start with the crate name"),
+                    )
+                    .help(format!(
+                        "prepend `{crate_prefix}` to the slug name: `{crate_prefix}{snake_name}`"
+                    ))
+                    .emit();
                 };
 
+                let snake_name = Ident::new(&snake_name, span);
+
                 constants.extend(quote! {
                     pub const #snake_name: crate::DiagnosticMessage =
                         crate::DiagnosticMessage::FluentIdentifier(
@@ -275,12 +277,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
 
         includes.extend(quote! { include_str!(#relative_ftl_path), });
 
-        let ident = res.ident;
-        generated.extend(quote! {
-            pub mod #ident {
-                #constants
-            }
-        });
+        generated.extend(constants);
     }
 
     quote! {
diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs
index f98cc66e9e9..860340b4390 100644
--- a/compiler/rustc_macros/src/diagnostics/mod.rs
+++ b/compiler/rustc_macros/src/diagnostics/mod.rs
@@ -23,14 +23,14 @@ use synstructure::Structure;
 /// # extern crate rust_middle;
 /// # use rustc_middle::ty::Ty;
 /// #[derive(Diagnostic)]
-/// #[diag(borrowck::move_out_of_borrow, code = "E0505")]
+/// #[diag(borrowck_move_out_of_borrow, code = "E0505")]
 /// pub struct MoveOutOfBorrowError<'tcx> {
 ///     pub name: Ident,
 ///     pub ty: Ty<'tcx>,
 ///     #[primary_span]
 ///     #[label]
 ///     pub span: Span,
-///     #[label(borrowck::first_borrow_label)]
+///     #[label(first_borrow_label)]
 ///     pub first_borrow_span: Span,
 ///     #[suggestion(code = "{name}.clone()")]
 ///     pub clone_sugg: Option<(Span, Applicability)>
@@ -67,14 +67,14 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream {
 ///
 /// ```ignore (rust)
 /// #[derive(LintDiagnostic)]
-/// #[diag(lint::atomic_ordering_invalid_fail_success)]
+/// #[diag(lint_atomic_ordering_invalid_fail_success)]
 /// pub struct AtomicOrderingInvalidLint {
 ///     method: Symbol,
 ///     success_ordering: Symbol,
 ///     fail_ordering: Symbol,
-///     #[label(lint::fail_label)]
+///     #[label(fail_label)]
 ///     fail_order_arg_span: Span,
-///     #[label(lint::success_label)]
+///     #[label(success_label)]
 ///     #[suggestion(
 ///         code = "std::sync::atomic::Ordering::{success_suggestion}",
 ///         applicability = "maybe-incorrect"
@@ -115,12 +115,12 @@ pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
 /// ```ignore (rust)
 /// #[derive(Subdiagnostic)]
 /// pub enum ExpectedIdentifierLabel<'tcx> {
-///     #[label(parser::expected_identifier)]
+///     #[label(expected_identifier)]
 ///     WithoutFound {
 ///         #[primary_span]
 ///         span: Span,
 ///     }
-///     #[label(parser::expected_identifier_found)]
+///     #[label(expected_identifier_found)]
 ///     WithFound {
 ///         #[primary_span]
 ///         span: Span,
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index dbfa22aaff0..7c387b9a9ec 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -12,41 +12,41 @@ use rustc_target::spec::{PanicStrategy, TargetTriple};
 use crate::locator::CrateFlavor;
 
 #[derive(Diagnostic)]
-#[diag(metadata::rlib_required)]
+#[diag(metadata_rlib_required)]
 pub struct RlibRequired {
     pub crate_name: Symbol,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::lib_required)]
+#[diag(metadata_lib_required)]
 pub struct LibRequired<'a> {
     pub crate_name: Symbol,
     pub kind: &'a str,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::crate_dep_multiple)]
+#[diag(metadata_crate_dep_multiple)]
 #[help]
 pub struct CrateDepMultiple {
     pub crate_name: Symbol,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::two_panic_runtimes)]
+#[diag(metadata_two_panic_runtimes)]
 pub struct TwoPanicRuntimes {
     pub prev_name: Symbol,
     pub cur_name: Symbol,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::bad_panic_strategy)]
+#[diag(metadata_bad_panic_strategy)]
 pub struct BadPanicStrategy {
     pub runtime: Symbol,
     pub strategy: PanicStrategy,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::required_panic_strategy)]
+#[diag(metadata_required_panic_strategy)]
 pub struct RequiredPanicStrategy {
     pub crate_name: Symbol,
     pub found_strategy: PanicStrategy,
@@ -54,7 +54,7 @@ pub struct RequiredPanicStrategy {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::incompatible_panic_in_drop_strategy)]
+#[diag(metadata_incompatible_panic_in_drop_strategy)]
 pub struct IncompatiblePanicInDropStrategy {
     pub crate_name: Symbol,
     pub found_strategy: PanicStrategy,
@@ -62,56 +62,56 @@ pub struct IncompatiblePanicInDropStrategy {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::multiple_names_in_link)]
+#[diag(metadata_multiple_names_in_link)]
 pub struct MultipleNamesInLink {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::multiple_kinds_in_link)]
+#[diag(metadata_multiple_kinds_in_link)]
 pub struct MultipleKindsInLink {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::link_name_form)]
+#[diag(metadata_link_name_form)]
 pub struct LinkNameForm {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::link_kind_form)]
+#[diag(metadata_link_kind_form)]
 pub struct LinkKindForm {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::link_modifiers_form)]
+#[diag(metadata_link_modifiers_form)]
 pub struct LinkModifiersForm {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::link_cfg_form)]
+#[diag(metadata_link_cfg_form)]
 pub struct LinkCfgForm {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::wasm_import_form)]
+#[diag(metadata_wasm_import_form)]
 pub struct WasmImportForm {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::empty_link_name, code = "E0454")]
+#[diag(metadata_empty_link_name, code = "E0454")]
 pub struct EmptyLinkName {
     #[primary_span]
     #[label]
@@ -119,21 +119,21 @@ pub struct EmptyLinkName {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::link_framework_apple, code = "E0455")]
+#[diag(metadata_link_framework_apple, code = "E0455")]
 pub struct LinkFrameworkApple {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::framework_only_windows, code = "E0455")]
+#[diag(metadata_framework_only_windows, code = "E0455")]
 pub struct FrameworkOnlyWindows {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::unknown_link_kind, code = "E0458")]
+#[diag(metadata_unknown_link_kind, code = "E0458")]
 pub struct UnknownLinkKind<'a> {
     #[primary_span]
     #[label]
@@ -142,49 +142,49 @@ pub struct UnknownLinkKind<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::multiple_link_modifiers)]
+#[diag(metadata_multiple_link_modifiers)]
 pub struct MultipleLinkModifiers {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::multiple_cfgs)]
+#[diag(metadata_multiple_cfgs)]
 pub struct MultipleCfgs {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::link_cfg_single_predicate)]
+#[diag(metadata_link_cfg_single_predicate)]
 pub struct LinkCfgSinglePredicate {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::multiple_wasm_import)]
+#[diag(metadata_multiple_wasm_import)]
 pub struct MultipleWasmImport {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::unexpected_link_arg)]
+#[diag(metadata_unexpected_link_arg)]
 pub struct UnexpectedLinkArg {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::invalid_link_modifier)]
+#[diag(metadata_invalid_link_modifier)]
 pub struct InvalidLinkModifier {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::multiple_modifiers)]
+#[diag(metadata_multiple_modifiers)]
 pub struct MultipleModifiers<'a> {
     #[primary_span]
     pub span: Span,
@@ -192,28 +192,28 @@ pub struct MultipleModifiers<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::bundle_needs_static)]
+#[diag(metadata_bundle_needs_static)]
 pub struct BundleNeedsStatic {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::whole_archive_needs_static)]
+#[diag(metadata_whole_archive_needs_static)]
 pub struct WholeArchiveNeedsStatic {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::as_needed_compatibility)]
+#[diag(metadata_as_needed_compatibility)]
 pub struct AsNeededCompatibility {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::unknown_link_modifier)]
+#[diag(metadata_unknown_link_modifier)]
 pub struct UnknownLinkModifier<'a> {
     #[primary_span]
     pub span: Span,
@@ -221,14 +221,14 @@ pub struct UnknownLinkModifier<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::incompatible_wasm_link)]
+#[diag(metadata_incompatible_wasm_link)]
 pub struct IncompatibleWasmLink {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::link_requires_name, code = "E0459")]
+#[diag(metadata_link_requires_name, code = "E0459")]
 pub struct LinkRequiresName {
     #[primary_span]
     #[label]
@@ -236,126 +236,126 @@ pub struct LinkRequiresName {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::raw_dylib_no_nul)]
+#[diag(metadata_raw_dylib_no_nul)]
 pub struct RawDylibNoNul {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::link_ordinal_raw_dylib)]
+#[diag(metadata_link_ordinal_raw_dylib)]
 pub struct LinkOrdinalRawDylib {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::lib_framework_apple)]
+#[diag(metadata_lib_framework_apple)]
 pub struct LibFrameworkApple;
 
 #[derive(Diagnostic)]
-#[diag(metadata::empty_renaming_target)]
+#[diag(metadata_empty_renaming_target)]
 pub struct EmptyRenamingTarget<'a> {
     pub lib_name: &'a str,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::renaming_no_link)]
+#[diag(metadata_renaming_no_link)]
 pub struct RenamingNoLink<'a> {
     pub lib_name: &'a str,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::multiple_renamings)]
+#[diag(metadata_multiple_renamings)]
 pub struct MultipleRenamings<'a> {
     pub lib_name: &'a str,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::no_link_mod_override)]
+#[diag(metadata_no_link_mod_override)]
 pub struct NoLinkModOverride {
     #[primary_span]
     pub span: Option<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::unsupported_abi_i686)]
+#[diag(metadata_unsupported_abi_i686)]
 pub struct UnsupportedAbiI686 {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::unsupported_abi)]
+#[diag(metadata_unsupported_abi)]
 pub struct UnsupportedAbi {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::fail_create_file_encoder)]
+#[diag(metadata_fail_create_file_encoder)]
 pub struct FailCreateFileEncoder {
     pub err: Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::fail_seek_file)]
+#[diag(metadata_fail_seek_file)]
 pub struct FailSeekFile {
     pub err: Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::fail_write_file)]
+#[diag(metadata_fail_write_file)]
 pub struct FailWriteFile {
     pub err: Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::crate_not_panic_runtime)]
+#[diag(metadata_crate_not_panic_runtime)]
 pub struct CrateNotPanicRuntime {
     pub crate_name: Symbol,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::no_panic_strategy)]
+#[diag(metadata_no_panic_strategy)]
 pub struct NoPanicStrategy {
     pub crate_name: Symbol,
     pub strategy: PanicStrategy,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::profiler_builtins_needs_core)]
+#[diag(metadata_profiler_builtins_needs_core)]
 pub struct ProfilerBuiltinsNeedsCore;
 
 #[derive(Diagnostic)]
-#[diag(metadata::not_profiler_runtime)]
+#[diag(metadata_not_profiler_runtime)]
 pub struct NotProfilerRuntime {
     pub crate_name: Symbol,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::no_multiple_global_alloc)]
+#[diag(metadata_no_multiple_global_alloc)]
 pub struct NoMultipleGlobalAlloc {
     #[primary_span]
     #[label]
     pub span2: Span,
-    #[label(metadata::prev_global_alloc)]
+    #[label(metadata_prev_global_alloc)]
     pub span1: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::conflicting_global_alloc)]
+#[diag(metadata_conflicting_global_alloc)]
 pub struct ConflictingGlobalAlloc {
     pub crate_name: Symbol,
     pub other_crate_name: Symbol,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::global_alloc_required)]
+#[diag(metadata_global_alloc_required)]
 pub struct GlobalAllocRequired;
 
 #[derive(Diagnostic)]
-#[diag(metadata::no_transitive_needs_dep)]
+#[diag(metadata_no_transitive_needs_dep)]
 pub struct NoTransitiveNeedsDep<'a> {
     pub crate_name: Symbol,
     pub needs_crate_name: &'a str,
@@ -363,14 +363,14 @@ pub struct NoTransitiveNeedsDep<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::failed_write_error)]
+#[diag(metadata_failed_write_error)]
 pub struct FailedWriteError {
     pub filename: PathBuf,
     pub err: Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::missing_native_library)]
+#[diag(metadata_missing_native_library)]
 pub struct MissingNativeLibrary<'a> {
     libname: &'a str,
     #[subdiagnostic]
@@ -404,32 +404,32 @@ impl<'a> MissingNativeLibrary<'a> {
 }
 
 #[derive(Subdiagnostic)]
-#[help(metadata::only_provide_library_name)]
+#[help(metadata_only_provide_library_name)]
 pub struct SuggestLibraryName<'a> {
     suggested_name: &'a str,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::failed_create_tempdir)]
+#[diag(metadata_failed_create_tempdir)]
 pub struct FailedCreateTempdir {
     pub err: Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::failed_create_file)]
+#[diag(metadata_failed_create_file)]
 pub struct FailedCreateFile<'a> {
     pub filename: &'a Path,
     pub err: Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::failed_create_encoded_metadata)]
+#[diag(metadata_failed_create_encoded_metadata)]
 pub struct FailedCreateEncodedMetadata {
     pub err: Error,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::non_ascii_name)]
+#[diag(metadata_non_ascii_name)]
 pub struct NonAsciiName {
     #[primary_span]
     pub span: Span,
@@ -437,7 +437,7 @@ pub struct NonAsciiName {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::extern_location_not_exist)]
+#[diag(metadata_extern_location_not_exist)]
 pub struct ExternLocationNotExist<'a> {
     #[primary_span]
     pub span: Span,
@@ -446,7 +446,7 @@ pub struct ExternLocationNotExist<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::extern_location_not_file)]
+#[diag(metadata_extern_location_not_file)]
 pub struct ExternLocationNotFile<'a> {
     #[primary_span]
     pub span: Span,
@@ -466,7 +466,7 @@ impl IntoDiagnostic<'_> for MultipleCandidates {
         self,
         handler: &'_ rustc_errors::Handler,
     ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
-        let mut diag = handler.struct_err(rustc_errors::fluent::metadata::multiple_candidates);
+        let mut diag = handler.struct_err(rustc_errors::fluent::metadata_multiple_candidates);
         diag.set_arg("crate_name", self.crate_name);
         diag.set_arg("flavor", self.flavor);
         diag.code(error_code!(E0465));
@@ -479,7 +479,7 @@ impl IntoDiagnostic<'_> for MultipleCandidates {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::multiple_matching_crates, code = "E0464")]
+#[diag(metadata_multiple_matching_crates, code = "E0464")]
 #[note]
 pub struct MultipleMatchingCrates {
     #[primary_span]
@@ -489,7 +489,7 @@ pub struct MultipleMatchingCrates {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::symbol_conflicts_current, code = "E0519")]
+#[diag(metadata_symbol_conflicts_current, code = "E0519")]
 pub struct SymbolConflictsCurrent {
     #[primary_span]
     pub span: Span,
@@ -497,7 +497,7 @@ pub struct SymbolConflictsCurrent {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::symbol_conflicts_others, code = "E0523")]
+#[diag(metadata_symbol_conflicts_others, code = "E0523")]
 pub struct SymbolConflictsOthers {
     #[primary_span]
     pub span: Span,
@@ -505,7 +505,7 @@ pub struct SymbolConflictsOthers {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::stable_crate_id_collision)]
+#[diag(metadata_stable_crate_id_collision)]
 pub struct StableCrateIdCollision {
     #[primary_span]
     pub span: Span,
@@ -514,7 +514,7 @@ pub struct StableCrateIdCollision {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::dl_error)]
+#[diag(metadata_dl_error)]
 pub struct DlError {
     #[primary_span]
     pub span: Span,
@@ -522,9 +522,9 @@ pub struct DlError {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::newer_crate_version, code = "E0460")]
+#[diag(metadata_newer_crate_version, code = "E0460")]
 #[note]
-#[note(metadata::found_crate_versions)]
+#[note(metadata_found_crate_versions)]
 pub struct NewerCrateVersion {
     #[primary_span]
     pub span: Span,
@@ -534,8 +534,8 @@ pub struct NewerCrateVersion {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::no_crate_with_triple, code = "E0461")]
-#[note(metadata::found_crate_versions)]
+#[diag(metadata_no_crate_with_triple, code = "E0461")]
+#[note(metadata_found_crate_versions)]
 pub struct NoCrateWithTriple<'a> {
     #[primary_span]
     pub span: Span,
@@ -546,8 +546,8 @@ pub struct NoCrateWithTriple<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::found_staticlib, code = "E0462")]
-#[note(metadata::found_crate_versions)]
+#[diag(metadata_found_staticlib, code = "E0462")]
+#[note(metadata_found_crate_versions)]
 #[help]
 pub struct FoundStaticlib {
     #[primary_span]
@@ -558,8 +558,8 @@ pub struct FoundStaticlib {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::incompatible_rustc, code = "E0514")]
-#[note(metadata::found_crate_versions)]
+#[diag(metadata_incompatible_rustc, code = "E0514")]
+#[note(metadata_found_crate_versions)]
 #[help]
 pub struct IncompatibleRustc {
     #[primary_span]
@@ -582,7 +582,7 @@ impl IntoDiagnostic<'_> for InvalidMetadataFiles {
         self,
         handler: &'_ rustc_errors::Handler,
     ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
-        let mut diag = handler.struct_err(rustc_errors::fluent::metadata::invalid_meta_files);
+        let mut diag = handler.struct_err(rustc_errors::fluent::metadata_invalid_meta_files);
         diag.set_arg("crate_name", self.crate_name);
         diag.set_arg("add_info", self.add_info);
         diag.code(error_code!(E0786));
@@ -610,7 +610,7 @@ impl IntoDiagnostic<'_> for CannotFindCrate {
         self,
         handler: &'_ rustc_errors::Handler,
     ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
-        let mut diag = handler.struct_err(rustc_errors::fluent::metadata::cannot_find_crate);
+        let mut diag = handler.struct_err(rustc_errors::fluent::metadata_cannot_find_crate);
         diag.set_arg("crate_name", self.crate_name);
         diag.set_arg("current_crate", self.current_crate);
         diag.set_arg("add_info", self.add_info);
@@ -621,38 +621,38 @@ impl IntoDiagnostic<'_> for CannotFindCrate {
             && self.locator_triple != TargetTriple::from_triple(config::host_triple())
         {
             if self.missing_core {
-                diag.note(rustc_errors::fluent::metadata::target_not_installed);
+                diag.note(rustc_errors::fluent::metadata_target_not_installed);
             } else {
-                diag.note(rustc_errors::fluent::metadata::target_no_std_support);
+                diag.note(rustc_errors::fluent::metadata_target_no_std_support);
             }
             // NOTE: this suggests using rustup, even though the user may not have it installed.
             // That's because they could choose to install it; or this may give them a hint which
             // target they need to install from their distro.
             if self.missing_core {
-                diag.help(rustc_errors::fluent::metadata::consider_downloading_target);
+                diag.help(rustc_errors::fluent::metadata_consider_downloading_target);
             }
             // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway.
             // NOTE: this is a dummy span if `extern crate std` was injected by the compiler.
             // If it's not a dummy, that means someone added `extern crate std` explicitly and
             // `#![no_std]` won't help.
             if !self.missing_core && self.span.is_dummy() {
-                diag.note(rustc_errors::fluent::metadata::std_required);
+                diag.note(rustc_errors::fluent::metadata_std_required);
             }
             if self.is_nightly_build {
-                diag.help(rustc_errors::fluent::metadata::consider_building_std);
+                diag.help(rustc_errors::fluent::metadata_consider_building_std);
             }
         } else if self.crate_name == self.profiler_runtime {
-            diag.note(rustc_errors::fluent::metadata::compiler_missing_profiler);
+            diag.note(rustc_errors::fluent::metadata_compiler_missing_profiler);
         } else if self.crate_name.as_str().starts_with("rustc_") {
-            diag.help(rustc_errors::fluent::metadata::install_missing_components);
+            diag.help(rustc_errors::fluent::metadata_install_missing_components);
         }
-        diag.span_label(self.span, rustc_errors::fluent::metadata::cant_find_crate);
+        diag.span_label(self.span, rustc_errors::fluent::metadata_cant_find_crate);
         diag
     }
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::no_dylib_plugin, code = "E0457")]
+#[diag(metadata_no_dylib_plugin, code = "E0457")]
 pub struct NoDylibPlugin {
     #[primary_span]
     pub span: Span,
@@ -660,7 +660,7 @@ pub struct NoDylibPlugin {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::crate_location_unknown_type)]
+#[diag(metadata_crate_location_unknown_type)]
 pub struct CrateLocationUnknownType<'a> {
     #[primary_span]
     pub span: Span,
@@ -668,7 +668,7 @@ pub struct CrateLocationUnknownType<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::lib_filename_form)]
+#[diag(metadata_lib_filename_form)]
 pub struct LibFilenameForm<'a> {
     #[primary_span]
     pub span: Span,
@@ -677,28 +677,28 @@ pub struct LibFilenameForm<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::multiple_import_name_type)]
+#[diag(metadata_multiple_import_name_type)]
 pub struct MultipleImportNameType {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::import_name_type_form)]
+#[diag(metadata_import_name_type_form)]
 pub struct ImportNameTypeForm {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::import_name_type_x86)]
+#[diag(metadata_import_name_type_x86)]
 pub struct ImportNameTypeX86 {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::unknown_import_name_type)]
+#[diag(metadata_unknown_import_name_type)]
 pub struct UnknownImportNameType<'a> {
     #[primary_span]
     pub span: Span,
@@ -706,7 +706,7 @@ pub struct UnknownImportNameType<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata::import_name_type_raw)]
+#[diag(metadata_import_name_type_raw)]
 pub struct ImportNameTypeRaw {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index c4dff8b3f48..a0a0855251b 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -15,7 +15,6 @@ use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::{self, TyCtxt, Visibility};
 use rustc_session::cstore::{CrateSource, CrateStore};
-use rustc_session::utils::NativeLibKind;
 use rustc_session::{Session, StableCrateId};
 use rustc_span::hygiene::{ExpnHash, ExpnId};
 use rustc_span::source_map::{Span, Spanned};
@@ -224,6 +223,7 @@ provide! { tcx, def_id, other, cdata,
     fn_arg_names => { table }
     generator_kind => { table }
     trait_def => { table }
+    deduced_param_attrs => { table }
     collect_trait_impl_trait_tys => {
         Ok(cdata
             .root
@@ -339,20 +339,10 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
     // resolve! Does this work? Unsure! That's what the issue is about
     *providers = Providers {
         allocator_kind: |tcx, ()| CStore::from_tcx(tcx).allocator_kind(),
-        is_dllimport_foreign_item: |tcx, id| match tcx.native_library_kind(id) {
-            Some(
-                NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified,
-            ) => true,
-            _ => false,
-        },
-        is_statically_included_foreign_item: |tcx, id| {
-            matches!(tcx.native_library_kind(id), Some(NativeLibKind::Static { .. }))
-        },
         is_private_dep: |_tcx, cnum| {
             assert_eq!(cnum, LOCAL_CRATE);
             false
         },
-        native_library_kind: |tcx, id| tcx.native_library(id).map(|l| l.kind),
         native_library: |tcx, id| {
             tcx.native_libraries(id.krate)
                 .iter()
@@ -597,11 +587,6 @@ impl CStore {
         self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess)
     }
 
-    /// Decodes all traits in the crate (for rustdoc).
-    pub fn traits_in_crate_untracked(&self, cnum: CrateNum) -> impl Iterator<Item = DefId> + '_ {
-        self.get_crate_data(cnum).get_traits()
-    }
-
     /// Decodes all trait impls in the crate (for rustdoc).
     pub fn trait_impls_in_crate_untracked(
         &self,
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 377e3f013be..c019211a948 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -31,7 +31,7 @@ use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
 use rustc_middle::util::common::to_readable_str;
 use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
-use rustc_session::config::CrateType;
+use rustc_session::config::{CrateType, OptLevel};
 use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
 use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
 use rustc_span::symbol::{sym, Symbol};
@@ -1478,6 +1478,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
             }
         }
+
+        // Encode all the deduced parameter attributes for everything that has MIR, even for items
+        // that can't be inlined. But don't if we aren't optimizing in non-incremental mode, to
+        // save the query traffic.
+        if tcx.sess.opts.output_types.should_codegen()
+            && tcx.sess.opts.optimize != OptLevel::No
+            && tcx.sess.opts.incremental.is_none()
+        {
+            for &local_def_id in tcx.mir_keys(()) {
+                if let DefKind::AssocFn | DefKind::Fn = tcx.def_kind(local_def_id) {
+                    record_array!(self.tables.deduced_param_attrs[local_def_id.to_def_id()] <-
+                        self.tcx.deduced_param_attrs(local_def_id.to_def_id()));
+                }
+            }
+        }
     }
 
     fn encode_stability(&mut self, def_id: DefId) {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index a509ecdf759..27dc8ff16ac 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -23,7 +23,7 @@ use rustc_middle::mir;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, ReprOptions, Ty};
-use rustc_middle::ty::{GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
+use rustc_middle::ty::{DeducedParamAttrs, GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
 use rustc_serialize::opaque::FileEncoder;
 use rustc_session::config::SymbolManglingVersion;
 use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
@@ -402,6 +402,7 @@ define_tables! {
     macro_definition: Table<DefIndex, LazyValue<ast::MacArgs>>,
     proc_macro: Table<DefIndex, MacroKind>,
     module_reexports: Table<DefIndex, LazyArray<ModChild>>,
+    deduced_param_attrs: Table<DefIndex, LazyArray<DeducedParamAttrs>>,
 
     trait_impl_trait_tys: Table<DefIndex, LazyValue<FxHashMap<DefId, Ty<'static>>>>,
 }
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index e69cb546d15..a7a7ac0599d 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -4,7 +4,7 @@ use rustc_span::Span;
 use crate::ty::Ty;
 
 #[derive(Diagnostic)]
-#[diag(middle::drop_check_overflow, code = "E0320")]
+#[diag(middle_drop_check_overflow, code = "E0320")]
 #[note]
 pub struct DropCheckOverflow<'tcx> {
     #[primary_span]
@@ -14,7 +14,7 @@ pub struct DropCheckOverflow<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(middle::opaque_hidden_type_mismatch)]
+#[diag(middle_opaque_hidden_type_mismatch)]
 pub struct OpaqueHiddenTypeMismatch<'tcx> {
     pub self_ty: Ty<'tcx>,
     pub other_ty: Ty<'tcx>,
@@ -27,12 +27,12 @@ pub struct OpaqueHiddenTypeMismatch<'tcx> {
 
 #[derive(Subdiagnostic)]
 pub enum TypeMismatchReason {
-    #[label(middle::conflict_types)]
+    #[label(middle_conflict_types)]
     ConflictType {
         #[primary_span]
         span: Span,
     },
-    #[note(middle::previous_use_here)]
+    #[note(middle_previous_use_here)]
     PreviousUse {
         #[primary_span]
         span: Span,
@@ -40,7 +40,7 @@ pub enum TypeMismatchReason {
 }
 
 #[derive(Diagnostic)]
-#[diag(middle::limit_invalid)]
+#[diag(middle_limit_invalid)]
 pub struct LimitInvalid<'a> {
     #[primary_span]
     pub span: Span,
@@ -50,7 +50,7 @@ pub struct LimitInvalid<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(middle::const_eval_non_int)]
+#[diag(middle_const_eval_non_int)]
 pub struct ConstEvalNonIntError {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 45c84680ad2..a58cbc3767e 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -55,6 +55,7 @@
 #![feature(drain_filter)]
 #![feature(intra_doc_pointers)]
 #![feature(yeet_expr)]
+#![feature(result_option_inspect)]
 #![feature(const_option)]
 #![recursion_limit = "512"]
 #![allow(rustc::potential_query_instability)]
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 8f67161420d..473894ac1ca 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -4,7 +4,9 @@ use crate::mir;
 use crate::ty::subst::InternalSubsts;
 use crate::ty::visit::TypeVisitable;
 use crate::ty::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt};
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
+use rustc_session::lint;
 use rustc_span::{Span, DUMMY_SP};
 
 impl<'tcx> TyCtxt<'tcx> {
@@ -51,7 +53,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
         match ty::Instance::resolve_opt_const_arg(
             self, param_env,
-            // FIXME: maybe have a seperate version for resolving mir::UnevaluatedConst?
+            // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst?
             ct.def, ct.substs,
         ) {
             Ok(Some(instance)) => {
@@ -83,7 +85,29 @@ impl<'tcx> TyCtxt<'tcx> {
         match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
             Ok(Some(instance)) => {
                 let cid = GlobalId { instance, promoted: None };
-                self.const_eval_global_id_for_typeck(param_env, cid, span)
+                self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| {
+                    // We are emitting the lint here instead of in `is_const_evaluatable`
+                    // as we normalize obligations before checking them, and normalization
+                    // uses this function to evaluate this constant.
+                    //
+                    // @lcnr believes that successfully evaluating even though there are
+                    // used generic parameters is a bug of evaluation, so checking for it
+                    // here does feel somewhat sensible.
+                    if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
+                        assert!(matches!(self.def_kind(ct.def.did), DefKind::AnonConst));
+                        let mir_body = self.mir_for_ctfe_opt_const_arg(ct.def);
+                        if mir_body.is_polymorphic {
+                            let Some(local_def_id) = ct.def.did.as_local() else { return };
+                            self.struct_span_lint_hir(
+                                lint::builtin::CONST_EVALUATABLE_UNCHECKED,
+                                self.hir().local_def_id_to_hir_id(local_def_id),
+                                self.def_span(ct.def.did),
+                                "cannot use constants which depend on generic parameters in types",
+                                |err| err,
+                            )
+                        }
+                    }
+                })
             }
             Ok(None) => Err(ErrorHandled::TooGeneric),
             Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index ea81d4465fb..2ab3b0d27c8 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1587,16 +1587,6 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    query is_dllimport_foreign_item(def_id: DefId) -> bool {
-        desc { |tcx| "checking if `{}` is a a dylib", tcx.def_path_str(def_id) }
-    }
-    query is_statically_included_foreign_item(def_id: DefId) -> bool {
-        desc { |tcx| "checking if `{}` is a staticlib", tcx.def_path_str(def_id) }
-    }
-    query native_library_kind(def_id: DefId)
-        -> Option<NativeLibKind> {
-        desc { |tcx| "getting the native library kind of `{}`", tcx.def_path_str(def_id) }
-    }
     query native_library(def_id: DefId) -> Option<&'tcx NativeLib> {
         desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) }
     }
@@ -1653,14 +1643,13 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    /// Computes the set of modules from which this type is visibly uninhabited.
-    /// To check whether a type is uninhabited at all (not just from a given module), you could
-    /// check whether the forest is empty.
-    query type_uninhabited_from(
-        key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
-    ) -> ty::inhabitedness::DefIdForest<'tcx> {
-        desc { "computing the inhabitedness of `{}`", key.value }
-        remap_env_constness
+    query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> {
+        desc { "computing the uninhabited predicate of `{:?}`", key }
+    }
+
+    /// Do not call this query directly: invoke `Ty::inhabited_predicate` instead.
+    query inhabited_predicate_type(key: Ty<'tcx>) -> ty::inhabitedness::InhabitedPredicate<'tcx> {
+        desc { "computing the uninhabited predicate of `{}`", key }
     }
 
     query dep_kind(_: CrateNum) -> CrateDepKind {
@@ -2127,4 +2116,9 @@ rustc_queries! {
     ) -> Result<(), ErrorGuaranteed> {
         desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0.to_def_id()) }
     }
+
+    query deduced_param_attrs(def_id: DefId) -> &'tcx [ty::DeducedParamAttrs] {
+        desc { |tcx| "deducing parameter attributes for {}", tcx.def_path_str(def_id) }
+        separate_provide_extern
+    }
 }
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 51137c52659..14ec88b7e0d 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -455,6 +455,7 @@ impl_arena_copy_decoder! {<'tcx>
     rustc_span::def_id::DefId,
     rustc_span::def_id::LocalDefId,
     (rustc_middle::middle::exported_symbols::ExportedSymbol<'tcx>, rustc_middle::middle::exported_symbols::SymbolExportInfo),
+    ty::DeducedParamAttrs,
 }
 
 #[macro_export]
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 315e3794f15..f998e608344 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -263,6 +263,10 @@ impl<'tcx> Const<'tcx> {
         self.try_eval_usize(tcx, param_env)
             .unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
     }
+
+    pub fn is_ct_infer(self) -> bool {
+        matches!(self.kind(), ty::ConstKind::Infer(_))
+    }
 }
 
 pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 03866d5e054..4ab761e0715 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -15,7 +15,7 @@ use super::ScalarInt;
 
 /// An unevaluated (potentially generic) constant used in the type-system.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
-#[derive(Hash, HashStable)]
+#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
 pub struct UnevaluatedConst<'tcx> {
     pub def: ty::WithOptConstParam<DefId>,
     pub substs: SubstsRef<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 03bb7e54fd5..0816a5cb8f1 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2954,6 +2954,21 @@ impl<'tcx> TyCtxtAt<'tcx> {
     }
 }
 
+/// Parameter attributes that can only be determined by examining the body of a function instead
+/// of just its signature.
+///
+/// These can be useful for optimization purposes when a function is directly called. We compute
+/// them and store them into the crate metadata so that downstream crates can make use of them.
+///
+/// Right now, we only have `read_only`, but `no_capture` and `no_alias` might be useful in the
+/// future.
+#[derive(Clone, Copy, PartialEq, Debug, Default, TyDecodable, TyEncodable, HashStable)]
+pub struct DeducedParamAttrs {
+    /// The parameter is marked immutable in the function and contains no `UnsafeCell` (i.e. its
+    /// type is freeze).
+    pub read_only: bool,
+}
+
 // We are comparing types with different invariant lifetimes, so `ptr::eq`
 // won't work for us.
 fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index ffade628e53..b8fd01e6a77 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -513,7 +513,7 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(borrowck::const_not_used_in_type_alias)]
+#[diag(borrowck_const_not_used_in_type_alias)]
 pub(super) struct ConstNotUsedTraitAlias {
     pub ct: String,
     #[primary_span]
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index a6d0678e99d..7201737be65 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -34,12 +34,6 @@ impl FlagComputation {
         result.flags
     }
 
-    pub fn for_unevaluated_const(uv: ty::UnevaluatedConst<'_>) -> TypeFlags {
-        let mut result = FlagComputation::new();
-        result.add_unevaluated_const(uv);
-        result.flags
-    }
-
     fn add_flags(&mut self, flags: TypeFlags) {
         self.flags = self.flags | flags;
     }
@@ -256,7 +250,7 @@ impl FlagComputation {
                 self.add_substs(substs);
             }
             ty::PredicateKind::ConstEvaluatable(uv) => {
-                self.add_unevaluated_const(uv);
+                self.add_const(uv);
             }
             ty::PredicateKind::ConstEquate(expected, found) => {
                 self.add_const(expected);
@@ -289,7 +283,10 @@ impl FlagComputation {
     fn add_const(&mut self, c: ty::Const<'_>) {
         self.add_ty(c.ty());
         match c.kind() {
-            ty::ConstKind::Unevaluated(unevaluated) => self.add_unevaluated_const(unevaluated),
+            ty::ConstKind::Unevaluated(uv) => {
+                self.add_substs(uv.substs);
+                self.add_flags(TypeFlags::HAS_CT_PROJECTION);
+            }
             ty::ConstKind::Infer(infer) => {
                 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
                 match infer {
@@ -313,11 +310,6 @@ impl FlagComputation {
         }
     }
 
-    fn add_unevaluated_const(&mut self, ct: ty::UnevaluatedConst<'_>) {
-        self.add_substs(ct.substs);
-        self.add_flags(TypeFlags::HAS_CT_PROJECTION);
-    }
-
     fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
         self.add_substs(projection.substs);
         match projection.term.unpack() {
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index f456999ae3e..54f1499eb3d 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -126,13 +126,6 @@ pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> {
         c.super_fold_with(self)
     }
 
-    fn fold_ty_unevaluated(
-        &mut self,
-        uv: ty::UnevaluatedConst<'tcx>,
-    ) -> ty::UnevaluatedConst<'tcx> {
-        uv.super_fold_with(self)
-    }
-
     fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
         p.super_fold_with(self)
     }
@@ -169,13 +162,6 @@ pub trait FallibleTypeFolder<'tcx>: Sized {
         c.try_super_fold_with(self)
     }
 
-    fn try_fold_ty_unevaluated(
-        &mut self,
-        c: ty::UnevaluatedConst<'tcx>,
-    ) -> Result<ty::UnevaluatedConst<'tcx>, Self::Error> {
-        c.try_super_fold_with(self)
-    }
-
     fn try_fold_predicate(
         &mut self,
         p: ty::Predicate<'tcx>,
@@ -215,13 +201,6 @@ where
         Ok(self.fold_const(c))
     }
 
-    fn try_fold_ty_unevaluated(
-        &mut self,
-        c: ty::UnevaluatedConst<'tcx>,
-    ) -> Result<ty::UnevaluatedConst<'tcx>, !> {
-        Ok(self.fold_ty_unevaluated(c))
-    }
-
     fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result<ty::Predicate<'tcx>, !> {
         Ok(self.fold_predicate(p))
     }
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs b/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs
deleted file mode 100644
index c4ad698ba76..00000000000
--- a/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs
+++ /dev/null
@@ -1,145 +0,0 @@
-use crate::ty::context::TyCtxt;
-use crate::ty::{DefId, DefIdTree};
-use rustc_span::def_id::CRATE_DEF_ID;
-use smallvec::SmallVec;
-use std::mem;
-
-use DefIdForest::*;
-
-/// Represents a forest of `DefId`s closed under the ancestor relation. That is,
-/// if a `DefId` representing a module is contained in the forest then all
-/// `DefId`s defined in that module or submodules are also implicitly contained
-/// in the forest.
-///
-/// This is used to represent a set of modules in which a type is visibly
-/// uninhabited.
-///
-/// We store the minimal set of `DefId`s required to represent the whole set. If A and B are
-/// `DefId`s in the `DefIdForest`, and A is a parent of B, then only A will be stored. When this is
-/// used with `type_uninhabited_from`, there will very rarely be more than one `DefId` stored.
-#[derive(Copy, Clone, HashStable, Debug)]
-pub enum DefIdForest<'a> {
-    Empty,
-    Single(DefId),
-    /// This variant is very rare.
-    /// Invariant: >1 elements
-    Multiple(&'a [DefId]),
-}
-
-/// Tests whether a slice of roots contains a given DefId.
-#[inline]
-fn slice_contains<'tcx>(tcx: TyCtxt<'tcx>, slice: &[DefId], id: DefId) -> bool {
-    slice.iter().any(|root_id| tcx.is_descendant_of(id, *root_id))
-}
-
-impl<'tcx> DefIdForest<'tcx> {
-    /// Creates an empty forest.
-    pub fn empty() -> DefIdForest<'tcx> {
-        DefIdForest::Empty
-    }
-
-    /// Creates a forest consisting of a single tree representing the entire
-    /// crate.
-    #[inline]
-    pub fn full() -> DefIdForest<'tcx> {
-        DefIdForest::from_id(CRATE_DEF_ID.to_def_id())
-    }
-
-    /// Creates a forest containing a `DefId` and all its descendants.
-    pub fn from_id(id: DefId) -> DefIdForest<'tcx> {
-        DefIdForest::Single(id)
-    }
-
-    fn as_slice(&self) -> &[DefId] {
-        match self {
-            Empty => &[],
-            Single(id) => std::slice::from_ref(id),
-            Multiple(root_ids) => root_ids,
-        }
-    }
-
-    // Only allocates in the rare `Multiple` case.
-    fn from_vec(tcx: TyCtxt<'tcx>, root_ids: SmallVec<[DefId; 1]>) -> DefIdForest<'tcx> {
-        match &root_ids[..] {
-            [] => Empty,
-            [id] => Single(*id),
-            _ => DefIdForest::Multiple(tcx.arena.alloc_from_iter(root_ids)),
-        }
-    }
-
-    /// Tests whether the forest is empty.
-    pub fn is_empty(&self) -> bool {
-        match self {
-            Empty => true,
-            Single(..) | Multiple(..) => false,
-        }
-    }
-
-    /// Iterate over the set of roots.
-    fn iter(&self) -> impl Iterator<Item = DefId> + '_ {
-        self.as_slice().iter().copied()
-    }
-
-    /// Tests whether the forest contains a given DefId.
-    pub fn contains(&self, tcx: TyCtxt<'tcx>, id: DefId) -> bool {
-        slice_contains(tcx, self.as_slice(), id)
-    }
-
-    /// Calculate the intersection of a collection of forests.
-    pub fn intersection<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest<'tcx>
-    where
-        I: IntoIterator<Item = DefIdForest<'tcx>>,
-    {
-        let mut iter = iter.into_iter();
-        let mut ret: SmallVec<[_; 1]> = if let Some(first) = iter.next() {
-            SmallVec::from_slice(first.as_slice())
-        } else {
-            return DefIdForest::full();
-        };
-
-        let mut next_ret: SmallVec<[_; 1]> = SmallVec::new();
-        for next_forest in iter {
-            // No need to continue if the intersection is already empty.
-            if ret.is_empty() || next_forest.is_empty() {
-                return DefIdForest::empty();
-            }
-
-            // We keep the elements in `ret` that are also in `next_forest`.
-            next_ret.extend(ret.iter().copied().filter(|&id| next_forest.contains(tcx, id)));
-            // We keep the elements in `next_forest` that are also in `ret`.
-            next_ret.extend(next_forest.iter().filter(|&id| slice_contains(tcx, &ret, id)));
-
-            mem::swap(&mut next_ret, &mut ret);
-            next_ret.clear();
-        }
-        DefIdForest::from_vec(tcx, ret)
-    }
-
-    /// Calculate the union of a collection of forests.
-    pub fn union<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest<'tcx>
-    where
-        I: IntoIterator<Item = DefIdForest<'tcx>>,
-    {
-        let mut ret: SmallVec<[_; 1]> = SmallVec::new();
-        let mut next_ret: SmallVec<[_; 1]> = SmallVec::new();
-        for next_forest in iter {
-            // Union with the empty set is a no-op.
-            if next_forest.is_empty() {
-                continue;
-            }
-
-            // We add everything in `ret` that is not in `next_forest`.
-            next_ret.extend(ret.iter().copied().filter(|&id| !next_forest.contains(tcx, id)));
-            // We add everything in `next_forest` that we haven't added yet.
-            for id in next_forest.iter() {
-                if !slice_contains(tcx, &next_ret, id) {
-                    next_ret.push(id);
-                }
-            }
-
-            mem::swap(&mut next_ret, &mut ret);
-            next_ret.clear();
-        }
-        DefIdForest::from_vec(tcx, ret)
-    }
-}
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
new file mode 100644
index 00000000000..b7aa455727d
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -0,0 +1,204 @@
+use crate::ty::context::TyCtxt;
+use crate::ty::{self, DefId, DefIdTree, ParamEnv, Ty};
+
+/// Represents whether some type is inhabited in a given context.
+/// Examples of uninhabited types are `!`, `enum Void {}`, or a struct
+/// containing either of those types.
+/// A type's inhabitedness may depend on the `ParamEnv` as well as what types
+/// are visible in the current module.
+#[derive(Clone, Copy, Debug, PartialEq, HashStable)]
+pub enum InhabitedPredicate<'tcx> {
+    /// Inhabited
+    True,
+    /// Uninhabited
+    False,
+    /// Uninhabited when a const value is non-zero. This occurs when there is an
+    /// array of uninhabited items, but the array is inhabited if it is empty.
+    ConstIsZero(ty::Const<'tcx>),
+    /// Uninhabited if within a certain module. This occurs when an uninhabited
+    /// type has restricted visibility.
+    NotInModule(DefId),
+    /// Inhabited if some generic type is inhabited.
+    /// These are replaced by calling [`Self::subst`].
+    GenericType(Ty<'tcx>),
+    /// A AND B
+    And(&'tcx [InhabitedPredicate<'tcx>; 2]),
+    /// A OR B
+    Or(&'tcx [InhabitedPredicate<'tcx>; 2]),
+}
+
+impl<'tcx> InhabitedPredicate<'tcx> {
+    /// Returns true if the corresponding type is inhabited in the given
+    /// `ParamEnv` and module
+    pub fn apply(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, module_def_id: DefId) -> bool {
+        let Ok(result) = self
+            .apply_inner::<!>(tcx, param_env, &|id| Ok(tcx.is_descendant_of(module_def_id, id)));
+        result
+    }
+
+    /// Same as `apply`, but returns `None` if self contains a module predicate
+    pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
+        self.apply_inner(tcx, param_env, &|_| Err(())).ok()
+    }
+
+    fn apply_inner<E>(
+        self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ParamEnv<'tcx>,
+        in_module: &impl Fn(DefId) -> Result<bool, E>,
+    ) -> Result<bool, E> {
+        match self {
+            Self::False => Ok(false),
+            Self::True => Ok(true),
+            Self::ConstIsZero(const_) => match const_.try_eval_usize(tcx, param_env) {
+                None | Some(0) => Ok(true),
+                Some(1..) => Ok(false),
+            },
+            Self::NotInModule(id) => in_module(id).map(|in_mod| !in_mod),
+            Self::GenericType(_) => Ok(true),
+            Self::And([a, b]) => try_and(a, b, |x| x.apply_inner(tcx, param_env, in_module)),
+            Self::Or([a, b]) => try_or(a, b, |x| x.apply_inner(tcx, param_env, in_module)),
+        }
+    }
+
+    pub fn and(self, tcx: TyCtxt<'tcx>, other: Self) -> Self {
+        self.reduce_and(tcx, other).unwrap_or_else(|| Self::And(tcx.arena.alloc([self, other])))
+    }
+
+    pub fn or(self, tcx: TyCtxt<'tcx>, other: Self) -> Self {
+        self.reduce_or(tcx, other).unwrap_or_else(|| Self::Or(tcx.arena.alloc([self, other])))
+    }
+
+    pub fn all(tcx: TyCtxt<'tcx>, iter: impl IntoIterator<Item = Self>) -> Self {
+        let mut result = Self::True;
+        for pred in iter {
+            if matches!(pred, Self::False) {
+                return Self::False;
+            }
+            result = result.and(tcx, pred);
+        }
+        result
+    }
+
+    pub fn any(tcx: TyCtxt<'tcx>, iter: impl IntoIterator<Item = Self>) -> Self {
+        let mut result = Self::False;
+        for pred in iter {
+            if matches!(pred, Self::True) {
+                return Self::True;
+            }
+            result = result.or(tcx, pred);
+        }
+        result
+    }
+
+    fn reduce_and(self, tcx: TyCtxt<'tcx>, other: Self) -> Option<Self> {
+        match (self, other) {
+            (Self::True, a) | (a, Self::True) => Some(a),
+            (Self::False, _) | (_, Self::False) => Some(Self::False),
+            (Self::ConstIsZero(a), Self::ConstIsZero(b)) if a == b => Some(Self::ConstIsZero(a)),
+            (Self::NotInModule(a), Self::NotInModule(b)) if a == b => Some(Self::NotInModule(a)),
+            (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(a, b) => {
+                Some(Self::NotInModule(b))
+            }
+            (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(b, a) => {
+                Some(Self::NotInModule(a))
+            }
+            (Self::GenericType(a), Self::GenericType(b)) if a == b => Some(Self::GenericType(a)),
+            (Self::And(&[a, b]), c) | (c, Self::And(&[a, b])) => {
+                if let Some(ac) = a.reduce_and(tcx, c) {
+                    Some(ac.and(tcx, b))
+                } else if let Some(bc) = b.reduce_and(tcx, c) {
+                    Some(Self::And(tcx.arena.alloc([a, bc])))
+                } else {
+                    None
+                }
+            }
+            _ => None,
+        }
+    }
+
+    fn reduce_or(self, tcx: TyCtxt<'tcx>, other: Self) -> Option<Self> {
+        match (self, other) {
+            (Self::True, _) | (_, Self::True) => Some(Self::True),
+            (Self::False, a) | (a, Self::False) => Some(a),
+            (Self::ConstIsZero(a), Self::ConstIsZero(b)) if a == b => Some(Self::ConstIsZero(a)),
+            (Self::NotInModule(a), Self::NotInModule(b)) if a == b => Some(Self::NotInModule(a)),
+            (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(a, b) => {
+                Some(Self::NotInModule(a))
+            }
+            (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(b, a) => {
+                Some(Self::NotInModule(b))
+            }
+            (Self::GenericType(a), Self::GenericType(b)) if a == b => Some(Self::GenericType(a)),
+            (Self::Or(&[a, b]), c) | (c, Self::Or(&[a, b])) => {
+                if let Some(ac) = a.reduce_or(tcx, c) {
+                    Some(ac.or(tcx, b))
+                } else if let Some(bc) = b.reduce_or(tcx, c) {
+                    Some(Self::Or(tcx.arena.alloc([a, bc])))
+                } else {
+                    None
+                }
+            }
+            _ => None,
+        }
+    }
+
+    /// Replaces generic types with its corresponding predicate
+    pub fn subst(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Self {
+        self.subst_opt(tcx, substs).unwrap_or(self)
+    }
+
+    fn subst_opt(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Option<Self> {
+        match self {
+            Self::ConstIsZero(c) => {
+                let c = ty::EarlyBinder(c).subst(tcx, substs);
+                let pred = match c.kind().try_to_machine_usize(tcx) {
+                    Some(0) => Self::True,
+                    Some(1..) => Self::False,
+                    None => Self::ConstIsZero(c),
+                };
+                Some(pred)
+            }
+            Self::GenericType(t) => {
+                Some(ty::EarlyBinder(t).subst(tcx, substs).inhabited_predicate(tcx))
+            }
+            Self::And(&[a, b]) => match a.subst_opt(tcx, substs) {
+                None => b.subst_opt(tcx, substs).map(|b| a.and(tcx, b)),
+                Some(InhabitedPredicate::False) => Some(InhabitedPredicate::False),
+                Some(a) => Some(a.and(tcx, b.subst_opt(tcx, substs).unwrap_or(b))),
+            },
+            Self::Or(&[a, b]) => match a.subst_opt(tcx, substs) {
+                None => b.subst_opt(tcx, substs).map(|b| a.or(tcx, b)),
+                Some(InhabitedPredicate::True) => Some(InhabitedPredicate::True),
+                Some(a) => Some(a.or(tcx, b.subst_opt(tcx, substs).unwrap_or(b))),
+            },
+            _ => None,
+        }
+    }
+}
+
+// this is basically like `f(a)? && f(b)?` but different in the case of
+// `Ok(false) && Err(_) -> Ok(false)`
+fn try_and<T, E>(a: T, b: T, f: impl Fn(T) -> Result<bool, E>) -> Result<bool, E> {
+    let a = f(a);
+    if matches!(a, Ok(false)) {
+        return Ok(false);
+    }
+    match (a, f(b)) {
+        (_, Ok(false)) | (Ok(false), _) => Ok(false),
+        (Ok(true), Ok(true)) => Ok(true),
+        (Err(e), _) | (_, Err(e)) => Err(e),
+    }
+}
+
+fn try_or<T, E>(a: T, b: T, f: impl Fn(T) -> Result<bool, E>) -> Result<bool, E> {
+    let a = f(a);
+    if matches!(a, Ok(true)) {
+        return Ok(true);
+    }
+    match (a, f(b)) {
+        (_, Ok(true)) | (Ok(true), _) => Ok(true),
+        (Ok(false), Ok(false)) => Ok(false),
+        (Err(e), _) | (_, Err(e)) => Err(e),
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index aaa66deb2a3..279a728ea39 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -1,57 +1,60 @@
-pub use self::def_id_forest::DefIdForest;
+//! This module contains logic for determining whether a type is inhabited or
+//! uninhabited. The [`InhabitedPredicate`] type captures the minimum
+//! information needed to determine whether a type is inhabited given a
+//! `ParamEnv` and module ID.
+//!
+//! # Example
+//! ```rust
+//! enum Void {}
+//! mod a {
+//!     pub mod b {
+//!         pub struct SecretlyUninhabited {
+//!             _priv: !,
+//!         }
+//!     }
+//! }
+//!
+//! mod c {
+//!     pub struct AlsoSecretlyUninhabited {
+//!         _priv: Void,
+//!     }
+//!     mod d {
+//!     }
+//! }
+//!
+//! struct Foo {
+//!     x: a::b::SecretlyUninhabited,
+//!     y: c::AlsoSecretlyUninhabited,
+//! }
+//! ```
+//! In this code, the type `Foo` will only be visibly uninhabited inside the
+//! modules `b`, `c` and `d`. Calling `uninhabited_predicate` on `Foo` will
+//! return `NotInModule(b) AND NotInModule(c)`.
+//!
+//! We need this information for pattern-matching on `Foo` or types that contain
+//! `Foo`.
+//!
+//! # Example
+//! ```rust
+//! let foo_result: Result<T, Foo> = ... ;
+//! let Ok(t) = foo_result;
+//! ```
+//! This code should only compile in modules where the uninhabitedness of `Foo`
+//! is visible.
 
-use crate::ty;
 use crate::ty::context::TyCtxt;
-use crate::ty::{AdtDef, FieldDef, Ty, VariantDef};
-use crate::ty::{AdtKind, Visibility};
-use crate::ty::{DefId, SubstsRef};
+use crate::ty::{self, DefId, Ty, VariantDef, Visibility};
 
 use rustc_type_ir::sty::TyKind::*;
 
-mod def_id_forest;
+pub mod inhabited_predicate;
 
-// The methods in this module calculate `DefIdForest`s of modules in which an
-// `AdtDef`/`VariantDef`/`FieldDef` is visibly uninhabited.
-//
-// # Example
-// ```rust
-// enum Void {}
-// mod a {
-//     pub mod b {
-//         pub struct SecretlyUninhabited {
-//             _priv: !,
-//         }
-//     }
-// }
-//
-// mod c {
-//     pub struct AlsoSecretlyUninhabited {
-//         _priv: Void,
-//     }
-//     mod d {
-//     }
-// }
-//
-// struct Foo {
-//     x: a::b::SecretlyUninhabited,
-//     y: c::AlsoSecretlyUninhabited,
-// }
-// ```
-// In this code, the type `Foo` will only be visibly uninhabited inside the
-// modules `b`, `c` and `d`. Calling `uninhabited_from` on `Foo` or its `AdtDef` will
-// return the forest of modules {`b`, `c`->`d`} (represented in a `DefIdForest` by the
-// set {`b`, `c`}).
-//
-// We need this information for pattern-matching on `Foo` or types that contain
-// `Foo`.
-//
-// # Example
-// ```rust
-// let foo_result: Result<T, Foo> = ... ;
-// let Ok(t) = foo_result;
-// ```
-// This code should only compile in modules where the uninhabitedness of `Foo` is
-// visible.
+pub use inhabited_predicate::InhabitedPredicate;
+
+pub(crate) fn provide(providers: &mut ty::query::Providers) {
+    *providers =
+        ty::query::Providers { inhabited_predicate_adt, inhabited_predicate_type, ..*providers };
+}
 
 impl<'tcx> TyCtxt<'tcx> {
     /// Checks whether a type is visibly uninhabited from a particular module.
@@ -100,131 +103,92 @@ impl<'tcx> TyCtxt<'tcx> {
         ty: Ty<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> bool {
-        // To check whether this type is uninhabited at all (not just from the
-        // given node), you could check whether the forest is empty.
-        // ```
-        // forest.is_empty()
-        // ```
-        ty.uninhabited_from(self, param_env).contains(self, module)
+        !ty.inhabited_predicate(self).apply(self, param_env, module)
     }
 }
 
-impl<'tcx> AdtDef<'tcx> {
-    /// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited.
-    fn uninhabited_from(
-        self,
-        tcx: TyCtxt<'tcx>,
-        substs: SubstsRef<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> DefIdForest<'tcx> {
-        // Non-exhaustive ADTs from other crates are always considered inhabited.
-        if self.is_variant_list_non_exhaustive() && !self.did().is_local() {
-            DefIdForest::empty()
-        } else {
-            DefIdForest::intersection(
-                tcx,
-                self.variants()
-                    .iter()
-                    .map(|v| v.uninhabited_from(tcx, substs, self.adt_kind(), param_env)),
-            )
+/// Returns an `InhabitedPredicate` that is generic over type parameters and
+/// requires calling [`InhabitedPredicate::subst`]
+fn inhabited_predicate_adt(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> {
+    if let Some(def_id) = def_id.as_local() {
+        if matches!(tcx.representability(def_id), ty::Representability::Infinite) {
+            return InhabitedPredicate::True;
         }
     }
+    let adt = tcx.adt_def(def_id);
+    InhabitedPredicate::any(
+        tcx,
+        adt.variants().iter().map(|variant| variant.inhabited_predicate(tcx, adt)),
+    )
 }
 
 impl<'tcx> VariantDef {
     /// Calculates the forest of `DefId`s from which this variant is visibly uninhabited.
-    pub fn uninhabited_from(
+    pub fn inhabited_predicate(
         &self,
         tcx: TyCtxt<'tcx>,
-        substs: SubstsRef<'tcx>,
-        adt_kind: AdtKind,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> DefIdForest<'tcx> {
-        let is_enum = match adt_kind {
-            // For now, `union`s are never considered uninhabited.
-            // The precise semantics of inhabitedness with respect to unions is currently undecided.
-            AdtKind::Union => return DefIdForest::empty(),
-            AdtKind::Enum => true,
-            AdtKind::Struct => false,
-        };
-        // Non-exhaustive variants from other crates are always considered inhabited.
+        adt: ty::AdtDef<'_>,
+    ) -> InhabitedPredicate<'tcx> {
+        debug_assert!(!adt.is_union());
         if self.is_field_list_non_exhaustive() && !self.def_id.is_local() {
-            DefIdForest::empty()
-        } else {
-            DefIdForest::union(
-                tcx,
-                self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum, param_env)),
-            )
+            // Non-exhaustive variants from other crates are always considered inhabited.
+            return InhabitedPredicate::True;
         }
-    }
-}
-
-impl<'tcx> FieldDef {
-    /// Calculates the forest of `DefId`s from which this field is visibly uninhabited.
-    fn uninhabited_from(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        substs: SubstsRef<'tcx>,
-        is_enum: bool,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> DefIdForest<'tcx> {
-        let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx, param_env);
-        if is_enum {
-            data_uninhabitedness()
-        } else {
-            match self.vis {
-                Visibility::Restricted(from) => {
-                    let forest = DefIdForest::from_id(from);
-                    let iter = Some(forest).into_iter().chain(Some(data_uninhabitedness()));
-                    DefIdForest::intersection(tcx, iter)
+        InhabitedPredicate::all(
+            tcx,
+            self.fields.iter().map(|field| {
+                let pred = tcx.type_of(field.did).inhabited_predicate(tcx);
+                if adt.is_enum() {
+                    return pred;
                 }
-                Visibility::Public => data_uninhabitedness(),
-            }
-        }
+                match field.vis {
+                    Visibility::Public => pred,
+                    Visibility::Restricted(from) => {
+                        pred.or(tcx, InhabitedPredicate::NotInModule(from))
+                    }
+                }
+            }),
+        )
     }
 }
 
 impl<'tcx> Ty<'tcx> {
-    /// Calculates the forest of `DefId`s from which this type is visibly uninhabited.
-    fn uninhabited_from(
-        self,
-        tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> DefIdForest<'tcx> {
-        tcx.type_uninhabited_from(param_env.and(self))
+    pub fn inhabited_predicate(self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx> {
+        match self.kind() {
+            // For now, union`s are always considered inhabited
+            Adt(adt, _) if adt.is_union() => InhabitedPredicate::True,
+            // Non-exhaustive ADTs from other crates are always considered inhabited
+            Adt(adt, _) if adt.is_variant_list_non_exhaustive() && !adt.did().is_local() => {
+                InhabitedPredicate::True
+            }
+            Never => InhabitedPredicate::False,
+            Param(_) | Projection(_) => InhabitedPredicate::GenericType(self),
+            Tuple(tys) if tys.is_empty() => InhabitedPredicate::True,
+            // use a query for more complex cases
+            Adt(..) | Array(..) | Tuple(_) => tcx.inhabited_predicate_type(self),
+            // references and other types are inhabited
+            _ => InhabitedPredicate::True,
+        }
     }
 }
 
-// Query provider for `type_uninhabited_from`.
-pub(crate) fn type_uninhabited_from<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
-) -> DefIdForest<'tcx> {
-    let ty = key.value;
-    let param_env = key.param_env;
+/// N.B. this query should only be called through `Ty::inhabited_predicate`
+fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedPredicate<'tcx> {
     match *ty.kind() {
-        Adt(def, substs) => def.uninhabited_from(tcx, substs, param_env),
+        Adt(adt, substs) => tcx.inhabited_predicate_adt(adt.did()).subst(tcx, substs),
 
-        Never => DefIdForest::full(),
-
-        Tuple(ref tys) => {
-            DefIdForest::union(tcx, tys.iter().map(|ty| ty.uninhabited_from(tcx, param_env)))
+        Tuple(tys) => {
+            InhabitedPredicate::all(tcx, tys.iter().map(|ty| ty.inhabited_predicate(tcx)))
         }
 
-        Array(ty, len) => match len.try_eval_usize(tcx, param_env) {
-            Some(0) | None => DefIdForest::empty(),
-            // If the array is definitely non-empty, it's uninhabited if
-            // the type of its elements is uninhabited.
-            Some(1..) => ty.uninhabited_from(tcx, param_env),
+        // If we can evaluate the array length before having a `ParamEnv`, then
+        // we can simplify the predicate. This is an optimization.
+        Array(ty, len) => match len.kind().try_to_machine_usize(tcx) {
+            Some(0) => InhabitedPredicate::True,
+            Some(1..) => ty.inhabited_predicate(tcx),
+            None => ty.inhabited_predicate(tcx).or(tcx, InhabitedPredicate::ConstIsZero(len)),
         },
 
-        // References to uninitialised memory are valid for any type, including
-        // uninhabited types, in unsafe code, so we treat all references as
-        // inhabited.
-        // The precise semantics of inhabitedness with respect to references is currently
-        // undecided.
-        Ref(..) => DefIdForest::empty(),
-
-        _ => DefIdForest::empty(),
+        _ => bug!("unexpected TyKind, use `Ty::inhabited_predicate`"),
     }
 }
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 6045c1acdd0..0a109fd8f44 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -196,16 +196,16 @@ impl<'a> IntoDiagnostic<'a, !> for LayoutError<'a> {
         match self {
             LayoutError::Unknown(ty) => {
                 diag.set_arg("ty", ty);
-                diag.set_primary_message(rustc_errors::fluent::middle::unknown_layout);
+                diag.set_primary_message(rustc_errors::fluent::middle_unknown_layout);
             }
             LayoutError::SizeOverflow(ty) => {
                 diag.set_arg("ty", ty);
-                diag.set_primary_message(rustc_errors::fluent::middle::values_too_big);
+                diag.set_primary_message(rustc_errors::fluent::middle_values_too_big);
             }
             LayoutError::NormalizationFailure(ty, e) => {
                 diag.set_arg("ty", ty);
                 diag.set_arg("failure_ty", e.get_type_for_failure());
-                diag.set_primary_message(rustc_errors::fluent::middle::cannot_be_normalized);
+                diag.set_primary_message(rustc_errors::fluent::middle_cannot_be_normalized);
             }
         }
         diag
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index a92bb0f2e55..c2aef8178e2 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -78,7 +78,7 @@ pub use self::consts::{
 };
 pub use self::context::{
     tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
-    CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData,
+    CtxtInterners, DeducedParamAttrs, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData,
     GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType,
     UserTypeAnnotationIndex,
 };
@@ -683,7 +683,7 @@ pub enum PredicateKind<'tcx> {
     Coerce(CoercePredicate<'tcx>),
 
     /// Constant initializer must evaluate successfully.
-    ConstEvaluatable(ty::UnevaluatedConst<'tcx>),
+    ConstEvaluatable(ty::Const<'tcx>),
 
     /// Constants must be equal. The first component is the const that is expected.
     ConstEquate(Const<'tcx>, Const<'tcx>),
@@ -2694,6 +2694,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
     closure::provide(providers);
     context::provide(providers);
     erase_regions::provide(providers);
+    inhabitedness::provide(providers);
     util::provide(providers);
     print::provide(providers);
     super::util::bug::provide(providers);
@@ -2701,7 +2702,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
     *providers = ty::query::Providers {
         trait_impls_of: trait_def::trait_impls_of_provider,
         incoherent_impls: trait_def::incoherent_impls_provider,
-        type_uninhabited_from: inhabitedness::type_uninhabited_from,
         const_param_default: consts::const_param_default,
         vtable_allocation: vtable::vtable_allocation_provider,
         ..*providers
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index f289f2265a2..e1e705a922f 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -61,6 +61,7 @@ trivially_parameterized_over_tcx! {
     crate::middle::resolve_lifetime::ObjectLifetimeDefault,
     crate::mir::ConstQualifs,
     ty::AssocItemContainer,
+    ty::DeducedParamAttrs,
     ty::Generics,
     ty::ImplPolarity,
     ty::ReprOptions,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 66354196b4e..b8ee2b994b1 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -16,6 +16,7 @@ use rustc_session::cstore::{ExternCrate, ExternCrateSource};
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_target::abi::Size;
 use rustc_target::spec::abi::Abi;
+use smallvec::SmallVec;
 
 use std::cell::Cell;
 use std::char;
@@ -794,9 +795,9 @@ pub trait PrettyPrinter<'tcx>:
         let mut traits = FxIndexMap::default();
         let mut fn_traits = FxIndexMap::default();
         let mut is_sized = false;
+        let mut lifetimes = SmallVec::<[ty::Region<'tcx>; 1]>::new();
 
-        for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
-            let predicate = predicate.subst(tcx, substs);
+        for (predicate, _) in bounds.subst_iter_copied(tcx, substs) {
             let bound_predicate = predicate.kind();
 
             match bound_predicate.skip_binder() {
@@ -825,6 +826,9 @@ pub trait PrettyPrinter<'tcx>:
                         &mut fn_traits,
                     );
                 }
+                ty::PredicateKind::TypeOutlives(outlives) => {
+                    lifetimes.push(outlives.1);
+                }
                 _ => {}
             }
         }
@@ -978,6 +982,11 @@ pub trait PrettyPrinter<'tcx>:
             write!(self, "Sized")?;
         }
 
+        for re in lifetimes {
+            write!(self, " + ")?;
+            self = self.print_region(re)?;
+        }
+
         Ok(self)
     }
 
@@ -2702,8 +2711,8 @@ define_print_and_forward_display! {
                 print_value_path(closure_def_id, &[]),
                 write("` implements the trait `{}`", kind))
             }
-            ty::PredicateKind::ConstEvaluatable(uv) => {
-                p!("the constant `", print_value_path(uv.def.did, uv.substs), "` can be evaluated")
+            ty::PredicateKind::ConstEvaluatable(ct) => {
+                p!("the constant `", print(ct), "` can be evaluated")
             }
             ty::PredicateKind::ConstEquate(c1, c2) => {
                 p!("the constant `", print(c1), "` equals `", print(c2), "`")
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index ce1b69935f2..9c97ce34f29 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -52,7 +52,6 @@ use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolMangli
 use rustc_session::cstore::{CrateDepKind, CrateSource};
 use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
 use rustc_session::lint::LintExpectationId;
-use rustc_session::utils::NativeLibKind;
 use rustc_session::Limits;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 1164cf3e01a..2cad333e3f5 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -166,8 +166,8 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
             ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
                 write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
             }
-            ty::PredicateKind::ConstEvaluatable(uv) => {
-                write!(f, "ConstEvaluatable({:?}, {:?})", uv.def, uv.substs)
+            ty::PredicateKind::ConstEvaluatable(ct) => {
+                write!(f, "ConstEvaluatable({ct:?})")
             }
             ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
             ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
@@ -832,27 +832,6 @@ impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for ty::UnevaluatedConst<'tcx> {
-    fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        folder.try_fold_ty_unevaluated(self)
-    }
-}
-
-impl<'tcx> TypeVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
-    fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        visitor.visit_ty_unevaluated(*self)
-    }
-}
-
-impl<'tcx> TypeSuperFoldable<'tcx> for ty::UnevaluatedConst<'tcx> {
-    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
-        self,
-        folder: &mut F,
-    ) -> Result<Self, F::Error> {
-        Ok(ty::UnevaluatedConst { def: self.def, substs: self.substs.try_fold_with(folder)? })
-    }
-}
-
 impl<'tcx> TypeSuperVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
         self.substs.visit_with(visitor)
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index c2a83ca9dbb..0660e9b79a7 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -6,6 +6,7 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
 use crate::ty::visit::{TypeVisitable, TypeVisitor};
 use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
 
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::intern::{Interned, WithStableHash};
 use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
@@ -188,6 +189,14 @@ impl<'tcx> GenericArg<'tcx> {
             _ => bug!("expected a const, but found another kind"),
         }
     }
+
+    pub fn is_non_region_infer(self) -> bool {
+        match self.unpack() {
+            GenericArgKind::Lifetime(_) => false,
+            GenericArgKind::Type(ty) => ty.is_ty_infer(),
+            GenericArgKind::Const(ct) => ct.is_ct_infer(),
+        }
+    }
 }
 
 impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> {
@@ -550,6 +559,28 @@ impl<T, U> EarlyBinder<(T, U)> {
     }
 }
 
+impl<'tcx, 's, T: IntoIterator<Item = I>, I: TypeFoldable<'tcx>> EarlyBinder<T> {
+    pub fn subst_iter(
+        self,
+        tcx: TyCtxt<'tcx>,
+        substs: &'s [GenericArg<'tcx>],
+    ) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> {
+        self.0.into_iter().map(move |t| EarlyBinder(t).subst(tcx, substs))
+    }
+}
+
+impl<'tcx, 's, 'a, T: IntoIterator<Item = &'a I>, I: Copy + TypeFoldable<'tcx> + 'a>
+    EarlyBinder<T>
+{
+    pub fn subst_iter_copied(
+        self,
+        tcx: TyCtxt<'tcx>,
+        substs: &'s [GenericArg<'tcx>],
+    ) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> + Captures<'a> {
+        self.0.into_iter().map(move |t| EarlyBinder(*t).subst(tcx, substs))
+    }
+}
+
 pub struct EarlyBinderIter<T> {
     t: T,
 }
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 5ca00a11ab9..c09f71f9a6d 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -197,13 +197,6 @@ pub trait TypeVisitor<'tcx>: Sized {
         c.super_visit_with(self)
     }
 
-    fn visit_ty_unevaluated(
-        &mut self,
-        uv: ty::UnevaluatedConst<'tcx>,
-    ) -> ControlFlow<Self::BreakTy> {
-        uv.super_visit_with(self)
-    }
-
     fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
         p.super_visit_with(self)
     }
@@ -594,21 +587,6 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
 
     #[inline]
     #[instrument(level = "trace", ret)]
-    fn visit_ty_unevaluated(
-        &mut self,
-        uv: ty::UnevaluatedConst<'tcx>,
-    ) -> ControlFlow<Self::BreakTy> {
-        let flags = FlagComputation::for_unevaluated_const(uv);
-        trace!(r.flags=?flags);
-        if flags.intersects(self.flags) {
-            ControlFlow::Break(FoundFlags)
-        } else {
-            ControlFlow::CONTINUE
-        }
-    }
-
-    #[inline]
-    #[instrument(level = "trace", ret)]
     fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
         debug!(
             "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index a3e11bbf056..91db9698c41 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -112,6 +112,22 @@ impl<'tcx> Ty<'tcx> {
     }
 }
 
+impl<'tcx> ty::Const<'tcx> {
+    /// Iterator that walks `self` and any types reachable from
+    /// `self`, in depth-first order. Note that just walks the types
+    /// that appear in `self`, it does not descend into the fields of
+    /// structs or variants. For example:
+    ///
+    /// ```text
+    /// isize => { isize }
+    /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
+    /// [isize] => { [isize], isize }
+    /// ```
+    pub fn walk(self) -> TypeWalker<'tcx> {
+        TypeWalker::new(self.into())
+    }
+}
+
 /// We push `GenericArg`s on the stack in reverse order so as to
 /// maintain a pre-order traversal. As of the time of this
 /// writing, the fact that the traversal is pre-order is not
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index 828f32db361..924d2f555b9 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -264,14 +264,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
                     i == variant_index || {
                         self.tcx.features().exhaustive_patterns
-                            && !v
-                                .uninhabited_from(
-                                    self.tcx,
-                                    substs,
-                                    adt_def.adt_kind(),
-                                    self.param_env,
-                                )
-                                .is_empty()
+                            && v.inhabited_predicate(self.tcx, adt_def)
+                                .subst(self.tcx, substs)
+                                .apply_any_module(self.tcx, self.param_env)
+                                != Some(true)
                     }
                 }) && (adt_def.did().is_local()
                     || !adt_def.is_variant_list_non_exhaustive());
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index 91ecfccdb5f..595abc8f668 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -988,10 +988,12 @@ impl<'tcx> SplitWildcard<'tcx> {
                     .filter(|(_, v)| {
                         // If `exhaustive_patterns` is enabled, we exclude variants known to be
                         // uninhabited.
-                        let is_uninhabited = is_exhaustive_pat_feature
-                            && v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env)
-                                .contains(cx.tcx, cx.module);
-                        !is_uninhabited
+                        !is_exhaustive_pat_feature
+                            || v.inhabited_predicate(cx.tcx, *def).subst(cx.tcx, substs).apply(
+                                cx.tcx,
+                                cx.param_env,
+                                cx.module,
+                            )
                     })
                     .map(|(idx, _)| Variant(idx))
                     .collect();
diff --git a/compiler/rustc_mir_dataflow/src/errors.rs b/compiler/rustc_mir_dataflow/src/errors.rs
index 5b1a88cb284..cfacc0ec370 100644
--- a/compiler/rustc_mir_dataflow/src/errors.rs
+++ b/compiler/rustc_mir_dataflow/src/errors.rs
@@ -2,21 +2,21 @@ use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
-#[diag(mir_dataflow::path_must_end_in_filename)]
+#[diag(mir_dataflow_path_must_end_in_filename)]
 pub(crate) struct PathMustEndInFilename {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_dataflow::unknown_formatter)]
+#[diag(mir_dataflow_unknown_formatter)]
 pub(crate) struct UnknownFormatter {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_dataflow::duplicate_values_for)]
+#[diag(mir_dataflow_duplicate_values_for)]
 pub(crate) struct DuplicateValuesFor {
     #[primary_span]
     pub span: Span,
@@ -24,7 +24,7 @@ pub(crate) struct DuplicateValuesFor {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_dataflow::requires_an_argument)]
+#[diag(mir_dataflow_requires_an_argument)]
 pub(crate) struct RequiresAnArgument {
     #[primary_span]
     pub span: Span,
@@ -32,39 +32,39 @@ pub(crate) struct RequiresAnArgument {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_dataflow::stop_after_dataflow_ended_compilation)]
+#[diag(mir_dataflow_stop_after_dataflow_ended_compilation)]
 pub(crate) struct StopAfterDataFlowEndedCompilation;
 
 #[derive(Diagnostic)]
-#[diag(mir_dataflow::peek_must_be_place_or_ref_place)]
+#[diag(mir_dataflow_peek_must_be_place_or_ref_place)]
 pub(crate) struct PeekMustBePlaceOrRefPlace {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_dataflow::peek_must_be_not_temporary)]
+#[diag(mir_dataflow_peek_must_be_not_temporary)]
 pub(crate) struct PeekMustBeNotTemporary {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_dataflow::peek_bit_not_set)]
+#[diag(mir_dataflow_peek_bit_not_set)]
 pub(crate) struct PeekBitNotSet {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_dataflow::peek_argument_not_a_local)]
+#[diag(mir_dataflow_peek_argument_not_a_local)]
 pub(crate) struct PeekArgumentNotALocal {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_dataflow::peek_argument_untracked)]
+#[diag(mir_dataflow_peek_argument_untracked)]
 pub(crate) struct PeekArgumentUntracked {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
new file mode 100644
index 00000000000..18352fbf675
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -0,0 +1,249 @@
+//! Deduces supplementary parameter attributes from MIR.
+//!
+//! Deduced parameter attributes are those that can only be soundly determined by examining the
+//! body of the function instead of just the signature. These can be useful for optimization
+//! purposes on a best-effort basis. We compute them here and store them into the crate metadata so
+//! dependent crates can use them.
+
+use rustc_hir::def_id::DefId;
+use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
+use rustc_middle::mir::{Body, Local, Location, Operand, Terminator, TerminatorKind, RETURN_PLACE};
+use rustc_middle::ty::{self, DeducedParamAttrs, ParamEnv, Ty, TyCtxt};
+use rustc_session::config::OptLevel;
+use rustc_span::DUMMY_SP;
+
+/// A visitor that determines which arguments have been mutated. We can't use the mutability field
+/// on LocalDecl for this because it has no meaning post-optimization.
+struct DeduceReadOnly {
+    /// Each bit is indexed by argument number, starting at zero (so 0 corresponds to local decl
+    /// 1). The bit is true if the argument may have been mutated or false if we know it hasn't
+    /// been up to the point we're at.
+    mutable_args: BitSet<usize>,
+}
+
+impl DeduceReadOnly {
+    /// Returns a new DeduceReadOnly instance.
+    fn new(arg_count: usize) -> Self {
+        Self { mutable_args: BitSet::new_empty(arg_count) }
+    }
+}
+
+impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
+    fn visit_local(&mut self, local: Local, mut context: PlaceContext, _: Location) {
+        // We're only interested in arguments.
+        if local == RETURN_PLACE || local.index() > self.mutable_args.domain_size() {
+            return;
+        }
+
+        // Replace place contexts that are moves with copies. This is safe in all cases except
+        // function argument position, which we already handled in `visit_terminator()` by using the
+        // ArgumentChecker. See the comment in that method for more details.
+        //
+        // In the future, we might want to move this out into a separate pass, but for now let's
+        // just do it on the fly because that's faster.
+        if matches!(context, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)) {
+            context = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy);
+        }
+
+        match context {
+            PlaceContext::MutatingUse(..)
+            | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => {
+                // This is a mutation, so mark it as such.
+                self.mutable_args.insert(local.index() - 1);
+            }
+            PlaceContext::NonMutatingUse(..) | PlaceContext::NonUse(..) => {
+                // Not mutating, so it's fine.
+            }
+        }
+    }
+
+    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
+        // OK, this is subtle. Suppose that we're trying to deduce whether `x` in `f` is read-only
+        // and we have the following:
+        //
+        //     fn f(x: BigStruct) { g(x) }
+        //     fn g(mut y: BigStruct) { y.foo = 1 }
+        //
+        // If, at the generated MIR level, `f` turned into something like:
+        //
+        //      fn f(_1: BigStruct) -> () {
+        //          let mut _0: ();
+        //          bb0: {
+        //              _0 = g(move _1) -> bb1;
+        //          }
+        //          ...
+        //      }
+        //
+        // then it would be incorrect to mark `x` (i.e. `_1`) as `readonly`, because `g`'s write to
+        // its copy of the indirect parameter would actually be a write directly to the pointer that
+        // `f` passes. Note that function arguments are the only situation in which this problem can
+        // arise: every other use of `move` in MIR doesn't actually write to the value it moves
+        // from.
+        //
+        // Anyway, right now this situation doesn't actually arise in practice. Instead, the MIR for
+        // that function looks like this:
+        //
+        //      fn f(_1: BigStruct) -> () {
+        //          let mut _0: ();
+        //          let mut _2: BigStruct;
+        //          bb0: {
+        //              _2 = move _1;
+        //              _0 = g(move _2) -> bb1;
+        //          }
+        //          ...
+        //      }
+        //
+        // Because of that extra move that MIR construction inserts, `x` (i.e. `_1`) can *in
+        // practice* safely be marked `readonly`.
+        //
+        // To handle the possibility that other optimizations (for example, destination propagation)
+        // might someday generate MIR like the first example above, we panic upon seeing an argument
+        // to *our* function that is directly moved into *another* function as an argument. Having
+        // eliminated that problematic case, we can safely treat moves as copies in this analysis.
+        //
+        // In the future, if MIR optimizations cause arguments of a caller to be directly moved into
+        // the argument of a callee, we can just add that argument to `mutated_args` instead of
+        // panicking.
+        //
+        // Note that, because the problematic MIR is never actually generated, we can't add a test
+        // case for this.
+
+        if let TerminatorKind::Call { ref args, .. } = terminator.kind {
+            for arg in args {
+                if let Operand::Move(_) = *arg {
+                    // ArgumentChecker panics if a direct move of an argument from a caller to a
+                    // callee was detected.
+                    //
+                    // If, in the future, MIR optimizations cause arguments to be moved directly
+                    // from callers to callees, change the panic to instead add the argument in
+                    // question to `mutating_uses`.
+                    ArgumentChecker::new(self.mutable_args.domain_size())
+                        .visit_operand(arg, location)
+                }
+            }
+        };
+
+        self.super_terminator(terminator, location);
+    }
+}
+
+/// A visitor that simply panics if a direct move of an argument from a caller to a callee was
+/// detected.
+struct ArgumentChecker {
+    /// The number of arguments to the calling function.
+    arg_count: usize,
+}
+
+impl ArgumentChecker {
+    /// Creates a new ArgumentChecker.
+    fn new(arg_count: usize) -> Self {
+        Self { arg_count }
+    }
+}
+
+impl<'tcx> Visitor<'tcx> for ArgumentChecker {
+    fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) {
+        // Check to make sure that, if this local is an argument, we didn't move directly from it.
+        if matches!(context, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move))
+            && local != RETURN_PLACE
+            && local.index() <= self.arg_count
+        {
+            // If, in the future, MIR optimizations cause arguments to be moved directly from
+            // callers to callees, change this panic to instead add the argument in question to
+            // `mutating_uses`.
+            panic!("Detected a direct move from a caller's argument to a callee's argument!")
+        }
+    }
+}
+
+/// Returns true if values of a given type will never be passed indirectly, regardless of ABI.
+fn type_will_always_be_passed_directly<'tcx>(ty: Ty<'tcx>) -> bool {
+    matches!(
+        ty.kind(),
+        ty::Bool
+            | ty::Char
+            | ty::Float(..)
+            | ty::Int(..)
+            | ty::RawPtr(..)
+            | ty::Ref(..)
+            | ty::Slice(..)
+            | ty::Uint(..)
+    )
+}
+
+/// Returns the deduced parameter attributes for a function.
+///
+/// Deduced parameter attributes are those that can only be soundly determined by examining the
+/// body of the function instead of just the signature. These can be useful for optimization
+/// purposes on a best-effort basis. We compute them here and store them into the crate metadata so
+/// dependent crates can use them.
+pub fn deduced_param_attrs<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx [DeducedParamAttrs] {
+    // This computation is unfortunately rather expensive, so don't do it unless we're optimizing.
+    // Also skip it in incremental mode.
+    if tcx.sess.opts.optimize == OptLevel::No || tcx.sess.opts.incremental.is_some() {
+        return &[];
+    }
+
+    // If the Freeze language item isn't present, then don't bother.
+    if tcx.lang_items().freeze_trait().is_none() {
+        return &[];
+    }
+
+    // Codegen won't use this information for anything if all the function parameters are passed
+    // directly. Detect that and bail, for compilation speed.
+    let fn_ty = tcx.type_of(def_id);
+    if matches!(fn_ty.kind(), ty::FnDef(..)) {
+        if fn_ty
+            .fn_sig(tcx)
+            .inputs()
+            .skip_binder()
+            .iter()
+            .cloned()
+            .all(type_will_always_be_passed_directly)
+        {
+            return &[];
+        }
+    }
+
+    // Don't deduce any attributes for functions that have no MIR.
+    if !tcx.is_mir_available(def_id) {
+        return &[];
+    }
+
+    // Deduced attributes for other crates should be read from the metadata instead of via this
+    // function.
+    debug_assert!(def_id.is_local());
+
+    // Grab the optimized MIR. Analyze it to determine which arguments have been mutated.
+    let body: &Body<'tcx> = tcx.optimized_mir(def_id);
+    let mut deduce_read_only = DeduceReadOnly::new(body.arg_count);
+    deduce_read_only.visit_body(body);
+
+    // Set the `readonly` attribute for every argument that we concluded is immutable and that
+    // contains no UnsafeCells.
+    //
+    // FIXME: This is overly conservative around generic parameters: `is_freeze()` will always
+    // return false for them. For a description of alternatives that could do a better job here,
+    // see [1].
+    //
+    // [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997
+    let mut deduced_param_attrs = tcx.arena.alloc_from_iter(
+        body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
+            |(arg_index, local_decl)| DeducedParamAttrs {
+                read_only: !deduce_read_only.mutable_args.contains(arg_index)
+                    && local_decl.ty.is_freeze(tcx.at(DUMMY_SP), ParamEnv::reveal_all()),
+            },
+        ),
+    );
+
+    // Trailing parameters past the size of the `deduced_param_attrs` array are assumed to have the
+    // default set of attributes, so we don't have to store them explicitly. Pop them off to save a
+    // few bytes in metadata.
+    while deduced_param_attrs.last() == Some(&DeducedParamAttrs::default()) {
+        let last_index = deduced_param_attrs.len() - 1;
+        deduced_param_attrs = &mut deduced_param_attrs[0..last_index];
+    }
+
+    deduced_param_attrs
+}
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 2230c3399f0..5c411fa5657 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -56,6 +56,7 @@ mod const_prop_lint;
 mod coverage;
 mod dead_store_elimination;
 mod deaggregator;
+mod deduce_param_attrs;
 mod deduplicate_blocks;
 mod deref_separator;
 mod dest_prop;
@@ -139,6 +140,7 @@ pub fn provide(providers: &mut Providers) {
         promoted_mir_of_const_arg: |tcx, (did, param_did)| {
             promoted_mir(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
         },
+        deduced_param_attrs: deduce_param_attrs::deduced_param_attrs,
         ..*providers
     };
 }
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index cf6e18c013b..ce097b8d846 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -6,7 +6,7 @@ use rustc_macros::{Diagnostic, LintDiagnostic};
 use rustc_span::Span;
 
 #[derive(Diagnostic)]
-#[diag(monomorphize::recursion_limit)]
+#[diag(monomorphize_recursion_limit)]
 pub struct RecursionLimit {
     #[primary_span]
     pub span: Span,
@@ -14,26 +14,26 @@ pub struct RecursionLimit {
     #[note]
     pub def_span: Span,
     pub def_path_str: String,
-    #[note(monomorphize::written_to_path)]
+    #[note(monomorphize_written_to_path)]
     pub was_written: Option<()>,
     pub path: PathBuf,
 }
 
 #[derive(Diagnostic)]
-#[diag(monomorphize::type_length_limit)]
-#[help(monomorphize::consider_type_length_limit)]
+#[diag(monomorphize_type_length_limit)]
+#[help(monomorphize_consider_type_length_limit)]
 pub struct TypeLengthLimit {
     #[primary_span]
     pub span: Span,
     pub shrunk: String,
-    #[note(monomorphize::written_to_path)]
+    #[note(monomorphize_written_to_path)]
     pub was_written: Option<()>,
     pub path: PathBuf,
     pub type_length: usize,
 }
 
 #[derive(Diagnostic)]
-#[diag(monomorphize::requires_lang_item)]
+#[diag(monomorphize_requires_lang_item)]
 pub struct RequiresLangItem {
     pub lang_item: String,
 }
@@ -49,8 +49,7 @@ impl IntoDiagnostic<'_> for UnusedGenericParams {
         self,
         handler: &'_ rustc_errors::Handler,
     ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
-        let mut diag =
-            handler.struct_err(rustc_errors::fluent::monomorphize::unused_generic_params);
+        let mut diag = handler.struct_err(rustc_errors::fluent::monomorphize_unused_generic_params);
         diag.set_span(self.span);
         for (span, name) in self.param_spans.into_iter().zip(self.param_names) {
             // FIXME: I can figure out how to do a label with a fluent string with a fixed message,
@@ -63,7 +62,7 @@ impl IntoDiagnostic<'_> for UnusedGenericParams {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(monomorphize::large_assignments)]
+#[diag(monomorphize_large_assignments)]
 #[note]
 pub struct LargeAssignmentsLint {
     #[label]
@@ -73,11 +72,11 @@ pub struct LargeAssignmentsLint {
 }
 
 #[derive(Diagnostic)]
-#[diag(monomorphize::unknown_partition_strategy)]
+#[diag(monomorphize_unknown_partition_strategy)]
 pub struct UnknownPartitionStrategy;
 
 #[derive(Diagnostic)]
-#[diag(monomorphize::symbol_already_defined)]
+#[diag(monomorphize_symbol_already_defined)]
 pub struct SymbolAlreadyDefined {
     #[primary_span]
     pub span: Option<Span>,
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 98fee997427..9b177c5189b 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -9,7 +9,7 @@ use rustc_span::{Span, Symbol};
 use crate::parser::TokenDescription;
 
 #[derive(Diagnostic)]
-#[diag(parser::maybe_report_ambiguous_plus)]
+#[diag(parser_maybe_report_ambiguous_plus)]
 pub(crate) struct AmbiguousPlus {
     pub sum_ty: String,
     #[primary_span]
@@ -18,7 +18,7 @@ pub(crate) struct AmbiguousPlus {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::maybe_recover_from_bad_type_plus, code = "E0178")]
+#[diag(parser_maybe_recover_from_bad_type_plus, code = "E0178")]
 pub(crate) struct BadTypePlus {
     pub ty: String,
     #[primary_span]
@@ -30,7 +30,7 @@ pub(crate) struct BadTypePlus {
 #[derive(Subdiagnostic)]
 pub(crate) enum BadTypePlusSub {
     #[suggestion(
-        parser::add_paren,
+        parser_add_paren,
         code = "{sum_with_parens}",
         applicability = "machine-applicable"
     )]
@@ -39,12 +39,12 @@ pub(crate) enum BadTypePlusSub {
         #[primary_span]
         span: Span,
     },
-    #[label(parser::forgot_paren)]
+    #[label(parser_forgot_paren)]
     ForgotParen {
         #[primary_span]
         span: Span,
     },
-    #[label(parser::expect_path)]
+    #[label(parser_expect_path)]
     ExpectPath {
         #[primary_span]
         span: Span,
@@ -52,7 +52,7 @@ pub(crate) enum BadTypePlusSub {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::maybe_recover_from_bad_qpath_stage_2)]
+#[diag(parser_maybe_recover_from_bad_qpath_stage_2)]
 pub(crate) struct BadQPathStage2 {
     #[primary_span]
     #[suggestion(code = "", applicability = "maybe-incorrect")]
@@ -61,7 +61,7 @@ pub(crate) struct BadQPathStage2 {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::incorrect_semicolon)]
+#[diag(parser_incorrect_semicolon)]
 pub(crate) struct IncorrectSemicolon<'a> {
     #[primary_span]
     #[suggestion_short(code = "", applicability = "machine-applicable")]
@@ -72,26 +72,26 @@ pub(crate) struct IncorrectSemicolon<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::incorrect_use_of_await)]
+#[diag(parser_incorrect_use_of_await)]
 pub(crate) struct IncorrectUseOfAwait {
     #[primary_span]
-    #[suggestion(parser::parentheses_suggestion, code = "", applicability = "machine-applicable")]
+    #[suggestion(parentheses_suggestion, code = "", applicability = "machine-applicable")]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::incorrect_use_of_await)]
+#[diag(parser_incorrect_use_of_await)]
 pub(crate) struct IncorrectAwait {
     #[primary_span]
     pub span: Span,
-    #[suggestion(parser::postfix_suggestion, code = "{expr}.await{question_mark}")]
+    #[suggestion(postfix_suggestion, code = "{expr}.await{question_mark}")]
     pub sugg_span: (Span, Applicability),
     pub expr: String,
     pub question_mark: &'static str,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::in_in_typo)]
+#[diag(parser_in_in_typo)]
 pub(crate) struct InInTypo {
     #[primary_span]
     pub span: Span,
@@ -100,7 +100,7 @@ pub(crate) struct InInTypo {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_variable_declaration)]
+#[diag(parser_invalid_variable_declaration)]
 pub(crate) struct InvalidVariableDeclaration {
     #[primary_span]
     pub span: Span,
@@ -110,26 +110,22 @@ pub(crate) struct InvalidVariableDeclaration {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum InvalidVariableDeclarationSub {
-    #[suggestion(
-        parser::switch_mut_let_order,
-        applicability = "maybe-incorrect",
-        code = "let mut"
-    )]
+    #[suggestion(parser_switch_mut_let_order, applicability = "maybe-incorrect", code = "let mut")]
     SwitchMutLetOrder(#[primary_span] Span),
     #[suggestion(
-        parser::missing_let_before_mut,
+        parser_missing_let_before_mut,
         applicability = "machine-applicable",
         code = "let mut"
     )]
     MissingLet(#[primary_span] Span),
-    #[suggestion(parser::use_let_not_auto, applicability = "machine-applicable", code = "let")]
+    #[suggestion(parser_use_let_not_auto, applicability = "machine-applicable", code = "let")]
     UseLetNotAuto(#[primary_span] Span),
-    #[suggestion(parser::use_let_not_var, applicability = "machine-applicable", code = "let")]
+    #[suggestion(parser_use_let_not_var, applicability = "machine-applicable", code = "let")]
     UseLetNotVar(#[primary_span] Span),
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_comparison_operator)]
+#[diag(parser_invalid_comparison_operator)]
 pub(crate) struct InvalidComparisonOperator {
     #[primary_span]
     pub span: Span,
@@ -140,23 +136,19 @@ pub(crate) struct InvalidComparisonOperator {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum InvalidComparisonOperatorSub {
-    #[suggestion_short(
-        parser::use_instead,
-        applicability = "machine-applicable",
-        code = "{correct}"
-    )]
+    #[suggestion_short(use_instead, applicability = "machine-applicable", code = "{correct}")]
     Correctable {
         #[primary_span]
         span: Span,
         invalid: String,
         correct: String,
     },
-    #[label(parser::spaceship_operator_invalid)]
+    #[label(spaceship_operator_invalid)]
     Spaceship(#[primary_span] Span),
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_logical_operator)]
+#[diag(parser_invalid_logical_operator)]
 #[note]
 pub(crate) struct InvalidLogicalOperator {
     #[primary_span]
@@ -169,13 +161,13 @@ pub(crate) struct InvalidLogicalOperator {
 #[derive(Subdiagnostic)]
 pub(crate) enum InvalidLogicalOperatorSub {
     #[suggestion_short(
-        parser::use_amp_amp_for_conjunction,
+        use_amp_amp_for_conjunction,
         applicability = "machine-applicable",
         code = "&&"
     )]
     Conjunction(#[primary_span] Span),
     #[suggestion_short(
-        parser::use_pipe_pipe_for_disjunction,
+        use_pipe_pipe_for_disjunction,
         applicability = "machine-applicable",
         code = "||"
     )]
@@ -183,7 +175,7 @@ pub(crate) enum InvalidLogicalOperatorSub {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::tilde_is_not_unary_operator)]
+#[diag(parser_tilde_is_not_unary_operator)]
 pub(crate) struct TildeAsUnaryOperator(
     #[primary_span]
     #[suggestion_short(applicability = "machine-applicable", code = "!")]
@@ -191,7 +183,7 @@ pub(crate) struct TildeAsUnaryOperator(
 );
 
 #[derive(Diagnostic)]
-#[diag(parser::unexpected_token_after_not)]
+#[diag(parser_unexpected_token_after_not)]
 pub(crate) struct NotAsNegationOperator {
     #[primary_span]
     pub negated: Span,
@@ -203,21 +195,21 @@ pub(crate) struct NotAsNegationOperator {
 #[derive(Subdiagnostic)]
 pub enum NotAsNegationOperatorSub {
     #[suggestion_short(
-        parser::unexpected_token_after_not_default,
+        parser_unexpected_token_after_not_default,
         applicability = "machine-applicable",
         code = "!"
     )]
     SuggestNotDefault(#[primary_span] Span),
 
     #[suggestion_short(
-        parser::unexpected_token_after_not_bitwise,
+        parser_unexpected_token_after_not_bitwise,
         applicability = "machine-applicable",
         code = "!"
     )]
     SuggestNotBitwise(#[primary_span] Span),
 
     #[suggestion_short(
-        parser::unexpected_token_after_not_logical,
+        parser_unexpected_token_after_not_logical,
         applicability = "machine-applicable",
         code = "!"
     )]
@@ -225,7 +217,7 @@ pub enum NotAsNegationOperatorSub {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::malformed_loop_label)]
+#[diag(parser_malformed_loop_label)]
 pub(crate) struct MalformedLoopLabel {
     #[primary_span]
     #[suggestion(applicability = "machine-applicable", code = "{correct_label}")]
@@ -234,7 +226,7 @@ pub(crate) struct MalformedLoopLabel {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::lifetime_in_borrow_expression)]
+#[diag(parser_lifetime_in_borrow_expression)]
 pub(crate) struct LifetimeInBorrowExpression {
     #[primary_span]
     pub span: Span,
@@ -244,27 +236,27 @@ pub(crate) struct LifetimeInBorrowExpression {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::field_expression_with_generic)]
+#[diag(parser_field_expression_with_generic)]
 pub(crate) struct FieldExpressionWithGeneric(#[primary_span] pub Span);
 
 #[derive(Diagnostic)]
-#[diag(parser::macro_invocation_with_qualified_path)]
+#[diag(parser_macro_invocation_with_qualified_path)]
 pub(crate) struct MacroInvocationWithQualifiedPath(#[primary_span] pub Span);
 
 #[derive(Diagnostic)]
-#[diag(parser::unexpected_token_after_label)]
+#[diag(parser_unexpected_token_after_label)]
 pub(crate) struct UnexpectedTokenAfterLabel {
     #[primary_span]
-    #[label(parser::unexpected_token_after_label)]
+    #[label(parser_unexpected_token_after_label)]
     pub span: Span,
-    #[suggestion_verbose(parser::suggestion_remove_label, code = "")]
+    #[suggestion_verbose(suggestion_remove_label, code = "")]
     pub remove_label: Option<Span>,
     #[subdiagnostic]
     pub enclose_in_block: Option<UnexpectedTokenAfterLabelSugg>,
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::suggestion_enclose_in_block, applicability = "machine-applicable")]
+#[multipart_suggestion(suggestion_enclose_in_block, applicability = "machine-applicable")]
 pub(crate) struct UnexpectedTokenAfterLabelSugg {
     #[suggestion_part(code = "{{ ")]
     pub left: Span,
@@ -273,7 +265,7 @@ pub(crate) struct UnexpectedTokenAfterLabelSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::require_colon_after_labeled_expression)]
+#[diag(parser_require_colon_after_labeled_expression)]
 #[note]
 pub(crate) struct RequireColonAfterLabeledExpression {
     #[primary_span]
@@ -285,7 +277,7 @@ pub(crate) struct RequireColonAfterLabeledExpression {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::do_catch_syntax_removed)]
+#[diag(parser_do_catch_syntax_removed)]
 #[note]
 pub(crate) struct DoCatchSyntaxRemoved {
     #[primary_span]
@@ -294,7 +286,7 @@ pub(crate) struct DoCatchSyntaxRemoved {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::float_literal_requires_integer_part)]
+#[diag(parser_float_literal_requires_integer_part)]
 pub(crate) struct FloatLiteralRequiresIntegerPart {
     #[primary_span]
     #[suggestion(applicability = "machine-applicable", code = "{correct}")]
@@ -303,7 +295,7 @@ pub(crate) struct FloatLiteralRequiresIntegerPart {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_int_literal_width)]
+#[diag(parser_invalid_int_literal_width)]
 #[help]
 pub(crate) struct InvalidIntLiteralWidth {
     #[primary_span]
@@ -312,7 +304,7 @@ pub(crate) struct InvalidIntLiteralWidth {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_num_literal_base_prefix)]
+#[diag(parser_invalid_num_literal_base_prefix)]
 #[note]
 pub(crate) struct InvalidNumLiteralBasePrefix {
     #[primary_span]
@@ -322,7 +314,7 @@ pub(crate) struct InvalidNumLiteralBasePrefix {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_num_literal_suffix)]
+#[diag(parser_invalid_num_literal_suffix)]
 #[help]
 pub(crate) struct InvalidNumLiteralSuffix {
     #[primary_span]
@@ -332,7 +324,7 @@ pub(crate) struct InvalidNumLiteralSuffix {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_float_literal_width)]
+#[diag(parser_invalid_float_literal_width)]
 #[help]
 pub(crate) struct InvalidFloatLiteralWidth {
     #[primary_span]
@@ -341,7 +333,7 @@ pub(crate) struct InvalidFloatLiteralWidth {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_float_literal_suffix)]
+#[diag(parser_invalid_float_literal_suffix)]
 #[help]
 pub(crate) struct InvalidFloatLiteralSuffix {
     #[primary_span]
@@ -351,14 +343,14 @@ pub(crate) struct InvalidFloatLiteralSuffix {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::int_literal_too_large)]
+#[diag(parser_int_literal_too_large)]
 pub(crate) struct IntLiteralTooLarge {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::missing_semicolon_before_array)]
+#[diag(parser_missing_semicolon_before_array)]
 pub(crate) struct MissingSemicolonBeforeArray {
     #[primary_span]
     pub open_delim: Span,
@@ -367,7 +359,7 @@ pub(crate) struct MissingSemicolonBeforeArray {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_block_macro_segment)]
+#[diag(parser_invalid_block_macro_segment)]
 pub(crate) struct InvalidBlockMacroSegment {
     #[primary_span]
     pub span: Span,
@@ -376,7 +368,7 @@ pub(crate) struct InvalidBlockMacroSegment {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::if_expression_missing_then_block)]
+#[diag(parser_if_expression_missing_then_block)]
 pub(crate) struct IfExpressionMissingThenBlock {
     #[primary_span]
     pub if_span: Span,
@@ -386,31 +378,31 @@ pub(crate) struct IfExpressionMissingThenBlock {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum IfExpressionMissingThenBlockSub {
-    #[help(parser::condition_possibly_unfinished)]
+    #[help(condition_possibly_unfinished)]
     UnfinishedCondition(#[primary_span] Span),
-    #[help(parser::add_then_block)]
+    #[help(add_then_block)]
     AddThenBlock(#[primary_span] Span),
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::if_expression_missing_condition)]
+#[diag(parser_if_expression_missing_condition)]
 pub(crate) struct IfExpressionMissingCondition {
     #[primary_span]
-    #[label(parser::condition_label)]
+    #[label(condition_label)]
     pub if_span: Span,
-    #[label(parser::block_label)]
+    #[label(block_label)]
     pub block_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::expected_expression_found_let)]
+#[diag(parser_expected_expression_found_let)]
 pub(crate) struct ExpectedExpressionFoundLet {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::expected_else_block)]
+#[diag(parser_expected_else_block)]
 pub(crate) struct ExpectedElseBlock {
     #[primary_span]
     pub first_tok_span: Span,
@@ -422,15 +414,15 @@ pub(crate) struct ExpectedElseBlock {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::outer_attribute_not_allowed_on_if_else)]
+#[diag(parser_outer_attribute_not_allowed_on_if_else)]
 pub(crate) struct OuterAttributeNotAllowedOnIfElse {
     #[primary_span]
     pub last: Span,
 
-    #[label(parser::branch_label)]
+    #[label(branch_label)]
     pub branch_span: Span,
 
-    #[label(parser::ctx_label)]
+    #[label(ctx_label)]
     pub ctx_span: Span,
     pub ctx: String,
 
@@ -439,7 +431,7 @@ pub(crate) struct OuterAttributeNotAllowedOnIfElse {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::missing_in_in_for_loop)]
+#[diag(parser_missing_in_in_for_loop)]
 pub(crate) struct MissingInInForLoop {
     #[primary_span]
     pub span: Span,
@@ -450,14 +442,14 @@ pub(crate) struct MissingInInForLoop {
 #[derive(Subdiagnostic)]
 pub(crate) enum MissingInInForLoopSub {
     // Has been misleading, at least in the past (closed Issue #48492), thus maybe-incorrect
-    #[suggestion_short(parser::use_in_not_of, applicability = "maybe-incorrect", code = "in")]
+    #[suggestion_short(use_in_not_of, applicability = "maybe-incorrect", code = "in")]
     InNotOf(#[primary_span] Span),
-    #[suggestion_short(parser::add_in, applicability = "maybe-incorrect", code = " in ")]
+    #[suggestion_short(add_in, applicability = "maybe-incorrect", code = " in ")]
     AddIn(#[primary_span] Span),
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::missing_comma_after_match_arm)]
+#[diag(parser_missing_comma_after_match_arm)]
 pub(crate) struct MissingCommaAfterMatchArm {
     #[primary_span]
     #[suggestion(applicability = "machine-applicable", code = ",")]
@@ -465,7 +457,7 @@ pub(crate) struct MissingCommaAfterMatchArm {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::catch_after_try)]
+#[diag(parser_catch_after_try)]
 #[help]
 pub(crate) struct CatchAfterTry {
     #[primary_span]
@@ -473,7 +465,7 @@ pub(crate) struct CatchAfterTry {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::comma_after_base_struct)]
+#[diag(parser_comma_after_base_struct)]
 #[note]
 pub(crate) struct CommaAfterBaseStruct {
     #[primary_span]
@@ -483,7 +475,7 @@ pub(crate) struct CommaAfterBaseStruct {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::eq_field_init)]
+#[diag(parser_eq_field_init)]
 pub(crate) struct EqFieldInit {
     #[primary_span]
     pub span: Span,
@@ -492,16 +484,16 @@ pub(crate) struct EqFieldInit {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::dotdotdot)]
+#[diag(parser_dotdotdot)]
 pub(crate) struct DotDotDot {
     #[primary_span]
-    #[suggestion(parser::suggest_exclusive_range, applicability = "maybe-incorrect", code = "..")]
-    #[suggestion(parser::suggest_inclusive_range, applicability = "maybe-incorrect", code = "..=")]
+    #[suggestion(suggest_exclusive_range, applicability = "maybe-incorrect", code = "..")]
+    #[suggestion(suggest_inclusive_range, applicability = "maybe-incorrect", code = "..=")]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::left_arrow_operator)]
+#[diag(parser_left_arrow_operator)]
 pub(crate) struct LeftArrowOperator {
     #[primary_span]
     #[suggestion(applicability = "maybe-incorrect", code = "< -")]
@@ -509,7 +501,7 @@ pub(crate) struct LeftArrowOperator {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::remove_let)]
+#[diag(parser_remove_let)]
 pub(crate) struct RemoveLet {
     #[primary_span]
     #[suggestion(applicability = "machine-applicable", code = "")]
@@ -517,7 +509,7 @@ pub(crate) struct RemoveLet {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::use_eq_instead)]
+#[diag(parser_use_eq_instead)]
 pub(crate) struct UseEqInstead {
     #[primary_span]
     #[suggestion_short(applicability = "machine-applicable", code = "=")]
@@ -525,7 +517,7 @@ pub(crate) struct UseEqInstead {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::use_empty_block_not_semi)]
+#[diag(parser_use_empty_block_not_semi)]
 pub(crate) struct UseEmptyBlockNotSemi {
     #[primary_span]
     #[suggestion_hidden(applicability = "machine-applicable", code = "{{}}")]
@@ -533,33 +525,33 @@ pub(crate) struct UseEmptyBlockNotSemi {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::comparison_interpreted_as_generic)]
+#[diag(parser_comparison_interpreted_as_generic)]
 pub(crate) struct ComparisonInterpretedAsGeneric {
     #[primary_span]
-    #[label(parser::label_comparison)]
+    #[label(label_comparison)]
     pub comparison: Span,
     pub r#type: Path,
-    #[label(parser::label_args)]
+    #[label(label_args)]
     pub args: Span,
     #[subdiagnostic]
     pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::shift_interpreted_as_generic)]
+#[diag(parser_shift_interpreted_as_generic)]
 pub(crate) struct ShiftInterpretedAsGeneric {
     #[primary_span]
-    #[label(parser::label_comparison)]
+    #[label(label_comparison)]
     pub shift: Span,
     pub r#type: Path,
-    #[label(parser::label_args)]
+    #[label(label_args)]
     pub args: Span,
     #[subdiagnostic]
     pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg,
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
 pub(crate) struct ComparisonOrShiftInterpretedAsGenericSugg {
     #[suggestion_part(code = "(")]
     pub left: Span,
@@ -568,7 +560,7 @@ pub(crate) struct ComparisonOrShiftInterpretedAsGenericSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::found_expr_would_be_stmt)]
+#[diag(parser_found_expr_would_be_stmt)]
 pub(crate) struct FoundExprWouldBeStmt {
     #[primary_span]
     #[label]
@@ -579,23 +571,19 @@ pub(crate) struct FoundExprWouldBeStmt {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::leading_plus_not_supported)]
+#[diag(parser_leading_plus_not_supported)]
 pub(crate) struct LeadingPlusNotSupported {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[suggestion_verbose(
-        parser::suggestion_remove_plus,
-        code = "",
-        applicability = "machine-applicable"
-    )]
+    #[suggestion_verbose(suggestion_remove_plus, code = "", applicability = "machine-applicable")]
     pub remove_plus: Option<Span>,
     #[subdiagnostic]
     pub add_parentheses: Option<ExprParenthesesNeeded>,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::parentheses_with_struct_fields)]
+#[diag(parser_parentheses_with_struct_fields)]
 pub(crate) struct ParenthesesWithStructFields {
     #[primary_span]
     pub span: Span,
@@ -607,7 +595,7 @@ pub(crate) struct ParenthesesWithStructFields {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::suggestion_braces_for_struct, applicability = "maybe-incorrect")]
+#[multipart_suggestion(suggestion_braces_for_struct, applicability = "maybe-incorrect")]
 pub(crate) struct BracesForStructLiteral {
     #[suggestion_part(code = " {{ ")]
     pub first: Span,
@@ -616,14 +604,14 @@ pub(crate) struct BracesForStructLiteral {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::suggestion_no_fields_for_fn, applicability = "maybe-incorrect")]
+#[multipart_suggestion(suggestion_no_fields_for_fn, applicability = "maybe-incorrect")]
 pub(crate) struct NoFieldsForFnCall {
     #[suggestion_part(code = "")]
     pub fields: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::labeled_loop_in_break)]
+#[diag(parser_labeled_loop_in_break)]
 pub(crate) struct LabeledLoopInBreak {
     #[primary_span]
     pub span: Span,
@@ -633,7 +621,7 @@ pub(crate) struct LabeledLoopInBreak {
 
 #[derive(Subdiagnostic)]
 #[multipart_suggestion(
-    parser::sugg_wrap_expression_in_parentheses,
+    parser_sugg_wrap_expression_in_parentheses,
     applicability = "machine-applicable"
 )]
 pub(crate) struct WrapExpressionInParentheses {
@@ -644,7 +632,7 @@ pub(crate) struct WrapExpressionInParentheses {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::array_brackets_instead_of_braces)]
+#[diag(parser_array_brackets_instead_of_braces)]
 pub(crate) struct ArrayBracketsInsteadOfSpaces {
     #[primary_span]
     pub span: Span,
@@ -653,7 +641,7 @@ pub(crate) struct ArrayBracketsInsteadOfSpaces {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::suggestion, applicability = "maybe-incorrect")]
+#[multipart_suggestion(suggestion, applicability = "maybe-incorrect")]
 pub(crate) struct ArrayBracketsInsteadOfSpacesSugg {
     #[suggestion_part(code = "[")]
     pub left: Span,
@@ -662,12 +650,12 @@ pub(crate) struct ArrayBracketsInsteadOfSpacesSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::match_arm_body_without_braces)]
+#[diag(parser_match_arm_body_without_braces)]
 pub(crate) struct MatchArmBodyWithoutBraces {
     #[primary_span]
-    #[label(parser::label_statements)]
+    #[label(label_statements)]
     pub statements: Span,
-    #[label(parser::label_arrow)]
+    #[label(label_arrow)]
     pub arrow: Span,
     pub num_statements: usize,
     #[subdiagnostic]
@@ -676,7 +664,7 @@ pub(crate) struct MatchArmBodyWithoutBraces {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum MatchArmBodyWithoutBracesSugg {
-    #[multipart_suggestion(parser::suggestion_add_braces, applicability = "machine-applicable")]
+    #[multipart_suggestion(suggestion_add_braces, applicability = "machine-applicable")]
     AddBraces {
         #[suggestion_part(code = "{{ ")]
         left: Span,
@@ -684,7 +672,7 @@ pub(crate) enum MatchArmBodyWithoutBracesSugg {
         right: Span,
     },
     #[suggestion(
-        parser::suggestion_use_comma_not_semicolon,
+        suggestion_use_comma_not_semicolon,
         code = ",",
         applicability = "machine-applicable"
     )]
@@ -695,7 +683,7 @@ pub(crate) enum MatchArmBodyWithoutBracesSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::struct_literal_not_allowed_here)]
+#[diag(parser_struct_literal_not_allowed_here)]
 pub(crate) struct StructLiteralNotAllowedHere {
     #[primary_span]
     pub span: Span,
@@ -704,7 +692,7 @@ pub(crate) struct StructLiteralNotAllowedHere {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
 pub(crate) struct StructLiteralNotAllowedHereSugg {
     #[suggestion_part(code = "(")]
     pub left: Span,
@@ -713,38 +701,38 @@ pub(crate) struct StructLiteralNotAllowedHereSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_interpolated_expression)]
+#[diag(parser_invalid_interpolated_expression)]
 pub(crate) struct InvalidInterpolatedExpression {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::hexadecimal_float_literal_not_supported)]
+#[diag(parser_hexadecimal_float_literal_not_supported)]
 pub(crate) struct HexadecimalFloatLiteralNotSupported {
     #[primary_span]
-    #[label(parser::not_supported)]
+    #[label(parser_not_supported)]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::octal_float_literal_not_supported)]
+#[diag(parser_octal_float_literal_not_supported)]
 pub(crate) struct OctalFloatLiteralNotSupported {
     #[primary_span]
-    #[label(parser::not_supported)]
+    #[label(parser_not_supported)]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::binary_float_literal_not_supported)]
+#[diag(parser_binary_float_literal_not_supported)]
 pub(crate) struct BinaryFloatLiteralNotSupported {
     #[primary_span]
-    #[label(parser::not_supported)]
+    #[label(parser_not_supported)]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_literal_suffix)]
+#[diag(parser_invalid_literal_suffix)]
 pub(crate) struct InvalidLiteralSuffix {
     #[primary_span]
     #[label]
@@ -755,20 +743,20 @@ pub(crate) struct InvalidLiteralSuffix {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_literal_suffix_on_tuple_index)]
+#[diag(parser_invalid_literal_suffix_on_tuple_index)]
 pub(crate) struct InvalidLiteralSuffixOnTupleIndex {
     #[primary_span]
     #[label]
     pub span: Span,
     pub suffix: Symbol,
-    #[help(parser::tuple_exception_line_1)]
-    #[help(parser::tuple_exception_line_2)]
-    #[help(parser::tuple_exception_line_3)]
+    #[help(tuple_exception_line_1)]
+    #[help(tuple_exception_line_2)]
+    #[help(tuple_exception_line_3)]
     pub exception: Option<()>,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::non_string_abi_literal)]
+#[diag(parser_non_string_abi_literal)]
 pub(crate) struct NonStringAbiLiteral {
     #[primary_span]
     #[suggestion(code = "\"C\"", applicability = "maybe-incorrect")]
@@ -776,21 +764,21 @@ pub(crate) struct NonStringAbiLiteral {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::mismatched_closing_delimiter)]
+#[diag(parser_mismatched_closing_delimiter)]
 pub(crate) struct MismatchedClosingDelimiter {
     #[primary_span]
     pub spans: Vec<Span>,
     pub delimiter: String,
-    #[label(parser::label_unmatched)]
+    #[label(label_unmatched)]
     pub unmatched: Span,
-    #[label(parser::label_opening_candidate)]
+    #[label(label_opening_candidate)]
     pub opening_candidate: Option<Span>,
-    #[label(parser::label_unclosed)]
+    #[label(label_unclosed)]
     pub unclosed: Option<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::incorrect_visibility_restriction, code = "E0704")]
+#[diag(parser_incorrect_visibility_restriction, code = "E0704")]
 #[help]
 pub(crate) struct IncorrectVisibilityRestriction {
     #[primary_span]
@@ -800,21 +788,21 @@ pub(crate) struct IncorrectVisibilityRestriction {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::assignment_else_not_allowed)]
+#[diag(parser_assignment_else_not_allowed)]
 pub(crate) struct AssignmentElseNotAllowed {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::expected_statement_after_outer_attr)]
+#[diag(parser_expected_statement_after_outer_attr)]
 pub(crate) struct ExpectedStatementAfterOuterAttr {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::doc_comment_does_not_document_anything, code = "E0585")]
+#[diag(parser_doc_comment_does_not_document_anything, code = "E0585")]
 #[help]
 pub(crate) struct DocCommentDoesNotDocumentAnything {
     #[primary_span]
@@ -824,7 +812,7 @@ pub(crate) struct DocCommentDoesNotDocumentAnything {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::const_let_mutually_exclusive)]
+#[diag(parser_const_let_mutually_exclusive)]
 pub(crate) struct ConstLetMutuallyExclusive {
     #[primary_span]
     #[suggestion(code = "const", applicability = "maybe-incorrect")]
@@ -832,7 +820,7 @@ pub(crate) struct ConstLetMutuallyExclusive {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_expression_in_let_else)]
+#[diag(parser_invalid_expression_in_let_else)]
 pub(crate) struct InvalidExpressionInLetElse {
     #[primary_span]
     pub span: Span,
@@ -842,7 +830,7 @@ pub(crate) struct InvalidExpressionInLetElse {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_curly_in_let_else)]
+#[diag(parser_invalid_curly_in_let_else)]
 pub(crate) struct InvalidCurlyInLetElse {
     #[primary_span]
     pub span: Span,
@@ -851,7 +839,7 @@ pub(crate) struct InvalidCurlyInLetElse {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::compound_assignment_expression_in_let)]
+#[diag(parser_compound_assignment_expression_in_let)]
 #[help]
 pub(crate) struct CompoundAssignmentExpressionInLet {
     #[primary_span]
@@ -860,7 +848,7 @@ pub(crate) struct CompoundAssignmentExpressionInLet {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::suffixed_literal_in_attribute)]
+#[diag(parser_suffixed_literal_in_attribute)]
 #[help]
 pub(crate) struct SuffixedLiteralInAttribute {
     #[primary_span]
@@ -868,7 +856,7 @@ pub(crate) struct SuffixedLiteralInAttribute {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::invalid_meta_item)]
+#[diag(parser_invalid_meta_item)]
 pub(crate) struct InvalidMetaItem {
     #[primary_span]
     pub span: Span,
@@ -877,7 +865,7 @@ pub(crate) struct InvalidMetaItem {
 
 #[derive(Subdiagnostic)]
 #[suggestion_verbose(
-    parser::sugg_escape_to_use_as_identifier,
+    parser_sugg_escape_to_use_as_identifier,
     applicability = "maybe-incorrect",
     code = "r#"
 )]
@@ -888,7 +876,7 @@ pub(crate) struct SuggEscapeToUseAsIdentifier {
 }
 
 #[derive(Subdiagnostic)]
-#[suggestion(parser::sugg_remove_comma, applicability = "machine-applicable", code = "")]
+#[suggestion(parser_sugg_remove_comma, applicability = "machine-applicable", code = "")]
 pub(crate) struct SuggRemoveComma {
     #[primary_span]
     pub span: Span,
@@ -896,15 +884,15 @@ pub(crate) struct SuggRemoveComma {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum ExpectedIdentifierFound {
-    #[label(parser::expected_identifier_found_reserved_identifier)]
+    #[label(parser_expected_identifier_found_reserved_identifier)]
     ReservedIdentifier(#[primary_span] Span),
-    #[label(parser::expected_identifier_found_keyword)]
+    #[label(parser_expected_identifier_found_keyword)]
     Keyword(#[primary_span] Span),
-    #[label(parser::expected_identifier_found_reserved_keyword)]
+    #[label(parser_expected_identifier_found_reserved_keyword)]
     ReservedKeyword(#[primary_span] Span),
-    #[label(parser::expected_identifier_found_doc_comment)]
+    #[label(parser_expected_identifier_found_doc_comment)]
     DocComment(#[primary_span] Span),
-    #[label(parser::expected_identifier)]
+    #[label(parser_expected_identifier)]
     Other(#[primary_span] Span),
 }
 
@@ -938,18 +926,16 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier {
 
         let mut diag = handler.struct_diagnostic(match token_descr {
             Some(TokenDescription::ReservedIdentifier) => {
-                fluent::parser::expected_identifier_found_reserved_identifier_str
-            }
-            Some(TokenDescription::Keyword) => {
-                fluent::parser::expected_identifier_found_keyword_str
+                fluent::parser_expected_identifier_found_reserved_identifier_str
             }
+            Some(TokenDescription::Keyword) => fluent::parser_expected_identifier_found_keyword_str,
             Some(TokenDescription::ReservedKeyword) => {
-                fluent::parser::expected_identifier_found_reserved_keyword_str
+                fluent::parser_expected_identifier_found_reserved_keyword_str
             }
             Some(TokenDescription::DocComment) => {
-                fluent::parser::expected_identifier_found_doc_comment_str
+                fluent::parser_expected_identifier_found_doc_comment_str
             }
-            None => fluent::parser::expected_identifier_found_str,
+            None => fluent::parser_expected_identifier_found_str,
         });
         diag.set_span(self.span);
         diag.set_arg("token", self.token);
@@ -985,22 +971,22 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedSemi {
 
         let mut diag = handler.struct_diagnostic(match token_descr {
             Some(TokenDescription::ReservedIdentifier) => {
-                fluent::parser::expected_semi_found_reserved_identifier_str
+                fluent::parser_expected_semi_found_reserved_identifier_str
             }
-            Some(TokenDescription::Keyword) => fluent::parser::expected_semi_found_keyword_str,
+            Some(TokenDescription::Keyword) => fluent::parser_expected_semi_found_keyword_str,
             Some(TokenDescription::ReservedKeyword) => {
-                fluent::parser::expected_semi_found_reserved_keyword_str
+                fluent::parser_expected_semi_found_reserved_keyword_str
             }
             Some(TokenDescription::DocComment) => {
-                fluent::parser::expected_semi_found_doc_comment_str
+                fluent::parser_expected_semi_found_doc_comment_str
             }
-            None => fluent::parser::expected_semi_found_str,
+            None => fluent::parser_expected_semi_found_str,
         });
         diag.set_span(self.span);
         diag.set_arg("token", self.token);
 
         if let Some(unexpected_token_label) = self.unexpected_token_label {
-            diag.span_label(unexpected_token_label, fluent::parser::label_unexpected_token);
+            diag.span_label(unexpected_token_label, fluent::parser_label_unexpected_token);
         }
 
         self.sugg.add_to_diagnostic(&mut diag);
@@ -1012,17 +998,17 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedSemi {
 #[derive(Subdiagnostic)]
 pub(crate) enum ExpectedSemiSugg {
     #[suggestion(
-        parser::sugg_change_this_to_semi,
+        parser_sugg_change_this_to_semi,
         code = ";",
         applicability = "machine-applicable"
     )]
     ChangeToSemi(#[primary_span] Span),
-    #[suggestion_short(parser::sugg_add_semi, code = ";", applicability = "machine-applicable")]
+    #[suggestion_short(parser_sugg_add_semi, code = ";", applicability = "machine-applicable")]
     AddSemi(#[primary_span] Span),
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::struct_literal_body_without_path)]
+#[diag(parser_struct_literal_body_without_path)]
 pub(crate) struct StructLiteralBodyWithoutPath {
     #[primary_span]
     pub span: Span,
@@ -1031,7 +1017,7 @@ pub(crate) struct StructLiteralBodyWithoutPath {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::suggestion, applicability = "has-placeholders")]
+#[multipart_suggestion(suggestion, applicability = "has-placeholders")]
 pub(crate) struct StructLiteralBodyWithoutPathSugg {
     #[suggestion_part(code = "{{ SomeStruct ")]
     pub before: Span,
@@ -1040,7 +1026,7 @@ pub(crate) struct StructLiteralBodyWithoutPathSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::unmatched_angle_brackets)]
+#[diag(parser_unmatched_angle_brackets)]
 pub(crate) struct UnmatchedAngleBrackets {
     #[primary_span]
     #[suggestion(code = "", applicability = "machine-applicable")]
@@ -1049,7 +1035,7 @@ pub(crate) struct UnmatchedAngleBrackets {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::generic_parameters_without_angle_brackets)]
+#[diag(parser_generic_parameters_without_angle_brackets)]
 pub(crate) struct GenericParamsWithoutAngleBrackets {
     #[primary_span]
     pub span: Span,
@@ -1058,7 +1044,7 @@ pub(crate) struct GenericParamsWithoutAngleBrackets {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
 pub(crate) struct GenericParamsWithoutAngleBracketsSugg {
     #[suggestion_part(code = "<")]
     pub left: Span,
@@ -1067,18 +1053,18 @@ pub(crate) struct GenericParamsWithoutAngleBracketsSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::comparison_operators_cannot_be_chained)]
+#[diag(parser_comparison_operators_cannot_be_chained)]
 pub(crate) struct ComparisonOperatorsCannotBeChained {
     #[primary_span]
     pub span: Vec<Span>,
     #[suggestion_verbose(
-        parser::sugg_turbofish_syntax,
+        parser_sugg_turbofish_syntax,
         code = "::",
         applicability = "maybe-incorrect"
     )]
     pub suggest_turbofish: Option<Span>,
-    #[help(parser::sugg_turbofish_syntax)]
-    #[help(parser::sugg_parentheses_for_function_args)]
+    #[help(parser_sugg_turbofish_syntax)]
+    #[help(sugg_parentheses_for_function_args)]
     pub help_turbofish: Option<()>,
     #[subdiagnostic]
     pub chaining_sugg: Option<ComparisonOperatorsCannotBeChainedSugg>,
@@ -1087,7 +1073,7 @@ pub(crate) struct ComparisonOperatorsCannotBeChained {
 #[derive(Subdiagnostic)]
 pub(crate) enum ComparisonOperatorsCannotBeChainedSugg {
     #[suggestion_verbose(
-        parser::sugg_split_comparison,
+        sugg_split_comparison,
         code = " && {middle_term}",
         applicability = "maybe-incorrect"
     )]
@@ -1096,7 +1082,7 @@ pub(crate) enum ComparisonOperatorsCannotBeChainedSugg {
         span: Span,
         middle_term: String,
     },
-    #[multipart_suggestion(parser::sugg_parenthesize, applicability = "maybe-incorrect")]
+    #[multipart_suggestion(sugg_parenthesize, applicability = "maybe-incorrect")]
     Parenthesize {
         #[suggestion_part(code = "(")]
         left: Span,
@@ -1106,7 +1092,7 @@ pub(crate) enum ComparisonOperatorsCannotBeChainedSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::question_mark_in_type)]
+#[diag(parser_question_mark_in_type)]
 pub(crate) struct QuestionMarkInType {
     #[primary_span]
     #[label]
@@ -1116,7 +1102,7 @@ pub(crate) struct QuestionMarkInType {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
 pub(crate) struct QuestionMarkInTypeSugg {
     #[suggestion_part(code = "Option<")]
     pub left: Span,
@@ -1125,7 +1111,7 @@ pub(crate) struct QuestionMarkInTypeSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::unexpected_parentheses_in_for_head)]
+#[diag(parser_unexpected_parentheses_in_for_head)]
 pub(crate) struct ParenthesesInForHead {
     #[primary_span]
     pub span: Vec<Span>,
@@ -1134,7 +1120,7 @@ pub(crate) struct ParenthesesInForHead {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
 pub(crate) struct ParenthesesInForHeadSugg {
     #[suggestion_part(code = "")]
     pub left: Span,
@@ -1143,7 +1129,7 @@ pub(crate) struct ParenthesesInForHeadSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::doc_comment_on_param_type)]
+#[diag(parser_doc_comment_on_param_type)]
 pub(crate) struct DocCommentOnParamType {
     #[primary_span]
     #[label]
@@ -1151,7 +1137,7 @@ pub(crate) struct DocCommentOnParamType {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::attribute_on_param_type)]
+#[diag(parser_attribute_on_param_type)]
 pub(crate) struct AttributeOnParamType {
     #[primary_span]
     #[label]
@@ -1159,7 +1145,7 @@ pub(crate) struct AttributeOnParamType {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::pattern_method_param_without_body, code = "E0642")]
+#[diag(parser_pattern_method_param_without_body, code = "E0642")]
 pub(crate) struct PatternMethodParamWithoutBody {
     #[primary_span]
     #[suggestion(code = "_", applicability = "machine-applicable")]
@@ -1167,7 +1153,7 @@ pub(crate) struct PatternMethodParamWithoutBody {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::self_param_not_first)]
+#[diag(parser_self_param_not_first)]
 pub(crate) struct SelfParamNotFirst {
     #[primary_span]
     #[label]
@@ -1175,7 +1161,7 @@ pub(crate) struct SelfParamNotFirst {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::const_generic_without_braces)]
+#[diag(parser_const_generic_without_braces)]
 pub(crate) struct ConstGenericWithoutBraces {
     #[primary_span]
     pub span: Span,
@@ -1184,7 +1170,7 @@ pub(crate) struct ConstGenericWithoutBraces {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
 pub(crate) struct ConstGenericWithoutBracesSugg {
     #[suggestion_part(code = "{{ ")]
     pub left: Span,
@@ -1193,7 +1179,7 @@ pub(crate) struct ConstGenericWithoutBracesSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::unexpected_const_param_declaration)]
+#[diag(parser_unexpected_const_param_declaration)]
 pub(crate) struct UnexpectedConstParamDeclaration {
     #[primary_span]
     #[label]
@@ -1204,7 +1190,7 @@ pub(crate) struct UnexpectedConstParamDeclaration {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum UnexpectedConstParamDeclarationSugg {
-    #[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
+    #[multipart_suggestion(suggestion, applicability = "machine-applicable")]
     AddParam {
         #[suggestion_part(code = "<{snippet}>")]
         impl_generics: Span,
@@ -1213,7 +1199,7 @@ pub(crate) enum UnexpectedConstParamDeclarationSugg {
         snippet: String,
         ident: String,
     },
-    #[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")]
+    #[multipart_suggestion(suggestion, applicability = "machine-applicable")]
     AppendParam {
         #[suggestion_part(code = ", {snippet}")]
         impl_generics_end: Span,
@@ -1225,7 +1211,7 @@ pub(crate) enum UnexpectedConstParamDeclarationSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::unexpected_const_in_generic_param)]
+#[diag(parser_unexpected_const_in_generic_param)]
 pub(crate) struct UnexpectedConstInGenericParam {
     #[primary_span]
     pub span: Span,
@@ -1234,7 +1220,7 @@ pub(crate) struct UnexpectedConstInGenericParam {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::async_move_order_incorrect)]
+#[diag(parser_async_move_order_incorrect)]
 pub(crate) struct AsyncMoveOrderIncorrect {
     #[primary_span]
     #[suggestion_verbose(code = "async move", applicability = "maybe-incorrect")]
@@ -1242,7 +1228,7 @@ pub(crate) struct AsyncMoveOrderIncorrect {
 }
 
 #[derive(Diagnostic)]
-#[diag(parser::double_colon_in_bound)]
+#[diag(parser_double_colon_in_bound)]
 pub(crate) struct DoubleColonInBound {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 88540e13ef2..462bce16ad7 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -3,7 +3,9 @@ use rustc_ast::ast::{self, AttrStyle};
 use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::util::unicode::contains_text_flow_control_chars;
-use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
+use rustc_errors::{
+    error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult, StashKey,
+};
 use rustc_lexer::unescape::{self, Mode};
 use rustc_lexer::Cursor;
 use rustc_lexer::{Base, DocStyle, RawStrError};
@@ -203,7 +205,10 @@ impl<'a> StringReader<'a> {
                     // this is necessary.
                     let lifetime_name = self.str_from(start);
                     if starts_with_number {
-                        self.err_span_(start, self.pos, "lifetimes cannot start with a number");
+                        let span = self.mk_sp(start, self.pos);
+                        let mut diag = self.sess.struct_err("lifetimes cannot start with a number");
+                        diag.set_span(span);
+                        diag.stash(span, StashKey::LifetimeIsChar);
                     }
                     let ident = Symbol::intern(lifetime_name);
                     token::Lifetime(ident)
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index 77c4fadab45..f075de71426 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -113,11 +113,26 @@ pub(crate) fn emit_unescape_error(
                 } else {
                     ("", "if you meant to write a `str` literal, use double quotes")
                 };
-
+                let mut escaped = String::with_capacity(lit.len());
+                let mut chrs = lit.chars().peekable();
+                while let Some(first) = chrs.next() {
+                    match (first, chrs.peek()) {
+                        ('\\', Some('"')) => {
+                            escaped.push('\\');
+                            escaped.push('"');
+                            chrs.next();
+                        }
+                        ('"', _) => {
+                            escaped.push('\\');
+                            escaped.push('"')
+                        }
+                        (c, _) => escaped.push(c),
+                    };
+                }
                 handler.span_suggestion(
                     span_with_quotes,
                     msg,
-                    format!("{}\"{}\"", prefix, lit),
+                    format!("{prefix}\"{escaped}\""),
                     Applicability::MachineApplicable,
                 );
             }
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index 58be348883c..9e45656946b 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -55,7 +55,7 @@ impl<'a> Parser<'a> {
                     let span = self.token.span;
                     let mut err = self.sess.span_diagnostic.struct_span_err_with_code(
                         span,
-                        fluent::parser::inner_doc_comment_not_permitted,
+                        fluent::parser_inner_doc_comment_not_permitted,
                         error_code!(E0753),
                     );
                     if let Some(replacement_span) = self.annotate_following_item_if_applicable(
@@ -66,10 +66,10 @@ impl<'a> Parser<'a> {
                             token::CommentKind::Block => OuterAttributeType::DocBlockComment,
                         },
                     ) {
-                        err.note(fluent::parser::note);
+                        err.note(fluent::note);
                         err.span_suggestion_verbose(
                             replacement_span,
-                            fluent::parser::suggestion,
+                            fluent::suggestion,
                             "",
                             rustc_errors::Applicability::MachineApplicable,
                         );
@@ -173,10 +173,10 @@ impl<'a> Parser<'a> {
             Ok(Some(item)) => {
                 // FIXME(#100717)
                 err.set_arg("item", item.kind.descr());
-                err.span_label(item.span, fluent::parser::label_does_not_annotate_this);
+                err.span_label(item.span, fluent::label_does_not_annotate_this);
                 err.span_suggestion_verbose(
                     replacement_span,
-                    fluent::parser::sugg_change_inner_to_outer,
+                    fluent::sugg_change_inner_to_outer,
                     match attr_type {
                         OuterAttributeType::Attribute => "",
                         OuterAttributeType::DocBlockComment => "*",
@@ -200,27 +200,27 @@ impl<'a> Parser<'a> {
                 Some(InnerAttrForbiddenReason::AfterOuterDocComment { prev_doc_comment_span }) => {
                     let mut diag = self.struct_span_err(
                         attr_sp,
-                        fluent::parser::inner_attr_not_permitted_after_outer_doc_comment,
+                        fluent::parser_inner_attr_not_permitted_after_outer_doc_comment,
                     );
-                    diag.span_label(attr_sp, fluent::parser::label_attr)
-                        .span_label(prev_doc_comment_span, fluent::parser::label_prev_doc_comment);
+                    diag.span_label(attr_sp, fluent::label_attr)
+                        .span_label(prev_doc_comment_span, fluent::label_prev_doc_comment);
                     diag
                 }
                 Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => {
                     let mut diag = self.struct_span_err(
                         attr_sp,
-                        fluent::parser::inner_attr_not_permitted_after_outer_attr,
+                        fluent::parser_inner_attr_not_permitted_after_outer_attr,
                     );
-                    diag.span_label(attr_sp, fluent::parser::label_attr)
-                        .span_label(prev_outer_attr_sp, fluent::parser::label_prev_attr);
+                    diag.span_label(attr_sp, fluent::label_attr)
+                        .span_label(prev_outer_attr_sp, fluent::label_prev_attr);
                     diag
                 }
                 Some(InnerAttrForbiddenReason::InCodeBlock) | None => {
-                    self.struct_span_err(attr_sp, fluent::parser::inner_attr_not_permitted)
+                    self.struct_span_err(attr_sp, fluent::parser_inner_attr_not_permitted)
                 }
             };
 
-            diag.note(fluent::parser::inner_attr_explanation);
+            diag.note(fluent::parser_inner_attr_explanation);
             if self
                 .annotate_following_item_if_applicable(
                     &mut diag,
@@ -229,7 +229,7 @@ impl<'a> Parser<'a> {
                 )
                 .is_some()
             {
-                diag.note(fluent::parser::outer_attr_explanation);
+                diag.note(fluent::parser_outer_attr_explanation);
             };
             diag.emit();
         }
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index d654d84cdd5..887a4a6de33 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -926,7 +926,7 @@ impl<'a> Parser<'a> {
                     if self.eat(&token::Gt) {
                         e.span_suggestion_verbose(
                             binop.span.shrink_to_lo(),
-                            fluent::parser::sugg_turbofish_syntax,
+                            fluent::parser_sugg_turbofish_syntax,
                             "::",
                             Applicability::MaybeIncorrect,
                         )
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index afa116ce1bc..98520a446a6 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -42,8 +42,10 @@ use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty
 use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
 use rustc_ast::{ClosureBinder, StmtKind};
 use rustc_ast_pretty::pprust;
-use rustc_errors::IntoDiagnostic;
-use rustc_errors::{Applicability, Diagnostic, PResult};
+use rustc_errors::{
+    Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult,
+    StashKey,
+};
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
 use rustc_session::lint::BuiltinLintDiagnostics;
@@ -1513,11 +1515,11 @@ impl<'a> Parser<'a> {
     /// Parse `'label: $expr`. The label is already parsed.
     fn parse_labeled_expr(
         &mut self,
-        label: Label,
+        label_: Label,
         mut consume_colon: bool,
     ) -> PResult<'a, P<Expr>> {
-        let lo = label.ident.span;
-        let label = Some(label);
+        let lo = label_.ident.span;
+        let label = Some(label_);
         let ate_colon = self.eat(&token::Colon);
         let expr = if self.eat_keyword(kw::While) {
             self.parse_while_expr(label, lo)
@@ -1530,6 +1532,19 @@ impl<'a> Parser<'a> {
         {
             self.parse_block_expr(label, lo, BlockCheckMode::Default)
         } else if !ate_colon
+            && (matches!(self.token.kind, token::CloseDelim(_) | token::Comma)
+                || self.token.is_op())
+        {
+            let lit = self.recover_unclosed_char(label_.ident, |self_| {
+                self_.sess.create_err(UnexpectedTokenAfterLabel {
+                    span: self_.token.span,
+                    remove_label: None,
+                    enclose_in_block: None,
+                })
+            });
+            consume_colon = false;
+            Ok(self.mk_expr(lo, ExprKind::Lit(lit)))
+        } else if !ate_colon
             && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
         {
             // We're probably inside of a `Path<'a>` that needs a turbofish
@@ -1603,6 +1618,39 @@ impl<'a> Parser<'a> {
         Ok(expr)
     }
 
+    /// Emit an error when a char is parsed as a lifetime because of a missing quote
+    pub(super) fn recover_unclosed_char(
+        &mut self,
+        lifetime: Ident,
+        err: impl FnOnce(&mut Self) -> DiagnosticBuilder<'a, ErrorGuaranteed>,
+    ) -> ast::Lit {
+        if let Some(mut diag) =
+            self.sess.span_diagnostic.steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar)
+        {
+            diag.span_suggestion_verbose(
+                lifetime.span.shrink_to_hi(),
+                "add `'` to close the char literal",
+                "'",
+                Applicability::MaybeIncorrect,
+            )
+            .emit();
+        } else {
+            err(self)
+                .span_suggestion_verbose(
+                    lifetime.span.shrink_to_hi(),
+                    "add `'` to close the char literal",
+                    "'",
+                    Applicability::MaybeIncorrect,
+                )
+                .emit();
+        }
+        ast::Lit {
+            token_lit: token::Lit::new(token::LitKind::Char, lifetime.name, None),
+            kind: ast::LitKind::Char(lifetime.name.as_str().chars().next().unwrap_or('_')),
+            span: lifetime.span,
+        }
+    }
+
     /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
     fn recover_do_catch(&mut self) -> PResult<'a, P<Expr>> {
         let lo = self.token.span;
@@ -1728,7 +1776,7 @@ impl<'a> Parser<'a> {
     }
 
     pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> {
-        self.parse_opt_lit().ok_or_else(|| {
+        self.parse_opt_lit().ok_or(()).or_else(|()| {
             if let token::Interpolated(inner) = &self.token.kind {
                 let expr = match inner.as_ref() {
                     token::NtExpr(expr) => Some(expr),
@@ -1740,12 +1788,22 @@ impl<'a> Parser<'a> {
                         let mut err = InvalidInterpolatedExpression { span: self.token.span }
                             .into_diagnostic(&self.sess.span_diagnostic);
                         err.downgrade_to_delayed_bug();
-                        return err;
+                        return Err(err);
                     }
                 }
             }
-            let msg = format!("unexpected token: {}", super::token_descr(&self.token));
-            self.struct_span_err(self.token.span, &msg)
+            let token = self.token.clone();
+            let err = |self_: &mut Self| {
+                let msg = format!("unexpected token: {}", super::token_descr(&token));
+                self_.struct_span_err(token.span, &msg)
+            };
+            // On an error path, eagerly consider a lifetime to be an unclosed character lit
+            if self.token.is_lifetime() {
+                let lt = self.expect_lifetime();
+                Ok(self.recover_unclosed_char(lt.ident, err))
+            } else {
+                Err(err(self))
+            }
         })
     }
 
@@ -2051,6 +2109,10 @@ impl<'a> Parser<'a> {
 
         if self.token.kind == TokenKind::Semi
             && matches!(self.token_cursor.frame.delim_sp, Some((Delimiter::Parenthesis, _)))
+            // HACK: This is needed so we can detect whether we're inside a macro,
+            // where regular assumptions about what tokens can follow other tokens
+            // don't necessarily apply.
+            && self.subparser_name.is_none()
         {
             // It is likely that the closure body is a block but where the
             // braces have been removed. We will recover and eat the next
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 56efec422d6..52c11b4e35f 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -402,6 +402,25 @@ impl<'a> Parser<'a> {
             } else {
                 PatKind::Path(qself, path)
             }
+        } else if matches!(self.token.kind, token::Lifetime(_))
+            // In pattern position, we're totally fine with using "next token isn't colon"
+            // as a heuristic. We could probably just always try to recover if it's a lifetime,
+            // because we never have `'a: label {}` in a pattern position anyways, but it does
+            // keep us from suggesting something like `let 'a: Ty = ..` => `let 'a': Ty = ..`
+            && !self.look_ahead(1, |token| matches!(token.kind, token::Colon))
+        {
+            // Recover a `'a` as a `'a'` literal
+            let lt = self.expect_lifetime();
+            let lit = self.recover_unclosed_char(lt.ident, |self_| {
+                let expected = expected.unwrap_or("pattern");
+                let msg =
+                    format!("expected {}, found {}", expected, super::token_descr(&self_.token));
+
+                let mut err = self_.struct_span_err(self_.token.span, &msg);
+                err.span_label(self_.token.span, format!("expected {}", expected));
+                err
+            });
+            PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit)))
         } else {
             // Try to parse everything else as literal with optional minus
             match self.parse_literal_maybe_minus() {
@@ -799,6 +818,7 @@ impl<'a> Parser<'a> {
                 || t.kind == token::Dot // e.g. `.5` for recovery;
                 || t.can_begin_literal_maybe_minus() // e.g. `42`.
                 || t.is_whole_expr()
+                || t.is_lifetime() // recover `'a` instead of `'a'`
             })
     }
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 3c684fffac8..b19e85427e7 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -822,8 +822,8 @@ impl CheckAttrVisitor<'_> {
             if let Some((prev_inline, prev_span)) = *specified_inline {
                 if do_inline != prev_inline {
                     let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]);
-                    spans.push_span_label(prev_span, fluent::passes::doc_inline_conflict_first);
-                    spans.push_span_label(meta.span(), fluent::passes::doc_inline_conflict_second);
+                    spans.push_span_label(prev_span, fluent::passes_doc_inline_conflict_first);
+                    spans.push_span_label(meta.span(), fluent::passes_doc_inline_conflict_second);
                     self.tcx.sess.emit_err(errors::DocKeywordConflict { spans });
                     return false;
                 }
@@ -873,7 +873,7 @@ impl CheckAttrVisitor<'_> {
                 INVALID_DOC_ATTRIBUTES,
                 hir_id,
                 meta.span(),
-                fluent::passes::attr_crate_level,
+                fluent::passes_attr_crate_level,
                 |err| {
                     if attr.style == AttrStyle::Outer
                         && self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID
@@ -882,15 +882,15 @@ impl CheckAttrVisitor<'_> {
                             src.insert(1, '!');
                             err.span_suggestion_verbose(
                                 attr.span,
-                                fluent::passes::suggestion,
+                                fluent::suggestion,
                                 src,
                                 Applicability::MaybeIncorrect,
                             );
                         } else {
-                            err.span_help(attr.span, fluent::passes::help);
+                            err.span_help(attr.span, fluent::help);
                         }
                     }
-                    err.note(fluent::passes::note);
+                    err.note(fluent::note);
                     err
                 },
             );
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index ed548341344..adaaf539242 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -13,37 +13,37 @@ use rustc_span::{Span, Symbol, DUMMY_SP};
 use crate::lang_items::Duplicate;
 
 #[derive(LintDiagnostic)]
-#[diag(passes::outer_crate_level_attr)]
+#[diag(passes_outer_crate_level_attr)]
 pub struct OuterCrateLevelAttr;
 
 #[derive(LintDiagnostic)]
-#[diag(passes::inner_crate_level_attr)]
+#[diag(passes_inner_crate_level_attr)]
 pub struct InnerCrateLevelAttr;
 
 #[derive(LintDiagnostic)]
-#[diag(passes::ignored_attr_with_macro)]
+#[diag(passes_ignored_attr_with_macro)]
 pub struct IgnoredAttrWithMacro<'a> {
     pub sym: &'a str,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::ignored_attr)]
+#[diag(passes_ignored_attr)]
 pub struct IgnoredAttr<'a> {
     pub sym: &'a str,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::inline_ignored_function_prototype)]
+#[diag(passes_inline_ignored_function_prototype)]
 pub struct IgnoredInlineAttrFnProto;
 
 #[derive(LintDiagnostic)]
-#[diag(passes::inline_ignored_constants)]
+#[diag(passes_inline_ignored_constants)]
 #[warning]
 #[note]
 pub struct IgnoredInlineAttrConstants;
 
 #[derive(Diagnostic)]
-#[diag(passes::inline_not_fn_or_closure, code = "E0518")]
+#[diag(passes_inline_not_fn_or_closure, code = "E0518")]
 pub struct InlineNotFnOrClosure {
     #[primary_span]
     pub attr_span: Span,
@@ -52,19 +52,19 @@ pub struct InlineNotFnOrClosure {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::no_coverage_ignored_function_prototype)]
+#[diag(passes_no_coverage_ignored_function_prototype)]
 pub struct IgnoredNoCoverageFnProto;
 
 #[derive(LintDiagnostic)]
-#[diag(passes::no_coverage_propagate)]
+#[diag(passes_no_coverage_propagate)]
 pub struct IgnoredNoCoveragePropagate;
 
 #[derive(LintDiagnostic)]
-#[diag(passes::no_coverage_fn_defn)]
+#[diag(passes_no_coverage_fn_defn)]
 pub struct IgnoredNoCoverageFnDefn;
 
 #[derive(Diagnostic)]
-#[diag(passes::no_coverage_not_coverable, code = "E0788")]
+#[diag(passes_no_coverage_not_coverable, code = "E0788")]
 pub struct IgnoredNoCoverageNotCoverable {
     #[primary_span]
     pub attr_span: Span,
@@ -73,7 +73,7 @@ pub struct IgnoredNoCoverageNotCoverable {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::should_be_applied_to_fn)]
+#[diag(passes_should_be_applied_to_fn)]
 pub struct AttrShouldBeAppliedToFn {
     #[primary_span]
     pub attr_span: Span,
@@ -82,14 +82,14 @@ pub struct AttrShouldBeAppliedToFn {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::naked_tracked_caller, code = "E0736")]
+#[diag(passes_naked_tracked_caller, code = "E0736")]
 pub struct NakedTrackedCaller {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::should_be_applied_to_fn, code = "E0739")]
+#[diag(passes_should_be_applied_to_fn, code = "E0739")]
 pub struct TrackedCallerWrongLocation {
     #[primary_span]
     pub attr_span: Span,
@@ -98,7 +98,7 @@ pub struct TrackedCallerWrongLocation {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::should_be_applied_to_struct_enum, code = "E0701")]
+#[diag(passes_should_be_applied_to_struct_enum, code = "E0701")]
 pub struct NonExhaustiveWrongLocation {
     #[primary_span]
     pub attr_span: Span,
@@ -107,7 +107,7 @@ pub struct NonExhaustiveWrongLocation {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::should_be_applied_to_trait)]
+#[diag(passes_should_be_applied_to_trait)]
 pub struct AttrShouldBeAppliedToTrait {
     #[primary_span]
     pub attr_span: Span,
@@ -116,11 +116,11 @@ pub struct AttrShouldBeAppliedToTrait {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::target_feature_on_statement)]
+#[diag(passes_target_feature_on_statement)]
 pub struct TargetFeatureOnStatement;
 
 #[derive(Diagnostic)]
-#[diag(passes::should_be_applied_to_static)]
+#[diag(passes_should_be_applied_to_static)]
 pub struct AttrShouldBeAppliedToStatic {
     #[primary_span]
     pub attr_span: Span,
@@ -129,7 +129,7 @@ pub struct AttrShouldBeAppliedToStatic {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_expect_str)]
+#[diag(passes_doc_expect_str)]
 pub struct DocExpectStr<'a> {
     #[primary_span]
     pub attr_span: Span,
@@ -137,7 +137,7 @@ pub struct DocExpectStr<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_alias_empty)]
+#[diag(passes_doc_alias_empty)]
 pub struct DocAliasEmpty<'a> {
     #[primary_span]
     pub span: Span,
@@ -145,7 +145,7 @@ pub struct DocAliasEmpty<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_alias_bad_char)]
+#[diag(passes_doc_alias_bad_char)]
 pub struct DocAliasBadChar<'a> {
     #[primary_span]
     pub span: Span,
@@ -154,7 +154,7 @@ pub struct DocAliasBadChar<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_alias_start_end)]
+#[diag(passes_doc_alias_start_end)]
 pub struct DocAliasStartEnd<'a> {
     #[primary_span]
     pub span: Span,
@@ -162,7 +162,7 @@ pub struct DocAliasStartEnd<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_alias_bad_location)]
+#[diag(passes_doc_alias_bad_location)]
 pub struct DocAliasBadLocation<'a> {
     #[primary_span]
     pub span: Span,
@@ -171,7 +171,7 @@ pub struct DocAliasBadLocation<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_alias_not_an_alias)]
+#[diag(passes_doc_alias_not_an_alias)]
 pub struct DocAliasNotAnAlias<'a> {
     #[primary_span]
     pub span: Span,
@@ -179,42 +179,42 @@ pub struct DocAliasNotAnAlias<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::doc_alias_duplicated)]
+#[diag(passes_doc_alias_duplicated)]
 pub struct DocAliasDuplicated {
     #[label]
     pub first_defn: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_alias_not_string_literal)]
+#[diag(passes_doc_alias_not_string_literal)]
 pub struct DocAliasNotStringLiteral {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_alias_malformed)]
+#[diag(passes_doc_alias_malformed)]
 pub struct DocAliasMalformed {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_keyword_empty_mod)]
+#[diag(passes_doc_keyword_empty_mod)]
 pub struct DocKeywordEmptyMod {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_keyword_not_mod)]
+#[diag(passes_doc_keyword_not_mod)]
 pub struct DocKeywordNotMod {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_keyword_invalid_ident)]
+#[diag(passes_doc_keyword_invalid_ident)]
 pub struct DocKeywordInvalidIdent {
     #[primary_span]
     pub span: Span,
@@ -222,21 +222,21 @@ pub struct DocKeywordInvalidIdent {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_fake_variadic_not_valid)]
+#[diag(passes_doc_fake_variadic_not_valid)]
 pub struct DocFakeVariadicNotValid {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_keyword_only_impl)]
+#[diag(passes_doc_keyword_only_impl)]
 pub struct DocKeywordOnlyImpl {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_inline_conflict)]
+#[diag(passes_doc_inline_conflict)]
 #[help]
 pub struct DocKeywordConflict {
     #[primary_span]
@@ -244,17 +244,17 @@ pub struct DocKeywordConflict {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::doc_inline_only_use)]
+#[diag(passes_doc_inline_only_use)]
 #[note]
 pub struct DocInlineOnlyUse {
     #[label]
     pub attr_span: Span,
-    #[label(passes::not_a_use_item_label)]
+    #[label(not_a_use_item_label)]
     pub item_span: Option<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::doc_attr_not_crate_level)]
+#[diag(passes_doc_attr_not_crate_level)]
 pub struct DocAttrNotCrateLevel<'a> {
     #[primary_span]
     pub span: Span,
@@ -262,33 +262,33 @@ pub struct DocAttrNotCrateLevel<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::doc_test_unknown)]
+#[diag(passes_doc_test_unknown)]
 pub struct DocTestUnknown {
     pub path: String,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::doc_test_takes_list)]
+#[diag(passes_doc_test_takes_list)]
 pub struct DocTestTakesList;
 
 #[derive(LintDiagnostic)]
-#[diag(passes::doc_cfg_hide_takes_list)]
+#[diag(passes_doc_cfg_hide_takes_list)]
 pub struct DocCfgHideTakesList;
 
 #[derive(LintDiagnostic)]
-#[diag(passes::doc_primitive)]
+#[diag(passes_doc_primitive)]
 pub struct DocPrimitive;
 
 #[derive(LintDiagnostic)]
-#[diag(passes::doc_test_unknown_any)]
+#[diag(passes_doc_test_unknown_any)]
 pub struct DocTestUnknownAny {
     pub path: String,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::doc_test_unknown_spotlight)]
+#[diag(passes_doc_test_unknown_spotlight)]
 #[note]
-#[note(passes::no_op_note)]
+#[note(no_op_note)]
 pub struct DocTestUnknownSpotlight {
     pub path: String,
     #[suggestion_short(applicability = "machine-applicable", code = "notable_trait")]
@@ -296,7 +296,7 @@ pub struct DocTestUnknownSpotlight {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::doc_test_unknown_include)]
+#[diag(passes_doc_test_unknown_include)]
 pub struct DocTestUnknownInclude {
     pub path: String,
     pub value: String,
@@ -306,11 +306,11 @@ pub struct DocTestUnknownInclude {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::doc_invalid)]
+#[diag(passes_doc_invalid)]
 pub struct DocInvalid;
 
 #[derive(Diagnostic)]
-#[diag(passes::pass_by_value)]
+#[diag(passes_pass_by_value)]
 pub struct PassByValue {
     #[primary_span]
     pub attr_span: Span,
@@ -319,7 +319,7 @@ pub struct PassByValue {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::allow_incoherent_impl)]
+#[diag(passes_allow_incoherent_impl)]
 pub struct AllowIncoherentImpl {
     #[primary_span]
     pub attr_span: Span,
@@ -328,7 +328,7 @@ pub struct AllowIncoherentImpl {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::has_incoherent_inherent_impl)]
+#[diag(passes_has_incoherent_inherent_impl)]
 pub struct HasIncoherentInherentImpl {
     #[primary_span]
     pub attr_span: Span,
@@ -337,21 +337,21 @@ pub struct HasIncoherentInherentImpl {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::must_use_async)]
+#[diag(passes_must_use_async)]
 pub struct MustUseAsync {
     #[label]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::must_use_no_effect)]
+#[diag(passes_must_use_no_effect)]
 pub struct MustUseNoEffect {
     pub article: &'static str,
     pub target: rustc_hir::Target,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::must_not_suspend)]
+#[diag(passes_must_not_suspend)]
 pub struct MustNotSuspend {
     #[primary_span]
     pub attr_span: Span,
@@ -360,7 +360,7 @@ pub struct MustNotSuspend {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::cold)]
+#[diag(passes_cold)]
 #[warning]
 pub struct Cold {
     #[label]
@@ -368,7 +368,7 @@ pub struct Cold {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::link)]
+#[diag(passes_link)]
 #[warning]
 pub struct Link {
     #[label]
@@ -376,7 +376,7 @@ pub struct Link {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::link_name)]
+#[diag(passes_link_name)]
 #[warning]
 pub struct LinkName<'a> {
     #[help]
@@ -387,7 +387,7 @@ pub struct LinkName<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::no_link)]
+#[diag(passes_no_link)]
 pub struct NoLink {
     #[primary_span]
     pub attr_span: Span,
@@ -396,7 +396,7 @@ pub struct NoLink {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::export_name)]
+#[diag(passes_export_name)]
 pub struct ExportName {
     #[primary_span]
     pub attr_span: Span,
@@ -405,7 +405,7 @@ pub struct ExportName {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::rustc_layout_scalar_valid_range_not_struct)]
+#[diag(passes_rustc_layout_scalar_valid_range_not_struct)]
 pub struct RustcLayoutScalarValidRangeNotStruct {
     #[primary_span]
     pub attr_span: Span,
@@ -414,14 +414,14 @@ pub struct RustcLayoutScalarValidRangeNotStruct {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::rustc_layout_scalar_valid_range_arg)]
+#[diag(passes_rustc_layout_scalar_valid_range_arg)]
 pub struct RustcLayoutScalarValidRangeArg {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::rustc_legacy_const_generics_only)]
+#[diag(passes_rustc_legacy_const_generics_only)]
 pub struct RustcLegacyConstGenericsOnly {
     #[primary_span]
     pub attr_span: Span,
@@ -430,7 +430,7 @@ pub struct RustcLegacyConstGenericsOnly {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::rustc_legacy_const_generics_index)]
+#[diag(passes_rustc_legacy_const_generics_index)]
 pub struct RustcLegacyConstGenericsIndex {
     #[primary_span]
     pub attr_span: Span,
@@ -439,7 +439,7 @@ pub struct RustcLegacyConstGenericsIndex {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::rustc_legacy_const_generics_index_exceed)]
+#[diag(passes_rustc_legacy_const_generics_index_exceed)]
 pub struct RustcLegacyConstGenericsIndexExceed {
     #[primary_span]
     #[label]
@@ -448,21 +448,21 @@ pub struct RustcLegacyConstGenericsIndexExceed {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::rustc_legacy_const_generics_index_negative)]
+#[diag(passes_rustc_legacy_const_generics_index_negative)]
 pub struct RustcLegacyConstGenericsIndexNegative {
     #[primary_span]
     pub invalid_args: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::rustc_dirty_clean)]
+#[diag(passes_rustc_dirty_clean)]
 pub struct RustcDirtyClean {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::link_section)]
+#[diag(passes_link_section)]
 #[warning]
 pub struct LinkSection {
     #[label]
@@ -470,7 +470,7 @@ pub struct LinkSection {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::no_mangle_foreign)]
+#[diag(passes_no_mangle_foreign)]
 #[warning]
 #[note]
 pub struct NoMangleForeign {
@@ -482,7 +482,7 @@ pub struct NoMangleForeign {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::no_mangle)]
+#[diag(passes_no_mangle)]
 #[warning]
 pub struct NoMangle {
     #[label]
@@ -490,32 +490,32 @@ pub struct NoMangle {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::repr_ident, code = "E0565")]
+#[diag(passes_repr_ident, code = "E0565")]
 pub struct ReprIdent {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::repr_conflicting, code = "E0566")]
+#[diag(passes_repr_conflicting, code = "E0566")]
 pub struct ReprConflicting;
 
 #[derive(Diagnostic)]
-#[diag(passes::used_static)]
+#[diag(passes_used_static)]
 pub struct UsedStatic {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::used_compiler_linker)]
+#[diag(passes_used_compiler_linker)]
 pub struct UsedCompilerLinker {
     #[primary_span]
     pub spans: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::allow_internal_unstable)]
+#[diag(passes_allow_internal_unstable)]
 pub struct AllowInternalUnstable {
     #[primary_span]
     pub attr_span: Span,
@@ -524,24 +524,24 @@ pub struct AllowInternalUnstable {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::debug_visualizer_placement)]
+#[diag(passes_debug_visualizer_placement)]
 pub struct DebugVisualizerPlacement {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::debug_visualizer_invalid)]
-#[note(passes::note_1)]
-#[note(passes::note_2)]
-#[note(passes::note_3)]
+#[diag(passes_debug_visualizer_invalid)]
+#[note(note_1)]
+#[note(note_2)]
+#[note(note_3)]
 pub struct DebugVisualizerInvalid {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::debug_visualizer_unreadable)]
+#[diag(passes_debug_visualizer_unreadable)]
 pub struct DebugVisualizerUnreadable<'a> {
     #[primary_span]
     pub span: Span,
@@ -550,7 +550,7 @@ pub struct DebugVisualizerUnreadable<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::rustc_allow_const_fn_unstable)]
+#[diag(passes_rustc_allow_const_fn_unstable)]
 pub struct RustcAllowConstFnUnstable {
     #[primary_span]
     pub attr_span: Span,
@@ -559,7 +559,7 @@ pub struct RustcAllowConstFnUnstable {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::rustc_std_internal_symbol)]
+#[diag(passes_rustc_std_internal_symbol)]
 pub struct RustcStdInternalSymbol {
     #[primary_span]
     pub attr_span: Span,
@@ -568,56 +568,56 @@ pub struct RustcStdInternalSymbol {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::const_trait)]
+#[diag(passes_const_trait)]
 pub struct ConstTrait {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::link_ordinal)]
+#[diag(passes_link_ordinal)]
 pub struct LinkOrdinal {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::stability_promotable)]
+#[diag(passes_stability_promotable)]
 pub struct StabilityPromotable {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::deprecated)]
+#[diag(passes_deprecated)]
 pub struct Deprecated;
 
 #[derive(LintDiagnostic)]
-#[diag(passes::macro_use)]
+#[diag(passes_macro_use)]
 pub struct MacroUse {
     pub name: Symbol,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::macro_export)]
+#[diag(passes_macro_export)]
 pub struct MacroExport;
 
 #[derive(LintDiagnostic)]
-#[diag(passes::plugin_registrar)]
+#[diag(passes_plugin_registrar)]
 pub struct PluginRegistrar;
 
 #[derive(Subdiagnostic)]
 pub enum UnusedNote {
-    #[note(passes::unused_empty_lints_note)]
+    #[note(passes_unused_empty_lints_note)]
     EmptyList { name: Symbol },
-    #[note(passes::unused_no_lints_note)]
+    #[note(passes_unused_no_lints_note)]
     NoLints { name: Symbol },
-    #[note(passes::unused_default_method_body_const_note)]
+    #[note(passes_unused_default_method_body_const_note)]
     DefaultMethodBodyConst,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::unused)]
+#[diag(passes_unused)]
 pub struct Unused {
     #[suggestion(code = "", applicability = "machine-applicable")]
     pub attr_span: Span,
@@ -626,7 +626,7 @@ pub struct Unused {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::non_exported_macro_invalid_attrs, code = "E0518")]
+#[diag(passes_non_exported_macro_invalid_attrs, code = "E0518")]
 pub struct NonExportedMacroInvalidAttrs {
     #[primary_span]
     #[label]
@@ -634,7 +634,7 @@ pub struct NonExportedMacroInvalidAttrs {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::unused_duplicate)]
+#[diag(passes_unused_duplicate)]
 pub struct UnusedDuplicate {
     #[suggestion(code = "", applicability = "machine-applicable")]
     pub this: Span,
@@ -645,7 +645,7 @@ pub struct UnusedDuplicate {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::unused_multiple)]
+#[diag(passes_unused_multiple)]
 pub struct UnusedMultiple {
     #[primary_span]
     #[suggestion(code = "", applicability = "machine-applicable")]
@@ -656,7 +656,7 @@ pub struct UnusedMultiple {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::rustc_lint_opt_ty)]
+#[diag(passes_rustc_lint_opt_ty)]
 pub struct RustcLintOptTy {
     #[primary_span]
     pub attr_span: Span,
@@ -665,7 +665,7 @@ pub struct RustcLintOptTy {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::rustc_lint_opt_deny_field_access)]
+#[diag(passes_rustc_lint_opt_deny_field_access)]
 pub struct RustcLintOptDenyFieldAccess {
     #[primary_span]
     pub attr_span: Span,
@@ -674,7 +674,7 @@ pub struct RustcLintOptDenyFieldAccess {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::collapse_debuginfo)]
+#[diag(passes_collapse_debuginfo)]
 pub struct CollapseDebuginfo {
     #[primary_span]
     pub attr_span: Span,
@@ -683,14 +683,14 @@ pub struct CollapseDebuginfo {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::deprecated_annotation_has_no_effect)]
+#[diag(passes_deprecated_annotation_has_no_effect)]
 pub struct DeprecatedAnnotationHasNoEffect {
     #[suggestion(applicability = "machine-applicable", code = "")]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::unknown_external_lang_item, code = "E0264")]
+#[diag(passes_unknown_external_lang_item, code = "E0264")]
 pub struct UnknownExternLangItem {
     #[primary_span]
     pub span: Span,
@@ -698,19 +698,19 @@ pub struct UnknownExternLangItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::missing_panic_handler)]
+#[diag(passes_missing_panic_handler)]
 pub struct MissingPanicHandler;
 
 #[derive(Diagnostic)]
-#[diag(passes::alloc_func_required)]
+#[diag(passes_alloc_func_required)]
 pub struct AllocFuncRequired;
 
 #[derive(Diagnostic)]
-#[diag(passes::missing_alloc_error_handler)]
+#[diag(passes_missing_alloc_error_handler)]
 pub struct MissingAllocErrorHandler;
 
 #[derive(Diagnostic)]
-#[diag(passes::missing_lang_item)]
+#[diag(passes_missing_lang_item)]
 #[note]
 #[help]
 pub struct MissingLangItem {
@@ -718,7 +718,7 @@ pub struct MissingLangItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::lang_item_on_incorrect_target, code = "E0718")]
+#[diag(passes_lang_item_on_incorrect_target, code = "E0718")]
 pub struct LangItemOnIncorrectTarget {
     #[primary_span]
     #[label]
@@ -729,7 +729,7 @@ pub struct LangItemOnIncorrectTarget {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::unknown_lang_item, code = "E0522")]
+#[diag(passes_unknown_lang_item, code = "E0522")]
 pub struct UnknownLangItem {
     #[primary_span]
     #[label]
@@ -748,8 +748,7 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
         self,
         handler: &'_ rustc_errors::Handler,
     ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
-        let mut diag =
-            handler.struct_err(rustc_errors::fluent::passes::invalid_attr_at_crate_level);
+        let mut diag = handler.struct_err(rustc_errors::fluent::passes_invalid_attr_at_crate_level);
         diag.set_span(self.span);
         diag.set_arg("name", self.name);
         // Only emit an error with a suggestion if we can create a string out
@@ -758,7 +757,7 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
             let replacement = src.replace("#!", "#");
             diag.span_suggestion_verbose(
                 self.span,
-                rustc_errors::fluent::passes::suggestion,
+                rustc_errors::fluent::suggestion,
                 replacement,
                 rustc_errors::Applicability::MachineApplicable,
             );
@@ -768,7 +767,7 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::duplicate_diagnostic_item)]
+#[diag(passes_duplicate_diagnostic_item)]
 pub struct DuplicateDiagnosticItem {
     #[primary_span]
     pub span: Span,
@@ -776,9 +775,9 @@ pub struct DuplicateDiagnosticItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::duplicate_diagnostic_item_in_crate)]
+#[diag(passes_duplicate_diagnostic_item_in_crate)]
 pub struct DuplicateDiagnosticItemInCrate {
-    #[note(passes::diagnostic_item_first_defined)]
+    #[note(passes_diagnostic_item_first_defined)]
     pub span: Option<Span>,
     pub orig_crate_name: Symbol,
     #[note]
@@ -788,7 +787,7 @@ pub struct DuplicateDiagnosticItemInCrate {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::abi)]
+#[diag(passes_abi)]
 pub struct Abi {
     #[primary_span]
     pub span: Span,
@@ -796,7 +795,7 @@ pub struct Abi {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::align)]
+#[diag(passes_align)]
 pub struct Align {
     #[primary_span]
     pub span: Span,
@@ -804,7 +803,7 @@ pub struct Align {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::size)]
+#[diag(passes_size)]
 pub struct Size {
     #[primary_span]
     pub span: Span,
@@ -812,7 +811,7 @@ pub struct Size {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::homogeneous_aggregate)]
+#[diag(passes_homogeneous_aggregate)]
 pub struct HomogeneousAggregate {
     #[primary_span]
     pub span: Span,
@@ -820,7 +819,7 @@ pub struct HomogeneousAggregate {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::layout_of)]
+#[diag(passes_layout_of)]
 pub struct LayoutOf {
     #[primary_span]
     pub span: Span,
@@ -829,7 +828,7 @@ pub struct LayoutOf {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::unrecognized_field)]
+#[diag(passes_unrecognized_field)]
 pub struct UnrecognizedField {
     #[primary_span]
     pub span: Span,
@@ -837,7 +836,7 @@ pub struct UnrecognizedField {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::feature_stable_twice, code = "E0711")]
+#[diag(passes_feature_stable_twice, code = "E0711")]
 pub struct FeatureStableTwice {
     #[primary_span]
     pub span: Span,
@@ -847,7 +846,7 @@ pub struct FeatureStableTwice {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::feature_previously_declared, code = "E0711")]
+#[diag(passes_feature_previously_declared, code = "E0711")]
 pub struct FeaturePreviouslyDeclared<'a, 'b> {
     #[primary_span]
     pub span: Span,
@@ -857,7 +856,7 @@ pub struct FeaturePreviouslyDeclared<'a, 'b> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::expr_not_allowed_in_context, code = "E0744")]
+#[diag(passes_expr_not_allowed_in_context, code = "E0744")]
 pub struct ExprNotAllowedInContext<'a> {
     #[primary_span]
     pub span: Span,
@@ -883,17 +882,17 @@ impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> {
     ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
         let mut diag = handler.struct_span_err_with_code(
             self.span,
-            rustc_errors::fluent::passes::break_non_loop,
+            rustc_errors::fluent::passes_break_non_loop,
             error_code!(E0571),
         );
         diag.set_arg("kind", self.kind);
-        diag.span_label(self.span, rustc_errors::fluent::passes::label);
+        diag.span_label(self.span, rustc_errors::fluent::label);
         if let Some(head) = self.head {
-            diag.span_label(head, rustc_errors::fluent::passes::label2);
+            diag.span_label(head, rustc_errors::fluent::label2);
         }
         diag.span_suggestion(
             self.span,
-            rustc_errors::fluent::passes::suggestion,
+            rustc_errors::fluent::suggestion,
             self.suggestion,
             Applicability::MaybeIncorrect,
         );
@@ -911,7 +910,7 @@ impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> {
                 _ => {
                     diag.span_suggestion(
                         self.break_expr_span,
-                        rustc_errors::fluent::passes::break_expr_suggestion,
+                        rustc_errors::fluent::break_expr_suggestion,
                         label.ident,
                         Applicability::MaybeIncorrect,
                     );
@@ -923,39 +922,39 @@ impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::continue_labeled_block, code = "E0696")]
+#[diag(passes_continue_labeled_block, code = "E0696")]
 pub struct ContinueLabeledBlock {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label(passes::block_label)]
+    #[label(block_label)]
     pub block_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::break_inside_closure, code = "E0267")]
+#[diag(passes_break_inside_closure, code = "E0267")]
 pub struct BreakInsideClosure<'a> {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label(passes::closure_label)]
+    #[label(closure_label)]
     pub closure_span: Span,
     pub name: &'a str,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::break_inside_async_block, code = "E0267")]
+#[diag(passes_break_inside_async_block, code = "E0267")]
 pub struct BreakInsideAsyncBlock<'a> {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label(passes::async_block_label)]
+    #[label(async_block_label)]
     pub closure_span: Span,
     pub name: &'a str,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::outside_loop, code = "E0268")]
+#[diag(passes_outside_loop, code = "E0268")]
 pub struct OutsideLoop<'a> {
     #[primary_span]
     #[label]
@@ -964,7 +963,7 @@ pub struct OutsideLoop<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::unlabeled_in_labeled_block, code = "E0695")]
+#[diag(passes_unlabeled_in_labeled_block, code = "E0695")]
 pub struct UnlabeledInLabeledBlock<'a> {
     #[primary_span]
     #[label]
@@ -973,7 +972,7 @@ pub struct UnlabeledInLabeledBlock<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::unlabeled_cf_in_while_condition, code = "E0590")]
+#[diag(passes_unlabeled_cf_in_while_condition, code = "E0590")]
 pub struct UnlabeledCfInWhileCondition<'a> {
     #[primary_span]
     #[label]
@@ -982,25 +981,25 @@ pub struct UnlabeledCfInWhileCondition<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::cannot_inline_naked_function)]
+#[diag(passes_cannot_inline_naked_function)]
 pub struct CannotInlineNakedFunction {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::undefined_naked_function_abi)]
+#[diag(passes_undefined_naked_function_abi)]
 pub struct UndefinedNakedFunctionAbi;
 
 #[derive(Diagnostic)]
-#[diag(passes::no_patterns)]
+#[diag(passes_no_patterns)]
 pub struct NoPatterns {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::params_not_allowed)]
+#[diag(passes_params_not_allowed)]
 #[help]
 pub struct ParamsNotAllowed {
     #[primary_span]
@@ -1020,28 +1019,28 @@ impl IntoDiagnostic<'_> for NakedFunctionsAsmBlock {
     ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
         let mut diag = handler.struct_span_err_with_code(
             self.span,
-            rustc_errors::fluent::passes::naked_functions_asm_block,
+            rustc_errors::fluent::passes_naked_functions_asm_block,
             error_code!(E0787),
         );
         for span in self.multiple_asms.iter() {
-            diag.span_label(*span, rustc_errors::fluent::passes::label_multiple_asm);
+            diag.span_label(*span, rustc_errors::fluent::label_multiple_asm);
         }
         for span in self.non_asms.iter() {
-            diag.span_label(*span, rustc_errors::fluent::passes::label_non_asm);
+            diag.span_label(*span, rustc_errors::fluent::label_non_asm);
         }
         diag
     }
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::naked_functions_operands, code = "E0787")]
+#[diag(passes_naked_functions_operands, code = "E0787")]
 pub struct NakedFunctionsOperands {
     #[primary_span]
     pub unsupported_operands: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::naked_functions_asm_options, code = "E0787")]
+#[diag(passes_naked_functions_asm_options, code = "E0787")]
 pub struct NakedFunctionsAsmOptions {
     #[primary_span]
     pub span: Span,
@@ -1049,7 +1048,7 @@ pub struct NakedFunctionsAsmOptions {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::naked_functions_must_use_noreturn, code = "E0787")]
+#[diag(passes_naked_functions_must_use_noreturn, code = "E0787")]
 pub struct NakedFunctionsMustUseNoreturn {
     #[primary_span]
     pub span: Span,
@@ -1058,7 +1057,7 @@ pub struct NakedFunctionsMustUseNoreturn {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::attr_only_on_main)]
+#[diag(passes_attr_only_on_main)]
 pub struct AttrOnlyOnMain {
     #[primary_span]
     pub span: Span,
@@ -1066,7 +1065,7 @@ pub struct AttrOnlyOnMain {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::attr_only_on_root_main)]
+#[diag(passes_attr_only_on_root_main)]
 pub struct AttrOnlyOnRootMain {
     #[primary_span]
     pub span: Span,
@@ -1074,7 +1073,7 @@ pub struct AttrOnlyOnRootMain {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::attr_only_in_functions)]
+#[diag(passes_attr_only_in_functions)]
 pub struct AttrOnlyInFunctions {
     #[primary_span]
     pub span: Span,
@@ -1082,43 +1081,43 @@ pub struct AttrOnlyInFunctions {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::multiple_rustc_main, code = "E0137")]
+#[diag(passes_multiple_rustc_main, code = "E0137")]
 pub struct MultipleRustcMain {
     #[primary_span]
     pub span: Span,
-    #[label(passes::first)]
+    #[label(first)]
     pub first: Span,
-    #[label(passes::additional)]
+    #[label(additional)]
     pub additional: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::multiple_start_functions, code = "E0138")]
+#[diag(passes_multiple_start_functions, code = "E0138")]
 pub struct MultipleStartFunctions {
     #[primary_span]
     pub span: Span,
     #[label]
     pub labeled: Span,
-    #[label(passes::previous)]
+    #[label(previous)]
     pub previous: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::extern_main)]
+#[diag(passes_extern_main)]
 pub struct ExternMain {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::unix_sigpipe_values)]
+#[diag(passes_unix_sigpipe_values)]
 pub struct UnixSigpipeValues {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::no_main_function, code = "E0601")]
+#[diag(passes_no_main_function, code = "E0601")]
 pub struct NoMainFunction {
     #[primary_span]
     pub span: Span,
@@ -1143,7 +1142,7 @@ impl<'a> IntoDiagnostic<'a> for NoMainErr {
     ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> {
         let mut diag = handler.struct_span_err_with_code(
             DUMMY_SP,
-            rustc_errors::fluent::passes::no_main_function,
+            rustc_errors::fluent::passes_no_main_function,
             error_code!(E0601),
         );
         diag.set_arg("crate_name", self.crate_name);
@@ -1151,16 +1150,16 @@ impl<'a> IntoDiagnostic<'a> for NoMainErr {
         diag.set_arg("has_filename", self.has_filename);
         let note = if !self.non_main_fns.is_empty() {
             for &span in &self.non_main_fns {
-                diag.span_note(span, rustc_errors::fluent::passes::here_is_main);
+                diag.span_note(span, rustc_errors::fluent::here_is_main);
             }
-            diag.note(rustc_errors::fluent::passes::one_or_more_possible_main);
-            diag.help(rustc_errors::fluent::passes::consider_moving_main);
+            diag.note(rustc_errors::fluent::one_or_more_possible_main);
+            diag.help(rustc_errors::fluent::consider_moving_main);
             // There were some functions named `main` though. Try to give the user a hint.
-            rustc_errors::fluent::passes::main_must_be_defined_at_crate
+            rustc_errors::fluent::main_must_be_defined_at_crate
         } else if self.has_filename {
-            rustc_errors::fluent::passes::consider_adding_main_to_file
+            rustc_errors::fluent::consider_adding_main_to_file
         } else {
-            rustc_errors::fluent::passes::consider_adding_main_at_crate
+            rustc_errors::fluent::consider_adding_main_at_crate
         };
         if self.file_empty {
             diag.note(note);
@@ -1171,11 +1170,11 @@ impl<'a> IntoDiagnostic<'a> for NoMainErr {
 
         if let Some(main_def) = self.main_def_opt && main_def.opt_fn_def_id().is_none(){
             // There is something at `crate::main`, but it is not a function definition.
-            diag.span_label(main_def.span, rustc_errors::fluent::passes::non_function_main);
+            diag.span_label(main_def.span, rustc_errors::fluent::non_function_main);
         }
 
         if self.add_teach_note {
-            diag.note(rustc_errors::fluent::passes::teach_note);
+            diag.note(rustc_errors::fluent::teach_note);
         }
         diag
     }
@@ -1203,11 +1202,11 @@ impl IntoDiagnostic<'_> for DuplicateLangItem {
     ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
         let mut diag = handler.struct_err_with_code(
             match self.duplicate {
-                Duplicate::Plain => rustc_errors::fluent::passes::duplicate_lang_item,
+                Duplicate::Plain => rustc_errors::fluent::passes_duplicate_lang_item,
 
-                Duplicate::Crate => rustc_errors::fluent::passes::duplicate_lang_item_crate,
+                Duplicate::Crate => rustc_errors::fluent::passes_duplicate_lang_item_crate,
                 Duplicate::CrateDepends => {
-                    rustc_errors::fluent::passes::duplicate_lang_item_crate_depends
+                    rustc_errors::fluent::passes_duplicate_lang_item_crate_depends
                 }
             },
             error_code!(E0152),
@@ -1223,24 +1222,24 @@ impl IntoDiagnostic<'_> for DuplicateLangItem {
             diag.set_span(span);
         }
         if let Some(span) = self.first_defined_span {
-            diag.span_note(span, rustc_errors::fluent::passes::first_defined_span);
+            diag.span_note(span, rustc_errors::fluent::first_defined_span);
         } else {
             if self.orig_dependency_of.is_empty() {
-                diag.note(rustc_errors::fluent::passes::first_defined_crate);
+                diag.note(rustc_errors::fluent::first_defined_crate);
             } else {
-                diag.note(rustc_errors::fluent::passes::first_defined_crate_depends);
+                diag.note(rustc_errors::fluent::first_defined_crate_depends);
             }
 
             if self.orig_is_local {
-                diag.note(rustc_errors::fluent::passes::first_definition_local);
+                diag.note(rustc_errors::fluent::first_definition_local);
             } else {
-                diag.note(rustc_errors::fluent::passes::first_definition_path);
+                diag.note(rustc_errors::fluent::first_definition_path);
             }
 
             if self.is_local {
-                diag.note(rustc_errors::fluent::passes::second_definition_local);
+                diag.note(rustc_errors::fluent::second_definition_local);
             } else {
-                diag.note(rustc_errors::fluent::passes::second_definition_path);
+                diag.note(rustc_errors::fluent::second_definition_path);
             }
         }
         diag
@@ -1248,7 +1247,7 @@ impl IntoDiagnostic<'_> for DuplicateLangItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::incorrect_target, code = "E0718")]
+#[diag(passes_incorrect_target, code = "E0718")]
 pub struct IncorrectTarget<'a> {
     #[primary_span]
     pub span: Span,
@@ -1262,21 +1261,21 @@ pub struct IncorrectTarget<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::useless_assignment)]
+#[diag(passes_useless_assignment)]
 pub struct UselessAssignment<'a> {
     pub is_field_assign: bool,
     pub ty: Ty<'a>,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes::only_has_effect_on)]
+#[diag(passes_only_has_effect_on)]
 pub struct OnlyHasEffectOn {
     pub attr_name: Symbol,
     pub target_name: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::object_lifetime_err)]
+#[diag(passes_object_lifetime_err)]
 pub struct ObjectLifetimeErr {
     #[primary_span]
     pub span: Span,
@@ -1284,7 +1283,7 @@ pub struct ObjectLifetimeErr {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::unrecognized_repr_hint, code = "E0552")]
+#[diag(passes_unrecognized_repr_hint, code = "E0552")]
 #[help]
 pub struct UnrecognizedReprHint {
     #[primary_span]
@@ -1293,35 +1292,35 @@ pub struct UnrecognizedReprHint {
 
 #[derive(Diagnostic)]
 pub enum AttrApplication {
-    #[diag(passes::attr_application_enum, code = "E0517")]
+    #[diag(passes_attr_application_enum, code = "E0517")]
     Enum {
         #[primary_span]
         hint_span: Span,
         #[label]
         span: Span,
     },
-    #[diag(passes::attr_application_struct, code = "E0517")]
+    #[diag(passes_attr_application_struct, code = "E0517")]
     Struct {
         #[primary_span]
         hint_span: Span,
         #[label]
         span: Span,
     },
-    #[diag(passes::attr_application_struct_union, code = "E0517")]
+    #[diag(passes_attr_application_struct_union, code = "E0517")]
     StructUnion {
         #[primary_span]
         hint_span: Span,
         #[label]
         span: Span,
     },
-    #[diag(passes::attr_application_struct_enum_union, code = "E0517")]
+    #[diag(passes_attr_application_struct_enum_union, code = "E0517")]
     StructEnumUnion {
         #[primary_span]
         hint_span: Span,
         #[label]
         span: Span,
     },
-    #[diag(passes::attr_application_struct_enum_function_union, code = "E0517")]
+    #[diag(passes_attr_application_struct_enum_function_union, code = "E0517")]
     StructEnumFunctionUnion {
         #[primary_span]
         hint_span: Span,
@@ -1331,7 +1330,7 @@ pub enum AttrApplication {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::transparent_incompatible, code = "E0692")]
+#[diag(passes_transparent_incompatible, code = "E0692")]
 pub struct TransparentIncompatible {
     #[primary_span]
     pub hint_spans: Vec<Span>,
@@ -1339,54 +1338,54 @@ pub struct TransparentIncompatible {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::deprecated_attribute, code = "E0549")]
+#[diag(passes_deprecated_attribute, code = "E0549")]
 pub struct DeprecatedAttribute {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::useless_stability)]
+#[diag(passes_useless_stability)]
 pub struct UselessStability {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label(passes::item)]
+    #[label(item)]
     pub item_sp: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::invalid_stability)]
+#[diag(passes_invalid_stability)]
 pub struct InvalidStability {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label(passes::item)]
+    #[label(item)]
     pub item_sp: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::cannot_stabilize_deprecated)]
+#[diag(passes_cannot_stabilize_deprecated)]
 pub struct CannotStabilizeDeprecated {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label(passes::item)]
+    #[label(item)]
     pub item_sp: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::invalid_deprecation_version)]
+#[diag(passes_invalid_deprecation_version)]
 pub struct InvalidDeprecationVersion {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label(passes::item)]
+    #[label(item)]
     pub item_sp: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::missing_stability_attr)]
+#[diag(passes_missing_stability_attr)]
 pub struct MissingStabilityAttr<'a> {
     #[primary_span]
     pub span: Span,
@@ -1394,7 +1393,7 @@ pub struct MissingStabilityAttr<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::missing_const_stab_attr)]
+#[diag(passes_missing_const_stab_attr)]
 pub struct MissingConstStabAttr<'a> {
     #[primary_span]
     pub span: Span,
@@ -1402,7 +1401,7 @@ pub struct MissingConstStabAttr<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::trait_impl_const_stable)]
+#[diag(passes_trait_impl_const_stable)]
 #[note]
 pub struct TraitImplConstStable {
     #[primary_span]
@@ -1410,7 +1409,7 @@ pub struct TraitImplConstStable {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::feature_only_on_nightly, code = "E0554")]
+#[diag(passes_feature_only_on_nightly, code = "E0554")]
 pub struct FeatureOnlyOnNightly {
     #[primary_span]
     pub span: Span,
@@ -1418,7 +1417,7 @@ pub struct FeatureOnlyOnNightly {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::unknown_feature, code = "E0635")]
+#[diag(passes_unknown_feature, code = "E0635")]
 pub struct UnknownFeature {
     #[primary_span]
     pub span: Span,
@@ -1426,7 +1425,7 @@ pub struct UnknownFeature {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::implied_feature_not_exist)]
+#[diag(passes_implied_feature_not_exist)]
 pub struct ImpliedFeatureNotExist {
     #[primary_span]
     pub span: Span,
@@ -1435,14 +1434,14 @@ pub struct ImpliedFeatureNotExist {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes::duplicate_feature_err, code = "E0636")]
+#[diag(passes_duplicate_feature_err, code = "E0636")]
 pub struct DuplicateFeatureErr {
     #[primary_span]
     pub span: Span,
     pub feature: Symbol,
 }
 #[derive(Diagnostic)]
-#[diag(passes::missing_const_err)]
+#[diag(passes_missing_const_err)]
 pub struct MissingConstErr {
     #[primary_span]
     #[help]
diff --git a/compiler/rustc_plugin_impl/src/errors.rs b/compiler/rustc_plugin_impl/src/errors.rs
index 07ce92a9b26..e6a7fc86bee 100644
--- a/compiler/rustc_plugin_impl/src/errors.rs
+++ b/compiler/rustc_plugin_impl/src/errors.rs
@@ -4,7 +4,7 @@ use rustc_macros::Diagnostic;
 use rustc_span::Span;
 
 #[derive(Diagnostic)]
-#[diag(plugin_impl::load_plugin_error)]
+#[diag(plugin_impl_load_plugin_error)]
 pub struct LoadPluginError {
     #[primary_span]
     pub span: Span,
@@ -12,7 +12,7 @@ pub struct LoadPluginError {
 }
 
 #[derive(Diagnostic)]
-#[diag(plugin_impl::malformed_plugin_attribute, code = "E0498")]
+#[diag(plugin_impl_malformed_plugin_attribute, code = "E0498")]
 pub struct MalformedPluginAttribute {
     #[primary_span]
     #[label]
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
index f3a617c2f0f..a6c95f1a815 100644
--- a/compiler/rustc_privacy/src/errors.rs
+++ b/compiler/rustc_privacy/src/errors.rs
@@ -3,7 +3,7 @@ use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
-#[diag(privacy::field_is_private, code = "E0451")]
+#[diag(privacy_field_is_private, code = "E0451")]
 pub struct FieldIsPrivate {
     #[primary_span]
     pub span: Span,
@@ -16,13 +16,13 @@ pub struct FieldIsPrivate {
 
 #[derive(Subdiagnostic)]
 pub enum FieldIsPrivateLabel {
-    #[label(privacy::field_is_private_is_update_syntax_label)]
+    #[label(privacy_field_is_private_is_update_syntax_label)]
     IsUpdateSyntax {
         #[primary_span]
         span: Span,
         field_name: Symbol,
     },
-    #[label(privacy::field_is_private_label)]
+    #[label(privacy_field_is_private_label)]
     Other {
         #[primary_span]
         span: Span,
@@ -30,7 +30,7 @@ pub enum FieldIsPrivateLabel {
 }
 
 #[derive(Diagnostic)]
-#[diag(privacy::item_is_private)]
+#[diag(privacy_item_is_private)]
 pub struct ItemIsPrivate<'a> {
     #[primary_span]
     #[label]
@@ -40,7 +40,7 @@ pub struct ItemIsPrivate<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(privacy::unnamed_item_is_private)]
+#[diag(privacy_unnamed_item_is_private)]
 pub struct UnnamedItemIsPrivate {
     #[primary_span]
     pub span: Span,
@@ -49,7 +49,7 @@ pub struct UnnamedItemIsPrivate {
 
 // Duplicate of `InPublicInterface` but with a different error code, shares the same slug.
 #[derive(Diagnostic)]
-#[diag(privacy::in_public_interface, code = "E0445")]
+#[diag(privacy_in_public_interface, code = "E0445")]
 pub struct InPublicInterfaceTraits<'a> {
     #[primary_span]
     #[label]
@@ -57,13 +57,13 @@ pub struct InPublicInterfaceTraits<'a> {
     pub vis_descr: &'static str,
     pub kind: &'a str,
     pub descr: DiagnosticArgFromDisplay<'a>,
-    #[label(privacy::visibility_label)]
+    #[label(visibility_label)]
     pub vis_span: Span,
 }
 
 // Duplicate of `InPublicInterfaceTraits` but with a different error code, shares the same slug.
 #[derive(Diagnostic)]
-#[diag(privacy::in_public_interface, code = "E0446")]
+#[diag(privacy_in_public_interface, code = "E0446")]
 pub struct InPublicInterface<'a> {
     #[primary_span]
     #[label]
@@ -71,12 +71,12 @@ pub struct InPublicInterface<'a> {
     pub vis_descr: &'static str,
     pub kind: &'a str,
     pub descr: DiagnosticArgFromDisplay<'a>,
-    #[label(privacy::visibility_label)]
+    #[label(visibility_label)]
     pub vis_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(privacy::report_effective_visibility)]
+#[diag(privacy_report_effective_visibility)]
 pub struct ReportEffectiveVisibility {
     #[primary_span]
     pub span: Span,
@@ -84,7 +84,7 @@ pub struct ReportEffectiveVisibility {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(privacy::from_private_dep_in_public_interface)]
+#[diag(privacy_from_private_dep_in_public_interface)]
 pub struct FromPrivateDependencyInPublicInterface<'a> {
     pub kind: &'a str,
     pub descr: DiagnosticArgFromDisplay<'a>,
@@ -92,7 +92,7 @@ pub struct FromPrivateDependencyInPublicInterface<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(privacy::private_in_public_lint)]
+#[diag(privacy_private_in_public_lint)]
 pub struct PrivateInPublicLint<'a> {
     pub vis_descr: &'static str,
     pub kind: &'a str,
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index b36b893c78e..2636db6dbe1 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -159,34 +159,12 @@ where
                 ty.visit_with(self)
             }
             ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE,
-            ty::PredicateKind::ConstEvaluatable(uv)
-                if self.def_id_visitor.tcx().features().generic_const_exprs =>
-            {
-                let tcx = self.def_id_visitor.tcx();
-                if let Ok(Some(ct)) = AbstractConst::new(tcx, uv) {
-                    self.visit_abstract_const_expr(tcx, ct)?;
-                }
-                ControlFlow::CONTINUE
-            }
+            ty::PredicateKind::ConstEvaluatable(ct) => ct.visit_with(self),
             ty::PredicateKind::WellFormed(arg) => arg.visit_with(self),
             _ => bug!("unexpected predicate: {:?}", predicate),
         }
     }
 
-    fn visit_abstract_const_expr(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        ct: AbstractConst<'tcx>,
-    ) -> ControlFlow<V::BreakTy> {
-        walk_abstract_const(tcx, ct, |node| match node.root(tcx) {
-            ACNode::Leaf(leaf) => self.visit_const(leaf),
-            ACNode::Cast(_, _, ty) => self.visit_ty(ty),
-            ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => {
-                ControlFlow::CONTINUE
-            }
-        })
-    }
-
     fn visit_predicates(
         &mut self,
         predicates: ty::GenericPredicates<'tcx>,
@@ -309,9 +287,16 @@ where
         self.visit_ty(c.ty())?;
         let tcx = self.def_id_visitor.tcx();
         if let Ok(Some(ct)) = AbstractConst::from_const(tcx, c) {
-            self.visit_abstract_const_expr(tcx, ct)?;
+            walk_abstract_const(tcx, ct, |node| match node.root(tcx) {
+                ACNode::Leaf(leaf) => self.visit_const(leaf),
+                ACNode::Cast(_, _, ty) => self.visit_ty(ty),
+                ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => {
+                    ControlFlow::CONTINUE
+                }
+            })
+        } else {
+            ControlFlow::CONTINUE
         }
-        ControlFlow::CONTINUE
     }
 }
 
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index e96ea682cae..a5921650112 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -848,6 +848,7 @@ impl_ref_decoder! {<'tcx>
     rustc_span::def_id::DefId,
     rustc_span::def_id::LocalDefId,
     (rustc_middle::middle::exported_symbols::ExportedSymbol<'tcx>, rustc_middle::middle::exported_symbols::SymbolExportInfo),
+    ty::DeducedParamAttrs,
 }
 
 //- ENCODING -------------------------------------------------------------------
diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs
index 1e74e0e2990..7a20eaceba0 100644
--- a/compiler/rustc_query_system/src/error.rs
+++ b/compiler/rustc_query_system/src/error.rs
@@ -3,7 +3,7 @@ use rustc_session::Limit;
 use rustc_span::{Span, Symbol};
 
 #[derive(Subdiagnostic)]
-#[note(query_system::cycle_stack_middle)]
+#[note(query_system_cycle_stack_middle)]
 pub struct CycleStack {
     #[primary_span]
     pub span: Span,
@@ -19,24 +19,24 @@ pub enum HandleCycleError {
 
 #[derive(Subdiagnostic)]
 pub enum StackCount {
-    #[note(query_system::cycle_stack_single)]
+    #[note(query_system_cycle_stack_single)]
     Single,
-    #[note(query_system::cycle_stack_multiple)]
+    #[note(query_system_cycle_stack_multiple)]
     Multiple,
 }
 
 #[derive(Subdiagnostic)]
 pub enum Alias {
-    #[note(query_system::cycle_recursive_ty_alias)]
-    #[help(query_system::cycle_recursive_ty_alias_help1)]
-    #[help(query_system::cycle_recursive_ty_alias_help2)]
+    #[note(query_system_cycle_recursive_ty_alias)]
+    #[help(query_system_cycle_recursive_ty_alias_help1)]
+    #[help(query_system_cycle_recursive_ty_alias_help2)]
     Ty,
-    #[note(query_system::cycle_recursive_trait_alias)]
+    #[note(query_system_cycle_recursive_trait_alias)]
     Trait,
 }
 
 #[derive(Subdiagnostic)]
-#[note(query_system::cycle_usage)]
+#[note(query_system_cycle_usage)]
 pub struct CycleUsage {
     #[primary_span]
     pub span: Span,
@@ -44,7 +44,7 @@ pub struct CycleUsage {
 }
 
 #[derive(Diagnostic)]
-#[diag(query_system::cycle, code = "E0391")]
+#[diag(query_system_cycle, code = "E0391")]
 pub struct Cycle {
     #[primary_span]
     pub span: Span,
@@ -60,14 +60,14 @@ pub struct Cycle {
 }
 
 #[derive(Diagnostic)]
-#[diag(query_system::reentrant)]
+#[diag(query_system_reentrant)]
 pub struct Reentrant;
 
 #[derive(Diagnostic)]
-#[diag(query_system::increment_compilation)]
+#[diag(query_system_increment_compilation)]
 #[help]
-#[note(query_system::increment_compilation_note1)]
-#[note(query_system::increment_compilation_note2)]
+#[note(query_system_increment_compilation_note1)]
+#[note(query_system_increment_compilation_note2)]
 pub struct IncrementCompilation {
     pub run_cmd: String,
     pub dep_node: String,
@@ -75,7 +75,7 @@ pub struct IncrementCompilation {
 
 #[derive(Diagnostic)]
 #[help]
-#[diag(query_system::query_overflow)]
+#[diag(query_system_query_overflow)]
 pub struct QueryOverflow {
     #[primary_span]
     pub span: Option<Span>,
@@ -86,7 +86,7 @@ pub struct QueryOverflow {
 }
 
 #[derive(Subdiagnostic)]
-#[note(query_system::layout_of_depth)]
+#[note(query_system_layout_of_depth)]
 pub struct LayoutOfDepth {
     pub desc: String,
     pub depth: usize,
diff --git a/compiler/rustc_resolve/src/access_levels.rs b/compiler/rustc_resolve/src/access_levels.rs
index 1cef60949d8..257784341e3 100644
--- a/compiler/rustc_resolve/src/access_levels.rs
+++ b/compiler/rustc_resolve/src/access_levels.rs
@@ -1,5 +1,4 @@
-use crate::NameBindingKind;
-use crate::Resolver;
+use crate::{ImportKind, NameBindingKind, Resolver};
 use rustc_ast::ast;
 use rustc_ast::visit;
 use rustc_ast::visit::Visitor;
@@ -45,14 +44,13 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
         let module = self.r.get_module(module_id.to_def_id()).unwrap();
         let resolutions = self.r.resolutions(module);
 
-        for (key, name_resolution) in resolutions.borrow().iter() {
+        for (_, name_resolution) in resolutions.borrow().iter() {
             if let Some(mut binding) = name_resolution.borrow().binding() && !binding.is_ambiguity() {
                 // Set the given binding access level to `AccessLevel::Public` and
                 // sets the rest of the `use` chain to `AccessLevel::Exported` until
                 // we hit the actual exported item.
 
-                // FIXME: tag and is_public() condition must be deleted,
-                // but assertion fail occurs in import_id_for_ns
+                // FIXME: tag and is_public() condition should be removed, but assertions occur.
                 let tag = if binding.is_import() { AccessLevel::Exported } else { AccessLevel::Public };
                 if binding.vis.is_public() {
                     let mut prev_parent_id = module_id;
@@ -60,16 +58,26 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
                     while let NameBindingKind::Import { binding: nested_binding, import, .. } =
                         binding.kind
                     {
-                        let id = self.r.local_def_id(self.r.import_id_for_ns(import, key.ns));
-                        self.update(
-                            id,
+                        let mut update = |node_id| self.update(
+                            self.r.local_def_id(node_id),
                             binding.vis.expect_local(),
                             prev_parent_id,
                             level,
                         );
+                        // In theory all the import IDs have individual visibilities and effective
+                        // visibilities, but in practice these IDs go straigth to HIR where all
+                        // their few uses assume that their (effective) visibility applies to the
+                        // whole syntactic `use` item. So we update them all to the maximum value
+                        // among the potential individual effective visibilities. Maybe HIR for
+                        // imports shouldn't use three IDs at all.
+                        update(import.id);
+                        if let ImportKind::Single { additional_ids, .. } = import.kind {
+                            update(additional_ids.0);
+                            update(additional_ids.1);
+                        }
 
                         level = AccessLevel::Exported;
-                        prev_parent_id = id;
+                        prev_parent_id = self.r.local_def_id(import.id);
                         binding = nested_binding;
                     }
                 }
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 0a86374d76d..f2cc50c199f 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -2,7 +2,7 @@
 
 use crate::diagnostics::{import_candidates, Suggestion};
 use crate::Determinacy::{self, *};
-use crate::Namespace::{self, *};
+use crate::Namespace::*;
 use crate::{module_to_string, names_to_string, ImportSuggestion};
 use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment};
 use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet};
@@ -371,31 +371,6 @@ impl<'a> Resolver<'a> {
             self.used_imports.insert(import.id);
         }
     }
-
-    /// Take primary and additional node IDs from an import and select one that corresponds to the
-    /// given namespace. The logic must match the corresponding logic from `fn lower_use_tree` that
-    /// assigns resolutons to IDs.
-    pub(crate) fn import_id_for_ns(&self, import: &Import<'_>, ns: Namespace) -> NodeId {
-        if let ImportKind::Single { additional_ids: (id1, id2), .. } = import.kind {
-            if let Some(resolutions) = self.import_res_map.get(&import.id) {
-                assert!(resolutions[ns].is_some(), "incorrectly finalized import");
-                return match ns {
-                    TypeNS => import.id,
-                    ValueNS => match resolutions.type_ns {
-                        Some(_) => id1,
-                        None => import.id,
-                    },
-                    MacroNS => match (resolutions.type_ns, resolutions.value_ns) {
-                        (Some(_), Some(_)) => id2,
-                        (Some(_), None) | (None, Some(_)) => id1,
-                        (None, None) => import.id,
-                    },
-                };
-            }
-        }
-
-        import.id
-    }
 }
 
 /// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index ba3d8f64bbc..58853346a92 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -524,6 +524,9 @@ struct DiagnosticMetadata<'ast> {
     /// Used to detect possible `if let` written without `let` and to provide structured suggestion.
     in_if_condition: Option<&'ast Expr>,
 
+    /// Used to detect possible new binding written without `let` and to provide structured suggestion.
+    in_assignment: Option<&'ast Expr>,
+
     /// If we are currently in a trait object definition. Used to point at the bounds when
     /// encountering a struct or enum.
     current_trait_object: Option<&'ast [ast::GenericBound]>,
@@ -3905,6 +3908,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 self.resolve_expr(elem, Some(expr));
                 self.visit_expr(idx);
             }
+            ExprKind::Assign(..) => {
+                let old = self.diagnostic_metadata.in_assignment.replace(expr);
+                visit::walk_expr(self, expr);
+                self.diagnostic_metadata.in_assignment = old;
+            }
             _ => {
                 visit::walk_expr(self, expr);
             }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index e3dba2366a4..23c5fac8b71 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -708,7 +708,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
 
             // If the trait has a single item (which wasn't matched by Levenshtein), suggest it
             let suggestion = self.get_single_associated_item(&path, &source, is_expected);
-            self.r.add_typo_suggestion(err, suggestion, ident_span);
+            if !self.r.add_typo_suggestion(err, suggestion, ident_span) {
+                fallback = !self.let_binding_suggestion(err, ident_span);
+            }
         }
         fallback
     }
@@ -1105,41 +1107,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         // where a brace being opened means a block is being started. Look
         // ahead for the next text to see if `span` is followed by a `{`.
         let sm = self.r.session.source_map();
-        let mut sp = span;
-        loop {
-            sp = sm.next_point(sp);
-            match sm.span_to_snippet(sp) {
-                Ok(ref snippet) => {
-                    if snippet.chars().any(|c| !c.is_whitespace()) {
-                        break;
-                    }
-                }
-                _ => break,
-            }
-        }
+        let sp = sm.span_look_ahead(span, None, Some(50));
         let followed_by_brace = matches!(sm.span_to_snippet(sp), Ok(ref snippet) if snippet == "{");
         // In case this could be a struct literal that needs to be surrounded
         // by parentheses, find the appropriate span.
-        let mut i = 0;
-        let mut closing_brace = None;
-        loop {
-            sp = sm.next_point(sp);
-            match sm.span_to_snippet(sp) {
-                Ok(ref snippet) => {
-                    if snippet == "}" {
-                        closing_brace = Some(span.to(sp));
-                        break;
-                    }
-                }
-                _ => break,
-            }
-            i += 1;
-            // The bigger the span, the more likely we're incorrect --
-            // bound it to 100 chars long.
-            if i > 100 {
-                break;
-            }
-        }
+        let closing_span = sm.span_look_ahead(span, Some("}"), Some(50));
+        let closing_brace: Option<Span> = sm
+            .span_to_snippet(closing_span)
+            .map_or(None, |s| if s == "}" { Some(span.to(closing_span)) } else { None });
         (followed_by_brace, closing_brace)
     }
 
@@ -1779,26 +1754,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                             }
                         }
                         if let Ok(base_snippet) = base_snippet {
-                            let mut sp = after_colon_sp;
-                            for _ in 0..100 {
-                                // Try to find an assignment
-                                sp = sm.next_point(sp);
-                                let snippet = sm.span_to_snippet(sp);
-                                match snippet {
-                                    Ok(ref x) if x.as_str() == "=" => {
-                                        err.span_suggestion(
-                                            base_span,
-                                            "maybe you meant to write an assignment here",
-                                            format!("let {}", base_snippet),
-                                            Applicability::MaybeIncorrect,
-                                        );
-                                        show_label = false;
-                                        break;
-                                    }
-                                    Ok(ref x) if x.as_str() == "\n" => break,
-                                    Err(_) => break,
-                                    Ok(_) => {}
-                                }
+                            // Try to find an assignment
+                            let eq_span = sm.span_look_ahead(after_colon_sp, Some("="), Some(50));
+                            if let Ok(ref snippet) = sm.span_to_snippet(eq_span) && snippet == "=" {
+                                err.span_suggestion(
+                                    base_span,
+                                    "maybe you meant to write an assignment here",
+                                    format!("let {}", base_snippet),
+                                    Applicability::MaybeIncorrect,
+                                );
+                                show_label = false;
                             }
                         }
                     }
@@ -1815,6 +1780,31 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         false
     }
 
+    fn let_binding_suggestion(&self, err: &mut Diagnostic, ident_span: Span) -> bool {
+        // try to give a suggestion for this pattern: `name = 1`, which is common in other languages
+        let mut added_suggestion = false;
+        if let Some(Expr { kind: ExprKind::Assign(lhs, _rhs, _), .. }) = self.diagnostic_metadata.in_assignment &&
+            let ast::ExprKind::Path(None, _) = lhs.kind {
+                let sm = self.r.session.source_map();
+                let line_span = sm.span_extend_to_line(ident_span);
+                let ident_name = sm.span_to_snippet(ident_span).unwrap();
+                // HACK(chenyukang): make sure ident_name is at the starting of the line to protect against macros
+                if sm
+                    .span_to_snippet(line_span)
+                    .map_or(false, |s| s.trim().starts_with(&ident_name))
+                {
+                    err.span_suggestion_verbose(
+                        ident_span.shrink_to_lo(),
+                        "you might have meant to introduce a new binding",
+                        "let ".to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
+                    added_suggestion = true;
+                }
+            }
+        added_suggestion
+    }
+
     fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> {
         let mut result = None;
         let mut seen_modules = FxHashSet::default();
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index f6f0b3c1139..9526296f951 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -12,7 +12,7 @@ use rustc_attr::StabilityLevel;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::struct_span_err;
+use rustc_errors::{struct_span_err, Applicability};
 use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand};
 use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
 use rustc_expand::compile_declarative_macro;
@@ -694,7 +694,19 @@ impl<'a> Resolver<'a> {
                     check_consistency(self, &path, path_span, kind, initial_res, res)
                 }
                 path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed { .. } => {
+                    let mut suggestion = None;
                     let (span, label) = if let PathResult::Failed { span, label, .. } = path_res {
+                        // try to suggest if it's not a macro, maybe a function
+                        if let PathResult::NonModule(partial_res) = self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope)
+                            && partial_res.unresolved_segments() == 0 {
+                            let sm = self.session.source_map();
+                            let exclamation_span = sm.next_point(span);
+                            suggestion = Some((
+                                vec![(exclamation_span, "".to_string())],
+                                    format!("{} is not a macro, but a {}, try to remove `!`", Segment::names_to_string(&path), partial_res.base_res().descr()),
+                                    Applicability::MaybeIncorrect
+                                ));
+                        }
                         (span, label)
                     } else {
                         (
@@ -708,7 +720,7 @@ impl<'a> Resolver<'a> {
                     };
                     self.report_error(
                         span,
-                        ResolutionError::FailedToResolve { label, suggestion: None },
+                        ResolutionError::FailedToResolve { label, suggestion },
                     );
                 }
                 PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
diff --git a/compiler/rustc_save_analysis/src/errors.rs b/compiler/rustc_save_analysis/src/errors.rs
index 8a15ba63661..585aac8c1c3 100644
--- a/compiler/rustc_save_analysis/src/errors.rs
+++ b/compiler/rustc_save_analysis/src/errors.rs
@@ -3,7 +3,7 @@ use rustc_macros::Diagnostic;
 use std::path::Path;
 
 #[derive(Diagnostic)]
-#[diag(save_analysis::could_not_open)]
+#[diag(save_analysis_could_not_open)]
 pub(crate) struct CouldNotOpen<'a> {
     pub file_name: &'a Path,
     pub err: std::io::Error,
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 500ab4a584c..bf542faec41 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -7,7 +7,7 @@ use rustc_span::{Span, Symbol};
 use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
 
 #[derive(Diagnostic)]
-#[diag(session::incorrect_cgu_reuse_type)]
+#[diag(session_incorrect_cgu_reuse_type)]
 pub struct IncorrectCguReuseType<'a> {
     #[primary_span]
     pub span: Span,
@@ -18,14 +18,14 @@ pub struct IncorrectCguReuseType<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(session::cgu_not_recorded)]
+#[diag(session_cgu_not_recorded)]
 pub struct CguNotRecorded<'a> {
     pub cgu_user_name: &'a str,
     pub cgu_name: &'a str,
 }
 
 #[derive(Diagnostic)]
-#[diag(session::feature_gate_error, code = "E0658")]
+#[diag(session_feature_gate_error, code = "E0658")]
 pub struct FeatureGateError<'a> {
     #[primary_span]
     pub span: MultiSpan,
@@ -33,99 +33,99 @@ pub struct FeatureGateError<'a> {
 }
 
 #[derive(Subdiagnostic)]
-#[note(session::feature_diagnostic_for_issue)]
+#[note(session_feature_diagnostic_for_issue)]
 pub struct FeatureDiagnosticForIssue {
     pub n: NonZeroU32,
 }
 
 #[derive(Subdiagnostic)]
-#[help(session::feature_diagnostic_help)]
+#[help(session_feature_diagnostic_help)]
 pub struct FeatureDiagnosticHelp {
     pub feature: Symbol,
 }
 
 #[derive(Diagnostic)]
-#[diag(session::not_circumvent_feature)]
+#[diag(session_not_circumvent_feature)]
 pub struct NotCircumventFeature;
 
 #[derive(Diagnostic)]
-#[diag(session::linker_plugin_lto_windows_not_supported)]
+#[diag(session_linker_plugin_lto_windows_not_supported)]
 pub struct LinkerPluginToWindowsNotSupported;
 
 #[derive(Diagnostic)]
-#[diag(session::profile_use_file_does_not_exist)]
+#[diag(session_profile_use_file_does_not_exist)]
 pub struct ProfileUseFileDoesNotExist<'a> {
     pub path: &'a std::path::Path,
 }
 
 #[derive(Diagnostic)]
-#[diag(session::profile_sample_use_file_does_not_exist)]
+#[diag(session_profile_sample_use_file_does_not_exist)]
 pub struct ProfileSampleUseFileDoesNotExist<'a> {
     pub path: &'a std::path::Path,
 }
 
 #[derive(Diagnostic)]
-#[diag(session::target_requires_unwind_tables)]
+#[diag(session_target_requires_unwind_tables)]
 pub struct TargetRequiresUnwindTables;
 
 #[derive(Diagnostic)]
-#[diag(session::sanitizer_not_supported)]
+#[diag(session_sanitizer_not_supported)]
 pub struct SanitizerNotSupported {
     pub us: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(session::sanitizers_not_supported)]
+#[diag(session_sanitizers_not_supported)]
 pub struct SanitizersNotSupported {
     pub us: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(session::cannot_mix_and_match_sanitizers)]
+#[diag(session_cannot_mix_and_match_sanitizers)]
 pub struct CannotMixAndMatchSanitizers {
     pub first: String,
     pub second: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(session::cannot_enable_crt_static_linux)]
+#[diag(session_cannot_enable_crt_static_linux)]
 pub struct CannotEnableCrtStaticLinux;
 
 #[derive(Diagnostic)]
-#[diag(session::sanitizer_cfi_enabled)]
+#[diag(session_sanitizer_cfi_enabled)]
 pub struct SanitizerCfiEnabled;
 
 #[derive(Diagnostic)]
-#[diag(session::unstable_virtual_function_elimination)]
+#[diag(session_unstable_virtual_function_elimination)]
 pub struct UnstableVirtualFunctionElimination;
 
 #[derive(Diagnostic)]
-#[diag(session::unsupported_dwarf_version)]
+#[diag(session_unsupported_dwarf_version)]
 pub struct UnsupportedDwarfVersion {
     pub dwarf_version: u32,
 }
 
 #[derive(Diagnostic)]
-#[diag(session::target_stack_protector_not_supported)]
+#[diag(session_target_stack_protector_not_supported)]
 pub struct StackProtectorNotSupportedForTarget<'a> {
     pub stack_protector: StackProtector,
     pub target_triple: &'a TargetTriple,
 }
 
 #[derive(Diagnostic)]
-#[diag(session::split_debuginfo_unstable_platform)]
+#[diag(session_split_debuginfo_unstable_platform)]
 pub struct SplitDebugInfoUnstablePlatform {
     pub debuginfo: SplitDebuginfo,
 }
 
 #[derive(Diagnostic)]
-#[diag(session::file_is_not_writeable)]
+#[diag(session_file_is_not_writeable)]
 pub struct FileIsNotWriteable<'a> {
     pub file: &'a std::path::Path,
 }
 
 #[derive(Diagnostic)]
-#[diag(session::crate_name_does_not_match)]
+#[diag(session_crate_name_does_not_match)]
 pub struct CrateNameDoesNotMatch<'a> {
     #[primary_span]
     pub span: Span,
@@ -134,20 +134,20 @@ pub struct CrateNameDoesNotMatch<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(session::crate_name_invalid)]
+#[diag(session_crate_name_invalid)]
 pub struct CrateNameInvalid<'a> {
     pub s: &'a str,
 }
 
 #[derive(Diagnostic)]
-#[diag(session::crate_name_empty)]
+#[diag(session_crate_name_empty)]
 pub struct CrateNameEmpty {
     #[primary_span]
     pub span: Option<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(session::invalid_character_in_create_name)]
+#[diag(session_invalid_character_in_create_name)]
 pub struct InvalidCharacterInCrateName<'a> {
     #[primary_span]
     pub span: Option<Span>,
@@ -156,7 +156,7 @@ pub struct InvalidCharacterInCrateName<'a> {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(session::expr_parentheses_needed, applicability = "machine-applicable")]
+#[multipart_suggestion(session_expr_parentheses_needed, applicability = "machine-applicable")]
 pub struct ExprParenthesesNeeded {
     #[suggestion_part(code = "(")]
     pub left: Span,
@@ -171,7 +171,7 @@ impl ExprParenthesesNeeded {
 }
 
 #[derive(Diagnostic)]
-#[diag(session::skipping_const_checks)]
+#[diag(session_skipping_const_checks)]
 pub struct SkippingConstChecks {
     #[subdiagnostic(eager)]
     pub unleashed_features: Vec<UnleashedFeatureHelp>,
@@ -179,13 +179,13 @@ pub struct SkippingConstChecks {
 
 #[derive(Subdiagnostic)]
 pub enum UnleashedFeatureHelp {
-    #[help(session::unleashed_feature_help_named)]
+    #[help(session_unleashed_feature_help_named)]
     Named {
         #[primary_span]
         span: Span,
         gate: Symbol,
     },
-    #[help(session::unleashed_feature_help_unnamed)]
+    #[help(session_unleashed_feature_help_unnamed)]
     Unnamed {
         #[primary_span]
         span: Span,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index a8be318dea8..3f234a47a3d 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1295,6 +1295,8 @@ options! {
         an additional `.html` file showing the computed coverage spans."),
     dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
         "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
+    dylib_lto: bool = (false, parse_bool, [UNTRACKED],
+        "enables LTO for dylib crate type"),
     emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
         "emit a section containing stack size metadata (default: no)"),
     emit_thin_lto: bool = (true, parse_bool, [TRACKED],
diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs
index 9a4f6f9f9ef..e65b6891e32 100644
--- a/compiler/rustc_session/src/utils.rs
+++ b/compiler/rustc_session/src/utils.rs
@@ -53,6 +53,17 @@ impl NativeLibKind {
             NativeLibKind::RawDylib | NativeLibKind::Unspecified | NativeLibKind::LinkArg => false,
         }
     }
+
+    pub fn is_statically_included(&self) -> bool {
+        matches!(self, NativeLibKind::Static { .. })
+    }
+
+    pub fn is_dllimport(&self) -> bool {
+        matches!(
+            self,
+            NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified
+        )
+    }
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 91eef647713..842aa98bc9e 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -1631,10 +1631,7 @@ impl SourceFile {
     /// number. If the source_file is empty or the position is located before the
     /// first line, `None` is returned.
     pub fn lookup_line(&self, pos: BytePos) -> Option<usize> {
-        self.lines(|lines| match lines.partition_point(|x| x <= &pos) {
-            0 => None,
-            i => Some(i - 1),
-        })
+        self.lines(|lines| lines.partition_point(|x| x <= &pos).checked_sub(1))
     }
 
     pub fn line_bounds(&self, line_index: usize) -> Range<BytePos> {
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 506ce6955d3..f9566eeee94 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -877,6 +877,26 @@ impl SourceMap {
         Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt(), None)
     }
 
+    /// Returns a new span to check next none-whitespace character or some specified expected character
+    /// If `expect` is none, the first span of non-whitespace character is returned.
+    /// If `expect` presented, the first span of the character `expect` is returned
+    /// Otherwise, the span reached to limit is returned.
+    pub fn span_look_ahead(&self, span: Span, expect: Option<&str>, limit: Option<usize>) -> Span {
+        let mut sp = span;
+        for _ in 0..limit.unwrap_or(100 as usize) {
+            sp = self.next_point(sp);
+            if let Ok(ref snippet) = self.span_to_snippet(sp) {
+                if expect.map_or(false, |es| snippet == es) {
+                    break;
+                }
+                if expect.is_none() && snippet.chars().any(|c| !c.is_whitespace()) {
+                    break;
+                }
+            }
+        }
+        sp
+    }
+
     /// Finds the width of the character, either before or after the end of provided span,
     /// depending on the `forwards` parameter.
     fn find_width_of_character_at_span(&self, sp: Span, forwards: bool) -> u32 {
diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs
index eb487a03c93..f4d0751f753 100644
--- a/compiler/rustc_symbol_mangling/src/errors.rs
+++ b/compiler/rustc_symbol_mangling/src/errors.rs
@@ -5,7 +5,7 @@ use rustc_macros::Diagnostic;
 use rustc_span::Span;
 
 #[derive(Diagnostic)]
-#[diag(symbol_mangling::test_output)]
+#[diag(symbol_mangling_test_output)]
 pub struct TestOutput {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 61793468594..7f870582444 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -5,7 +5,7 @@ use rustc_session::Limit;
 use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
-#[diag(trait_selection::dump_vtable_entries)]
+#[diag(trait_selection_dump_vtable_entries)]
 pub struct DumpVTableEntries<'a> {
     #[primary_span]
     pub span: Span,
@@ -14,7 +14,7 @@ pub struct DumpVTableEntries<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(trait_selection::unable_to_construct_constant_value)]
+#[diag(trait_selection_unable_to_construct_constant_value)]
 pub struct UnableToConstructConstantValue<'a> {
     #[primary_span]
     pub span: Span,
@@ -23,7 +23,7 @@ pub struct UnableToConstructConstantValue<'a> {
 
 #[derive(Diagnostic)]
 #[help]
-#[diag(trait_selection::auto_deref_reached_recursion_limit, code = "E0055")]
+#[diag(trait_selection_auto_deref_reached_recursion_limit, code = "E0055")]
 pub struct AutoDerefReachedRecursionLimit<'a> {
     #[primary_span]
     #[label]
@@ -34,7 +34,7 @@ pub struct AutoDerefReachedRecursionLimit<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(trait_selection::empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
+#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
 pub struct EmptyOnClauseInOnUnimplemented {
     #[primary_span]
     #[label]
@@ -42,7 +42,7 @@ pub struct EmptyOnClauseInOnUnimplemented {
 }
 
 #[derive(Diagnostic)]
-#[diag(trait_selection::invalid_on_clause_in_rustc_on_unimplemented, code = "E0232")]
+#[diag(trait_selection_invalid_on_clause_in_rustc_on_unimplemented, code = "E0232")]
 pub struct InvalidOnClauseInOnUnimplemented {
     #[primary_span]
     #[label]
@@ -50,7 +50,7 @@ pub struct InvalidOnClauseInOnUnimplemented {
 }
 
 #[derive(Diagnostic)]
-#[diag(trait_selection::no_value_in_rustc_on_unimplemented, code = "E0232")]
+#[diag(trait_selection_no_value_in_rustc_on_unimplemented, code = "E0232")]
 #[note]
 pub struct NoValueInOnUnimplemented {
     #[primary_span]
@@ -71,7 +71,7 @@ impl IntoDiagnostic<'_> for NegativePositiveConflict<'_> {
         self,
         handler: &Handler,
     ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
-        let mut diag = handler.struct_err(fluent::trait_selection::negative_positive_conflict);
+        let mut diag = handler.struct_err(fluent::trait_selection_negative_positive_conflict);
         diag.set_arg("trait_desc", self.trait_desc);
         diag.set_arg(
             "self_desc",
@@ -81,19 +81,19 @@ impl IntoDiagnostic<'_> for NegativePositiveConflict<'_> {
         diag.code(rustc_errors::error_code!(E0751));
         match self.negative_impl_span {
             Ok(span) => {
-                diag.span_label(span, fluent::trait_selection::negative_implementation_here);
+                diag.span_label(span, fluent::negative_implementation_here);
             }
             Err(cname) => {
-                diag.note(fluent::trait_selection::negative_implementation_in_crate);
+                diag.note(fluent::negative_implementation_in_crate);
                 diag.set_arg("negative_impl_cname", cname.to_string());
             }
         }
         match self.positive_impl_span {
             Ok(span) => {
-                diag.span_label(span, fluent::trait_selection::positive_implementation_here);
+                diag.span_label(span, fluent::positive_implementation_here);
             }
             Err(cname) => {
-                diag.note(fluent::trait_selection::positive_implementation_in_crate);
+                diag.note(fluent::positive_implementation_in_crate);
                 diag.set_arg("positive_impl_cname", cname.to_string());
             }
         }
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index b06f24ddf2e..84038625fb2 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -9,14 +9,12 @@
 //! `thir_abstract_const` which can then be checked for structural equality with other
 //! generic constants mentioned in the `caller_bounds` of the current environment.
 use rustc_errors::ErrorGuaranteed;
-use rustc_hir::def::DefKind;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::abstract_const::{
     walk_abstract_const, AbstractConst, FailureKind, Node, NotConstEvaluatable,
 };
 use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
-use rustc_session::lint;
 use rustc_span::Span;
 
 use std::iter;
@@ -161,11 +159,20 @@ pub fn try_unify_abstract_consts<'tcx>(
 #[instrument(skip(infcx), level = "debug")]
 pub fn is_const_evaluatable<'tcx>(
     infcx: &InferCtxt<'tcx>,
-    uv: ty::UnevaluatedConst<'tcx>,
+    ct: ty::Const<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     span: Span,
 ) -> Result<(), NotConstEvaluatable> {
     let tcx = infcx.tcx;
+    let uv = match ct.kind() {
+        ty::ConstKind::Unevaluated(uv) => uv,
+        ty::ConstKind::Param(_)
+        | ty::ConstKind::Bound(_, _)
+        | ty::ConstKind::Placeholder(_)
+        | ty::ConstKind::Value(_)
+        | ty::ConstKind::Error(_) => return Ok(()),
+        ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
+    };
 
     if tcx.features().generic_const_exprs {
         if let Some(ct) = AbstractConst::new(tcx, uv)? {
@@ -253,25 +260,7 @@ pub fn is_const_evaluatable<'tcx>(
                 Err(NotConstEvaluatable::Error(reported))
             }
             Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
-            Ok(_) => {
-                if uv.substs.has_non_region_param() {
-                    assert!(matches!(infcx.tcx.def_kind(uv.def.did), DefKind::AnonConst));
-                    let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
-
-                    if mir_body.is_polymorphic {
-                        let Some(local_def_id) = uv.def.did.as_local() else { return Ok(()) };
-                        tcx.struct_span_lint_hir(
-                            lint::builtin::CONST_EVALUATABLE_UNCHECKED,
-                            tcx.hir().local_def_id_to_hir_id(local_def_id),
-                            span,
-                            "cannot use constants which depend on generic parameters in types",
-                            |err| err
-                        )
-                    }
-                }
-
-                Ok(())
-            },
+            Ok(_) => Ok(()),
         }
     }
 }
@@ -285,7 +274,7 @@ fn satisfied_from_param_env<'tcx>(
     for pred in param_env.caller_bounds() {
         match pred.kind().skip_binder() {
             ty::PredicateKind::ConstEvaluatable(uv) => {
-                if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
+                if let Some(b_ct) = AbstractConst::from_const(tcx, uv)? {
                     let const_unify_ctxt = ConstUnifyCtxt { tcx, param_env };
 
                     // Try to unify with each subtree in the AbstractConst to allow for
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index b7e6a564f39..1217d264a9c 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -764,6 +764,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty);
                         }
 
+                        let mut unsatisfied_const = false;
                         if trait_predicate.is_const_if_const() && obligation.param_env.is_const() {
                             let non_const_predicate = trait_ref.without_const();
                             let non_const_obligation = Obligation {
@@ -773,6 +774,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 recursion_depth: obligation.recursion_depth,
                             };
                             if self.predicate_may_hold(&non_const_obligation) {
+                                unsatisfied_const = true;
                                 err.span_note(
                                     span,
                                     &format!(
@@ -924,7 +926,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 }
                             }
                         } else if !trait_ref.has_non_region_infer()
-                            && self.predicate_can_apply(obligation.param_env, trait_ref)
+                            && self.predicate_can_apply(obligation.param_env, trait_predicate)
                         {
                             // If a where-clause may be useful, remind the
                             // user that they can add it.
@@ -939,7 +941,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 None,
                                 obligation.cause.body_id,
                             );
-                        } else if !suggested {
+                        } else if !suggested && !unsatisfied_const {
                             // Can't show anything else useful, try to find similar impls.
                             let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
                             if !self.report_similar_impl_candidates(
@@ -1304,7 +1306,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
 
                 match obligation.predicate.kind().skip_binder() {
-                    ty::PredicateKind::ConstEvaluatable(uv) => {
+                    ty::PredicateKind::ConstEvaluatable(ct) => {
+                        let ty::ConstKind::Unevaluated(uv) = ct.kind() else {
+                            bug!("const evaluatable failed for non-unevaluated const `{ct:?}`");
+                        };
                         let mut err =
                             self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
                         let const_span = self.tcx.def_span(uv.def.did);
@@ -1433,7 +1438,7 @@ trait InferCtxtPrivExt<'tcx> {
     fn predicate_can_apply(
         &self,
         param_env: ty::ParamEnv<'tcx>,
-        pred: ty::PolyTraitRef<'tcx>,
+        pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool;
 
     fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>);
@@ -2368,7 +2373,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 if predicate.references_error() || self.is_tainted_by_errors() {
                     return;
                 }
-                let subst = data.substs.iter().find(|g| g.has_non_region_infer());
+                let subst = data.walk().find(|g| g.is_non_region_infer());
                 if let Some(subst) = subst {
                     let err = self.emit_inference_failure_err(
                         body_id,
@@ -2508,7 +2513,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     fn predicate_can_apply(
         &self,
         param_env: ty::ParamEnv<'tcx>,
-        pred: ty::PolyTraitRef<'tcx>,
+        pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
         struct ParamToVarFolder<'a, 'tcx> {
             infcx: &'a InferCtxt<'tcx>,
@@ -2552,7 +2557,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             let obligation = Obligation::new(
                 ObligationCause::dummy(),
                 param_env,
-                cleaned_pred.without_const().to_predicate(selcx.tcx()),
+                cleaned_pred.to_predicate(selcx.tcx()),
             );
 
             self.predicate_may_hold(&obligation)
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index d4c73427386..a417e1440b9 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -476,9 +476,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         Err(NotConstEvaluatable::MentionsInfer) => {
                             pending_obligation.stalled_on.clear();
                             pending_obligation.stalled_on.extend(
-                                uv.substs
-                                    .iter()
-                                    .filter_map(TyOrConstInferVar::maybe_from_generic_arg),
+                                uv.walk().filter_map(TyOrConstInferVar::maybe_from_generic_arg),
                             );
                             ProcessResult::Unchanged
                         }
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 545524f63a7..0bb25a74dc8 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -837,24 +837,14 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
             }
         }
 
-        fn visit_ty_unevaluated(
-            &mut self,
-            uv: ty::UnevaluatedConst<'tcx>,
-        ) -> ControlFlow<Self::BreakTy> {
+        fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
             // Constants can only influence object safety if they reference `Self`.
             // This is only possible for unevaluated constants, so we walk these here.
             //
-            // If `AbstractConst::new` returned an error we already failed compilation
+            // If `AbstractConst::from_const` returned an error we already failed compilation
             // so we don't have to emit an additional error here.
-            //
-            // We currently recurse into abstract consts here but do not recurse in
-            // `is_const_evaluatable`. This means that the object safety check is more
-            // liberal than the const eval check.
-            //
-            // This shouldn't really matter though as we can't really use any
-            // constants which are not considered const evaluatable.
             use rustc_middle::ty::abstract_const::Node;
-            if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv) {
+            if let Ok(Some(ct)) = AbstractConst::from_const(self.tcx, ct) {
                 walk_abstract_const(self.tcx, ct, |node| match node.root(self.tcx) {
                     Node::Leaf(leaf) => self.visit_const(leaf),
                     Node::Cast(_, _, ty) => self.visit_ty(ty),
@@ -863,7 +853,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
                     }
                 })
             } else {
-                ControlFlow::CONTINUE
+                ct.super_visit_with(self)
             }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 693c1728931..c8276854016 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -264,7 +264,7 @@ fn project_and_unify_type<'cx, 'tcx>(
     };
     debug!(?normalized, ?obligations, "project_and_unify_type result");
     let actual = obligation.predicate.term;
-    // For an example where this is neccessary see src/test/ui/impl-trait/nested-return-type2.rs
+    // For an example where this is necessary see src/test/ui/impl-trait/nested-return-type2.rs
     // This allows users to omit re-mentioning all bounds on an associated type and just use an
     // `impl Trait` for the assoc type to add more bounds.
     let InferOk { value: actual, obligations: new } =
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index aa8094a60dd..715f5be8e2f 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -14,6 +14,7 @@ use rustc_infer::traits::Normalized;
 use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
 use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
+use rustc_span::DUMMY_SP;
 
 use std::ops::ControlFlow;
 
@@ -253,7 +254,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
                 let result = tcx.normalize_projection_ty(c_data)?;
                 // We don't expect ambiguity.
                 if result.is_ambiguous() {
-                    bug!("unexpected ambiguity: {:?} {:?}", c_data, result);
+                    // Rustdoc normalizes possibly not well-formed types, so only
+                    // treat this as a bug if we're not in rustdoc.
+                    if !tcx.sess.opts.actually_rustdoc {
+                        tcx.sess.delay_span_bug(
+                            DUMMY_SP,
+                            format!("unexpected ambiguity: {:?} {:?}", c_data, result),
+                        );
+                    }
+                    return Err(NoSolution);
                 }
                 let InferOk { value: result, obligations } =
                     self.infcx.instantiate_query_response_and_region_obligations(
@@ -296,7 +305,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
                 let result = tcx.normalize_projection_ty(c_data)?;
                 // We don't expect ambiguity.
                 if result.is_ambiguous() {
-                    bug!("unexpected ambiguity: {:?} {:?}", c_data, result);
+                    // Rustdoc normalizes possibly not well-formed types, so only
+                    // treat this as a bug if we're not in rustdoc.
+                    if !tcx.sess.opts.actually_rustdoc {
+                        tcx.sess.delay_span_bug(
+                            DUMMY_SP,
+                            format!("unexpected ambiguity: {:?} {:?}", c_data, result),
+                        );
+                    }
+                    return Err(NoSolution);
                 }
                 let InferOk { value: result, obligations } =
                     self.infcx.instantiate_query_response_and_region_obligations(
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 635cdde0e8e..0870833cc35 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -148,13 +148,8 @@ pub fn predicate_obligations<'tcx>(
             wf.compute(a.into());
             wf.compute(b.into());
         }
-        ty::PredicateKind::ConstEvaluatable(uv) => {
-            let obligations = wf.nominal_obligations(uv.def.did, uv.substs);
-            wf.out.extend(obligations);
-
-            for arg in uv.substs.iter() {
-                wf.compute(arg);
-            }
+        ty::PredicateKind::ConstEvaluatable(ct) => {
+            wf.compute(ct.into());
         }
         ty::PredicateKind::ConstEquate(c1, c2) => {
             wf.compute(c1.into());
@@ -476,14 +471,14 @@ impl<'tcx> WfPredicates<'tcx> {
                 // obligations are handled by the parent (e.g. `ty::Ref`).
                 GenericArgKind::Lifetime(_) => continue,
 
-                GenericArgKind::Const(constant) => {
-                    match constant.kind() {
+                GenericArgKind::Const(ct) => {
+                    match ct.kind() {
                         ty::ConstKind::Unevaluated(uv) => {
                             let obligations = self.nominal_obligations(uv.def.did, uv.substs);
                             self.out.extend(obligations);
 
                             let predicate =
-                                ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
+                                ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
                                     .to_predicate(self.tcx());
                             let cause = self.cause(traits::WellFormed(None));
                             self.out.push(traits::Obligation::with_depth(
@@ -500,7 +495,7 @@ impl<'tcx> WfPredicates<'tcx> {
                                 cause,
                                 self.recursion_depth,
                                 self.param_env,
-                                ty::Binder::dummy(ty::PredicateKind::WellFormed(constant.into()))
+                                ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into()))
                                     .to_predicate(self.tcx()),
                             ));
                         }
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 6e34ee21082..73c7eb6992f 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -4,6 +4,7 @@ use rustc_middle::ty::layout::{
     fn_can_unwind, FnAbiError, HasParamEnv, HasTyCtxt, LayoutCx, LayoutOf, TyAndLayout,
 };
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::config::OptLevel;
 use rustc_span::def_id::DefId;
 use rustc_target::abi::call::{
     ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind,
@@ -384,7 +385,7 @@ fn fn_abi_new_uncached<'tcx>(
         conv,
         can_unwind: fn_can_unwind(cx.tcx(), fn_def_id, sig.abi),
     };
-    fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi)?;
+    fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi, fn_def_id)?;
     debug!("fn_abi_new_uncached = {:?}", fn_abi);
     Ok(cx.tcx.arena.alloc(fn_abi))
 }
@@ -394,6 +395,7 @@ fn fn_abi_adjust_for_abi<'tcx>(
     cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
     fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>,
     abi: SpecAbi,
+    fn_def_id: Option<DefId>,
 ) -> Result<(), FnAbiError<'tcx>> {
     if abi == SpecAbi::Unadjusted {
         return Ok(());
@@ -404,7 +406,18 @@ fn fn_abi_adjust_for_abi<'tcx>(
         || abi == SpecAbi::RustIntrinsic
         || abi == SpecAbi::PlatformIntrinsic
     {
-        let fixup = |arg: &mut ArgAbi<'tcx, Ty<'tcx>>| {
+        // Look up the deduced parameter attributes for this function, if we have its def ID and
+        // we're optimizing in non-incremental mode. We'll tag its parameters with those attributes
+        // as appropriate.
+        let deduced_param_attrs = if cx.tcx.sess.opts.optimize != OptLevel::No
+            && cx.tcx.sess.opts.incremental.is_none()
+        {
+            fn_def_id.map(|fn_def_id| cx.tcx.deduced_param_attrs(fn_def_id)).unwrap_or_default()
+        } else {
+            &[]
+        };
+
+        let fixup = |arg: &mut ArgAbi<'tcx, Ty<'tcx>>, arg_idx: Option<usize>| {
             if arg.is_ignore() {
                 return;
             }
@@ -451,10 +464,30 @@ fn fn_abi_adjust_for_abi<'tcx>(
                 // so we pick an appropriately sized integer type instead.
                 arg.cast_to(Reg { kind: RegKind::Integer, size });
             }
+
+            // If we deduced that this parameter was read-only, add that to the attribute list now.
+            //
+            // The `readonly` parameter only applies to pointers, so we can only do this if the
+            // argument was passed indirectly. (If the argument is passed directly, it's an SSA
+            // value, so it's implicitly immutable.)
+            if let (Some(arg_idx), &mut PassMode::Indirect { ref mut attrs, .. }) =
+                (arg_idx, &mut arg.mode)
+            {
+                // The `deduced_param_attrs` list could be empty if this is a type of function
+                // we can't deduce any parameters for, so make sure the argument index is in
+                // bounds.
+                if let Some(deduced_param_attrs) = deduced_param_attrs.get(arg_idx) {
+                    if deduced_param_attrs.read_only {
+                        attrs.regular.insert(ArgAttribute::ReadOnly);
+                        debug!("added deduced read-only attribute");
+                    }
+                }
+            }
         };
-        fixup(&mut fn_abi.ret);
-        for arg in fn_abi.args.iter_mut() {
-            fixup(arg);
+
+        fixup(&mut fn_abi.ret, None);
+        for (arg_idx, arg) in fn_abi.args.iter_mut().enumerate() {
+            fixup(arg, Some(arg_idx));
         }
     } else {
         fn_abi.adjust_for_foreign_abi(cx, abi)?;
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index 753c474a34b..c05eeb353a8 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -5,18 +5,18 @@ use rustc_middle::ty::Ty;
 use rustc_span::Span;
 
 #[derive(Diagnostic)]
-#[diag(ty_utils::needs_drop_overflow)]
+#[diag(ty_utils_needs_drop_overflow)]
 pub struct NeedsDropOverflow<'tcx> {
     pub query_ty: Ty<'tcx>,
 }
 
 #[derive(Diagnostic)]
-#[diag(ty_utils::generic_constant_too_complex)]
+#[diag(ty_utils_generic_constant_too_complex)]
 #[help]
 pub struct GenericConstantTooComplex {
     #[primary_span]
     pub span: Span,
-    #[note(ty_utils::maybe_supported)]
+    #[note(maybe_supported)]
     pub maybe_supported: Option<()>,
     #[subdiagnostic]
     pub sub: GenericConstantTooComplexSub,
@@ -24,46 +24,46 @@ pub struct GenericConstantTooComplex {
 
 #[derive(Subdiagnostic)]
 pub enum GenericConstantTooComplexSub {
-    #[label(ty_utils::borrow_not_supported)]
+    #[label(ty_utils_borrow_not_supported)]
     BorrowNotSupported(#[primary_span] Span),
-    #[label(ty_utils::address_and_deref_not_supported)]
+    #[label(ty_utils_address_and_deref_not_supported)]
     AddressAndDerefNotSupported(#[primary_span] Span),
-    #[label(ty_utils::array_not_supported)]
+    #[label(ty_utils_array_not_supported)]
     ArrayNotSupported(#[primary_span] Span),
-    #[label(ty_utils::block_not_supported)]
+    #[label(ty_utils_block_not_supported)]
     BlockNotSupported(#[primary_span] Span),
-    #[label(ty_utils::never_to_any_not_supported)]
+    #[label(ty_utils_never_to_any_not_supported)]
     NeverToAnyNotSupported(#[primary_span] Span),
-    #[label(ty_utils::tuple_not_supported)]
+    #[label(ty_utils_tuple_not_supported)]
     TupleNotSupported(#[primary_span] Span),
-    #[label(ty_utils::index_not_supported)]
+    #[label(ty_utils_index_not_supported)]
     IndexNotSupported(#[primary_span] Span),
-    #[label(ty_utils::field_not_supported)]
+    #[label(ty_utils_field_not_supported)]
     FieldNotSupported(#[primary_span] Span),
-    #[label(ty_utils::const_block_not_supported)]
+    #[label(ty_utils_const_block_not_supported)]
     ConstBlockNotSupported(#[primary_span] Span),
-    #[label(ty_utils::adt_not_supported)]
+    #[label(ty_utils_adt_not_supported)]
     AdtNotSupported(#[primary_span] Span),
-    #[label(ty_utils::pointer_not_supported)]
+    #[label(ty_utils_pointer_not_supported)]
     PointerNotSupported(#[primary_span] Span),
-    #[label(ty_utils::yield_not_supported)]
+    #[label(ty_utils_yield_not_supported)]
     YieldNotSupported(#[primary_span] Span),
-    #[label(ty_utils::loop_not_supported)]
+    #[label(ty_utils_loop_not_supported)]
     LoopNotSupported(#[primary_span] Span),
-    #[label(ty_utils::box_not_supported)]
+    #[label(ty_utils_box_not_supported)]
     BoxNotSupported(#[primary_span] Span),
-    #[label(ty_utils::binary_not_supported)]
+    #[label(ty_utils_binary_not_supported)]
     BinaryNotSupported(#[primary_span] Span),
-    #[label(ty_utils::logical_op_not_supported)]
+    #[label(ty_utils_logical_op_not_supported)]
     LogicalOpNotSupported(#[primary_span] Span),
-    #[label(ty_utils::assign_not_supported)]
+    #[label(ty_utils_assign_not_supported)]
     AssignNotSupported(#[primary_span] Span),
-    #[label(ty_utils::closure_and_return_not_supported)]
+    #[label(ty_utils_closure_and_return_not_supported)]
     ClosureAndReturnNotSupported(#[primary_span] Span),
-    #[label(ty_utils::control_flow_not_supported)]
+    #[label(ty_utils_control_flow_not_supported)]
     ControlFlowNotSupported(#[primary_span] Span),
-    #[label(ty_utils::inline_asm_not_supported)]
+    #[label(ty_utils_inline_asm_not_supported)]
     InlineAsmNotSupported(#[primary_span] Span),
-    #[label(ty_utils::operation_not_supported)]
+    #[label(ty_utils_operation_not_supported)]
     OperationNotSupported(#[primary_span] Span),
 }
diff --git a/config.toml.example b/config.toml.example
index 1f5747456e9..a46813e4d7a 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -638,6 +638,11 @@ changelog-seen = 2
 # If an explicit setting is given, it will be used for all parts of the codebase.
 #new-symbol-mangling = true|false (see comment)
 
+# Select LTO mode that will be used for compiling rustc. By default, thin local LTO
+# (LTO within a single crate) is used (like for any Rust crate). You can also select
+# "thin" or "fat" to apply Thin/Fat LTO to the `rustc_driver` dylib.
+#lto = "thin-local"
+
 # =============================================================================
 # Options for specific targets
 #
diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs
index 904a53bb4ac..83a1385599b 100644
--- a/library/alloc/src/borrow.rs
+++ b/library/alloc/src/borrow.rs
@@ -21,7 +21,6 @@ use Cow::*;
 impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B>
 where
     B: ToOwned,
-    <B as ToOwned>::Owned: 'a,
 {
     fn borrow(&self) -> &B {
         &**self
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 6d247681c66..9c229665c7e 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -1386,7 +1386,7 @@ impl<T: ?Sized> Rc<T> {
             Self::allocate_for_layout(
                 Layout::for_value(&*ptr),
                 |layout| Global.allocate(layout),
-                |mem| mem.with_metadata_of(ptr as *mut RcBox<T>),
+                |mem| mem.with_metadata_of(ptr as *const RcBox<T>),
             )
         }
     }
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 983376a282b..c436adf7006 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -67,7 +67,7 @@ use core::str::Utf8Chunks;
 use crate::borrow::{Cow, ToOwned};
 use crate::boxed::Box;
 use crate::collections::TryReserveError;
-use crate::str::{self, Chars, Utf8Error};
+use crate::str::{self, from_utf8_unchecked_mut, Chars, Utf8Error};
 #[cfg(not(no_global_oom_handling))]
 use crate::str::{from_boxed_utf8_unchecked, FromStr};
 use crate::vec::Vec;
@@ -1849,6 +1849,35 @@ impl String {
         let slice = self.vec.into_boxed_slice();
         unsafe { from_boxed_utf8_unchecked(slice) }
     }
+
+    /// Consumes and leaks the `String`, returning a mutable reference to the contents,
+    /// `&'static mut str`.
+    ///
+    /// This is mainly useful for data that lives for the remainder of
+    /// the program's life. Dropping the returned reference will cause a memory
+    /// leak.
+    ///
+    /// It does not reallocate or shrink the `String`,
+    /// so the leaked allocation may include unused capacity that is not part
+    /// of the returned slice.
+    ///
+    /// # Examples
+    ///
+    /// Simple usage:
+    ///
+    /// ```
+    /// #![feature(string_leak)]
+    ///
+    /// let x = String::from("bucket");
+    /// let static_ref: &'static mut str = x.leak();
+    /// assert_eq!(static_ref, "bucket");
+    /// ```
+    #[unstable(feature = "string_leak", issue = "102929")]
+    #[inline]
+    pub fn leak(self) -> &'static mut str {
+        let slice = self.vec.leak();
+        unsafe { from_utf8_unchecked_mut(slice) }
+    }
 }
 
 impl FromUtf8Error {
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index df315dad893..e8d9de4fb3c 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -1204,7 +1204,7 @@ impl<T: ?Sized> Arc<T> {
             Self::allocate_for_layout(
                 Layout::for_value(&*ptr),
                 |layout| Global.allocate(layout),
-                |mem| mem.with_metadata_of(ptr as *mut ArcInner<T>),
+                |mem| mem.with_metadata_of(ptr as *const ArcInner<T>),
             )
         }
     }
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index b5b2eb0ece0..6a71f08330c 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1999,9 +1999,7 @@ impl<T, A: Allocator> Vec<T, A> {
         unsafe {
             // set self.vec length's to start, to be safe in case Drain is leaked
             self.set_len(start);
-            // Use the borrow in the IterMut to indicate borrowing behavior of the
-            // whole Drain iterator (like &mut T).
-            let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start), end - start);
+            let range_slice = slice::from_raw_parts(self.as_ptr().add(start), end - start);
             Drain {
                 tail_start: end,
                 tail_len: len - end,
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 04dd821efde..eae0e1c7618 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -32,6 +32,10 @@ pub use iter::IntoIter;
 /// # Example
 ///
 /// ```rust
+/// // type inference is helping us here, the way `from_fn` knows how many
+/// // elements to produce is the length of array down there: only arrays of
+/// // equal lengths can be compared, so the const generic parameter `N` is
+/// // inferred to be 5, thus creating array of 5 elements.
 /// let array = core::array::from_fn(|i| i);
 /// assert_eq!(array, [0, 1, 2, 3, 4]);
 /// ```
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 4a8efe15e59..89053060fbb 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -493,8 +493,8 @@ impl Error for crate::char::ParseCharError {
     }
 }
 
-#[unstable(feature = "duration_checked_float", issue = "83400")]
-impl Error for crate::time::FromFloatSecsError {}
+#[stable(feature = "duration_checked_float", since = "CURRENT_RUSTC_VERSION")]
+impl Error for crate::time::TryFromFloatSecsError {}
 
 #[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")]
 impl Error for crate::ffi::FromBytesWithNulError {
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index efad9a9391b..7757c95de9d 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -146,7 +146,6 @@ use crate::slice;
 ///
 /// ```
 /// use std::mem::MaybeUninit;
-/// use std::ptr;
 ///
 /// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
 /// // safe because the type we are claiming to have initialized here is a
@@ -162,7 +161,7 @@ use crate::slice;
 ///
 /// // For each item in the array, drop if we allocated it.
 /// for elem in &mut data[0..data_len] {
-///     unsafe { ptr::drop_in_place(elem.as_mut_ptr()); }
+///     unsafe { elem.assume_init_drop(); }
 /// }
 /// ```
 ///
diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs
index 8865c834c88..caa10f1818b 100644
--- a/library/core/src/ptr/metadata.rs
+++ b/library/core/src/ptr/metadata.rs
@@ -135,16 +135,16 @@ pub const fn from_raw_parts_mut<T: ?Sized>(
 }
 
 #[repr(C)]
-pub(crate) union PtrRepr<T: ?Sized> {
-    pub(crate) const_ptr: *const T,
-    pub(crate) mut_ptr: *mut T,
-    pub(crate) components: PtrComponents<T>,
+union PtrRepr<T: ?Sized> {
+    const_ptr: *const T,
+    mut_ptr: *mut T,
+    components: PtrComponents<T>,
 }
 
 #[repr(C)]
-pub(crate) struct PtrComponents<T: ?Sized> {
-    pub(crate) data_address: *const (),
-    pub(crate) metadata: <T as Pointee>::Metadata,
+struct PtrComponents<T: ?Sized> {
+    data_address: *const (),
+    metadata: <T as Pointee>::Metadata,
 }
 
 // Manual impl needed to avoid `T: Copy` bound.
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 8e2bad35993..cfffe351a87 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -394,7 +394,6 @@ pub use crate::intrinsics::copy;
 pub use crate::intrinsics::write_bytes;
 
 mod metadata;
-pub(crate) use metadata::PtrRepr;
 #[unstable(feature = "ptr_metadata", issue = "81513")]
 pub use metadata::{from_raw_parts, from_raw_parts_mut, metadata, DynMetadata, Pointee, Thin};
 
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index bbcc7c699e0..0bb2566fd4c 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -80,10 +80,14 @@ impl<T: ?Sized> *mut T {
     #[unstable(feature = "set_ptr_value", issue = "75091")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[inline]
-    pub fn with_metadata_of<U>(self, mut val: *mut U) -> *mut U
+    pub fn with_metadata_of<U>(self, val: *const U) -> *mut U
     where
         U: ?Sized,
     {
+        // Prepare in the type system that we will replace the pointer value with a mutable
+        // pointer, taking the mutable provenance from the `self` pointer.
+        let mut val = val as *mut U;
+        // Pointer to the pointer value within the value.
         let target = &mut val as *mut *mut U as *mut *mut u8;
         // SAFETY: In case of a thin pointer, this operations is identical
         // to a simple assignment. In case of a fat pointer, with the current
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index f3ef094cbcc..7264d57ba6a 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -2,6 +2,7 @@ use crate::cmp::Ordering;
 use crate::convert::From;
 use crate::fmt;
 use crate::hash;
+use crate::intrinsics::assert_unsafe_precondition;
 use crate::marker::Unsize;
 use crate::mem::{self, MaybeUninit};
 use crate::num::NonZeroUsize;
@@ -195,7 +196,10 @@ impl<T: ?Sized> NonNull<T> {
     #[inline]
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
         // SAFETY: the caller must guarantee that `ptr` is non-null.
-        unsafe { NonNull { pointer: ptr as _ } }
+        unsafe {
+            assert_unsafe_precondition!([T: ?Sized](ptr: *mut T) => !ptr.is_null());
+            NonNull { pointer: ptr as _ }
+        }
     }
 
     /// Creates a new `NonNull` if `ptr` is non-null.
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 5f1a05706f2..94ab13ed2e0 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -123,18 +123,11 @@ impl<T> [T] {
     #[lang = "slice_len_fn"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_slice_len", since = "1.39.0")]
+    #[rustc_allow_const_fn_unstable(ptr_metadata)]
     #[inline]
     #[must_use]
-    // SAFETY: const sound because we transmute out the length field as a usize (which it must be)
     pub const fn len(&self) -> usize {
-        // FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable.
-        // As of this writing this causes a "Const-stable functions can only call other
-        // const-stable functions" error.
-
-        // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
-        // and PtrComponents<T> have the same memory layouts. Only std can make this
-        // guarantee.
-        unsafe { crate::ptr::PtrRepr { const_ptr: self }.components.metadata }
+        ptr::metadata(self)
     }
 
     /// Returns `true` if the slice has a length of 0.
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 7cbb477d7a3..37c3611d0a9 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -1225,7 +1225,6 @@ impl fmt::Debug for Duration {
 /// # Example
 ///
 /// ```
-/// #![feature(duration_checked_float)]
 /// use std::time::Duration;
 ///
 /// if let Err(e) = Duration::try_from_secs_f32(-1.0) {
@@ -1233,33 +1232,33 @@ impl fmt::Debug for Duration {
 /// }
 /// ```
 #[derive(Debug, Clone, PartialEq, Eq)]
-#[unstable(feature = "duration_checked_float", issue = "83400")]
-pub struct FromFloatSecsError {
-    kind: FromFloatSecsErrorKind,
+#[stable(feature = "duration_checked_float", since = "CURRENT_RUSTC_VERSION")]
+pub struct TryFromFloatSecsError {
+    kind: TryFromFloatSecsErrorKind,
 }
 
-impl FromFloatSecsError {
+impl TryFromFloatSecsError {
     const fn description(&self) -> &'static str {
         match self.kind {
-            FromFloatSecsErrorKind::Negative => {
+            TryFromFloatSecsErrorKind::Negative => {
                 "can not convert float seconds to Duration: value is negative"
             }
-            FromFloatSecsErrorKind::OverflowOrNan => {
+            TryFromFloatSecsErrorKind::OverflowOrNan => {
                 "can not convert float seconds to Duration: value is either too big or NaN"
             }
         }
     }
 }
 
-#[unstable(feature = "duration_checked_float", issue = "83400")]
-impl fmt::Display for FromFloatSecsError {
+#[stable(feature = "duration_checked_float", since = "CURRENT_RUSTC_VERSION")]
+impl fmt::Display for TryFromFloatSecsError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.description().fmt(f)
     }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq)]
-enum FromFloatSecsErrorKind {
+enum TryFromFloatSecsErrorKind {
     // Value is negative.
     Negative,
     // Value is either too big to be represented as `Duration` or `NaN`.
@@ -1280,7 +1279,7 @@ macro_rules! try_from_secs {
         const EXP_MASK: $bits_ty = (1 << $exp_bits) - 1;
 
         if $secs < 0.0 {
-            return Err(FromFloatSecsError { kind: FromFloatSecsErrorKind::Negative });
+            return Err(TryFromFloatSecsError { kind: TryFromFloatSecsErrorKind::Negative });
         }
 
         let bits = $secs.to_bits();
@@ -1339,7 +1338,7 @@ macro_rules! try_from_secs {
             let secs = u64::from(mant) << (exp - $mant_bits);
             (secs, 0)
         } else {
-            return Err(FromFloatSecsError { kind: FromFloatSecsErrorKind::OverflowOrNan });
+            return Err(TryFromFloatSecsError { kind: TryFromFloatSecsErrorKind::OverflowOrNan });
         };
 
         Ok(Duration::new(secs, nanos))
@@ -1355,8 +1354,6 @@ impl Duration {
     ///
     /// # Examples
     /// ```
-    /// #![feature(duration_checked_float)]
-    ///
     /// use std::time::Duration;
     ///
     /// let res = Duration::try_from_secs_f32(0.0);
@@ -1404,9 +1401,10 @@ impl Duration {
     /// let res = Duration::try_from_secs_f32(val);
     /// assert_eq!(res, Ok(Duration::new(1, 2_929_688)));
     /// ```
-    #[unstable(feature = "duration_checked_float", issue = "83400")]
+    #[stable(feature = "duration_checked_float", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
     #[inline]
-    pub const fn try_from_secs_f32(secs: f32) -> Result<Duration, FromFloatSecsError> {
+    pub const fn try_from_secs_f32(secs: f32) -> Result<Duration, TryFromFloatSecsError> {
         try_from_secs!(
             secs = secs,
             mantissa_bits = 23,
@@ -1425,8 +1423,6 @@ impl Duration {
     ///
     /// # Examples
     /// ```
-    /// #![feature(duration_checked_float)]
-    ///
     /// use std::time::Duration;
     ///
     /// let res = Duration::try_from_secs_f64(0.0);
@@ -1482,9 +1478,10 @@ impl Duration {
     /// let res = Duration::try_from_secs_f64(val);
     /// assert_eq!(res, Ok(Duration::new(1, 2_929_688)));
     /// ```
-    #[unstable(feature = "duration_checked_float", issue = "83400")]
+    #[stable(feature = "duration_checked_float", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
     #[inline]
-    pub const fn try_from_secs_f64(secs: f64) -> Result<Duration, FromFloatSecsError> {
+    pub const fn try_from_secs_f64(secs: f64) -> Result<Duration, TryFromFloatSecsError> {
         try_from_secs!(
             secs = secs,
             mantissa_bits = 52,
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index b1f492381b1..3012a78b9c9 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -103,7 +103,6 @@
 #![feature(provide_any)]
 #![feature(utf8_chunks)]
 #![feature(is_ascii_octdigit)]
-#![feature(duration_checked_float)]
 #![deny(unsafe_op_in_unsafe_fn)]
 
 extern crate test;
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index b8c35ecd349..bc10b12ec2a 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
-libc = { version = "0.2.126", default-features = false, features = ['rustc-dep-of-std'] }
+libc = { version = "0.2.135", default-features = false, features = ['rustc-dep-of-std'] }
 compiler_builtins = { version = "0.1.73" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index c6c78dc3939..188ff00e1f8 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -1365,6 +1365,34 @@ impl FileTimes {
 impl Permissions {
     /// Returns `true` if these permissions describe a readonly (unwritable) file.
     ///
+    /// # Note
+    ///
+    /// This function does not take Access Control Lists (ACLs) or Unix group
+    /// membership into account.
+    ///
+    /// # Windows
+    ///
+    /// On Windows this returns [`FILE_ATTRIBUTE_READONLY`](https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants).
+    /// If `FILE_ATTRIBUTE_READONLY` is set then writes to the file will fail
+    /// but the user may still have permission to change this flag. If
+    /// `FILE_ATTRIBUTE_READONLY` is *not* set then writes may still fail due
+    /// to lack of write permission.
+    /// The behavior of this attribute for directories depends on the Windows
+    /// version.
+    ///
+    /// # Unix (including macOS)
+    ///
+    /// On Unix-based platforms this checks if *any* of the owner, group or others
+    /// write permission bits are set. It does not check if the current
+    /// user is in the file's assigned group. It also does not check ACLs.
+    /// Therefore even if this returns true you may not be able to write to the
+    /// file, and vice versa. The [`PermissionsExt`] trait gives direct access
+    /// to the permission bits but also does not read ACLs. If you need to
+    /// accurately know whether or not a file is writable use the `access()`
+    /// function from libc.
+    ///
+    /// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -1390,8 +1418,40 @@ impl Permissions {
     /// using the resulting `Permission` will update file permissions to allow
     /// writing.
     ///
-    /// This operation does **not** modify the filesystem. To modify the
-    /// filesystem use the [`set_permissions`] function.
+    /// This operation does **not** modify the files attributes. This only
+    /// changes the in-memory value of these attributes for this `Permissions`
+    /// instance. To modify the files attributes use the [`set_permissions`]
+    /// function which commits these attribute changes to the file.
+    ///
+    /// # Note
+    ///
+    /// `set_readonly(false)` makes the file *world-writable* on Unix.
+    /// You can use the [`PermissionsExt`] trait on Unix to avoid this issue.
+    ///
+    /// It also does not take Access Control Lists (ACLs) or Unix group
+    /// membership into account.
+    ///
+    /// # Windows
+    ///
+    /// On Windows this sets or clears [`FILE_ATTRIBUTE_READONLY`](https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants).
+    /// If `FILE_ATTRIBUTE_READONLY` is set then writes to the file will fail
+    /// but the user may still have permission to change this flag. If
+    /// `FILE_ATTRIBUTE_READONLY` is *not* set then the write may still fail if
+    /// the user does not have permission to write to the file.
+    ///
+    /// In Windows 7 and earlier this attribute prevents deleting empty
+    /// directories. It does not prevent modifying the directory contents.
+    /// On later versions of Windows this attribute is ignored for directories.
+    ///
+    /// # Unix (including macOS)
+    ///
+    /// On Unix-based platforms this sets or clears the write access bit for
+    /// the owner, group *and* others, equivalent to `chmod a+w <file>`
+    /// or `chmod a-w <file>` respectively. The latter will grant write access
+    /// to all users! You can use the [`PermissionsExt`] trait on Unix
+    /// to avoid this issue.
+    ///
+    /// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt
     ///
     /// # Examples
     ///
@@ -1405,7 +1465,8 @@ impl Permissions {
     ///
     ///     permissions.set_readonly(true);
     ///
-    ///     // filesystem doesn't change
+    ///     // filesystem doesn't change, only the in memory state of the
+    ///     // readonly permission
     ///     assert_eq!(false, metadata.permissions().readonly());
     ///
     ///     // just this particular `permissions`.
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 0c29b001f01..23a13523fc2 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -583,7 +583,7 @@ pub trait Read {
     /// `n > buf.len()`.
     ///
     /// No guarantees are provided about the contents of `buf` when this
-    /// function is called, implementations cannot rely on any property of the
+    /// function is called, so implementations cannot rely on any property of the
     /// contents of `buf` being true. It is recommended that *implementations*
     /// only write data to `buf` instead of reading its contents.
     ///
@@ -759,7 +759,7 @@ pub trait Read {
     /// specified buffer `buf`.
     ///
     /// No guarantees are provided about the contents of `buf` when this
-    /// function is called, implementations cannot rely on any property of the
+    /// function is called, so implementations cannot rely on any property of the
     /// contents of `buf` being true. It is recommended that implementations
     /// only write data to `buf` instead of reading its contents. The
     /// documentation on [`read`] has a more detailed explanation on this
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 78838adb8dd..385585dada8 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -280,7 +280,6 @@
 #![feature(core_intrinsics)]
 #![feature(cstr_from_bytes_until_nul)]
 #![feature(cstr_internals)]
-#![feature(duration_checked_float)]
 #![feature(duration_constants)]
 #![feature(error_generic_member_access)]
 #![feature(error_in_core)]
diff --git a/library/std/src/sys/solid/fs.rs b/library/std/src/sys/solid/fs.rs
index 9692222534e..6c66b93a3e1 100644
--- a/library/std/src/sys/solid/fs.rs
+++ b/library/std/src/sys/solid/fs.rs
@@ -175,15 +175,19 @@ impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
 
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        unsafe {
-            let mut out_dirent = MaybeUninit::uninit();
-            error::SolidError::err_if_negative(abi::SOLID_FS_ReadDir(
+        let entry = unsafe {
+            let mut out_entry = MaybeUninit::uninit();
+            match error::SolidError::err_if_negative(abi::SOLID_FS_ReadDir(
                 self.inner.dirp,
-                out_dirent.as_mut_ptr(),
-            ))
-            .ok()?;
-            Some(Ok(DirEntry { entry: out_dirent.assume_init(), inner: Arc::clone(&self.inner) }))
-        }
+                out_entry.as_mut_ptr(),
+            )) {
+                Ok(_) => out_entry.assume_init(),
+                Err(e) if e.as_raw() == abi::SOLID_ERR_NOTFOUND => return None,
+                Err(e) => return Some(Err(e.as_io_error())),
+            }
+        };
+
+        (entry.d_name[0] != 0).then(|| Ok(DirEntry { entry, inner: Arc::clone(&self.inner) }))
     }
 }
 
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 780f46f8c11..e22b2f3340a 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -4,6 +4,15 @@ use crate::ffi::{CStr, OsStr, OsString};
 use crate::fmt;
 use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom};
 use crate::mem;
+#[cfg(any(
+    target_os = "android",
+    target_os = "linux",
+    target_os = "solaris",
+    target_os = "fuchsia",
+    target_os = "redox",
+    target_os = "illumos"
+))]
+use crate::mem::MaybeUninit;
 use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd};
 use crate::path::{Path, PathBuf};
 use crate::ptr;
@@ -584,33 +593,69 @@ impl Iterator for ReadDir {
                     };
                 }
 
-                // Only d_reclen bytes of *entry_ptr are valid, so we can't just copy the
-                // whole thing (#93384).  Instead, copy everything except the name.
-                let mut copy: dirent64 = mem::zeroed();
-                // Can't dereference entry_ptr, so use the local entry to get
-                // offsetof(struct dirent, d_name)
-                let copy_bytes = &mut copy as *mut _ as *mut u8;
-                let copy_name = &mut copy.d_name as *mut _ as *mut u8;
-                let name_offset = copy_name.offset_from(copy_bytes) as usize;
-                let entry_bytes = entry_ptr as *const u8;
-                let entry_name = entry_bytes.add(name_offset);
-                ptr::copy_nonoverlapping(entry_bytes, copy_bytes, name_offset);
+                // The dirent64 struct is a weird imaginary thing that isn't ever supposed
+                // to be worked with by value. Its trailing d_name field is declared
+                // variously as [c_char; 256] or [c_char; 1] on different systems but
+                // either way that size is meaningless; only the offset of d_name is
+                // meaningful. The dirent64 pointers that libc returns from readdir64 are
+                // allowed to point to allocations smaller _or_ LARGER than implied by the
+                // definition of the struct.
+                //
+                // As such, we need to be even more careful with dirent64 than if its
+                // contents were "simply" partially initialized data.
+                //
+                // Like for uninitialized contents, converting entry_ptr to `&dirent64`
+                // would not be legal. However, unique to dirent64 is that we don't even
+                // get to use `addr_of!((*entry_ptr).d_name)` because that operation
+                // requires the full extent of *entry_ptr to be in bounds of the same
+                // allocation, which is not necessarily the case here.
+                //
+                // Absent any other way to obtain a pointer to `(*entry_ptr).d_name`
+                // legally in Rust analogously to how it would be done in C, we instead
+                // need to make our own non-libc allocation that conforms to the weird
+                // imaginary definition of dirent64, and use that for a field offset
+                // computation.
+                macro_rules! offset_ptr {
+                    ($entry_ptr:expr, $field:ident) => {{
+                        const OFFSET: isize = {
+                            let delusion = MaybeUninit::<dirent64>::uninit();
+                            let entry_ptr = delusion.as_ptr();
+                            unsafe {
+                                ptr::addr_of!((*entry_ptr).$field)
+                                    .cast::<u8>()
+                                    .offset_from(entry_ptr.cast::<u8>())
+                            }
+                        };
+                        if true {
+                            // Cast to the same type determined by the else branch.
+                            $entry_ptr.byte_offset(OFFSET).cast::<_>()
+                        } else {
+                            #[allow(deref_nullptr)]
+                            {
+                                ptr::addr_of!((*ptr::null::<dirent64>()).$field)
+                            }
+                        }
+                    }};
+                }
+
+                // d_name is guaranteed to be null-terminated.
+                let name = CStr::from_ptr(offset_ptr!(entry_ptr, d_name).cast());
+                let name_bytes = name.to_bytes();
+                if name_bytes == b"." || name_bytes == b".." {
+                    continue;
+                }
 
                 let entry = dirent64_min {
-                    d_ino: copy.d_ino as u64,
+                    d_ino: *offset_ptr!(entry_ptr, d_ino) as u64,
                     #[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
-                    d_type: copy.d_type as u8,
+                    d_type: *offset_ptr!(entry_ptr, d_type) as u8,
                 };
 
-                let ret = DirEntry {
+                return Some(Ok(DirEntry {
                     entry,
-                    // d_name is guaranteed to be null-terminated.
-                    name: CStr::from_ptr(entry_name as *const _).to_owned(),
+                    name: name.to_owned(),
                     dir: Arc::clone(&self.inner),
-                };
-                if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
-                    return Some(Ok(ret));
-                }
+                }));
             }
         }
     }
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 4a9f356b63c..9055a011c51 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -382,16 +382,12 @@ cfg_if::cfg_if! {
         extern "C" {}
     } else if #[cfg(target_os = "macos")] {
         #[link(name = "System")]
-        // res_init and friends require -lresolv on macOS/iOS.
-        // See #41582 and https://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html
-        #[link(name = "resolv")]
         extern "C" {}
     } else if #[cfg(any(target_os = "ios", target_os = "watchos"))] {
         #[link(name = "System")]
         #[link(name = "objc")]
         #[link(name = "Security", kind = "framework")]
         #[link(name = "Foundation", kind = "framework")]
-        #[link(name = "resolv")]
         extern "C" {}
     } else if #[cfg(target_os = "fuchsia")] {
         #[link(name = "zircon")]
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index 917fc8e4995..be6fc2ebb7a 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -129,6 +129,8 @@ pub const FIONBIO: c_ulong = 0x8004667e;
 
 pub const MAX_PATH: usize = 260;
 
+pub const FILE_TYPE_PIPE: u32 = 3;
+
 #[repr(C)]
 #[derive(Copy)]
 pub struct WIN32_FIND_DATAW {
@@ -1114,6 +1116,7 @@ extern "system" {
         lpFileInformation: LPVOID,
         dwBufferSize: DWORD,
     ) -> BOOL;
+    pub fn GetFileType(hfile: HANDLE) -> DWORD;
     pub fn SleepConditionVariableSRW(
         ConditionVariable: PCONDITION_VARIABLE,
         SRWLock: PSRWLOCK,
diff --git a/library/std/src/sys/windows/io.rs b/library/std/src/sys/windows/io.rs
index 0879ef19933..2cc34c986b9 100644
--- a/library/std/src/sys/windows/io.rs
+++ b/library/std/src/sys/windows/io.rs
@@ -120,6 +120,11 @@ unsafe fn handle_is_console(handle: BorrowedHandle<'_>) -> bool {
 }
 
 unsafe fn msys_tty_on(handle: c::HANDLE) -> bool {
+    // Early return if the handle is not a pipe.
+    if c::GetFileType(handle) != c::FILE_TYPE_PIPE {
+        return false;
+    }
+
     const SIZE: usize = size_of::<c::FILE_NAME_INFO>() + c::MAX_PATH * size_of::<c::WCHAR>();
     let mut name_info_bytes = Align8([0u8; SIZE]);
     let res = c::GetFileInformationByHandleEx(
@@ -137,11 +142,13 @@ unsafe fn msys_tty_on(handle: c::HANDLE) -> bool {
     let name_ptr = name_info_bytes.0.as_ptr().offset(size_of::<c::DWORD>() as isize).cast::<u16>();
     let s = core::slice::from_raw_parts(name_ptr, name_len);
     let name = String::from_utf16_lossy(s);
+    // Get the file name only.
+    let name = name.rsplit('\\').next().unwrap_or(&name);
     // This checks whether 'pty' exists in the file name, which indicates that
     // a pseudo-terminal is attached. To mitigate against false positives
     // (e.g., an actual file name that contains 'pty'), we also require that
-    // either the strings 'msys-' or 'cygwin-' are in the file name as well.)
-    let is_msys = name.contains("msys-") || name.contains("cygwin-");
+    // the file name begins with either the strings 'msys-' or 'cygwin-'.)
+    let is_msys = name.starts_with("msys-") || name.starts_with("cygwin-");
     let is_pty = name.contains("-pty");
     is_msys && is_pty
 }
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index d4a1b9d9b50..34e18b5fa87 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -43,8 +43,8 @@ use crate::sys_common::{FromInner, IntoInner};
 #[stable(feature = "time", since = "1.3.0")]
 pub use core::time::Duration;
 
-#[unstable(feature = "duration_checked_float", issue = "83400")]
-pub use core::time::FromFloatSecsError;
+#[stable(feature = "duration_checked_float", since = "CURRENT_RUSTC_VERSION")]
+pub use core::time::TryFromFloatSecsError;
 
 /// A measurement of a monotonically nondecreasing clock.
 /// Opaque and useful only with [`Duration`].
diff --git a/library/test/src/console.rs b/library/test/src/console.rs
index e9dda98966d..b1270c27271 100644
--- a/library/test/src/console.rs
+++ b/library/test/src/console.rs
@@ -147,7 +147,7 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res
     let mut ntest = 0;
     let mut nbench = 0;
 
-    for test in filter_tests(&opts, tests) {
+    for test in filter_tests(&opts, tests).into_iter() {
         use crate::TestFn::*;
 
         let TestDescAndFn { desc: TestDesc { name, .. }, testfn } = test;
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index b1e0bbfc591..4de69455798 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -247,7 +247,7 @@ where
     let event = TestEvent::TeFiltered(filtered_descs, shuffle_seed);
     notify_about_test_event(event)?;
 
-    let (filtered_tests, filtered_benchs): (Vec<_>, _) = filtered_tests
+    let (mut filtered_tests, filtered_benchs): (Vec<_>, _) = filtered_tests
         .into_iter()
         .enumerate()
         .map(|(i, e)| (TestId(i), e))
@@ -255,12 +255,12 @@ where
 
     let concurrency = opts.test_threads.unwrap_or_else(get_concurrency);
 
-    let mut remaining = filtered_tests;
     if let Some(shuffle_seed) = shuffle_seed {
-        shuffle_tests(shuffle_seed, &mut remaining);
-    } else {
-        remaining.reverse();
+        shuffle_tests(shuffle_seed, &mut filtered_tests);
     }
+    // Store the tests in a VecDeque so we can efficiently remove the first element to run the
+    // tests in the order they were passed (unless shuffled).
+    let mut remaining = VecDeque::from(filtered_tests);
     let mut pending = 0;
 
     let (tx, rx) = channel::<CompletedTest>();
@@ -300,7 +300,7 @@ where
 
     if concurrency == 1 {
         while !remaining.is_empty() {
-            let (id, test) = remaining.pop().unwrap();
+            let (id, test) = remaining.pop_front().unwrap();
             let event = TestEvent::TeWait(test.desc.clone());
             notify_about_test_event(event)?;
             let join_handle =
@@ -314,7 +314,7 @@ where
     } else {
         while pending > 0 || !remaining.is_empty() {
             while pending < concurrency && !remaining.is_empty() {
-                let (id, test) = remaining.pop().unwrap();
+                let (id, test) = remaining.pop_front().unwrap();
                 let timeout = time::get_default_test_timeout();
                 let desc = test.desc.clone();
 
@@ -426,9 +426,6 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
         RunIgnored::No => {}
     }
 
-    // Sort the tests alphabetically
-    filtered.sort_by(|t1, t2| t1.desc.name.as_slice().cmp(t2.desc.name.as_slice()));
-
     filtered
 }
 
diff --git a/library/test/src/term.rs b/library/test/src/term.rs
index b256ab7b8f8..a14b0d4f5a9 100644
--- a/library/test/src/term.rs
+++ b/library/test/src/term.rs
@@ -39,7 +39,7 @@ pub(crate) fn stdout() -> Option<Box<StdoutTerminal>> {
 pub(crate) fn stdout() -> Option<Box<StdoutTerminal>> {
     TerminfoTerminal::new(io::stdout())
         .map(|t| Box::new(t) as Box<StdoutTerminal>)
-        .or_else(|| WinConsole::new(io::stdout()).ok().map(|t| Box::new(t) as Box<StdoutTerminal>))
+        .or_else(|| Some(Box::new(WinConsole::new(io::stdout())) as Box<StdoutTerminal>))
 }
 
 /// Terminal color definitions
diff --git a/library/test/src/term/win.rs b/library/test/src/term/win.rs
index 4bdbd6ee75f..55020141a82 100644
--- a/library/test/src/term/win.rs
+++ b/library/test/src/term/win.rs
@@ -113,8 +113,7 @@ impl<T: Write + Send + 'static> WinConsole<T> {
         }
     }
 
-    /// Returns `None` whenever the terminal cannot be created for some reason.
-    pub(crate) fn new(out: T) -> io::Result<WinConsole<T>> {
+    pub(crate) fn new(out: T) -> WinConsole<T> {
         use std::mem::MaybeUninit;
 
         let fg;
@@ -132,13 +131,13 @@ impl<T: Write + Send + 'static> WinConsole<T> {
                 bg = color::BLACK;
             }
         }
-        Ok(WinConsole {
+        WinConsole {
             buf: out,
             def_foreground: fg,
             def_background: bg,
             foreground: fg,
             background: bg,
-        })
+        }
     }
 }
 
diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs
index 278cfb15bb1..b54be64efcf 100644
--- a/library/test/src/tests.rs
+++ b/library/test/src/tests.rs
@@ -611,33 +611,6 @@ fn sample_tests() -> Vec<TestDescAndFn> {
 }
 
 #[test]
-pub fn sort_tests() {
-    let mut opts = TestOpts::new();
-    opts.run_tests = true;
-
-    let tests = sample_tests();
-    let filtered = filter_tests(&opts, tests);
-
-    let expected = vec![
-        "isize::test_pow".to_string(),
-        "isize::test_to_str".to_string(),
-        "sha1::test".to_string(),
-        "test::do_not_run_ignored_tests".to_string(),
-        "test::filter_for_ignored_option".to_string(),
-        "test::first_free_arg_should_be_a_filter".to_string(),
-        "test::ignored_tests_result_in_ignored".to_string(),
-        "test::parse_ignored_flag".to_string(),
-        "test::parse_include_ignored_flag".to_string(),
-        "test::run_include_ignored_option".to_string(),
-        "test::sort_tests".to_string(),
-    ];
-
-    for (a, b) in expected.iter().zip(filtered) {
-        assert_eq!(*a, b.desc.name.to_string());
-    }
-}
-
-#[test]
 pub fn shuffle_tests() {
     let mut opts = TestOpts::new();
     opts.shuffle = true;
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 4ccdabe4bb6..e02a10b8164 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -21,7 +21,7 @@ use serde::Deserialize;
 use crate::builder::Cargo;
 use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
 use crate::cache::{Interned, INTERNER};
-use crate::config::{LlvmLibunwind, TargetSelection};
+use crate::config::{LlvmLibunwind, RustcLto, TargetSelection};
 use crate::dist;
 use crate::native;
 use crate::tool::SourceType;
@@ -701,6 +701,28 @@ impl Step for Rustc {
             ));
         }
 
+        // cfg(bootstrap): remove if condition once the bootstrap compiler supports dylib LTO
+        if compiler.stage != 0 {
+            match builder.config.rust_lto {
+                RustcLto::Thin | RustcLto::Fat => {
+                    // Since using LTO for optimizing dylibs is currently experimental,
+                    // we need to pass -Zdylib-lto.
+                    cargo.rustflag("-Zdylib-lto");
+                    // Cargo by default passes `-Cembed-bitcode=no` and doesn't pass `-Clto` when
+                    // compiling dylibs (and their dependencies), even when LTO is enabled for the
+                    // crate. Therefore, we need to override `-Clto` and `-Cembed-bitcode` here.
+                    let lto_type = match builder.config.rust_lto {
+                        RustcLto::Thin => "thin",
+                        RustcLto::Fat => "fat",
+                        _ => unreachable!(),
+                    };
+                    cargo.rustflag(&format!("-Clto={}", lto_type));
+                    cargo.rustflag("-Cembed-bitcode=yes");
+                }
+                RustcLto::ThinLocal => { /* Do nothing, this is the default */ }
+            }
+        }
+
         builder.info(&format!(
             "Building stage{} compiler artifacts ({} -> {})",
             compiler.stage, &compiler.host, target
@@ -1155,6 +1177,20 @@ impl Step for Sysroot {
                 );
             }
         }
+        // Same for the rustc-src component.
+        let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
+        t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
+        let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
+        if let Err(e) =
+            symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
+        {
+            eprintln!(
+                "warning: creating symbolic link `{}` to `{}` failed with {}",
+                sysroot_lib_rustlib_rustcsrc_rust.display(),
+                builder.src.display(),
+                e,
+            );
+        }
 
         INTERNER.intern_path(sysroot)
     }
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 635823b958b..a8c403675d8 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -158,6 +158,7 @@ pub struct Config {
     pub rust_new_symbol_mangling: Option<bool>,
     pub rust_profile_use: Option<String>,
     pub rust_profile_generate: Option<String>,
+    pub rust_lto: RustcLto,
     pub llvm_profile_use: Option<String>,
     pub llvm_profile_generate: bool,
     pub llvm_libunwind_default: Option<LlvmLibunwind>,
@@ -319,6 +320,28 @@ impl SplitDebuginfo {
     }
 }
 
+/// LTO mode used for compiling rustc itself.
+#[derive(Default, Clone)]
+pub enum RustcLto {
+    #[default]
+    ThinLocal,
+    Thin,
+    Fat,
+}
+
+impl std::str::FromStr for RustcLto {
+    type Err = String;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "thin-local" => Ok(RustcLto::ThinLocal),
+            "thin" => Ok(RustcLto::Thin),
+            "fat" => Ok(RustcLto::Fat),
+            _ => Err(format!("Invalid value for rustc LTO: {}", s)),
+        }
+    }
+}
+
 #[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct TargetSelection {
     pub triple: Interned<String>,
@@ -726,6 +749,7 @@ define_config! {
         profile_use: Option<String> = "profile-use",
         // ignored; this is set from an env var set by bootstrap.py
         download_rustc: Option<StringOrBool> = "download-rustc",
+        lto: Option<String> = "lto",
     }
 }
 
@@ -1173,6 +1197,12 @@ impl Config {
             config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use);
             config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate);
             config.download_rustc_commit = download_ci_rustc_commit(&config, rust.download_rustc);
+
+            config.rust_lto = rust
+                .lto
+                .as_deref()
+                .map(|value| RustcLto::from_str(value).unwrap())
+                .unwrap_or_default();
         } else {
             config.rust_profile_use = flags.rust_profile_use;
             config.rust_profile_generate = flags.rust_profile_generate;
diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md
index 38629c4fae7..ea236bee563 100644
--- a/src/ci/docker/README.md
+++ b/src/ci/docker/README.md
@@ -250,6 +250,92 @@ For targets: `i586-unknown-linux-gnu`
 (\*) Compressed debug is enabled by default for gas (assembly) on Linux/x86 targets,
      but that makes our `compiler_builtins` incompatible with binutils < 2.32.
 
+### `mips-linux-gnu.config`
+
+For targets: `mips-unknown-linux-gnu`
+
+- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
+- Path and misc options > Patches origin = Bundled, then local
+- Path and misc options > Local patch directory = /tmp/patches
+- Target options > Target Architecture = mips
+- Target options > ABI = o32
+- Target options > Endianness = Big endian
+- Target options > Bitness = 32-bit
+- Target options > Architecture level = mips32r2
+- Operating System > Target OS = linux
+- Operating System > Linux kernel version = 4.4.174
+- Binary utilities > Version of binutils = 2.32
+- C-library > glibc version = 2.23
+- C compiler > gcc version = 8.3.0
+- C compiler > gcc extra config = --with-fp-32=xx --with-odd-spreg-32=no
+- C compiler > C++ = ENABLE -- to cross compile LLVM
+
+### `mipsel-linux-gnu.config`
+
+For targets: `mipsel-unknown-linux-gnu`
+
+- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
+- Path and misc options > Patches origin = Bundled, then local
+- Path and misc options > Local patch directory = /tmp/patches
+- Target options > Target Architecture = mips
+- Target options > ABI = o32
+- Target options > Endianness = Little endian
+- Target options > Bitness = 32-bit
+- Target options > Architecture level = mips32r2
+- Operating System > Target OS = linux
+- Operating System > Linux kernel version = 4.4.174
+- Binary utilities > Version of binutils = 2.32
+- C-library > glibc version = 2.23
+- C compiler > gcc version = 8.3.0
+- C compiler > gcc extra config = --with-fp-32=xx --with-odd-spreg-32=no
+- C compiler > C++ = ENABLE -- to cross compile LLVM
+
+### `mips64-linux-gnu.config`
+
+For targets: `mips64-unknown-linux-gnuabi64`
+
+- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
+- Path and misc options > Patches origin = Bundled, then local
+- Path and misc options > Local patch directory = /tmp/patches
+- Target options > Target Architecture = mips
+- Target options > ABI = n64
+- Target options > Endianness = Big endian
+- Target options > Bitness = 64-bit
+- Target options > Architecture level = mips64r2
+- Operating System > Target OS = linux
+- Operating System > Linux kernel version = 4.4.174
+- Binary utilities > Version of binutils = 2.32
+- C-library > glibc version = 2.23
+- C compiler > gcc version = 8.3.0
+- C compiler > C++ = ENABLE -- to cross compile LLVM
+
+### `mips64el-linux-gnu.config`
+
+For targets: `mips64el-unknown-linux-gnuabi64`
+
+- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
+- Path and misc options > Patches origin = Bundled, then local
+- Path and misc options > Local patch directory = /tmp/patches
+- Target options > Target Architecture = mips
+- Target options > ABI = n64
+- Target options > Endianness = Little endian
+- Target options > Bitness = 64-bit
+- Target options > Architecture level = mips64r2
+- Operating System > Target OS = linux
+- Operating System > Linux kernel version = 4.4.174
+- Binary utilities > Version of binutils = 2.32
+- C-library > glibc version = 2.23
+- C compiler > gcc version = 8.3.0
+- C compiler > C++ = ENABLE -- to cross compile LLVM
+
 ### `powerpc-linux-gnu.config`
 
 For targets: `powerpc-unknown-linux-gnu`
diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile
index 948fa40dd4b..eb511b32107 100644
--- a/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile
@@ -1,31 +1,30 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
-  make \
-  ninja-build \
-  file \
-  curl \
-  ca-certificates \
-  python3 \
-  git \
-  cmake \
-  sudo \
-  gdb \
-  xz-utils \
-  g++-mips-linux-gnu \
-  libssl-dev \
-  pkg-config
+FROM ubuntu:22.04
 
+COPY scripts/cross-apt-packages.sh /scripts/
+RUN sh /scripts/cross-apt-packages.sh
+
+COPY scripts/crosstool-ng-1.24.sh /scripts/
+RUN sh /scripts/crosstool-ng-1.24.sh
+
+COPY scripts/rustbuild-setup.sh /scripts/
+RUN sh /scripts/rustbuild-setup.sh
+WORKDIR /tmp
+
+COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/
+COPY host-x86_64/dist-mips-linux/mips-linux-gnu.config host-x86_64/dist-mips-linux/build-mips-toolchain.sh /tmp/
+RUN su rustbuild -c ./build-mips-toolchain.sh
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
+ENV PATH=$PATH:/x-tools/mips-unknown-linux-gnu/bin
+
+ENV \
+    CC_mips_unknown_linux_gnu=mips-unknown-linux-gnu-gcc \
+    AR_mips_unknown_linux_gnu=mips-unknown-linux-gnu-ar \
+    CXX_mips_unknown_linux_gnu=mips-unknown-linux-gnu-g++
 
 ENV HOSTS=mips-unknown-linux-gnu
 
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs \
-    --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/build-mips-toolchain.sh b/src/ci/docker/host-x86_64/dist-mips-linux/build-mips-toolchain.sh
new file mode 100755
index 00000000000..32612cf6852
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips-linux/build-mips-toolchain.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+set -ex
+
+hide_output() {
+  set +x
+  on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+  trap "$on_err" ERR
+  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+  PING_LOOP_PID=$!
+  "$@" &> /tmp/build.log
+  rm /tmp/build.log
+  trap - ERR
+  kill $PING_LOOP_PID
+  set -x
+}
+
+mkdir build
+cd build
+cp ../mips-linux-gnu.config .config
+hide_output ct-ng build
+cd ..
+rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.config b/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.config
new file mode 100644
index 00000000000..575584ef0cf
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.config
@@ -0,0 +1,740 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# crosstool-NG  Configuration
+#
+CT_CONFIGURE_has_static_link=y
+CT_CONFIGURE_has_cxx11=y
+CT_CONFIGURE_has_wget=y
+CT_CONFIGURE_has_curl=y
+CT_CONFIGURE_has_make_3_81_or_newer=y
+CT_CONFIGURE_has_make_4_0_or_newer=y
+CT_CONFIGURE_has_libtool_2_4_or_newer=y
+CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
+CT_CONFIGURE_has_autoconf_2_65_or_newer=y
+CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
+CT_CONFIGURE_has_automake_1_15_or_newer=y
+CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
+CT_CONFIGURE_has_python_3_4_or_newer=y
+CT_CONFIGURE_has_bison_2_7_or_newer=y
+CT_CONFIGURE_has_python=y
+CT_CONFIGURE_has_git=y
+CT_CONFIGURE_has_md5sum=y
+CT_CONFIGURE_has_sha1sum=y
+CT_CONFIGURE_has_sha256sum=y
+CT_CONFIGURE_has_sha512sum=y
+CT_CONFIGURE_has_install_with_strip_program=y
+CT_CONFIG_VERSION_CURRENT="3"
+CT_CONFIG_VERSION="3"
+CT_MODULES=y
+
+#
+# Paths and misc options
+#
+
+#
+# crosstool-NG behavior
+#
+# CT_OBSOLETE is not set
+# CT_EXPERIMENTAL is not set
+# CT_DEBUG_CT is not set
+
+#
+# Paths
+#
+CT_LOCAL_TARBALLS_DIR="${HOME}/src"
+CT_SAVE_TARBALLS=y
+# CT_TARBALLS_BUILDROOT_LAYOUT is not set
+CT_WORK_DIR="${CT_TOP_DIR}/.build"
+CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_RM_RF_PREFIX_DIR=y
+CT_REMOVE_DOCS=y
+CT_INSTALL_LICENSES=y
+CT_PREFIX_DIR_RO=y
+CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
+# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
+
+#
+# Downloading
+#
+CT_DOWNLOAD_AGENT_WGET=y
+# CT_DOWNLOAD_AGENT_CURL is not set
+# CT_DOWNLOAD_AGENT_NONE is not set
+# CT_FORBID_DOWNLOAD is not set
+# CT_FORCE_DOWNLOAD is not set
+CT_CONNECT_TIMEOUT=10
+CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
+# CT_ONLY_DOWNLOAD is not set
+CT_USE_MIRROR=y
+# CT_FORCE_MIRROR is not set
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_VERIFY_DOWNLOAD_DIGEST=y
+CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
+CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
+# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
+
+#
+# Extracting
+#
+# CT_FORCE_EXTRACT is not set
+CT_OVERRIDE_CONFIG_GUESS_SUB=y
+# CT_ONLY_EXTRACT is not set
+# CT_PATCH_BUNDLED is not set
+CT_PATCH_BUNDLED_LOCAL=y
+CT_PATCH_ORDER="bundled,local"
+CT_PATCH_USE_LOCAL=y
+CT_LOCAL_PATCH_DIR="/tmp/patches"
+
+#
+# Build behavior
+#
+CT_PARALLEL_JOBS=0
+CT_LOAD=""
+CT_USE_PIPES=y
+CT_EXTRA_CFLAGS_FOR_BUILD=""
+CT_EXTRA_LDFLAGS_FOR_BUILD=""
+CT_EXTRA_CFLAGS_FOR_HOST=""
+CT_EXTRA_LDFLAGS_FOR_HOST=""
+# CT_CONFIG_SHELL_SH is not set
+# CT_CONFIG_SHELL_ASH is not set
+CT_CONFIG_SHELL_BASH=y
+# CT_CONFIG_SHELL_CUSTOM is not set
+CT_CONFIG_SHELL="${bash}"
+
+#
+# Logging
+#
+# CT_LOG_ERROR is not set
+# CT_LOG_WARN is not set
+# CT_LOG_INFO is not set
+CT_LOG_EXTRA=y
+# CT_LOG_ALL is not set
+# CT_LOG_DEBUG is not set
+CT_LOG_LEVEL_MAX="EXTRA"
+# CT_LOG_SEE_TOOLS_WARN is not set
+CT_LOG_PROGRESS_BAR=y
+CT_LOG_TO_FILE=y
+CT_LOG_FILE_COMPRESS=y
+
+#
+# Target options
+#
+# CT_ARCH_ALPHA is not set
+# CT_ARCH_ARC is not set
+# CT_ARCH_ARM is not set
+# CT_ARCH_AVR is not set
+# CT_ARCH_M68K is not set
+CT_ARCH_MIPS=y
+# CT_ARCH_NIOS2 is not set
+# CT_ARCH_POWERPC is not set
+# CT_ARCH_S390 is not set
+# CT_ARCH_SH is not set
+# CT_ARCH_SPARC is not set
+# CT_ARCH_X86 is not set
+# CT_ARCH_XTENSA is not set
+CT_ARCH="mips"
+CT_ARCH_CHOICE_KSYM="MIPS"
+CT_ARCH_TUNE=""
+CT_ARCH_MIPS_SHOW=y
+
+#
+# Options for mips
+#
+CT_ARCH_MIPS_PKG_KSYM=""
+CT_ARCH_mips_o32=y
+CT_ARCH_mips_ABI="32"
+CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
+CT_ARCH_SUFFIX=""
+# CT_OMIT_TARGET_VENDOR is not set
+
+#
+# Generic target options
+#
+# CT_MULTILIB is not set
+CT_DEMULTILIB=y
+CT_ARCH_USE_MMU=y
+CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
+CT_ARCH_DEFAULT_BE=y
+CT_ARCH_BE=y
+# CT_ARCH_LE is not set
+CT_ARCH_ENDIAN="big"
+CT_ARCH_SUPPORTS_32=y
+CT_ARCH_SUPPORTS_64=y
+CT_ARCH_DEFAULT_32=y
+CT_ARCH_BITNESS=32
+CT_ARCH_32=y
+# CT_ARCH_64 is not set
+
+#
+# Target optimisations
+#
+CT_ARCH_SUPPORTS_WITH_ARCH=y
+CT_ARCH_SUPPORTS_WITH_TUNE=y
+CT_ARCH_SUPPORTS_WITH_FLOAT=y
+CT_ARCH_ARCH="mips32r2"
+CT_ARCH_FLOAT_AUTO=y
+# CT_ARCH_FLOAT_HW is not set
+# CT_ARCH_FLOAT_SW is not set
+CT_TARGET_CFLAGS=""
+CT_TARGET_LDFLAGS=""
+CT_ARCH_FLOAT="auto"
+
+#
+# Toolchain options
+#
+
+#
+# General toolchain options
+#
+CT_FORCE_SYSROOT=y
+CT_USE_SYSROOT=y
+CT_SYSROOT_NAME="sysroot"
+CT_SYSROOT_DIR_PREFIX=""
+CT_WANTS_STATIC_LINK=y
+CT_WANTS_STATIC_LINK_CXX=y
+# CT_STATIC_TOOLCHAIN is not set
+CT_SHOW_CT_VERSION=y
+CT_TOOLCHAIN_PKGVERSION=""
+CT_TOOLCHAIN_BUGURL=""
+
+#
+# Tuple completion and aliasing
+#
+CT_TARGET_VENDOR="unknown"
+CT_TARGET_ALIAS_SED_EXPR=""
+CT_TARGET_ALIAS=""
+
+#
+# Toolchain type
+#
+CT_CROSS=y
+# CT_CANADIAN is not set
+CT_TOOLCHAIN_TYPE="cross"
+
+#
+# Build system
+#
+CT_BUILD=""
+CT_BUILD_PREFIX=""
+CT_BUILD_SUFFIX=""
+
+#
+# Misc options
+#
+# CT_TOOLCHAIN_ENABLE_NLS is not set
+
+#
+# Operating System
+#
+CT_KERNEL_SUPPORTS_SHARED_LIBS=y
+# CT_KERNEL_BARE_METAL is not set
+CT_KERNEL_LINUX=y
+CT_KERNEL="linux"
+CT_KERNEL_CHOICE_KSYM="LINUX"
+CT_KERNEL_LINUX_SHOW=y
+
+#
+# Options for linux
+#
+CT_KERNEL_LINUX_PKG_KSYM="LINUX"
+CT_LINUX_DIR_NAME="linux"
+CT_LINUX_PKG_NAME="linux"
+CT_LINUX_SRC_RELEASE=y
+CT_LINUX_PATCH_ORDER="global"
+# CT_LINUX_V_4_20 is not set
+# CT_LINUX_V_4_19 is not set
+# CT_LINUX_V_4_18 is not set
+# CT_LINUX_V_4_17 is not set
+# CT_LINUX_V_4_16 is not set
+# CT_LINUX_V_4_15 is not set
+# CT_LINUX_V_4_14 is not set
+# CT_LINUX_V_4_13 is not set
+# CT_LINUX_V_4_12 is not set
+# CT_LINUX_V_4_11 is not set
+# CT_LINUX_V_4_10 is not set
+# CT_LINUX_V_4_9 is not set
+CT_LINUX_V_4_4=y
+# CT_LINUX_V_4_1 is not set
+# CT_LINUX_V_3_16 is not set
+# CT_LINUX_V_3_13 is not set
+# CT_LINUX_V_3_12 is not set
+# CT_LINUX_V_3_10 is not set
+# CT_LINUX_V_3_4 is not set
+# CT_LINUX_V_3_2 is not set
+# CT_LINUX_V_2_6_32 is not set
+# CT_LINUX_NO_VERSIONS is not set
+CT_LINUX_VERSION="4.4.174"
+CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
+CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
+CT_LINUX_4_8_or_older=y
+CT_LINUX_older_than_4_8=y
+CT_LINUX_later_than_3_7=y
+CT_LINUX_3_7_or_later=y
+CT_LINUX_later_than_3_2=y
+CT_LINUX_3_2_or_later=y
+CT_KERNEL_LINUX_VERBOSITY_0=y
+# CT_KERNEL_LINUX_VERBOSITY_1 is not set
+# CT_KERNEL_LINUX_VERBOSITY_2 is not set
+CT_KERNEL_LINUX_VERBOSE_LEVEL=0
+CT_KERNEL_LINUX_INSTALL_CHECK=y
+CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
+
+#
+# Common kernel options
+#
+CT_SHARED_LIBS=y
+
+#
+# Binary utilities
+#
+CT_ARCH_BINFMT_ELF=y
+CT_BINUTILS_BINUTILS=y
+CT_BINUTILS="binutils"
+CT_BINUTILS_CHOICE_KSYM="BINUTILS"
+CT_BINUTILS_BINUTILS_SHOW=y
+
+#
+# Options for binutils
+#
+CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
+CT_BINUTILS_DIR_NAME="binutils"
+CT_BINUTILS_USE_GNU=y
+CT_BINUTILS_USE="BINUTILS"
+CT_BINUTILS_PKG_NAME="binutils"
+CT_BINUTILS_SRC_RELEASE=y
+CT_BINUTILS_PATCH_ORDER="global"
+CT_BINUTILS_V_2_32=y
+# CT_BINUTILS_V_2_31 is not set
+# CT_BINUTILS_V_2_30 is not set
+# CT_BINUTILS_V_2_29 is not set
+# CT_BINUTILS_V_2_28 is not set
+# CT_BINUTILS_V_2_27 is not set
+# CT_BINUTILS_V_2_26 is not set
+# CT_BINUTILS_NO_VERSIONS is not set
+CT_BINUTILS_VERSION="2.32"
+CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
+CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
+CT_BINUTILS_later_than_2_30=y
+CT_BINUTILS_2_30_or_later=y
+CT_BINUTILS_later_than_2_27=y
+CT_BINUTILS_2_27_or_later=y
+CT_BINUTILS_later_than_2_25=y
+CT_BINUTILS_2_25_or_later=y
+CT_BINUTILS_later_than_2_23=y
+CT_BINUTILS_2_23_or_later=y
+
+#
+# GNU binutils
+#
+CT_BINUTILS_HAS_HASH_STYLE=y
+CT_BINUTILS_HAS_GOLD=y
+CT_BINUTILS_HAS_PLUGINS=y
+CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
+CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
+CT_BINUTILS_LINKER_LD=y
+CT_BINUTILS_LINKERS_LIST="ld"
+CT_BINUTILS_LINKER_DEFAULT="bfd"
+# CT_BINUTILS_PLUGINS is not set
+CT_BINUTILS_RELRO=m
+CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
+# CT_BINUTILS_FOR_TARGET is not set
+CT_ALL_BINUTILS_CHOICES="BINUTILS"
+
+#
+# C-library
+#
+CT_LIBC_GLIBC=y
+# CT_LIBC_UCLIBC is not set
+CT_LIBC="glibc"
+CT_LIBC_CHOICE_KSYM="GLIBC"
+CT_THREADS="nptl"
+CT_LIBC_GLIBC_SHOW=y
+
+#
+# Options for glibc
+#
+CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
+CT_GLIBC_DIR_NAME="glibc"
+CT_GLIBC_USE_GNU=y
+CT_GLIBC_USE="GLIBC"
+CT_GLIBC_PKG_NAME="glibc"
+CT_GLIBC_SRC_RELEASE=y
+CT_GLIBC_PATCH_ORDER="global"
+# CT_GLIBC_V_2_29 is not set
+# CT_GLIBC_V_2_28 is not set
+# CT_GLIBC_V_2_27 is not set
+# CT_GLIBC_V_2_26 is not set
+# CT_GLIBC_V_2_25 is not set
+# CT_GLIBC_V_2_24 is not set
+CT_GLIBC_V_2_23=y
+# CT_GLIBC_V_2_19 is not set
+# CT_GLIBC_V_2_17 is not set
+# CT_GLIBC_V_2_12_1 is not set
+# CT_GLIBC_NO_VERSIONS is not set
+CT_GLIBC_VERSION="2.23"
+CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
+CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
+CT_GLIBC_2_29_or_older=y
+CT_GLIBC_older_than_2_29=y
+CT_GLIBC_2_27_or_older=y
+CT_GLIBC_older_than_2_27=y
+CT_GLIBC_2_26_or_older=y
+CT_GLIBC_older_than_2_26=y
+CT_GLIBC_2_25_or_older=y
+CT_GLIBC_older_than_2_25=y
+CT_GLIBC_2_24_or_older=y
+CT_GLIBC_older_than_2_24=y
+CT_GLIBC_2_23_or_later=y
+CT_GLIBC_2_23_or_older=y
+CT_GLIBC_later_than_2_20=y
+CT_GLIBC_2_20_or_later=y
+CT_GLIBC_later_than_2_17=y
+CT_GLIBC_2_17_or_later=y
+CT_GLIBC_later_than_2_14=y
+CT_GLIBC_2_14_or_later=y
+CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
+CT_GLIBC_DEP_BINUTILS=y
+CT_GLIBC_DEP_GCC=y
+CT_GLIBC_DEP_PYTHON=y
+CT_GLIBC_HAS_LIBIDN_ADDON=y
+# CT_GLIBC_USE_LIBIDN_ADDON is not set
+CT_GLIBC_NO_SPARC_V8=y
+CT_GLIBC_HAS_OBSOLETE_RPC=y
+CT_GLIBC_EXTRA_CONFIG_ARRAY=""
+CT_GLIBC_CONFIGPARMS=""
+CT_GLIBC_EXTRA_CFLAGS=""
+CT_GLIBC_ENABLE_OBSOLETE_RPC=y
+# CT_GLIBC_DISABLE_VERSIONING is not set
+CT_GLIBC_OLDEST_ABI=""
+CT_GLIBC_FORCE_UNWIND=y
+# CT_GLIBC_LOCALES is not set
+# CT_GLIBC_KERNEL_VERSION_NONE is not set
+CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
+# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
+CT_GLIBC_MIN_KERNEL="4.4.174"
+CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
+CT_LIBC_SUPPORT_THREADS_ANY=y
+CT_LIBC_SUPPORT_THREADS_NATIVE=y
+
+#
+# Common C library options
+#
+CT_THREADS_NATIVE=y
+# CT_CREATE_LDSO_CONF is not set
+CT_LIBC_XLDD=y
+
+#
+# C compiler
+#
+CT_CC_CORE_PASSES_NEEDED=y
+CT_CC_CORE_PASS_1_NEEDED=y
+CT_CC_CORE_PASS_2_NEEDED=y
+CT_CC_SUPPORT_CXX=y
+CT_CC_SUPPORT_FORTRAN=y
+CT_CC_SUPPORT_ADA=y
+CT_CC_SUPPORT_OBJC=y
+CT_CC_SUPPORT_OBJCXX=y
+CT_CC_SUPPORT_GOLANG=y
+CT_CC_GCC=y
+CT_CC="gcc"
+CT_CC_CHOICE_KSYM="GCC"
+CT_CC_GCC_SHOW=y
+
+#
+# Options for gcc
+#
+CT_CC_GCC_PKG_KSYM="GCC"
+CT_GCC_DIR_NAME="gcc"
+CT_GCC_USE_GNU=y
+CT_GCC_USE="GCC"
+CT_GCC_PKG_NAME="gcc"
+CT_GCC_SRC_RELEASE=y
+CT_GCC_PATCH_ORDER="global"
+CT_GCC_V_8=y
+# CT_GCC_V_7 is not set
+# CT_GCC_V_6 is not set
+# CT_GCC_V_5 is not set
+# CT_GCC_V_4_9 is not set
+# CT_GCC_NO_VERSIONS is not set
+CT_GCC_VERSION="8.3.0"
+CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
+CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_GCC_SIGNATURE_FORMAT=""
+CT_GCC_later_than_7=y
+CT_GCC_7_or_later=y
+CT_GCC_later_than_6=y
+CT_GCC_6_or_later=y
+CT_GCC_later_than_5=y
+CT_GCC_5_or_later=y
+CT_GCC_later_than_4_9=y
+CT_GCC_4_9_or_later=y
+CT_GCC_later_than_4_8=y
+CT_GCC_4_8_or_later=y
+CT_CC_GCC_HAS_LIBMPX=y
+CT_CC_GCC_ENABLE_CXX_FLAGS=""
+CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_EXTRA_CONFIG_ARRAY="--with-fp-32=xx --with-odd-spreg-32=no"
+CT_CC_GCC_STATIC_LIBSTDCXX=y
+# CT_CC_GCC_SYSTEM_ZLIB is not set
+CT_CC_GCC_CONFIG_TLS=m
+
+#
+# Optimisation features
+#
+CT_CC_GCC_USE_GRAPHITE=y
+CT_CC_GCC_USE_LTO=y
+
+#
+# Settings for libraries running on target
+#
+CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
+# CT_CC_GCC_LIBMUDFLAP is not set
+# CT_CC_GCC_LIBGOMP is not set
+# CT_CC_GCC_LIBSSP is not set
+# CT_CC_GCC_LIBQUADMATH is not set
+# CT_CC_GCC_LIBSANITIZER is not set
+
+#
+# Misc. obscure options.
+#
+CT_CC_CXA_ATEXIT=y
+# CT_CC_GCC_DISABLE_PCH is not set
+CT_CC_GCC_SJLJ_EXCEPTIONS=m
+CT_CC_GCC_LDBL_128=m
+# CT_CC_GCC_BUILD_ID is not set
+CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
+# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
+# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
+# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
+CT_CC_GCC_LNK_HASH_STYLE=""
+CT_CC_GCC_DEC_FLOAT_AUTO=y
+# CT_CC_GCC_DEC_FLOAT_BID is not set
+# CT_CC_GCC_DEC_FLOAT_DPD is not set
+# CT_CC_GCC_DEC_FLOATS_NO is not set
+CT_CC_GCC_HAS_ARCH_OPTIONS=y
+
+#
+# archictecture-specific options
+#
+CT_CC_GCC_mips_llsc=m
+CT_CC_GCC_mips_synci=m
+# CT_CC_GCC_mips_plt is not set
+CT_ALL_CC_CHOICES="GCC"
+
+#
+# Additional supported languages:
+#
+CT_CC_LANG_CXX=y
+# CT_CC_LANG_FORTRAN is not set
+
+#
+# Debug facilities
+#
+# CT_DEBUG_DUMA is not set
+# CT_DEBUG_GDB is not set
+# CT_DEBUG_LTRACE is not set
+# CT_DEBUG_STRACE is not set
+CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
+
+#
+# Companion libraries
+#
+# CT_COMPLIBS_CHECK is not set
+# CT_COMP_LIBS_CLOOG is not set
+# CT_COMP_LIBS_EXPAT is not set
+CT_COMP_LIBS_GETTEXT=y
+CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
+CT_GETTEXT_DIR_NAME="gettext"
+CT_GETTEXT_PKG_NAME="gettext"
+CT_GETTEXT_SRC_RELEASE=y
+CT_GETTEXT_PATCH_ORDER="global"
+CT_GETTEXT_V_0_19_8_1=y
+# CT_GETTEXT_NO_VERSIONS is not set
+CT_GETTEXT_VERSION="0.19.8.1"
+CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
+CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
+CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_GMP=y
+CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
+CT_GMP_DIR_NAME="gmp"
+CT_GMP_PKG_NAME="gmp"
+CT_GMP_SRC_RELEASE=y
+CT_GMP_PATCH_ORDER="global"
+CT_GMP_V_6_1=y
+# CT_GMP_NO_VERSIONS is not set
+CT_GMP_VERSION="6.1.2"
+CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
+CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
+CT_GMP_SIGNATURE_FORMAT="packed/.sig"
+CT_GMP_later_than_5_1_0=y
+CT_GMP_5_1_0_or_later=y
+CT_GMP_later_than_5_0_0=y
+CT_GMP_5_0_0_or_later=y
+CT_GMP_REQUIRE_5_0_0_or_later=y
+CT_COMP_LIBS_ISL=y
+CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
+CT_ISL_DIR_NAME="isl"
+CT_ISL_PKG_NAME="isl"
+CT_ISL_SRC_RELEASE=y
+CT_ISL_PATCH_ORDER="global"
+CT_ISL_V_0_20=y
+# CT_ISL_V_0_19 is not set
+# CT_ISL_V_0_18 is not set
+# CT_ISL_V_0_17 is not set
+# CT_ISL_V_0_16 is not set
+# CT_ISL_V_0_15 is not set
+# CT_ISL_NO_VERSIONS is not set
+CT_ISL_VERSION="0.20"
+CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
+CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_ISL_SIGNATURE_FORMAT=""
+CT_ISL_later_than_0_18=y
+CT_ISL_0_18_or_later=y
+CT_ISL_later_than_0_15=y
+CT_ISL_0_15_or_later=y
+CT_ISL_REQUIRE_0_15_or_later=y
+CT_ISL_later_than_0_14=y
+CT_ISL_0_14_or_later=y
+CT_ISL_REQUIRE_0_14_or_later=y
+CT_ISL_later_than_0_13=y
+CT_ISL_0_13_or_later=y
+CT_ISL_later_than_0_12=y
+CT_ISL_0_12_or_later=y
+CT_ISL_REQUIRE_0_12_or_later=y
+# CT_COMP_LIBS_LIBELF is not set
+CT_COMP_LIBS_LIBICONV=y
+CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
+CT_LIBICONV_DIR_NAME="libiconv"
+CT_LIBICONV_PKG_NAME="libiconv"
+CT_LIBICONV_SRC_RELEASE=y
+CT_LIBICONV_PATCH_ORDER="global"
+CT_LIBICONV_V_1_15=y
+# CT_LIBICONV_NO_VERSIONS is not set
+CT_LIBICONV_VERSION="1.15"
+CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
+CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
+CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_MPC=y
+CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
+CT_MPC_DIR_NAME="mpc"
+CT_MPC_PKG_NAME="mpc"
+CT_MPC_SRC_RELEASE=y
+CT_MPC_PATCH_ORDER="global"
+CT_MPC_V_1_1=y
+# CT_MPC_V_1_0 is not set
+# CT_MPC_NO_VERSIONS is not set
+CT_MPC_VERSION="1.1.0"
+CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
+CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_FORMATS=".tar.gz"
+CT_MPC_SIGNATURE_FORMAT="packed/.sig"
+CT_MPC_1_1_0_or_later=y
+CT_MPC_1_1_0_or_older=y
+CT_COMP_LIBS_MPFR=y
+CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
+CT_MPFR_DIR_NAME="mpfr"
+CT_MPFR_PKG_NAME="mpfr"
+CT_MPFR_SRC_RELEASE=y
+CT_MPFR_PATCH_ORDER="global"
+CT_MPFR_V_4_0=y
+# CT_MPFR_V_3_1 is not set
+# CT_MPFR_NO_VERSIONS is not set
+CT_MPFR_VERSION="4.0.2"
+CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
+CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
+CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
+CT_MPFR_later_than_4_0_0=y
+CT_MPFR_4_0_0_or_later=y
+CT_MPFR_later_than_3_0_0=y
+CT_MPFR_3_0_0_or_later=y
+CT_MPFR_REQUIRE_3_0_0_or_later=y
+CT_COMP_LIBS_NCURSES=y
+CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
+CT_NCURSES_DIR_NAME="ncurses"
+CT_NCURSES_PKG_NAME="ncurses"
+CT_NCURSES_SRC_RELEASE=y
+CT_NCURSES_PATCH_ORDER="global"
+CT_NCURSES_V_6_1=y
+# CT_NCURSES_V_6_0 is not set
+# CT_NCURSES_NO_VERSIONS is not set
+CT_NCURSES_VERSION="6.1"
+CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
+CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
+CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
+CT_NCURSES_HOST_CONFIG_ARGS=""
+CT_NCURSES_HOST_DISABLE_DB=y
+CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
+CT_NCURSES_TARGET_CONFIG_ARGS=""
+# CT_NCURSES_TARGET_DISABLE_DB is not set
+CT_NCURSES_TARGET_FALLBACKS=""
+CT_COMP_LIBS_ZLIB=y
+CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
+CT_ZLIB_DIR_NAME="zlib"
+CT_ZLIB_PKG_NAME="zlib"
+CT_ZLIB_SRC_RELEASE=y
+CT_ZLIB_PATCH_ORDER="global"
+CT_ZLIB_V_1_2_11=y
+# CT_ZLIB_NO_VERSIONS is not set
+CT_ZLIB_VERSION="1.2.11"
+CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
+CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
+CT_LIBICONV_NEEDED=y
+CT_GETTEXT_NEEDED=y
+CT_GMP_NEEDED=y
+CT_MPFR_NEEDED=y
+CT_ISL_NEEDED=y
+CT_MPC_NEEDED=y
+CT_NCURSES_NEEDED=y
+CT_ZLIB_NEEDED=y
+CT_LIBICONV=y
+CT_GETTEXT=y
+CT_GMP=y
+CT_MPFR=y
+CT_ISL=y
+CT_MPC=y
+CT_NCURSES=y
+CT_ZLIB=y
+
+#
+# Companion tools
+#
+# CT_COMP_TOOLS_FOR_HOST is not set
+# CT_COMP_TOOLS_AUTOCONF is not set
+# CT_COMP_TOOLS_AUTOMAKE is not set
+# CT_COMP_TOOLS_BISON is not set
+# CT_COMP_TOOLS_DTC is not set
+# CT_COMP_TOOLS_LIBTOOL is not set
+# CT_COMP_TOOLS_M4 is not set
+# CT_COMP_TOOLS_MAKE is not set
+CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0001-MIPS-SPARC-fix-wrong-vfork-aliases-in-libpthread.so.patch b/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0001-MIPS-SPARC-fix-wrong-vfork-aliases-in-libpthread.so.patch
new file mode 100644
index 00000000000..393084df324
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0001-MIPS-SPARC-fix-wrong-vfork-aliases-in-libpthread.so.patch
@@ -0,0 +1,44 @@
+From 43c2948756bb6e144c7b871e827bba37d61ad3a3 Mon Sep 17 00:00:00 2001
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Sat, 18 Jun 2016 19:11:23 +0200
+Subject: [PATCH 1/2] MIPS, SPARC: fix wrong vfork aliases in libpthread.so
+
+With recent binutils versions the GNU libc fails to build on at least
+MISP and SPARC, with this kind of error:
+
+  /home/aurel32/glibc/glibc-build/nptl/libpthread.so:(*IND*+0x0): multiple definition of `vfork@GLIBC_2.0'
+  /home/aurel32/glibc/glibc-build/nptl/libpthread.so::(.text+0xee50): first defined here
+
+It appears that on these architectures pt-vfork.S includes vfork.S
+(through the alpha version of pt-vfork.S) and that the __vfork aliases
+are not conditionalized on IS_IN (libc) like on other architectures.
+Therefore the aliases are also wrongly included in libpthread.so.
+
+Fix this by properly conditionalizing the aliases like on other
+architectures.
+
+Changelog:
+	* sysdeps/unix/sysv/linux/mips/vfork.S (__vfork): Conditionalize
+	hidden_def, weak_alias and strong_alias on [IS_IN (libc)].
+	* sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S: Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S: Likewise.
+---
+ sysdeps/unix/sysv/linux/mips/vfork.S | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sysdeps/unix/sysv/linux/mips/vfork.S b/sysdeps/unix/sysv/linux/mips/vfork.S
+index 8c6615143708..c0c0ce699159 100644
+--- a/sysdeps/unix/sysv/linux/mips/vfork.S
++++ b/sysdeps/unix/sysv/linux/mips/vfork.S
+@@ -106,6 +106,8 @@ L(error):
+ #endif
+ 	END(__vfork)
+ 
++#if IS_IN (libc)
+ libc_hidden_def(__vfork)
+ weak_alias (__vfork, vfork)
+ strong_alias (__vfork, __libc_vfork)
++#endif
+-- 
+2.37.3
+
diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0002-MIPS-SPARC-more-fixes-to-the-vfork-aliases-in-libpth.patch b/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0002-MIPS-SPARC-more-fixes-to-the-vfork-aliases-in-libpth.patch
new file mode 100644
index 00000000000..e28c7ae99f0
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0002-MIPS-SPARC-more-fixes-to-the-vfork-aliases-in-libpth.patch
@@ -0,0 +1,63 @@
+From b87c1ec3fa398646f042a68f0ce0f7d09c1348c7 Mon Sep 17 00:00:00 2001
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Tue, 21 Jun 2016 23:59:37 +0200
+Subject: [PATCH 2/2] MIPS, SPARC: more fixes to the vfork aliases in
+ libpthread.so
+
+Commit 43c29487 tried to fix the vfork aliases in libpthread.so on MIPS
+and SPARC, but failed to do it correctly, introducing an ABI change.
+
+This patch does the remaining changes needed to align the MIPS and SPARC
+vfork implementations with the other architectures. That way the the
+alpha version of pt-vfork.S works correctly for MIPS and SPARC. The
+changes for alpha were done in 82aab97c.
+
+Changelog:
+	* sysdeps/unix/sysv/linux/mips/vfork.S (__vfork): Rename into
+	__libc_vfork.
+	(__vfork) [IS_IN (libc)]: Remove alias.
+	(__libc_vfork) [IS_IN (libc)]: Define as an alias.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S: Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S: Likewise.
+---
+ sysdeps/unix/sysv/linux/mips/vfork.S | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/sysdeps/unix/sysv/linux/mips/vfork.S b/sysdeps/unix/sysv/linux/mips/vfork.S
+index c0c0ce699159..1867c8626ebe 100644
+--- a/sysdeps/unix/sysv/linux/mips/vfork.S
++++ b/sysdeps/unix/sysv/linux/mips/vfork.S
+@@ -31,13 +31,13 @@
+ LOCALSZ= 1
+ FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+ GPOFF= FRAMESZ-(1*SZREG)
+-NESTED(__vfork,FRAMESZ,sp)
++NESTED(__libc_vfork,FRAMESZ,sp)
+ #ifdef __PIC__
+ 	SETUP_GP
+ #endif
+ 	PTR_SUBU sp, FRAMESZ
+ 	cfi_adjust_cfa_offset (FRAMESZ)
+-	SETUP_GP64_REG (a5, __vfork)
++	SETUP_GP64_REG (a5, __libc_vfork)
+ #ifdef __PIC__
+ 	SAVE_GP (GPOFF)
+ #endif
+@@ -104,10 +104,10 @@ L(error):
+ 	RESTORE_GP64_REG
+ 	j		__syscall_error
+ #endif
+-	END(__vfork)
++	END(__libc_vfork)
+ 
+ #if IS_IN (libc)
+-libc_hidden_def(__vfork)
+-weak_alias (__vfork, vfork)
+-strong_alias (__vfork, __libc_vfork)
++weak_alias (__libc_vfork, vfork)
++strong_alias (__libc_vfork, __vfork)
++libc_hidden_def (__vfork)
+ #endif
+-- 
+2.37.3
+
diff --git a/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile
index fd15dbd22c6..de862e1df2d 100644
--- a/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile
@@ -1,30 +1,30 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
-  make \
-  ninja-build \
-  file \
-  curl \
-  ca-certificates \
-  python3 \
-  git \
-  cmake \
-  sudo \
-  gdb \
-  xz-utils \
-  g++-mips64-linux-gnuabi64 \
-  libssl-dev \
-  pkg-config
+FROM ubuntu:22.04
+
+COPY scripts/cross-apt-packages.sh /scripts/
+RUN sh /scripts/cross-apt-packages.sh
+
+COPY scripts/crosstool-ng-1.24.sh /scripts/
+RUN sh /scripts/crosstool-ng-1.24.sh
+
+COPY scripts/rustbuild-setup.sh /scripts/
+RUN sh /scripts/rustbuild-setup.sh
+WORKDIR /tmp
+
+COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/
+COPY host-x86_64/dist-mips64-linux/mips64-linux-gnu.config host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh /tmp/
+RUN su rustbuild -c ./build-mips64-toolchain.sh
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
+ENV PATH=$PATH:/x-tools/mips64-unknown-linux-gnu/bin
+
+ENV \
+    CC_mips64_unknown_linux_gnuabi64=mips64-unknown-linux-gnu-gcc \
+    AR_mips64_unknown_linux_gnuabi64=mips64-unknown-linux-gnu-ar \
+    CXX_mips64_unknown_linux_gnuabi64=mips64-unknown-linux-gnu-g++
 
 ENV HOSTS=mips64-unknown-linux-gnuabi64
 
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs \
-    --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh b/src/ci/docker/host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh
new file mode 100755
index 00000000000..f554a5f4754
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+set -ex
+
+hide_output() {
+  set +x
+  on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+  trap "$on_err" ERR
+  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+  PING_LOOP_PID=$!
+  "$@" &> /tmp/build.log
+  rm /tmp/build.log
+  trap - ERR
+  kill $PING_LOOP_PID
+  set -x
+}
+
+mkdir build
+cd build
+cp ../mips64-linux-gnu.config .config
+hide_output ct-ng build
+cd ..
+rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.config b/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.config
new file mode 100644
index 00000000000..4b1efe24aed
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.config
@@ -0,0 +1,741 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# crosstool-NG  Configuration
+#
+CT_CONFIGURE_has_static_link=y
+CT_CONFIGURE_has_cxx11=y
+CT_CONFIGURE_has_wget=y
+CT_CONFIGURE_has_curl=y
+CT_CONFIGURE_has_make_3_81_or_newer=y
+CT_CONFIGURE_has_make_4_0_or_newer=y
+CT_CONFIGURE_has_libtool_2_4_or_newer=y
+CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
+CT_CONFIGURE_has_autoconf_2_65_or_newer=y
+CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
+CT_CONFIGURE_has_automake_1_15_or_newer=y
+CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
+CT_CONFIGURE_has_python_3_4_or_newer=y
+CT_CONFIGURE_has_bison_2_7_or_newer=y
+CT_CONFIGURE_has_python=y
+CT_CONFIGURE_has_git=y
+CT_CONFIGURE_has_md5sum=y
+CT_CONFIGURE_has_sha1sum=y
+CT_CONFIGURE_has_sha256sum=y
+CT_CONFIGURE_has_sha512sum=y
+CT_CONFIGURE_has_install_with_strip_program=y
+CT_CONFIG_VERSION_CURRENT="3"
+CT_CONFIG_VERSION="3"
+CT_MODULES=y
+
+#
+# Paths and misc options
+#
+
+#
+# crosstool-NG behavior
+#
+# CT_OBSOLETE is not set
+# CT_EXPERIMENTAL is not set
+# CT_DEBUG_CT is not set
+
+#
+# Paths
+#
+CT_LOCAL_TARBALLS_DIR="${HOME}/src"
+CT_SAVE_TARBALLS=y
+# CT_TARBALLS_BUILDROOT_LAYOUT is not set
+CT_WORK_DIR="${CT_TOP_DIR}/.build"
+CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_RM_RF_PREFIX_DIR=y
+CT_REMOVE_DOCS=y
+CT_INSTALL_LICENSES=y
+CT_PREFIX_DIR_RO=y
+CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
+# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
+
+#
+# Downloading
+#
+CT_DOWNLOAD_AGENT_WGET=y
+# CT_DOWNLOAD_AGENT_CURL is not set
+# CT_DOWNLOAD_AGENT_NONE is not set
+# CT_FORBID_DOWNLOAD is not set
+# CT_FORCE_DOWNLOAD is not set
+CT_CONNECT_TIMEOUT=10
+CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
+# CT_ONLY_DOWNLOAD is not set
+CT_USE_MIRROR=y
+# CT_FORCE_MIRROR is not set
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_VERIFY_DOWNLOAD_DIGEST=y
+CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
+CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
+# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
+
+#
+# Extracting
+#
+# CT_FORCE_EXTRACT is not set
+CT_OVERRIDE_CONFIG_GUESS_SUB=y
+# CT_ONLY_EXTRACT is not set
+# CT_PATCH_BUNDLED is not set
+CT_PATCH_BUNDLED_LOCAL=y
+CT_PATCH_ORDER="bundled,local"
+CT_PATCH_USE_LOCAL=y
+CT_LOCAL_PATCH_DIR="/tmp/patches"
+
+#
+# Build behavior
+#
+CT_PARALLEL_JOBS=0
+CT_LOAD=""
+CT_USE_PIPES=y
+CT_EXTRA_CFLAGS_FOR_BUILD=""
+CT_EXTRA_LDFLAGS_FOR_BUILD=""
+CT_EXTRA_CFLAGS_FOR_HOST=""
+CT_EXTRA_LDFLAGS_FOR_HOST=""
+# CT_CONFIG_SHELL_SH is not set
+# CT_CONFIG_SHELL_ASH is not set
+CT_CONFIG_SHELL_BASH=y
+# CT_CONFIG_SHELL_CUSTOM is not set
+CT_CONFIG_SHELL="${bash}"
+
+#
+# Logging
+#
+# CT_LOG_ERROR is not set
+# CT_LOG_WARN is not set
+# CT_LOG_INFO is not set
+CT_LOG_EXTRA=y
+# CT_LOG_ALL is not set
+# CT_LOG_DEBUG is not set
+CT_LOG_LEVEL_MAX="EXTRA"
+# CT_LOG_SEE_TOOLS_WARN is not set
+CT_LOG_PROGRESS_BAR=y
+CT_LOG_TO_FILE=y
+CT_LOG_FILE_COMPRESS=y
+
+#
+# Target options
+#
+# CT_ARCH_ALPHA is not set
+# CT_ARCH_ARC is not set
+# CT_ARCH_ARM is not set
+# CT_ARCH_AVR is not set
+# CT_ARCH_M68K is not set
+CT_ARCH_MIPS=y
+# CT_ARCH_NIOS2 is not set
+# CT_ARCH_POWERPC is not set
+# CT_ARCH_S390 is not set
+# CT_ARCH_SH is not set
+# CT_ARCH_SPARC is not set
+# CT_ARCH_X86 is not set
+# CT_ARCH_XTENSA is not set
+CT_ARCH="mips"
+CT_ARCH_CHOICE_KSYM="MIPS"
+CT_ARCH_TUNE=""
+CT_ARCH_MIPS_SHOW=y
+
+#
+# Options for mips
+#
+CT_ARCH_MIPS_PKG_KSYM=""
+# CT_ARCH_mips_n32 is not set
+CT_ARCH_mips_n64=y
+CT_ARCH_mips_ABI="64"
+CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
+CT_ARCH_SUFFIX=""
+# CT_OMIT_TARGET_VENDOR is not set
+
+#
+# Generic target options
+#
+# CT_MULTILIB is not set
+CT_DEMULTILIB=y
+CT_ARCH_USE_MMU=y
+CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
+CT_ARCH_DEFAULT_BE=y
+CT_ARCH_BE=y
+# CT_ARCH_LE is not set
+CT_ARCH_ENDIAN="big"
+CT_ARCH_SUPPORTS_32=y
+CT_ARCH_SUPPORTS_64=y
+CT_ARCH_DEFAULT_32=y
+CT_ARCH_BITNESS=64
+# CT_ARCH_32 is not set
+CT_ARCH_64=y
+
+#
+# Target optimisations
+#
+CT_ARCH_SUPPORTS_WITH_ARCH=y
+CT_ARCH_SUPPORTS_WITH_TUNE=y
+CT_ARCH_SUPPORTS_WITH_FLOAT=y
+CT_ARCH_ARCH="mips64r2"
+CT_ARCH_FLOAT_AUTO=y
+# CT_ARCH_FLOAT_HW is not set
+# CT_ARCH_FLOAT_SW is not set
+CT_TARGET_CFLAGS=""
+CT_TARGET_LDFLAGS=""
+CT_ARCH_FLOAT="auto"
+
+#
+# Toolchain options
+#
+
+#
+# General toolchain options
+#
+CT_FORCE_SYSROOT=y
+CT_USE_SYSROOT=y
+CT_SYSROOT_NAME="sysroot"
+CT_SYSROOT_DIR_PREFIX=""
+CT_WANTS_STATIC_LINK=y
+CT_WANTS_STATIC_LINK_CXX=y
+# CT_STATIC_TOOLCHAIN is not set
+CT_SHOW_CT_VERSION=y
+CT_TOOLCHAIN_PKGVERSION=""
+CT_TOOLCHAIN_BUGURL=""
+
+#
+# Tuple completion and aliasing
+#
+CT_TARGET_VENDOR="unknown"
+CT_TARGET_ALIAS_SED_EXPR=""
+CT_TARGET_ALIAS=""
+
+#
+# Toolchain type
+#
+CT_CROSS=y
+# CT_CANADIAN is not set
+CT_TOOLCHAIN_TYPE="cross"
+
+#
+# Build system
+#
+CT_BUILD=""
+CT_BUILD_PREFIX=""
+CT_BUILD_SUFFIX=""
+
+#
+# Misc options
+#
+# CT_TOOLCHAIN_ENABLE_NLS is not set
+
+#
+# Operating System
+#
+CT_KERNEL_SUPPORTS_SHARED_LIBS=y
+# CT_KERNEL_BARE_METAL is not set
+CT_KERNEL_LINUX=y
+CT_KERNEL="linux"
+CT_KERNEL_CHOICE_KSYM="LINUX"
+CT_KERNEL_LINUX_SHOW=y
+
+#
+# Options for linux
+#
+CT_KERNEL_LINUX_PKG_KSYM="LINUX"
+CT_LINUX_DIR_NAME="linux"
+CT_LINUX_PKG_NAME="linux"
+CT_LINUX_SRC_RELEASE=y
+CT_LINUX_PATCH_ORDER="global"
+# CT_LINUX_V_4_20 is not set
+# CT_LINUX_V_4_19 is not set
+# CT_LINUX_V_4_18 is not set
+# CT_LINUX_V_4_17 is not set
+# CT_LINUX_V_4_16 is not set
+# CT_LINUX_V_4_15 is not set
+# CT_LINUX_V_4_14 is not set
+# CT_LINUX_V_4_13 is not set
+# CT_LINUX_V_4_12 is not set
+# CT_LINUX_V_4_11 is not set
+# CT_LINUX_V_4_10 is not set
+# CT_LINUX_V_4_9 is not set
+CT_LINUX_V_4_4=y
+# CT_LINUX_V_4_1 is not set
+# CT_LINUX_V_3_16 is not set
+# CT_LINUX_V_3_13 is not set
+# CT_LINUX_V_3_12 is not set
+# CT_LINUX_V_3_10 is not set
+# CT_LINUX_V_3_4 is not set
+# CT_LINUX_V_3_2 is not set
+# CT_LINUX_V_2_6_32 is not set
+# CT_LINUX_NO_VERSIONS is not set
+CT_LINUX_VERSION="4.4.174"
+CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
+CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
+CT_LINUX_4_8_or_older=y
+CT_LINUX_older_than_4_8=y
+CT_LINUX_later_than_3_7=y
+CT_LINUX_3_7_or_later=y
+CT_LINUX_later_than_3_2=y
+CT_LINUX_3_2_or_later=y
+CT_KERNEL_LINUX_VERBOSITY_0=y
+# CT_KERNEL_LINUX_VERBOSITY_1 is not set
+# CT_KERNEL_LINUX_VERBOSITY_2 is not set
+CT_KERNEL_LINUX_VERBOSE_LEVEL=0
+CT_KERNEL_LINUX_INSTALL_CHECK=y
+CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
+
+#
+# Common kernel options
+#
+CT_SHARED_LIBS=y
+
+#
+# Binary utilities
+#
+CT_ARCH_BINFMT_ELF=y
+CT_BINUTILS_BINUTILS=y
+CT_BINUTILS="binutils"
+CT_BINUTILS_CHOICE_KSYM="BINUTILS"
+CT_BINUTILS_BINUTILS_SHOW=y
+
+#
+# Options for binutils
+#
+CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
+CT_BINUTILS_DIR_NAME="binutils"
+CT_BINUTILS_USE_GNU=y
+CT_BINUTILS_USE="BINUTILS"
+CT_BINUTILS_PKG_NAME="binutils"
+CT_BINUTILS_SRC_RELEASE=y
+CT_BINUTILS_PATCH_ORDER="global"
+CT_BINUTILS_V_2_32=y
+# CT_BINUTILS_V_2_31 is not set
+# CT_BINUTILS_V_2_30 is not set
+# CT_BINUTILS_V_2_29 is not set
+# CT_BINUTILS_V_2_28 is not set
+# CT_BINUTILS_V_2_27 is not set
+# CT_BINUTILS_V_2_26 is not set
+# CT_BINUTILS_NO_VERSIONS is not set
+CT_BINUTILS_VERSION="2.32"
+CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
+CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
+CT_BINUTILS_later_than_2_30=y
+CT_BINUTILS_2_30_or_later=y
+CT_BINUTILS_later_than_2_27=y
+CT_BINUTILS_2_27_or_later=y
+CT_BINUTILS_later_than_2_25=y
+CT_BINUTILS_2_25_or_later=y
+CT_BINUTILS_later_than_2_23=y
+CT_BINUTILS_2_23_or_later=y
+
+#
+# GNU binutils
+#
+CT_BINUTILS_HAS_HASH_STYLE=y
+CT_BINUTILS_HAS_GOLD=y
+CT_BINUTILS_HAS_PLUGINS=y
+CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
+CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
+CT_BINUTILS_LINKER_LD=y
+CT_BINUTILS_LINKERS_LIST="ld"
+CT_BINUTILS_LINKER_DEFAULT="bfd"
+# CT_BINUTILS_PLUGINS is not set
+CT_BINUTILS_RELRO=m
+CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
+# CT_BINUTILS_FOR_TARGET is not set
+CT_ALL_BINUTILS_CHOICES="BINUTILS"
+
+#
+# C-library
+#
+CT_LIBC_GLIBC=y
+# CT_LIBC_UCLIBC is not set
+CT_LIBC="glibc"
+CT_LIBC_CHOICE_KSYM="GLIBC"
+CT_THREADS="nptl"
+CT_LIBC_GLIBC_SHOW=y
+
+#
+# Options for glibc
+#
+CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
+CT_GLIBC_DIR_NAME="glibc"
+CT_GLIBC_USE_GNU=y
+CT_GLIBC_USE="GLIBC"
+CT_GLIBC_PKG_NAME="glibc"
+CT_GLIBC_SRC_RELEASE=y
+CT_GLIBC_PATCH_ORDER="global"
+# CT_GLIBC_V_2_29 is not set
+# CT_GLIBC_V_2_28 is not set
+# CT_GLIBC_V_2_27 is not set
+# CT_GLIBC_V_2_26 is not set
+# CT_GLIBC_V_2_25 is not set
+# CT_GLIBC_V_2_24 is not set
+CT_GLIBC_V_2_23=y
+# CT_GLIBC_V_2_19 is not set
+# CT_GLIBC_V_2_17 is not set
+# CT_GLIBC_V_2_12_1 is not set
+# CT_GLIBC_NO_VERSIONS is not set
+CT_GLIBC_VERSION="2.23"
+CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
+CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
+CT_GLIBC_2_29_or_older=y
+CT_GLIBC_older_than_2_29=y
+CT_GLIBC_2_27_or_older=y
+CT_GLIBC_older_than_2_27=y
+CT_GLIBC_2_26_or_older=y
+CT_GLIBC_older_than_2_26=y
+CT_GLIBC_2_25_or_older=y
+CT_GLIBC_older_than_2_25=y
+CT_GLIBC_2_24_or_older=y
+CT_GLIBC_older_than_2_24=y
+CT_GLIBC_2_23_or_later=y
+CT_GLIBC_2_23_or_older=y
+CT_GLIBC_later_than_2_20=y
+CT_GLIBC_2_20_or_later=y
+CT_GLIBC_later_than_2_17=y
+CT_GLIBC_2_17_or_later=y
+CT_GLIBC_later_than_2_14=y
+CT_GLIBC_2_14_or_later=y
+CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
+CT_GLIBC_DEP_BINUTILS=y
+CT_GLIBC_DEP_GCC=y
+CT_GLIBC_DEP_PYTHON=y
+CT_GLIBC_HAS_LIBIDN_ADDON=y
+# CT_GLIBC_USE_LIBIDN_ADDON is not set
+CT_GLIBC_NO_SPARC_V8=y
+CT_GLIBC_HAS_OBSOLETE_RPC=y
+CT_GLIBC_EXTRA_CONFIG_ARRAY=""
+CT_GLIBC_CONFIGPARMS=""
+CT_GLIBC_EXTRA_CFLAGS=""
+CT_GLIBC_ENABLE_OBSOLETE_RPC=y
+# CT_GLIBC_DISABLE_VERSIONING is not set
+CT_GLIBC_OLDEST_ABI=""
+CT_GLIBC_FORCE_UNWIND=y
+# CT_GLIBC_LOCALES is not set
+# CT_GLIBC_KERNEL_VERSION_NONE is not set
+CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
+# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
+CT_GLIBC_MIN_KERNEL="4.4.174"
+CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
+CT_LIBC_SUPPORT_THREADS_ANY=y
+CT_LIBC_SUPPORT_THREADS_NATIVE=y
+
+#
+# Common C library options
+#
+CT_THREADS_NATIVE=y
+# CT_CREATE_LDSO_CONF is not set
+CT_LIBC_XLDD=y
+
+#
+# C compiler
+#
+CT_CC_CORE_PASSES_NEEDED=y
+CT_CC_CORE_PASS_1_NEEDED=y
+CT_CC_CORE_PASS_2_NEEDED=y
+CT_CC_SUPPORT_CXX=y
+CT_CC_SUPPORT_FORTRAN=y
+CT_CC_SUPPORT_ADA=y
+CT_CC_SUPPORT_OBJC=y
+CT_CC_SUPPORT_OBJCXX=y
+CT_CC_SUPPORT_GOLANG=y
+CT_CC_GCC=y
+CT_CC="gcc"
+CT_CC_CHOICE_KSYM="GCC"
+CT_CC_GCC_SHOW=y
+
+#
+# Options for gcc
+#
+CT_CC_GCC_PKG_KSYM="GCC"
+CT_GCC_DIR_NAME="gcc"
+CT_GCC_USE_GNU=y
+CT_GCC_USE="GCC"
+CT_GCC_PKG_NAME="gcc"
+CT_GCC_SRC_RELEASE=y
+CT_GCC_PATCH_ORDER="global"
+CT_GCC_V_8=y
+# CT_GCC_V_7 is not set
+# CT_GCC_V_6 is not set
+# CT_GCC_V_5 is not set
+# CT_GCC_V_4_9 is not set
+# CT_GCC_NO_VERSIONS is not set
+CT_GCC_VERSION="8.3.0"
+CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
+CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_GCC_SIGNATURE_FORMAT=""
+CT_GCC_later_than_7=y
+CT_GCC_7_or_later=y
+CT_GCC_later_than_6=y
+CT_GCC_6_or_later=y
+CT_GCC_later_than_5=y
+CT_GCC_5_or_later=y
+CT_GCC_later_than_4_9=y
+CT_GCC_4_9_or_later=y
+CT_GCC_later_than_4_8=y
+CT_GCC_4_8_or_later=y
+CT_CC_GCC_HAS_LIBMPX=y
+CT_CC_GCC_ENABLE_CXX_FLAGS=""
+CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_STATIC_LIBSTDCXX=y
+# CT_CC_GCC_SYSTEM_ZLIB is not set
+CT_CC_GCC_CONFIG_TLS=m
+
+#
+# Optimisation features
+#
+CT_CC_GCC_USE_GRAPHITE=y
+CT_CC_GCC_USE_LTO=y
+
+#
+# Settings for libraries running on target
+#
+CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
+# CT_CC_GCC_LIBMUDFLAP is not set
+# CT_CC_GCC_LIBGOMP is not set
+# CT_CC_GCC_LIBSSP is not set
+# CT_CC_GCC_LIBQUADMATH is not set
+# CT_CC_GCC_LIBSANITIZER is not set
+
+#
+# Misc. obscure options.
+#
+CT_CC_CXA_ATEXIT=y
+# CT_CC_GCC_DISABLE_PCH is not set
+CT_CC_GCC_SJLJ_EXCEPTIONS=m
+CT_CC_GCC_LDBL_128=m
+# CT_CC_GCC_BUILD_ID is not set
+CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
+# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
+# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
+# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
+CT_CC_GCC_LNK_HASH_STYLE=""
+CT_CC_GCC_DEC_FLOAT_AUTO=y
+# CT_CC_GCC_DEC_FLOAT_BID is not set
+# CT_CC_GCC_DEC_FLOAT_DPD is not set
+# CT_CC_GCC_DEC_FLOATS_NO is not set
+CT_CC_GCC_HAS_ARCH_OPTIONS=y
+
+#
+# archictecture-specific options
+#
+CT_CC_GCC_mips_llsc=m
+CT_CC_GCC_mips_synci=m
+# CT_CC_GCC_mips_plt is not set
+CT_ALL_CC_CHOICES="GCC"
+
+#
+# Additional supported languages:
+#
+CT_CC_LANG_CXX=y
+# CT_CC_LANG_FORTRAN is not set
+
+#
+# Debug facilities
+#
+# CT_DEBUG_DUMA is not set
+# CT_DEBUG_GDB is not set
+# CT_DEBUG_LTRACE is not set
+# CT_DEBUG_STRACE is not set
+CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
+
+#
+# Companion libraries
+#
+# CT_COMPLIBS_CHECK is not set
+# CT_COMP_LIBS_CLOOG is not set
+# CT_COMP_LIBS_EXPAT is not set
+CT_COMP_LIBS_GETTEXT=y
+CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
+CT_GETTEXT_DIR_NAME="gettext"
+CT_GETTEXT_PKG_NAME="gettext"
+CT_GETTEXT_SRC_RELEASE=y
+CT_GETTEXT_PATCH_ORDER="global"
+CT_GETTEXT_V_0_19_8_1=y
+# CT_GETTEXT_NO_VERSIONS is not set
+CT_GETTEXT_VERSION="0.19.8.1"
+CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
+CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
+CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_GMP=y
+CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
+CT_GMP_DIR_NAME="gmp"
+CT_GMP_PKG_NAME="gmp"
+CT_GMP_SRC_RELEASE=y
+CT_GMP_PATCH_ORDER="global"
+CT_GMP_V_6_1=y
+# CT_GMP_NO_VERSIONS is not set
+CT_GMP_VERSION="6.1.2"
+CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
+CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
+CT_GMP_SIGNATURE_FORMAT="packed/.sig"
+CT_GMP_later_than_5_1_0=y
+CT_GMP_5_1_0_or_later=y
+CT_GMP_later_than_5_0_0=y
+CT_GMP_5_0_0_or_later=y
+CT_GMP_REQUIRE_5_0_0_or_later=y
+CT_COMP_LIBS_ISL=y
+CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
+CT_ISL_DIR_NAME="isl"
+CT_ISL_PKG_NAME="isl"
+CT_ISL_SRC_RELEASE=y
+CT_ISL_PATCH_ORDER="global"
+CT_ISL_V_0_20=y
+# CT_ISL_V_0_19 is not set
+# CT_ISL_V_0_18 is not set
+# CT_ISL_V_0_17 is not set
+# CT_ISL_V_0_16 is not set
+# CT_ISL_V_0_15 is not set
+# CT_ISL_NO_VERSIONS is not set
+CT_ISL_VERSION="0.20"
+CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
+CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_ISL_SIGNATURE_FORMAT=""
+CT_ISL_later_than_0_18=y
+CT_ISL_0_18_or_later=y
+CT_ISL_later_than_0_15=y
+CT_ISL_0_15_or_later=y
+CT_ISL_REQUIRE_0_15_or_later=y
+CT_ISL_later_than_0_14=y
+CT_ISL_0_14_or_later=y
+CT_ISL_REQUIRE_0_14_or_later=y
+CT_ISL_later_than_0_13=y
+CT_ISL_0_13_or_later=y
+CT_ISL_later_than_0_12=y
+CT_ISL_0_12_or_later=y
+CT_ISL_REQUIRE_0_12_or_later=y
+# CT_COMP_LIBS_LIBELF is not set
+CT_COMP_LIBS_LIBICONV=y
+CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
+CT_LIBICONV_DIR_NAME="libiconv"
+CT_LIBICONV_PKG_NAME="libiconv"
+CT_LIBICONV_SRC_RELEASE=y
+CT_LIBICONV_PATCH_ORDER="global"
+CT_LIBICONV_V_1_15=y
+# CT_LIBICONV_NO_VERSIONS is not set
+CT_LIBICONV_VERSION="1.15"
+CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
+CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
+CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_MPC=y
+CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
+CT_MPC_DIR_NAME="mpc"
+CT_MPC_PKG_NAME="mpc"
+CT_MPC_SRC_RELEASE=y
+CT_MPC_PATCH_ORDER="global"
+CT_MPC_V_1_1=y
+# CT_MPC_V_1_0 is not set
+# CT_MPC_NO_VERSIONS is not set
+CT_MPC_VERSION="1.1.0"
+CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
+CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_FORMATS=".tar.gz"
+CT_MPC_SIGNATURE_FORMAT="packed/.sig"
+CT_MPC_1_1_0_or_later=y
+CT_MPC_1_1_0_or_older=y
+CT_COMP_LIBS_MPFR=y
+CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
+CT_MPFR_DIR_NAME="mpfr"
+CT_MPFR_PKG_NAME="mpfr"
+CT_MPFR_SRC_RELEASE=y
+CT_MPFR_PATCH_ORDER="global"
+CT_MPFR_V_4_0=y
+# CT_MPFR_V_3_1 is not set
+# CT_MPFR_NO_VERSIONS is not set
+CT_MPFR_VERSION="4.0.2"
+CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
+CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
+CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
+CT_MPFR_later_than_4_0_0=y
+CT_MPFR_4_0_0_or_later=y
+CT_MPFR_later_than_3_0_0=y
+CT_MPFR_3_0_0_or_later=y
+CT_MPFR_REQUIRE_3_0_0_or_later=y
+CT_COMP_LIBS_NCURSES=y
+CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
+CT_NCURSES_DIR_NAME="ncurses"
+CT_NCURSES_PKG_NAME="ncurses"
+CT_NCURSES_SRC_RELEASE=y
+CT_NCURSES_PATCH_ORDER="global"
+CT_NCURSES_V_6_1=y
+# CT_NCURSES_V_6_0 is not set
+# CT_NCURSES_NO_VERSIONS is not set
+CT_NCURSES_VERSION="6.1"
+CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
+CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
+CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
+CT_NCURSES_HOST_CONFIG_ARGS=""
+CT_NCURSES_HOST_DISABLE_DB=y
+CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
+CT_NCURSES_TARGET_CONFIG_ARGS=""
+# CT_NCURSES_TARGET_DISABLE_DB is not set
+CT_NCURSES_TARGET_FALLBACKS=""
+CT_COMP_LIBS_ZLIB=y
+CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
+CT_ZLIB_DIR_NAME="zlib"
+CT_ZLIB_PKG_NAME="zlib"
+CT_ZLIB_SRC_RELEASE=y
+CT_ZLIB_PATCH_ORDER="global"
+CT_ZLIB_V_1_2_11=y
+# CT_ZLIB_NO_VERSIONS is not set
+CT_ZLIB_VERSION="1.2.11"
+CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
+CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
+CT_LIBICONV_NEEDED=y
+CT_GETTEXT_NEEDED=y
+CT_GMP_NEEDED=y
+CT_MPFR_NEEDED=y
+CT_ISL_NEEDED=y
+CT_MPC_NEEDED=y
+CT_NCURSES_NEEDED=y
+CT_ZLIB_NEEDED=y
+CT_LIBICONV=y
+CT_GETTEXT=y
+CT_GMP=y
+CT_MPFR=y
+CT_ISL=y
+CT_MPC=y
+CT_NCURSES=y
+CT_ZLIB=y
+
+#
+# Companion tools
+#
+# CT_COMP_TOOLS_FOR_HOST is not set
+# CT_COMP_TOOLS_AUTOCONF is not set
+# CT_COMP_TOOLS_AUTOMAKE is not set
+# CT_COMP_TOOLS_BISON is not set
+# CT_COMP_TOOLS_DTC is not set
+# CT_COMP_TOOLS_LIBTOOL is not set
+# CT_COMP_TOOLS_M4 is not set
+# CT_COMP_TOOLS_MAKE is not set
+CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile
index 376bdfb4a2f..b90950f7330 100644
--- a/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile
@@ -1,31 +1,30 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
-  make \
-  ninja-build \
-  file \
-  curl \
-  ca-certificates \
-  python3 \
-  git \
-  cmake \
-  sudo \
-  gdb \
-  xz-utils \
-  g++-mips64el-linux-gnuabi64 \
-  libssl-dev \
-  pkg-config
+FROM ubuntu:22.04
 
+COPY scripts/cross-apt-packages.sh /scripts/
+RUN sh /scripts/cross-apt-packages.sh
+
+COPY scripts/crosstool-ng-1.24.sh /scripts/
+RUN sh /scripts/crosstool-ng-1.24.sh
+
+COPY scripts/rustbuild-setup.sh /scripts/
+RUN sh /scripts/rustbuild-setup.sh
+WORKDIR /tmp
+
+COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/
+COPY host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh /tmp/
+RUN su rustbuild -c ./build-mips64el-toolchain.sh
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
+ENV PATH=$PATH:/x-tools/mips64el-unknown-linux-gnu/bin
+
+ENV \
+    CC_mips64el_unknown_linux_gnuabi64=mips64el-unknown-linux-gnu-gcc \
+    AR_mips64el_unknown_linux_gnuabi64=mips64el-unknown-linux-gnu-ar \
+    CXX_mips64el_unknown_linux_gnuabi64=mips64el-unknown-linux-gnu-g++
 
 ENV HOSTS=mips64el-unknown-linux-gnuabi64
 
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs \
-    --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh b/src/ci/docker/host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh
new file mode 100755
index 00000000000..1ad406800b1
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+set -ex
+
+hide_output() {
+  set +x
+  on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+  trap "$on_err" ERR
+  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+  PING_LOOP_PID=$!
+  "$@" &> /tmp/build.log
+  rm /tmp/build.log
+  trap - ERR
+  kill $PING_LOOP_PID
+  set -x
+}
+
+mkdir build
+cd build
+cp ../mips64el-linux-gnu.config .config
+hide_output ct-ng build
+cd ..
+rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config b/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config
new file mode 100644
index 00000000000..baff944cf97
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config
@@ -0,0 +1,741 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# crosstool-NG  Configuration
+#
+CT_CONFIGURE_has_static_link=y
+CT_CONFIGURE_has_cxx11=y
+CT_CONFIGURE_has_wget=y
+CT_CONFIGURE_has_curl=y
+CT_CONFIGURE_has_make_3_81_or_newer=y
+CT_CONFIGURE_has_make_4_0_or_newer=y
+CT_CONFIGURE_has_libtool_2_4_or_newer=y
+CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
+CT_CONFIGURE_has_autoconf_2_65_or_newer=y
+CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
+CT_CONFIGURE_has_automake_1_15_or_newer=y
+CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
+CT_CONFIGURE_has_python_3_4_or_newer=y
+CT_CONFIGURE_has_bison_2_7_or_newer=y
+CT_CONFIGURE_has_python=y
+CT_CONFIGURE_has_git=y
+CT_CONFIGURE_has_md5sum=y
+CT_CONFIGURE_has_sha1sum=y
+CT_CONFIGURE_has_sha256sum=y
+CT_CONFIGURE_has_sha512sum=y
+CT_CONFIGURE_has_install_with_strip_program=y
+CT_CONFIG_VERSION_CURRENT="3"
+CT_CONFIG_VERSION="3"
+CT_MODULES=y
+
+#
+# Paths and misc options
+#
+
+#
+# crosstool-NG behavior
+#
+# CT_OBSOLETE is not set
+# CT_EXPERIMENTAL is not set
+# CT_DEBUG_CT is not set
+
+#
+# Paths
+#
+CT_LOCAL_TARBALLS_DIR="${HOME}/src"
+CT_SAVE_TARBALLS=y
+# CT_TARBALLS_BUILDROOT_LAYOUT is not set
+CT_WORK_DIR="${CT_TOP_DIR}/.build"
+CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_RM_RF_PREFIX_DIR=y
+CT_REMOVE_DOCS=y
+CT_INSTALL_LICENSES=y
+CT_PREFIX_DIR_RO=y
+CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
+# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
+
+#
+# Downloading
+#
+CT_DOWNLOAD_AGENT_WGET=y
+# CT_DOWNLOAD_AGENT_CURL is not set
+# CT_DOWNLOAD_AGENT_NONE is not set
+# CT_FORBID_DOWNLOAD is not set
+# CT_FORCE_DOWNLOAD is not set
+CT_CONNECT_TIMEOUT=10
+CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
+# CT_ONLY_DOWNLOAD is not set
+CT_USE_MIRROR=y
+# CT_FORCE_MIRROR is not set
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_VERIFY_DOWNLOAD_DIGEST=y
+CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
+CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
+# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
+
+#
+# Extracting
+#
+# CT_FORCE_EXTRACT is not set
+CT_OVERRIDE_CONFIG_GUESS_SUB=y
+# CT_ONLY_EXTRACT is not set
+# CT_PATCH_BUNDLED is not set
+CT_PATCH_BUNDLED_LOCAL=y
+CT_PATCH_ORDER="bundled,local"
+CT_PATCH_USE_LOCAL=y
+CT_LOCAL_PATCH_DIR="/tmp/patches"
+
+#
+# Build behavior
+#
+CT_PARALLEL_JOBS=0
+CT_LOAD=""
+CT_USE_PIPES=y
+CT_EXTRA_CFLAGS_FOR_BUILD=""
+CT_EXTRA_LDFLAGS_FOR_BUILD=""
+CT_EXTRA_CFLAGS_FOR_HOST=""
+CT_EXTRA_LDFLAGS_FOR_HOST=""
+# CT_CONFIG_SHELL_SH is not set
+# CT_CONFIG_SHELL_ASH is not set
+CT_CONFIG_SHELL_BASH=y
+# CT_CONFIG_SHELL_CUSTOM is not set
+CT_CONFIG_SHELL="${bash}"
+
+#
+# Logging
+#
+# CT_LOG_ERROR is not set
+# CT_LOG_WARN is not set
+# CT_LOG_INFO is not set
+CT_LOG_EXTRA=y
+# CT_LOG_ALL is not set
+# CT_LOG_DEBUG is not set
+CT_LOG_LEVEL_MAX="EXTRA"
+# CT_LOG_SEE_TOOLS_WARN is not set
+CT_LOG_PROGRESS_BAR=y
+CT_LOG_TO_FILE=y
+CT_LOG_FILE_COMPRESS=y
+
+#
+# Target options
+#
+# CT_ARCH_ALPHA is not set
+# CT_ARCH_ARC is not set
+# CT_ARCH_ARM is not set
+# CT_ARCH_AVR is not set
+# CT_ARCH_M68K is not set
+CT_ARCH_MIPS=y
+# CT_ARCH_NIOS2 is not set
+# CT_ARCH_POWERPC is not set
+# CT_ARCH_S390 is not set
+# CT_ARCH_SH is not set
+# CT_ARCH_SPARC is not set
+# CT_ARCH_X86 is not set
+# CT_ARCH_XTENSA is not set
+CT_ARCH="mips"
+CT_ARCH_CHOICE_KSYM="MIPS"
+CT_ARCH_TUNE=""
+CT_ARCH_MIPS_SHOW=y
+
+#
+# Options for mips
+#
+CT_ARCH_MIPS_PKG_KSYM=""
+# CT_ARCH_mips_n32 is not set
+CT_ARCH_mips_n64=y
+CT_ARCH_mips_ABI="64"
+CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
+CT_ARCH_SUFFIX=""
+# CT_OMIT_TARGET_VENDOR is not set
+
+#
+# Generic target options
+#
+# CT_MULTILIB is not set
+CT_DEMULTILIB=y
+CT_ARCH_USE_MMU=y
+CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
+CT_ARCH_DEFAULT_BE=y
+# CT_ARCH_BE is not set
+CT_ARCH_LE=y
+CT_ARCH_ENDIAN="little"
+CT_ARCH_SUPPORTS_32=y
+CT_ARCH_SUPPORTS_64=y
+CT_ARCH_DEFAULT_32=y
+CT_ARCH_BITNESS=64
+# CT_ARCH_32 is not set
+CT_ARCH_64=y
+
+#
+# Target optimisations
+#
+CT_ARCH_SUPPORTS_WITH_ARCH=y
+CT_ARCH_SUPPORTS_WITH_TUNE=y
+CT_ARCH_SUPPORTS_WITH_FLOAT=y
+CT_ARCH_ARCH="mips64r2"
+CT_ARCH_FLOAT_AUTO=y
+# CT_ARCH_FLOAT_HW is not set
+# CT_ARCH_FLOAT_SW is not set
+CT_TARGET_CFLAGS=""
+CT_TARGET_LDFLAGS=""
+CT_ARCH_FLOAT="auto"
+
+#
+# Toolchain options
+#
+
+#
+# General toolchain options
+#
+CT_FORCE_SYSROOT=y
+CT_USE_SYSROOT=y
+CT_SYSROOT_NAME="sysroot"
+CT_SYSROOT_DIR_PREFIX=""
+CT_WANTS_STATIC_LINK=y
+CT_WANTS_STATIC_LINK_CXX=y
+# CT_STATIC_TOOLCHAIN is not set
+CT_SHOW_CT_VERSION=y
+CT_TOOLCHAIN_PKGVERSION=""
+CT_TOOLCHAIN_BUGURL=""
+
+#
+# Tuple completion and aliasing
+#
+CT_TARGET_VENDOR="unknown"
+CT_TARGET_ALIAS_SED_EXPR=""
+CT_TARGET_ALIAS=""
+
+#
+# Toolchain type
+#
+CT_CROSS=y
+# CT_CANADIAN is not set
+CT_TOOLCHAIN_TYPE="cross"
+
+#
+# Build system
+#
+CT_BUILD=""
+CT_BUILD_PREFIX=""
+CT_BUILD_SUFFIX=""
+
+#
+# Misc options
+#
+# CT_TOOLCHAIN_ENABLE_NLS is not set
+
+#
+# Operating System
+#
+CT_KERNEL_SUPPORTS_SHARED_LIBS=y
+# CT_KERNEL_BARE_METAL is not set
+CT_KERNEL_LINUX=y
+CT_KERNEL="linux"
+CT_KERNEL_CHOICE_KSYM="LINUX"
+CT_KERNEL_LINUX_SHOW=y
+
+#
+# Options for linux
+#
+CT_KERNEL_LINUX_PKG_KSYM="LINUX"
+CT_LINUX_DIR_NAME="linux"
+CT_LINUX_PKG_NAME="linux"
+CT_LINUX_SRC_RELEASE=y
+CT_LINUX_PATCH_ORDER="global"
+# CT_LINUX_V_4_20 is not set
+# CT_LINUX_V_4_19 is not set
+# CT_LINUX_V_4_18 is not set
+# CT_LINUX_V_4_17 is not set
+# CT_LINUX_V_4_16 is not set
+# CT_LINUX_V_4_15 is not set
+# CT_LINUX_V_4_14 is not set
+# CT_LINUX_V_4_13 is not set
+# CT_LINUX_V_4_12 is not set
+# CT_LINUX_V_4_11 is not set
+# CT_LINUX_V_4_10 is not set
+# CT_LINUX_V_4_9 is not set
+CT_LINUX_V_4_4=y
+# CT_LINUX_V_4_1 is not set
+# CT_LINUX_V_3_16 is not set
+# CT_LINUX_V_3_13 is not set
+# CT_LINUX_V_3_12 is not set
+# CT_LINUX_V_3_10 is not set
+# CT_LINUX_V_3_4 is not set
+# CT_LINUX_V_3_2 is not set
+# CT_LINUX_V_2_6_32 is not set
+# CT_LINUX_NO_VERSIONS is not set
+CT_LINUX_VERSION="4.4.174"
+CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
+CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
+CT_LINUX_4_8_or_older=y
+CT_LINUX_older_than_4_8=y
+CT_LINUX_later_than_3_7=y
+CT_LINUX_3_7_or_later=y
+CT_LINUX_later_than_3_2=y
+CT_LINUX_3_2_or_later=y
+CT_KERNEL_LINUX_VERBOSITY_0=y
+# CT_KERNEL_LINUX_VERBOSITY_1 is not set
+# CT_KERNEL_LINUX_VERBOSITY_2 is not set
+CT_KERNEL_LINUX_VERBOSE_LEVEL=0
+CT_KERNEL_LINUX_INSTALL_CHECK=y
+CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
+
+#
+# Common kernel options
+#
+CT_SHARED_LIBS=y
+
+#
+# Binary utilities
+#
+CT_ARCH_BINFMT_ELF=y
+CT_BINUTILS_BINUTILS=y
+CT_BINUTILS="binutils"
+CT_BINUTILS_CHOICE_KSYM="BINUTILS"
+CT_BINUTILS_BINUTILS_SHOW=y
+
+#
+# Options for binutils
+#
+CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
+CT_BINUTILS_DIR_NAME="binutils"
+CT_BINUTILS_USE_GNU=y
+CT_BINUTILS_USE="BINUTILS"
+CT_BINUTILS_PKG_NAME="binutils"
+CT_BINUTILS_SRC_RELEASE=y
+CT_BINUTILS_PATCH_ORDER="global"
+CT_BINUTILS_V_2_32=y
+# CT_BINUTILS_V_2_31 is not set
+# CT_BINUTILS_V_2_30 is not set
+# CT_BINUTILS_V_2_29 is not set
+# CT_BINUTILS_V_2_28 is not set
+# CT_BINUTILS_V_2_27 is not set
+# CT_BINUTILS_V_2_26 is not set
+# CT_BINUTILS_NO_VERSIONS is not set
+CT_BINUTILS_VERSION="2.32"
+CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
+CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
+CT_BINUTILS_later_than_2_30=y
+CT_BINUTILS_2_30_or_later=y
+CT_BINUTILS_later_than_2_27=y
+CT_BINUTILS_2_27_or_later=y
+CT_BINUTILS_later_than_2_25=y
+CT_BINUTILS_2_25_or_later=y
+CT_BINUTILS_later_than_2_23=y
+CT_BINUTILS_2_23_or_later=y
+
+#
+# GNU binutils
+#
+CT_BINUTILS_HAS_HASH_STYLE=y
+CT_BINUTILS_HAS_GOLD=y
+CT_BINUTILS_HAS_PLUGINS=y
+CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
+CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
+CT_BINUTILS_LINKER_LD=y
+CT_BINUTILS_LINKERS_LIST="ld"
+CT_BINUTILS_LINKER_DEFAULT="bfd"
+# CT_BINUTILS_PLUGINS is not set
+CT_BINUTILS_RELRO=m
+CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
+# CT_BINUTILS_FOR_TARGET is not set
+CT_ALL_BINUTILS_CHOICES="BINUTILS"
+
+#
+# C-library
+#
+CT_LIBC_GLIBC=y
+# CT_LIBC_UCLIBC is not set
+CT_LIBC="glibc"
+CT_LIBC_CHOICE_KSYM="GLIBC"
+CT_THREADS="nptl"
+CT_LIBC_GLIBC_SHOW=y
+
+#
+# Options for glibc
+#
+CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
+CT_GLIBC_DIR_NAME="glibc"
+CT_GLIBC_USE_GNU=y
+CT_GLIBC_USE="GLIBC"
+CT_GLIBC_PKG_NAME="glibc"
+CT_GLIBC_SRC_RELEASE=y
+CT_GLIBC_PATCH_ORDER="global"
+# CT_GLIBC_V_2_29 is not set
+# CT_GLIBC_V_2_28 is not set
+# CT_GLIBC_V_2_27 is not set
+# CT_GLIBC_V_2_26 is not set
+# CT_GLIBC_V_2_25 is not set
+# CT_GLIBC_V_2_24 is not set
+CT_GLIBC_V_2_23=y
+# CT_GLIBC_V_2_19 is not set
+# CT_GLIBC_V_2_17 is not set
+# CT_GLIBC_V_2_12_1 is not set
+# CT_GLIBC_NO_VERSIONS is not set
+CT_GLIBC_VERSION="2.23"
+CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
+CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
+CT_GLIBC_2_29_or_older=y
+CT_GLIBC_older_than_2_29=y
+CT_GLIBC_2_27_or_older=y
+CT_GLIBC_older_than_2_27=y
+CT_GLIBC_2_26_or_older=y
+CT_GLIBC_older_than_2_26=y
+CT_GLIBC_2_25_or_older=y
+CT_GLIBC_older_than_2_25=y
+CT_GLIBC_2_24_or_older=y
+CT_GLIBC_older_than_2_24=y
+CT_GLIBC_2_23_or_later=y
+CT_GLIBC_2_23_or_older=y
+CT_GLIBC_later_than_2_20=y
+CT_GLIBC_2_20_or_later=y
+CT_GLIBC_later_than_2_17=y
+CT_GLIBC_2_17_or_later=y
+CT_GLIBC_later_than_2_14=y
+CT_GLIBC_2_14_or_later=y
+CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
+CT_GLIBC_DEP_BINUTILS=y
+CT_GLIBC_DEP_GCC=y
+CT_GLIBC_DEP_PYTHON=y
+CT_GLIBC_HAS_LIBIDN_ADDON=y
+# CT_GLIBC_USE_LIBIDN_ADDON is not set
+CT_GLIBC_NO_SPARC_V8=y
+CT_GLIBC_HAS_OBSOLETE_RPC=y
+CT_GLIBC_EXTRA_CONFIG_ARRAY=""
+CT_GLIBC_CONFIGPARMS=""
+CT_GLIBC_EXTRA_CFLAGS=""
+CT_GLIBC_ENABLE_OBSOLETE_RPC=y
+# CT_GLIBC_DISABLE_VERSIONING is not set
+CT_GLIBC_OLDEST_ABI=""
+CT_GLIBC_FORCE_UNWIND=y
+# CT_GLIBC_LOCALES is not set
+# CT_GLIBC_KERNEL_VERSION_NONE is not set
+CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
+# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
+CT_GLIBC_MIN_KERNEL="4.4.174"
+CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
+CT_LIBC_SUPPORT_THREADS_ANY=y
+CT_LIBC_SUPPORT_THREADS_NATIVE=y
+
+#
+# Common C library options
+#
+CT_THREADS_NATIVE=y
+# CT_CREATE_LDSO_CONF is not set
+CT_LIBC_XLDD=y
+
+#
+# C compiler
+#
+CT_CC_CORE_PASSES_NEEDED=y
+CT_CC_CORE_PASS_1_NEEDED=y
+CT_CC_CORE_PASS_2_NEEDED=y
+CT_CC_SUPPORT_CXX=y
+CT_CC_SUPPORT_FORTRAN=y
+CT_CC_SUPPORT_ADA=y
+CT_CC_SUPPORT_OBJC=y
+CT_CC_SUPPORT_OBJCXX=y
+CT_CC_SUPPORT_GOLANG=y
+CT_CC_GCC=y
+CT_CC="gcc"
+CT_CC_CHOICE_KSYM="GCC"
+CT_CC_GCC_SHOW=y
+
+#
+# Options for gcc
+#
+CT_CC_GCC_PKG_KSYM="GCC"
+CT_GCC_DIR_NAME="gcc"
+CT_GCC_USE_GNU=y
+CT_GCC_USE="GCC"
+CT_GCC_PKG_NAME="gcc"
+CT_GCC_SRC_RELEASE=y
+CT_GCC_PATCH_ORDER="global"
+CT_GCC_V_8=y
+# CT_GCC_V_7 is not set
+# CT_GCC_V_6 is not set
+# CT_GCC_V_5 is not set
+# CT_GCC_V_4_9 is not set
+# CT_GCC_NO_VERSIONS is not set
+CT_GCC_VERSION="8.3.0"
+CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
+CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_GCC_SIGNATURE_FORMAT=""
+CT_GCC_later_than_7=y
+CT_GCC_7_or_later=y
+CT_GCC_later_than_6=y
+CT_GCC_6_or_later=y
+CT_GCC_later_than_5=y
+CT_GCC_5_or_later=y
+CT_GCC_later_than_4_9=y
+CT_GCC_4_9_or_later=y
+CT_GCC_later_than_4_8=y
+CT_GCC_4_8_or_later=y
+CT_CC_GCC_HAS_LIBMPX=y
+CT_CC_GCC_ENABLE_CXX_FLAGS=""
+CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_STATIC_LIBSTDCXX=y
+# CT_CC_GCC_SYSTEM_ZLIB is not set
+CT_CC_GCC_CONFIG_TLS=m
+
+#
+# Optimisation features
+#
+CT_CC_GCC_USE_GRAPHITE=y
+CT_CC_GCC_USE_LTO=y
+
+#
+# Settings for libraries running on target
+#
+CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
+# CT_CC_GCC_LIBMUDFLAP is not set
+# CT_CC_GCC_LIBGOMP is not set
+# CT_CC_GCC_LIBSSP is not set
+# CT_CC_GCC_LIBQUADMATH is not set
+# CT_CC_GCC_LIBSANITIZER is not set
+
+#
+# Misc. obscure options.
+#
+CT_CC_CXA_ATEXIT=y
+# CT_CC_GCC_DISABLE_PCH is not set
+CT_CC_GCC_SJLJ_EXCEPTIONS=m
+CT_CC_GCC_LDBL_128=m
+# CT_CC_GCC_BUILD_ID is not set
+CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
+# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
+# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
+# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
+CT_CC_GCC_LNK_HASH_STYLE=""
+CT_CC_GCC_DEC_FLOAT_AUTO=y
+# CT_CC_GCC_DEC_FLOAT_BID is not set
+# CT_CC_GCC_DEC_FLOAT_DPD is not set
+# CT_CC_GCC_DEC_FLOATS_NO is not set
+CT_CC_GCC_HAS_ARCH_OPTIONS=y
+
+#
+# archictecture-specific options
+#
+CT_CC_GCC_mips_llsc=m
+CT_CC_GCC_mips_synci=m
+# CT_CC_GCC_mips_plt is not set
+CT_ALL_CC_CHOICES="GCC"
+
+#
+# Additional supported languages:
+#
+CT_CC_LANG_CXX=y
+# CT_CC_LANG_FORTRAN is not set
+
+#
+# Debug facilities
+#
+# CT_DEBUG_DUMA is not set
+# CT_DEBUG_GDB is not set
+# CT_DEBUG_LTRACE is not set
+# CT_DEBUG_STRACE is not set
+CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
+
+#
+# Companion libraries
+#
+# CT_COMPLIBS_CHECK is not set
+# CT_COMP_LIBS_CLOOG is not set
+# CT_COMP_LIBS_EXPAT is not set
+CT_COMP_LIBS_GETTEXT=y
+CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
+CT_GETTEXT_DIR_NAME="gettext"
+CT_GETTEXT_PKG_NAME="gettext"
+CT_GETTEXT_SRC_RELEASE=y
+CT_GETTEXT_PATCH_ORDER="global"
+CT_GETTEXT_V_0_19_8_1=y
+# CT_GETTEXT_NO_VERSIONS is not set
+CT_GETTEXT_VERSION="0.19.8.1"
+CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
+CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
+CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_GMP=y
+CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
+CT_GMP_DIR_NAME="gmp"
+CT_GMP_PKG_NAME="gmp"
+CT_GMP_SRC_RELEASE=y
+CT_GMP_PATCH_ORDER="global"
+CT_GMP_V_6_1=y
+# CT_GMP_NO_VERSIONS is not set
+CT_GMP_VERSION="6.1.2"
+CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
+CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
+CT_GMP_SIGNATURE_FORMAT="packed/.sig"
+CT_GMP_later_than_5_1_0=y
+CT_GMP_5_1_0_or_later=y
+CT_GMP_later_than_5_0_0=y
+CT_GMP_5_0_0_or_later=y
+CT_GMP_REQUIRE_5_0_0_or_later=y
+CT_COMP_LIBS_ISL=y
+CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
+CT_ISL_DIR_NAME="isl"
+CT_ISL_PKG_NAME="isl"
+CT_ISL_SRC_RELEASE=y
+CT_ISL_PATCH_ORDER="global"
+CT_ISL_V_0_20=y
+# CT_ISL_V_0_19 is not set
+# CT_ISL_V_0_18 is not set
+# CT_ISL_V_0_17 is not set
+# CT_ISL_V_0_16 is not set
+# CT_ISL_V_0_15 is not set
+# CT_ISL_NO_VERSIONS is not set
+CT_ISL_VERSION="0.20"
+CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
+CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_ISL_SIGNATURE_FORMAT=""
+CT_ISL_later_than_0_18=y
+CT_ISL_0_18_or_later=y
+CT_ISL_later_than_0_15=y
+CT_ISL_0_15_or_later=y
+CT_ISL_REQUIRE_0_15_or_later=y
+CT_ISL_later_than_0_14=y
+CT_ISL_0_14_or_later=y
+CT_ISL_REQUIRE_0_14_or_later=y
+CT_ISL_later_than_0_13=y
+CT_ISL_0_13_or_later=y
+CT_ISL_later_than_0_12=y
+CT_ISL_0_12_or_later=y
+CT_ISL_REQUIRE_0_12_or_later=y
+# CT_COMP_LIBS_LIBELF is not set
+CT_COMP_LIBS_LIBICONV=y
+CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
+CT_LIBICONV_DIR_NAME="libiconv"
+CT_LIBICONV_PKG_NAME="libiconv"
+CT_LIBICONV_SRC_RELEASE=y
+CT_LIBICONV_PATCH_ORDER="global"
+CT_LIBICONV_V_1_15=y
+# CT_LIBICONV_NO_VERSIONS is not set
+CT_LIBICONV_VERSION="1.15"
+CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
+CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
+CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_MPC=y
+CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
+CT_MPC_DIR_NAME="mpc"
+CT_MPC_PKG_NAME="mpc"
+CT_MPC_SRC_RELEASE=y
+CT_MPC_PATCH_ORDER="global"
+CT_MPC_V_1_1=y
+# CT_MPC_V_1_0 is not set
+# CT_MPC_NO_VERSIONS is not set
+CT_MPC_VERSION="1.1.0"
+CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
+CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_FORMATS=".tar.gz"
+CT_MPC_SIGNATURE_FORMAT="packed/.sig"
+CT_MPC_1_1_0_or_later=y
+CT_MPC_1_1_0_or_older=y
+CT_COMP_LIBS_MPFR=y
+CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
+CT_MPFR_DIR_NAME="mpfr"
+CT_MPFR_PKG_NAME="mpfr"
+CT_MPFR_SRC_RELEASE=y
+CT_MPFR_PATCH_ORDER="global"
+CT_MPFR_V_4_0=y
+# CT_MPFR_V_3_1 is not set
+# CT_MPFR_NO_VERSIONS is not set
+CT_MPFR_VERSION="4.0.2"
+CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
+CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
+CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
+CT_MPFR_later_than_4_0_0=y
+CT_MPFR_4_0_0_or_later=y
+CT_MPFR_later_than_3_0_0=y
+CT_MPFR_3_0_0_or_later=y
+CT_MPFR_REQUIRE_3_0_0_or_later=y
+CT_COMP_LIBS_NCURSES=y
+CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
+CT_NCURSES_DIR_NAME="ncurses"
+CT_NCURSES_PKG_NAME="ncurses"
+CT_NCURSES_SRC_RELEASE=y
+CT_NCURSES_PATCH_ORDER="global"
+CT_NCURSES_V_6_1=y
+# CT_NCURSES_V_6_0 is not set
+# CT_NCURSES_NO_VERSIONS is not set
+CT_NCURSES_VERSION="6.1"
+CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
+CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
+CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
+CT_NCURSES_HOST_CONFIG_ARGS=""
+CT_NCURSES_HOST_DISABLE_DB=y
+CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
+CT_NCURSES_TARGET_CONFIG_ARGS=""
+# CT_NCURSES_TARGET_DISABLE_DB is not set
+CT_NCURSES_TARGET_FALLBACKS=""
+CT_COMP_LIBS_ZLIB=y
+CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
+CT_ZLIB_DIR_NAME="zlib"
+CT_ZLIB_PKG_NAME="zlib"
+CT_ZLIB_SRC_RELEASE=y
+CT_ZLIB_PATCH_ORDER="global"
+CT_ZLIB_V_1_2_11=y
+# CT_ZLIB_NO_VERSIONS is not set
+CT_ZLIB_VERSION="1.2.11"
+CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
+CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
+CT_LIBICONV_NEEDED=y
+CT_GETTEXT_NEEDED=y
+CT_GMP_NEEDED=y
+CT_MPFR_NEEDED=y
+CT_ISL_NEEDED=y
+CT_MPC_NEEDED=y
+CT_NCURSES_NEEDED=y
+CT_ZLIB_NEEDED=y
+CT_LIBICONV=y
+CT_GETTEXT=y
+CT_GMP=y
+CT_MPFR=y
+CT_ISL=y
+CT_MPC=y
+CT_NCURSES=y
+CT_ZLIB=y
+
+#
+# Companion tools
+#
+# CT_COMP_TOOLS_FOR_HOST is not set
+# CT_COMP_TOOLS_AUTOCONF is not set
+# CT_COMP_TOOLS_AUTOMAKE is not set
+# CT_COMP_TOOLS_BISON is not set
+# CT_COMP_TOOLS_DTC is not set
+# CT_COMP_TOOLS_LIBTOOL is not set
+# CT_COMP_TOOLS_M4 is not set
+# CT_COMP_TOOLS_MAKE is not set
+CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile
index 70c8b2a96c8..6cc2de5e47d 100644
--- a/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile
@@ -1,30 +1,30 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
-  make \
-  ninja-build \
-  file \
-  curl \
-  ca-certificates \
-  python3 \
-  git \
-  cmake \
-  sudo \
-  gdb \
-  xz-utils \
-  g++-mipsel-linux-gnu \
-  libssl-dev \
-  pkg-config
+FROM ubuntu:22.04
+
+COPY scripts/cross-apt-packages.sh /scripts/
+RUN sh /scripts/cross-apt-packages.sh
+
+COPY scripts/crosstool-ng-1.24.sh /scripts/
+RUN sh /scripts/crosstool-ng-1.24.sh
+
+COPY scripts/rustbuild-setup.sh /scripts/
+RUN sh /scripts/rustbuild-setup.sh
+WORKDIR /tmp
+
+COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/
+COPY host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh /tmp/
+RUN su rustbuild -c ./build-mipsel-toolchain.sh
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
+ENV PATH=$PATH:/x-tools/mipsel-unknown-linux-gnu/bin
+
+ENV \
+    CC_mipsel_unknown_linux_gnu=mipsel-unknown-linux-gnu-gcc \
+    AR_mipsel_unknown_linux_gnu=mipsel-unknown-linux-gnu-ar \
+    CXX_mipsel_unknown_linux_gnu=mipsel-unknown-linux-gnu-g++
 
 ENV HOSTS=mipsel-unknown-linux-gnu
 
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs \
-    --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh b/src/ci/docker/host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh
new file mode 100755
index 00000000000..598e4893325
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+set -ex
+
+hide_output() {
+  set +x
+  on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+  trap "$on_err" ERR
+  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+  PING_LOOP_PID=$!
+  "$@" &> /tmp/build.log
+  rm /tmp/build.log
+  trap - ERR
+  kill $PING_LOOP_PID
+  set -x
+}
+
+mkdir build
+cd build
+cp ../mipsel-linux-gnu.config .config
+hide_output ct-ng build
+cd ..
+rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config b/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config
new file mode 100644
index 00000000000..adb2da7ddee
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config
@@ -0,0 +1,740 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# crosstool-NG  Configuration
+#
+CT_CONFIGURE_has_static_link=y
+CT_CONFIGURE_has_cxx11=y
+CT_CONFIGURE_has_wget=y
+CT_CONFIGURE_has_curl=y
+CT_CONFIGURE_has_make_3_81_or_newer=y
+CT_CONFIGURE_has_make_4_0_or_newer=y
+CT_CONFIGURE_has_libtool_2_4_or_newer=y
+CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
+CT_CONFIGURE_has_autoconf_2_65_or_newer=y
+CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
+CT_CONFIGURE_has_automake_1_15_or_newer=y
+CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
+CT_CONFIGURE_has_python_3_4_or_newer=y
+CT_CONFIGURE_has_bison_2_7_or_newer=y
+CT_CONFIGURE_has_python=y
+CT_CONFIGURE_has_git=y
+CT_CONFIGURE_has_md5sum=y
+CT_CONFIGURE_has_sha1sum=y
+CT_CONFIGURE_has_sha256sum=y
+CT_CONFIGURE_has_sha512sum=y
+CT_CONFIGURE_has_install_with_strip_program=y
+CT_CONFIG_VERSION_CURRENT="3"
+CT_CONFIG_VERSION="3"
+CT_MODULES=y
+
+#
+# Paths and misc options
+#
+
+#
+# crosstool-NG behavior
+#
+# CT_OBSOLETE is not set
+# CT_EXPERIMENTAL is not set
+# CT_DEBUG_CT is not set
+
+#
+# Paths
+#
+CT_LOCAL_TARBALLS_DIR="${HOME}/src"
+CT_SAVE_TARBALLS=y
+# CT_TARBALLS_BUILDROOT_LAYOUT is not set
+CT_WORK_DIR="${CT_TOP_DIR}/.build"
+CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_RM_RF_PREFIX_DIR=y
+CT_REMOVE_DOCS=y
+CT_INSTALL_LICENSES=y
+CT_PREFIX_DIR_RO=y
+CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
+# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
+
+#
+# Downloading
+#
+CT_DOWNLOAD_AGENT_WGET=y
+# CT_DOWNLOAD_AGENT_CURL is not set
+# CT_DOWNLOAD_AGENT_NONE is not set
+# CT_FORBID_DOWNLOAD is not set
+# CT_FORCE_DOWNLOAD is not set
+CT_CONNECT_TIMEOUT=10
+CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
+# CT_ONLY_DOWNLOAD is not set
+CT_USE_MIRROR=y
+# CT_FORCE_MIRROR is not set
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_VERIFY_DOWNLOAD_DIGEST=y
+CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
+CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
+# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
+
+#
+# Extracting
+#
+# CT_FORCE_EXTRACT is not set
+CT_OVERRIDE_CONFIG_GUESS_SUB=y
+# CT_ONLY_EXTRACT is not set
+# CT_PATCH_BUNDLED is not set
+CT_PATCH_BUNDLED_LOCAL=y
+CT_PATCH_ORDER="bundled,local"
+CT_PATCH_USE_LOCAL=y
+CT_LOCAL_PATCH_DIR="/tmp/patches"
+
+#
+# Build behavior
+#
+CT_PARALLEL_JOBS=0
+CT_LOAD=""
+CT_USE_PIPES=y
+CT_EXTRA_CFLAGS_FOR_BUILD=""
+CT_EXTRA_LDFLAGS_FOR_BUILD=""
+CT_EXTRA_CFLAGS_FOR_HOST=""
+CT_EXTRA_LDFLAGS_FOR_HOST=""
+# CT_CONFIG_SHELL_SH is not set
+# CT_CONFIG_SHELL_ASH is not set
+CT_CONFIG_SHELL_BASH=y
+# CT_CONFIG_SHELL_CUSTOM is not set
+CT_CONFIG_SHELL="${bash}"
+
+#
+# Logging
+#
+# CT_LOG_ERROR is not set
+# CT_LOG_WARN is not set
+# CT_LOG_INFO is not set
+CT_LOG_EXTRA=y
+# CT_LOG_ALL is not set
+# CT_LOG_DEBUG is not set
+CT_LOG_LEVEL_MAX="EXTRA"
+# CT_LOG_SEE_TOOLS_WARN is not set
+CT_LOG_PROGRESS_BAR=y
+CT_LOG_TO_FILE=y
+CT_LOG_FILE_COMPRESS=y
+
+#
+# Target options
+#
+# CT_ARCH_ALPHA is not set
+# CT_ARCH_ARC is not set
+# CT_ARCH_ARM is not set
+# CT_ARCH_AVR is not set
+# CT_ARCH_M68K is not set
+CT_ARCH_MIPS=y
+# CT_ARCH_NIOS2 is not set
+# CT_ARCH_POWERPC is not set
+# CT_ARCH_S390 is not set
+# CT_ARCH_SH is not set
+# CT_ARCH_SPARC is not set
+# CT_ARCH_X86 is not set
+# CT_ARCH_XTENSA is not set
+CT_ARCH="mips"
+CT_ARCH_CHOICE_KSYM="MIPS"
+CT_ARCH_TUNE=""
+CT_ARCH_MIPS_SHOW=y
+
+#
+# Options for mips
+#
+CT_ARCH_MIPS_PKG_KSYM=""
+CT_ARCH_mips_o32=y
+CT_ARCH_mips_ABI="32"
+CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
+CT_ARCH_SUFFIX=""
+# CT_OMIT_TARGET_VENDOR is not set
+
+#
+# Generic target options
+#
+# CT_MULTILIB is not set
+CT_DEMULTILIB=y
+CT_ARCH_USE_MMU=y
+CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
+CT_ARCH_DEFAULT_BE=y
+# CT_ARCH_BE is not set
+CT_ARCH_LE=y
+CT_ARCH_ENDIAN="little"
+CT_ARCH_SUPPORTS_32=y
+CT_ARCH_SUPPORTS_64=y
+CT_ARCH_DEFAULT_32=y
+CT_ARCH_BITNESS=32
+CT_ARCH_32=y
+# CT_ARCH_64 is not set
+
+#
+# Target optimisations
+#
+CT_ARCH_SUPPORTS_WITH_ARCH=y
+CT_ARCH_SUPPORTS_WITH_TUNE=y
+CT_ARCH_SUPPORTS_WITH_FLOAT=y
+CT_ARCH_ARCH="mips32r2"
+CT_ARCH_FLOAT_AUTO=y
+# CT_ARCH_FLOAT_HW is not set
+# CT_ARCH_FLOAT_SW is not set
+CT_TARGET_CFLAGS=""
+CT_TARGET_LDFLAGS=""
+CT_ARCH_FLOAT="auto"
+
+#
+# Toolchain options
+#
+
+#
+# General toolchain options
+#
+CT_FORCE_SYSROOT=y
+CT_USE_SYSROOT=y
+CT_SYSROOT_NAME="sysroot"
+CT_SYSROOT_DIR_PREFIX=""
+CT_WANTS_STATIC_LINK=y
+CT_WANTS_STATIC_LINK_CXX=y
+# CT_STATIC_TOOLCHAIN is not set
+CT_SHOW_CT_VERSION=y
+CT_TOOLCHAIN_PKGVERSION=""
+CT_TOOLCHAIN_BUGURL=""
+
+#
+# Tuple completion and aliasing
+#
+CT_TARGET_VENDOR="unknown"
+CT_TARGET_ALIAS_SED_EXPR=""
+CT_TARGET_ALIAS=""
+
+#
+# Toolchain type
+#
+CT_CROSS=y
+# CT_CANADIAN is not set
+CT_TOOLCHAIN_TYPE="cross"
+
+#
+# Build system
+#
+CT_BUILD=""
+CT_BUILD_PREFIX=""
+CT_BUILD_SUFFIX=""
+
+#
+# Misc options
+#
+# CT_TOOLCHAIN_ENABLE_NLS is not set
+
+#
+# Operating System
+#
+CT_KERNEL_SUPPORTS_SHARED_LIBS=y
+# CT_KERNEL_BARE_METAL is not set
+CT_KERNEL_LINUX=y
+CT_KERNEL="linux"
+CT_KERNEL_CHOICE_KSYM="LINUX"
+CT_KERNEL_LINUX_SHOW=y
+
+#
+# Options for linux
+#
+CT_KERNEL_LINUX_PKG_KSYM="LINUX"
+CT_LINUX_DIR_NAME="linux"
+CT_LINUX_PKG_NAME="linux"
+CT_LINUX_SRC_RELEASE=y
+CT_LINUX_PATCH_ORDER="global"
+# CT_LINUX_V_4_20 is not set
+# CT_LINUX_V_4_19 is not set
+# CT_LINUX_V_4_18 is not set
+# CT_LINUX_V_4_17 is not set
+# CT_LINUX_V_4_16 is not set
+# CT_LINUX_V_4_15 is not set
+# CT_LINUX_V_4_14 is not set
+# CT_LINUX_V_4_13 is not set
+# CT_LINUX_V_4_12 is not set
+# CT_LINUX_V_4_11 is not set
+# CT_LINUX_V_4_10 is not set
+# CT_LINUX_V_4_9 is not set
+CT_LINUX_V_4_4=y
+# CT_LINUX_V_4_1 is not set
+# CT_LINUX_V_3_16 is not set
+# CT_LINUX_V_3_13 is not set
+# CT_LINUX_V_3_12 is not set
+# CT_LINUX_V_3_10 is not set
+# CT_LINUX_V_3_4 is not set
+# CT_LINUX_V_3_2 is not set
+# CT_LINUX_V_2_6_32 is not set
+# CT_LINUX_NO_VERSIONS is not set
+CT_LINUX_VERSION="4.4.174"
+CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
+CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
+CT_LINUX_4_8_or_older=y
+CT_LINUX_older_than_4_8=y
+CT_LINUX_later_than_3_7=y
+CT_LINUX_3_7_or_later=y
+CT_LINUX_later_than_3_2=y
+CT_LINUX_3_2_or_later=y
+CT_KERNEL_LINUX_VERBOSITY_0=y
+# CT_KERNEL_LINUX_VERBOSITY_1 is not set
+# CT_KERNEL_LINUX_VERBOSITY_2 is not set
+CT_KERNEL_LINUX_VERBOSE_LEVEL=0
+CT_KERNEL_LINUX_INSTALL_CHECK=y
+CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
+
+#
+# Common kernel options
+#
+CT_SHARED_LIBS=y
+
+#
+# Binary utilities
+#
+CT_ARCH_BINFMT_ELF=y
+CT_BINUTILS_BINUTILS=y
+CT_BINUTILS="binutils"
+CT_BINUTILS_CHOICE_KSYM="BINUTILS"
+CT_BINUTILS_BINUTILS_SHOW=y
+
+#
+# Options for binutils
+#
+CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
+CT_BINUTILS_DIR_NAME="binutils"
+CT_BINUTILS_USE_GNU=y
+CT_BINUTILS_USE="BINUTILS"
+CT_BINUTILS_PKG_NAME="binutils"
+CT_BINUTILS_SRC_RELEASE=y
+CT_BINUTILS_PATCH_ORDER="global"
+CT_BINUTILS_V_2_32=y
+# CT_BINUTILS_V_2_31 is not set
+# CT_BINUTILS_V_2_30 is not set
+# CT_BINUTILS_V_2_29 is not set
+# CT_BINUTILS_V_2_28 is not set
+# CT_BINUTILS_V_2_27 is not set
+# CT_BINUTILS_V_2_26 is not set
+# CT_BINUTILS_NO_VERSIONS is not set
+CT_BINUTILS_VERSION="2.32"
+CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
+CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
+CT_BINUTILS_later_than_2_30=y
+CT_BINUTILS_2_30_or_later=y
+CT_BINUTILS_later_than_2_27=y
+CT_BINUTILS_2_27_or_later=y
+CT_BINUTILS_later_than_2_25=y
+CT_BINUTILS_2_25_or_later=y
+CT_BINUTILS_later_than_2_23=y
+CT_BINUTILS_2_23_or_later=y
+
+#
+# GNU binutils
+#
+CT_BINUTILS_HAS_HASH_STYLE=y
+CT_BINUTILS_HAS_GOLD=y
+CT_BINUTILS_HAS_PLUGINS=y
+CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
+CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
+CT_BINUTILS_LINKER_LD=y
+CT_BINUTILS_LINKERS_LIST="ld"
+CT_BINUTILS_LINKER_DEFAULT="bfd"
+# CT_BINUTILS_PLUGINS is not set
+CT_BINUTILS_RELRO=m
+CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
+# CT_BINUTILS_FOR_TARGET is not set
+CT_ALL_BINUTILS_CHOICES="BINUTILS"
+
+#
+# C-library
+#
+CT_LIBC_GLIBC=y
+# CT_LIBC_UCLIBC is not set
+CT_LIBC="glibc"
+CT_LIBC_CHOICE_KSYM="GLIBC"
+CT_THREADS="nptl"
+CT_LIBC_GLIBC_SHOW=y
+
+#
+# Options for glibc
+#
+CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
+CT_GLIBC_DIR_NAME="glibc"
+CT_GLIBC_USE_GNU=y
+CT_GLIBC_USE="GLIBC"
+CT_GLIBC_PKG_NAME="glibc"
+CT_GLIBC_SRC_RELEASE=y
+CT_GLIBC_PATCH_ORDER="global"
+# CT_GLIBC_V_2_29 is not set
+# CT_GLIBC_V_2_28 is not set
+# CT_GLIBC_V_2_27 is not set
+# CT_GLIBC_V_2_26 is not set
+# CT_GLIBC_V_2_25 is not set
+# CT_GLIBC_V_2_24 is not set
+CT_GLIBC_V_2_23=y
+# CT_GLIBC_V_2_19 is not set
+# CT_GLIBC_V_2_17 is not set
+# CT_GLIBC_V_2_12_1 is not set
+# CT_GLIBC_NO_VERSIONS is not set
+CT_GLIBC_VERSION="2.23"
+CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
+CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
+CT_GLIBC_2_29_or_older=y
+CT_GLIBC_older_than_2_29=y
+CT_GLIBC_2_27_or_older=y
+CT_GLIBC_older_than_2_27=y
+CT_GLIBC_2_26_or_older=y
+CT_GLIBC_older_than_2_26=y
+CT_GLIBC_2_25_or_older=y
+CT_GLIBC_older_than_2_25=y
+CT_GLIBC_2_24_or_older=y
+CT_GLIBC_older_than_2_24=y
+CT_GLIBC_2_23_or_later=y
+CT_GLIBC_2_23_or_older=y
+CT_GLIBC_later_than_2_20=y
+CT_GLIBC_2_20_or_later=y
+CT_GLIBC_later_than_2_17=y
+CT_GLIBC_2_17_or_later=y
+CT_GLIBC_later_than_2_14=y
+CT_GLIBC_2_14_or_later=y
+CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
+CT_GLIBC_DEP_BINUTILS=y
+CT_GLIBC_DEP_GCC=y
+CT_GLIBC_DEP_PYTHON=y
+CT_GLIBC_HAS_LIBIDN_ADDON=y
+# CT_GLIBC_USE_LIBIDN_ADDON is not set
+CT_GLIBC_NO_SPARC_V8=y
+CT_GLIBC_HAS_OBSOLETE_RPC=y
+CT_GLIBC_EXTRA_CONFIG_ARRAY=""
+CT_GLIBC_CONFIGPARMS=""
+CT_GLIBC_EXTRA_CFLAGS=""
+CT_GLIBC_ENABLE_OBSOLETE_RPC=y
+# CT_GLIBC_DISABLE_VERSIONING is not set
+CT_GLIBC_OLDEST_ABI=""
+CT_GLIBC_FORCE_UNWIND=y
+# CT_GLIBC_LOCALES is not set
+# CT_GLIBC_KERNEL_VERSION_NONE is not set
+CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
+# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
+CT_GLIBC_MIN_KERNEL="4.4.174"
+CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
+CT_LIBC_SUPPORT_THREADS_ANY=y
+CT_LIBC_SUPPORT_THREADS_NATIVE=y
+
+#
+# Common C library options
+#
+CT_THREADS_NATIVE=y
+# CT_CREATE_LDSO_CONF is not set
+CT_LIBC_XLDD=y
+
+#
+# C compiler
+#
+CT_CC_CORE_PASSES_NEEDED=y
+CT_CC_CORE_PASS_1_NEEDED=y
+CT_CC_CORE_PASS_2_NEEDED=y
+CT_CC_SUPPORT_CXX=y
+CT_CC_SUPPORT_FORTRAN=y
+CT_CC_SUPPORT_ADA=y
+CT_CC_SUPPORT_OBJC=y
+CT_CC_SUPPORT_OBJCXX=y
+CT_CC_SUPPORT_GOLANG=y
+CT_CC_GCC=y
+CT_CC="gcc"
+CT_CC_CHOICE_KSYM="GCC"
+CT_CC_GCC_SHOW=y
+
+#
+# Options for gcc
+#
+CT_CC_GCC_PKG_KSYM="GCC"
+CT_GCC_DIR_NAME="gcc"
+CT_GCC_USE_GNU=y
+CT_GCC_USE="GCC"
+CT_GCC_PKG_NAME="gcc"
+CT_GCC_SRC_RELEASE=y
+CT_GCC_PATCH_ORDER="global"
+CT_GCC_V_8=y
+# CT_GCC_V_7 is not set
+# CT_GCC_V_6 is not set
+# CT_GCC_V_5 is not set
+# CT_GCC_V_4_9 is not set
+# CT_GCC_NO_VERSIONS is not set
+CT_GCC_VERSION="8.3.0"
+CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
+CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_GCC_SIGNATURE_FORMAT=""
+CT_GCC_later_than_7=y
+CT_GCC_7_or_later=y
+CT_GCC_later_than_6=y
+CT_GCC_6_or_later=y
+CT_GCC_later_than_5=y
+CT_GCC_5_or_later=y
+CT_GCC_later_than_4_9=y
+CT_GCC_4_9_or_later=y
+CT_GCC_later_than_4_8=y
+CT_GCC_4_8_or_later=y
+CT_CC_GCC_HAS_LIBMPX=y
+CT_CC_GCC_ENABLE_CXX_FLAGS=""
+CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_EXTRA_CONFIG_ARRAY="--with-fp-32=xx --with-odd-spreg-32=no"
+CT_CC_GCC_STATIC_LIBSTDCXX=y
+# CT_CC_GCC_SYSTEM_ZLIB is not set
+CT_CC_GCC_CONFIG_TLS=m
+
+#
+# Optimisation features
+#
+CT_CC_GCC_USE_GRAPHITE=y
+CT_CC_GCC_USE_LTO=y
+
+#
+# Settings for libraries running on target
+#
+CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
+# CT_CC_GCC_LIBMUDFLAP is not set
+# CT_CC_GCC_LIBGOMP is not set
+# CT_CC_GCC_LIBSSP is not set
+# CT_CC_GCC_LIBQUADMATH is not set
+# CT_CC_GCC_LIBSANITIZER is not set
+
+#
+# Misc. obscure options.
+#
+CT_CC_CXA_ATEXIT=y
+# CT_CC_GCC_DISABLE_PCH is not set
+CT_CC_GCC_SJLJ_EXCEPTIONS=m
+CT_CC_GCC_LDBL_128=m
+# CT_CC_GCC_BUILD_ID is not set
+CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
+# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
+# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
+# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
+CT_CC_GCC_LNK_HASH_STYLE=""
+CT_CC_GCC_DEC_FLOAT_AUTO=y
+# CT_CC_GCC_DEC_FLOAT_BID is not set
+# CT_CC_GCC_DEC_FLOAT_DPD is not set
+# CT_CC_GCC_DEC_FLOATS_NO is not set
+CT_CC_GCC_HAS_ARCH_OPTIONS=y
+
+#
+# archictecture-specific options
+#
+CT_CC_GCC_mips_llsc=m
+CT_CC_GCC_mips_synci=m
+# CT_CC_GCC_mips_plt is not set
+CT_ALL_CC_CHOICES="GCC"
+
+#
+# Additional supported languages:
+#
+CT_CC_LANG_CXX=y
+# CT_CC_LANG_FORTRAN is not set
+
+#
+# Debug facilities
+#
+# CT_DEBUG_DUMA is not set
+# CT_DEBUG_GDB is not set
+# CT_DEBUG_LTRACE is not set
+# CT_DEBUG_STRACE is not set
+CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
+
+#
+# Companion libraries
+#
+# CT_COMPLIBS_CHECK is not set
+# CT_COMP_LIBS_CLOOG is not set
+# CT_COMP_LIBS_EXPAT is not set
+CT_COMP_LIBS_GETTEXT=y
+CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
+CT_GETTEXT_DIR_NAME="gettext"
+CT_GETTEXT_PKG_NAME="gettext"
+CT_GETTEXT_SRC_RELEASE=y
+CT_GETTEXT_PATCH_ORDER="global"
+CT_GETTEXT_V_0_19_8_1=y
+# CT_GETTEXT_NO_VERSIONS is not set
+CT_GETTEXT_VERSION="0.19.8.1"
+CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
+CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
+CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_GMP=y
+CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
+CT_GMP_DIR_NAME="gmp"
+CT_GMP_PKG_NAME="gmp"
+CT_GMP_SRC_RELEASE=y
+CT_GMP_PATCH_ORDER="global"
+CT_GMP_V_6_1=y
+# CT_GMP_NO_VERSIONS is not set
+CT_GMP_VERSION="6.1.2"
+CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
+CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
+CT_GMP_SIGNATURE_FORMAT="packed/.sig"
+CT_GMP_later_than_5_1_0=y
+CT_GMP_5_1_0_or_later=y
+CT_GMP_later_than_5_0_0=y
+CT_GMP_5_0_0_or_later=y
+CT_GMP_REQUIRE_5_0_0_or_later=y
+CT_COMP_LIBS_ISL=y
+CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
+CT_ISL_DIR_NAME="isl"
+CT_ISL_PKG_NAME="isl"
+CT_ISL_SRC_RELEASE=y
+CT_ISL_PATCH_ORDER="global"
+CT_ISL_V_0_20=y
+# CT_ISL_V_0_19 is not set
+# CT_ISL_V_0_18 is not set
+# CT_ISL_V_0_17 is not set
+# CT_ISL_V_0_16 is not set
+# CT_ISL_V_0_15 is not set
+# CT_ISL_NO_VERSIONS is not set
+CT_ISL_VERSION="0.20"
+CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
+CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_ISL_SIGNATURE_FORMAT=""
+CT_ISL_later_than_0_18=y
+CT_ISL_0_18_or_later=y
+CT_ISL_later_than_0_15=y
+CT_ISL_0_15_or_later=y
+CT_ISL_REQUIRE_0_15_or_later=y
+CT_ISL_later_than_0_14=y
+CT_ISL_0_14_or_later=y
+CT_ISL_REQUIRE_0_14_or_later=y
+CT_ISL_later_than_0_13=y
+CT_ISL_0_13_or_later=y
+CT_ISL_later_than_0_12=y
+CT_ISL_0_12_or_later=y
+CT_ISL_REQUIRE_0_12_or_later=y
+# CT_COMP_LIBS_LIBELF is not set
+CT_COMP_LIBS_LIBICONV=y
+CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
+CT_LIBICONV_DIR_NAME="libiconv"
+CT_LIBICONV_PKG_NAME="libiconv"
+CT_LIBICONV_SRC_RELEASE=y
+CT_LIBICONV_PATCH_ORDER="global"
+CT_LIBICONV_V_1_15=y
+# CT_LIBICONV_NO_VERSIONS is not set
+CT_LIBICONV_VERSION="1.15"
+CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
+CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
+CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_MPC=y
+CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
+CT_MPC_DIR_NAME="mpc"
+CT_MPC_PKG_NAME="mpc"
+CT_MPC_SRC_RELEASE=y
+CT_MPC_PATCH_ORDER="global"
+CT_MPC_V_1_1=y
+# CT_MPC_V_1_0 is not set
+# CT_MPC_NO_VERSIONS is not set
+CT_MPC_VERSION="1.1.0"
+CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
+CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_FORMATS=".tar.gz"
+CT_MPC_SIGNATURE_FORMAT="packed/.sig"
+CT_MPC_1_1_0_or_later=y
+CT_MPC_1_1_0_or_older=y
+CT_COMP_LIBS_MPFR=y
+CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
+CT_MPFR_DIR_NAME="mpfr"
+CT_MPFR_PKG_NAME="mpfr"
+CT_MPFR_SRC_RELEASE=y
+CT_MPFR_PATCH_ORDER="global"
+CT_MPFR_V_4_0=y
+# CT_MPFR_V_3_1 is not set
+# CT_MPFR_NO_VERSIONS is not set
+CT_MPFR_VERSION="4.0.2"
+CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
+CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
+CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
+CT_MPFR_later_than_4_0_0=y
+CT_MPFR_4_0_0_or_later=y
+CT_MPFR_later_than_3_0_0=y
+CT_MPFR_3_0_0_or_later=y
+CT_MPFR_REQUIRE_3_0_0_or_later=y
+CT_COMP_LIBS_NCURSES=y
+CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
+CT_NCURSES_DIR_NAME="ncurses"
+CT_NCURSES_PKG_NAME="ncurses"
+CT_NCURSES_SRC_RELEASE=y
+CT_NCURSES_PATCH_ORDER="global"
+CT_NCURSES_V_6_1=y
+# CT_NCURSES_V_6_0 is not set
+# CT_NCURSES_NO_VERSIONS is not set
+CT_NCURSES_VERSION="6.1"
+CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
+CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
+CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
+CT_NCURSES_HOST_CONFIG_ARGS=""
+CT_NCURSES_HOST_DISABLE_DB=y
+CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
+CT_NCURSES_TARGET_CONFIG_ARGS=""
+# CT_NCURSES_TARGET_DISABLE_DB is not set
+CT_NCURSES_TARGET_FALLBACKS=""
+CT_COMP_LIBS_ZLIB=y
+CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
+CT_ZLIB_DIR_NAME="zlib"
+CT_ZLIB_PKG_NAME="zlib"
+CT_ZLIB_SRC_RELEASE=y
+CT_ZLIB_PATCH_ORDER="global"
+CT_ZLIB_V_1_2_11=y
+# CT_ZLIB_NO_VERSIONS is not set
+CT_ZLIB_VERSION="1.2.11"
+CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
+CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
+CT_LIBICONV_NEEDED=y
+CT_GETTEXT_NEEDED=y
+CT_GMP_NEEDED=y
+CT_MPFR_NEEDED=y
+CT_ISL_NEEDED=y
+CT_MPC_NEEDED=y
+CT_NCURSES_NEEDED=y
+CT_ZLIB_NEEDED=y
+CT_LIBICONV=y
+CT_GETTEXT=y
+CT_GMP=y
+CT_MPFR=y
+CT_ISL=y
+CT_MPC=y
+CT_NCURSES=y
+CT_ZLIB=y
+
+#
+# Companion tools
+#
+# CT_COMP_TOOLS_FOR_HOST is not set
+# CT_COMP_TOOLS_AUTOCONF is not set
+# CT_COMP_TOOLS_AUTOMAKE is not set
+# CT_COMP_TOOLS_BISON is not set
+# CT_COMP_TOOLS_DTC is not set
+# CT_COMP_TOOLS_LIBTOOL is not set
+# CT_COMP_TOOLS_M4 is not set
+# CT_COMP_TOOLS_MAKE is not set
+CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
index b960239807a..423aba06cca 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
@@ -78,7 +78,8 @@ ENV RUST_CONFIGURE_ARGS \
       --set llvm.thin-lto=true \
       --set llvm.ninja=false \
       --set rust.jemalloc \
-      --set rust.use-lld=true
+      --set rust.use-lld=true \
+      --set rust.lto=thin
 ENV SCRIPT ../src/ci/pgo.sh python3 ../x.py dist \
     --host $HOSTS --target $HOSTS \
     --include-default-paths \
diff --git a/src/doc/unstable-book/src/compiler-flags/dylib-lto.md b/src/doc/unstable-book/src/compiler-flags/dylib-lto.md
new file mode 100644
index 00000000000..f69ea334f5a
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/dylib-lto.md
@@ -0,0 +1,4 @@
+## `dylib-lto`
+
+This option enables using LTO for the `dylib` crate type. This is currently only used for compiling
+`rustc` itself (more specifically, the `librustc_driver` dylib).
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 95061ae61e3..7c59e785752 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -13,116 +13,124 @@ pub(crate) struct BlanketImplFinder<'a, 'tcx> {
 
 impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
     pub(crate) fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
-        let param_env = self.cx.tcx.param_env(item_def_id);
-        let ty = self.cx.tcx.bound_type_of(item_def_id);
+        let cx = &mut self.cx;
+        let param_env = cx.tcx.param_env(item_def_id);
+        let ty = cx.tcx.bound_type_of(item_def_id);
 
         trace!("get_blanket_impls({:?})", ty);
         let mut impls = Vec::new();
-        self.cx.with_all_traits(|cx, all_traits| {
-            for &trait_def_id in all_traits {
-                if !cx.cache.access_levels.is_public(trait_def_id)
-                    || cx.generated_synthetics.get(&(ty.0, trait_def_id)).is_some()
-                {
+        for trait_def_id in cx.tcx.all_traits() {
+            if !cx.cache.access_levels.is_public(trait_def_id)
+                || cx.generated_synthetics.get(&(ty.0, trait_def_id)).is_some()
+            {
+                continue;
+            }
+            // NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls
+            let trait_impls = cx.tcx.trait_impls_of(trait_def_id);
+            'blanket_impls: for &impl_def_id in trait_impls.blanket_impls() {
+                trace!(
+                    "get_blanket_impls: Considering impl for trait '{:?}' {:?}",
+                    trait_def_id,
+                    impl_def_id
+                );
+                let trait_ref = cx.tcx.bound_impl_trait_ref(impl_def_id).unwrap();
+                if !matches!(trait_ref.0.self_ty().kind(), ty::Param(_)) {
                     continue;
                 }
-                // NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls
-                let trait_impls = cx.tcx.trait_impls_of(trait_def_id);
-                'blanket_impls: for &impl_def_id in trait_impls.blanket_impls() {
-                    trace!(
-                        "get_blanket_impls: Considering impl for trait '{:?}' {:?}",
-                        trait_def_id,
-                        impl_def_id
-                    );
-                    let trait_ref = cx.tcx.bound_impl_trait_ref(impl_def_id).unwrap();
-                    if !matches!(trait_ref.0.self_ty().kind(), ty::Param(_)) {
-                        continue;
-                    }
-                    let infcx = cx.tcx.infer_ctxt().build();
-                    let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id);
-                    let impl_ty = ty.subst(infcx.tcx, substs);
-                    let param_env = EarlyBinder(param_env).subst(infcx.tcx, substs);
+                let infcx = cx.tcx.infer_ctxt().build();
+                let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id);
+                let impl_ty = ty.subst(infcx.tcx, substs);
+                let param_env = EarlyBinder(param_env).subst(infcx.tcx, substs);
 
-                    let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
-                    let impl_trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
+                let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+                let impl_trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
 
-                    // Require the type the impl is implemented on to match
-                    // our type, and ignore the impl if there was a mismatch.
-                    let cause = traits::ObligationCause::dummy();
-                    let Ok(eq_result) = infcx.at(&cause, param_env).eq(impl_trait_ref.self_ty(), impl_ty) else {
+                // Require the type the impl is implemented on to match
+                // our type, and ignore the impl if there was a mismatch.
+                let cause = traits::ObligationCause::dummy();
+                let Ok(eq_result) = infcx.at(&cause, param_env).eq(impl_trait_ref.self_ty(), impl_ty) else {
                         continue
                     };
-                    let InferOk { value: (), obligations } = eq_result;
-                    // FIXME(eddyb) ignoring `obligations` might cause false positives.
-                    drop(obligations);
+                let InferOk { value: (), obligations } = eq_result;
+                // FIXME(eddyb) ignoring `obligations` might cause false positives.
+                drop(obligations);
 
-                    trace!(
-                        "invoking predicate_may_hold: param_env={:?}, impl_trait_ref={:?}, impl_ty={:?}",
+                trace!(
+                    "invoking predicate_may_hold: param_env={:?}, impl_trait_ref={:?}, impl_ty={:?}",
+                    param_env,
+                    impl_trait_ref,
+                    impl_ty
+                );
+                let predicates = cx
+                    .tcx
+                    .predicates_of(impl_def_id)
+                    .instantiate(cx.tcx, impl_substs)
+                    .predicates
+                    .into_iter()
+                    .chain(Some(
+                        ty::Binder::dummy(impl_trait_ref)
+                            .to_poly_trait_predicate()
+                            .map_bound(ty::PredicateKind::Trait)
+                            .to_predicate(infcx.tcx),
+                    ));
+                for predicate in predicates {
+                    debug!("testing predicate {:?}", predicate);
+                    let obligation = traits::Obligation::new(
+                        traits::ObligationCause::dummy(),
                         param_env,
-                        impl_trait_ref,
-                        impl_ty
+                        predicate,
                     );
-                    let predicates = cx
-                        .tcx
-                        .predicates_of(impl_def_id)
-                        .instantiate(cx.tcx, impl_substs)
-                        .predicates
-                        .into_iter()
-                        .chain(Some(
-                            ty::Binder::dummy(impl_trait_ref)
-                                .to_poly_trait_predicate()
-                                .map_bound(ty::PredicateKind::Trait)
-                                .to_predicate(infcx.tcx),
-                        ));
-                    for predicate in predicates {
-                        debug!("testing predicate {:?}", predicate);
-                        let obligation = traits::Obligation::new(
-                            traits::ObligationCause::dummy(),
-                            param_env,
-                            predicate,
-                        );
-                        match infcx.evaluate_obligation(&obligation) {
-                            Ok(eval_result) if eval_result.may_apply() => {}
-                            Err(traits::OverflowError::Canonical) => {}
-                            Err(traits::OverflowError::ErrorReporting) => {}
-                            _ => continue 'blanket_impls,
-                        }
+                    match infcx.evaluate_obligation(&obligation) {
+                        Ok(eval_result) if eval_result.may_apply() => {}
+                        Err(traits::OverflowError::Canonical) => {}
+                        Err(traits::OverflowError::ErrorReporting) => {}
+                        _ => continue 'blanket_impls,
                     }
-                    debug!(
-                        "get_blanket_impls: found applicable impl for trait_ref={:?}, ty={:?}",
-                        trait_ref, ty
-                    );
+                }
+                debug!(
+                    "get_blanket_impls: found applicable impl for trait_ref={:?}, ty={:?}",
+                    trait_ref, ty
+                );
 
-                    cx.generated_synthetics.insert((ty.0, trait_def_id));
+                cx.generated_synthetics.insert((ty.0, trait_def_id));
 
-                    impls.push(Item {
-                        name: None,
-                        attrs: Default::default(),
-                        visibility: Inherited,
-                        item_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
-                        kind: Box::new(ImplItem(Box::new(Impl {
-                            unsafety: hir::Unsafety::Normal,
-                            generics: clean_ty_generics(
-                                cx,
-                                cx.tcx.generics_of(impl_def_id),
-                                cx.tcx.explicit_predicates_of(impl_def_id),
-                            ),
-                            // FIXME(eddyb) compute both `trait_` and `for_` from
-                            // the post-inference `trait_ref`, as it's more accurate.
-                            trait_: Some(clean_trait_ref_with_bindings(cx, trait_ref.0, ThinVec::new())),
-                            for_: clean_middle_ty(ty.0, cx, None),
-                            items: cx.tcx
-                                .associated_items(impl_def_id)
-                                .in_definition_order()
-                                .map(|x| clean_middle_assoc_item(x, cx))
-                                .collect::<Vec<_>>(),
-                            polarity: ty::ImplPolarity::Positive,
-                            kind: ImplKind::Blanket(Box::new(clean_middle_ty(trait_ref.0.self_ty(), cx, None))),
-                        }))),
-                        cfg: None,
-                    });
-                }
+                impls.push(Item {
+                    name: None,
+                    attrs: Default::default(),
+                    visibility: Inherited,
+                    item_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
+                    kind: Box::new(ImplItem(Box::new(Impl {
+                        unsafety: hir::Unsafety::Normal,
+                        generics: clean_ty_generics(
+                            cx,
+                            cx.tcx.generics_of(impl_def_id),
+                            cx.tcx.explicit_predicates_of(impl_def_id),
+                        ),
+                        // FIXME(eddyb) compute both `trait_` and `for_` from
+                        // the post-inference `trait_ref`, as it's more accurate.
+                        trait_: Some(clean_trait_ref_with_bindings(
+                            cx,
+                            trait_ref.0,
+                            ThinVec::new(),
+                        )),
+                        for_: clean_middle_ty(ty.0, cx, None),
+                        items: cx
+                            .tcx
+                            .associated_items(impl_def_id)
+                            .in_definition_order()
+                            .map(|x| clean_middle_assoc_item(x, cx))
+                            .collect::<Vec<_>>(),
+                        polarity: ty::ImplPolarity::Positive,
+                        kind: ImplKind::Blanket(Box::new(clean_middle_ty(
+                            trait_ref.0.self_ty(),
+                            cx,
+                            None,
+                        ))),
+                    }))),
+                    cfg: None,
+                });
             }
-        });
+        }
 
         impls
     }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 5f674ed7441..d86a2682641 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -774,31 +774,36 @@ fn clean_ty_generics<'tcx>(
     let mut where_predicates =
         where_predicates.into_iter().flat_map(|p| clean_predicate(*p, cx)).collect::<Vec<_>>();
 
-    // Type parameters have a Sized bound by default unless removed with
-    // ?Sized. Scan through the predicates and mark any type parameter with
-    // a Sized bound, removing the bounds as we find them.
+    // In the surface language, all type parameters except `Self` have an
+    // implicit `Sized` bound unless removed with `?Sized`.
+    // However, in the list of where-predicates below, `Sized` appears like a
+    // normal bound: It's either present (the type is sized) or
+    // absent (the type is unsized) but never *maybe* (i.e. `?Sized`).
     //
-    // Note that associated types also have a sized bound by default, but we
+    // This is unsuitable for rendering.
+    // Thus, as a first step remove all `Sized` bounds that should be implicit.
+    //
+    // Note that associated types also have an implicit `Sized` bound but we
     // don't actually know the set of associated types right here so that's
-    // handled in cleaning associated types
+    // handled when cleaning associated types.
     let mut sized_params = FxHashSet::default();
-    where_predicates.retain(|pred| match *pred {
-        WherePredicate::BoundPredicate { ty: Generic(ref g), ref bounds, .. } => {
-            if bounds.iter().any(|b| b.is_sized_bound(cx)) {
-                sized_params.insert(*g);
-                false
-            } else {
-                true
-            }
+    where_predicates.retain(|pred| {
+        if let WherePredicate::BoundPredicate { ty: Generic(g), bounds, .. } = pred
+        && *g != kw::SelfUpper
+        && bounds.iter().any(|b| b.is_sized_bound(cx))
+        {
+            sized_params.insert(*g);
+            false
+        } else {
+            true
         }
-        _ => true,
     });
 
-    // Run through the type parameters again and insert a ?Sized
-    // unbound for any we didn't find to be Sized.
+    // As a final step, go through the type parameters again and insert a
+    // `?Sized` bound for each one we didn't find to be `Sized`.
     for tp in &stripped_params {
-        if matches!(tp.kind, types::GenericParamDefKind::Type { .. })
-            && !sized_params.contains(&tp.name)
+        if let types::GenericParamDefKind::Type { .. } = tp.kind
+        && !sized_params.contains(&tp.name)
         {
             where_predicates.push(WherePredicate::BoundPredicate {
                 ty: Type::Generic(tp.name),
@@ -1201,21 +1206,19 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
             }
 
             if let ty::TraitContainer = assoc_item.container {
-                // FIXME(fmease): `tcx.explicit_item_bounds` does not contain the bounds of GATs,
-                //                e.g. the bounds `Copy`, `Display` & (implicitly) `Sized` in
-                //                `type Assoc<T: Copy> where T: Display`. This also means that we
-                //                later incorrectly render `where T: ?Sized`.
-                //
-                //                The result of `tcx.explicit_predicates_of` *does* contain them but
-                //                it does not contain the other bounds / predicates we need.
-                //                Either merge those two interned lists somehow or refactor
-                //                `clean_ty_generics` to call `explicit_item_bounds` by itself.
                 let bounds = tcx.explicit_item_bounds(assoc_item.def_id);
-                let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
-                let mut generics =
-                    clean_ty_generics(cx, tcx.generics_of(assoc_item.def_id), predicates);
-                // Filter out the bounds that are (likely?) directly attached to the associated type,
-                // as opposed to being located in the where clause.
+                let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
+                let predicates =
+                    tcx.arena.alloc_from_iter(bounds.into_iter().chain(predicates).copied());
+                let mut generics = clean_ty_generics(
+                    cx,
+                    tcx.generics_of(assoc_item.def_id),
+                    ty::GenericPredicates { parent: None, predicates },
+                );
+                // Move bounds that are (likely) directly attached to the associated type
+                // from the where clause to the associated type.
+                // There is no guarantee that this is what the user actually wrote but we have
+                // no way of knowing.
                 let mut bounds = generics
                     .where_predicates
                     .drain_filter(|pred| match *pred {
@@ -1273,6 +1276,24 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
                     }
                     None => bounds.push(GenericBound::maybe_sized(cx)),
                 }
+                // Move bounds that are (likely) directly attached to the parameters of the
+                // (generic) associated type from the where clause to the respective parameter.
+                // There is no guarantee that this is what the user actually wrote but we have
+                // no way of knowing.
+                let mut where_predicates = Vec::new();
+                for mut pred in generics.where_predicates {
+                    if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred
+                    && let Some(GenericParamDef {
+                        kind: GenericParamDefKind::Type { bounds: param_bounds, .. },
+                        ..
+                    }) = generics.params.iter_mut().find(|param| &param.name == arg)
+                    {
+                        param_bounds.extend(mem::take(bounds));
+                    } else {
+                        where_predicates.push(pred);
+                    }
+                }
+                generics.where_predicates = where_predicates;
 
                 if tcx.impl_defaultness(assoc_item.def_id).has_value() {
                     AssocTypeItem(
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 858e939bd96..8232353f915 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -38,7 +38,6 @@ pub(crate) struct ResolverCaches {
     /// Traits in scope for a given module.
     /// See `collect_intra_doc_links::traits_implemented_by` for more details.
     pub(crate) traits_in_scope: DefIdMap<Vec<TraitCandidate>>,
-    pub(crate) all_traits: Option<Vec<DefId>>,
     pub(crate) all_trait_impls: Option<Vec<DefId>>,
     pub(crate) all_macro_rules: FxHashMap<Symbol, Res<NodeId>>,
 }
@@ -134,12 +133,6 @@ impl<'tcx> DocContext<'tcx> {
         }
     }
 
-    pub(crate) fn with_all_traits(&mut self, f: impl FnOnce(&mut Self, &[DefId])) {
-        let all_traits = self.resolver_caches.all_traits.take();
-        f(self, all_traits.as_ref().expect("`all_traits` are already borrowed"));
-        self.resolver_caches.all_traits = all_traits;
-    }
-
     pub(crate) fn with_all_trait_impls(&mut self, f: impl FnOnce(&mut Self, &[DefId])) {
         let all_trait_impls = self.resolver_caches.all_trait_impls.take();
         f(self, all_trait_impls.as_ref().expect("`all_trait_impls` are already borrowed"));
@@ -353,14 +346,8 @@ pub(crate) fn run_global_ctxt(
     });
     rustc_passes::stability::check_unused_or_stable_features(tcx);
 
-    let auto_traits = resolver_caches
-        .all_traits
-        .as_ref()
-        .expect("`all_traits` are already borrowed")
-        .iter()
-        .copied()
-        .filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id))
-        .collect();
+    let auto_traits =
+        tcx.all_traits().filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id)).collect();
     let access_levels = tcx.privacy_access_levels(()).map_id(Into::into);
 
     let mut ctxt = DocContext {
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index cb216970c7c..db70029f6ec 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -208,12 +208,13 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
 pub(crate) fn run_tests(
     mut test_args: Vec<String>,
     nocapture: bool,
-    tests: Vec<test::TestDescAndFn>,
+    mut tests: Vec<test::TestDescAndFn>,
 ) {
     test_args.insert(0, "rustdoctest".to_string());
     if nocapture {
         test_args.push("--nocapture".to_string());
     }
+    tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice()));
     test::test_main(&test_args, tests, None);
 }
 
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index afe1ca5d7e5..293c9787609 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -184,7 +184,6 @@ h4.code-header {
 }
 .code-header {
 	font-weight: 600;
-	border-bottom-style: none;
 	margin: 0;
 	padding: 0;
 }
@@ -634,7 +633,6 @@ pre.example-line-numbers {
 .out-of-band {
 	flex-grow: 0;
 	font-size: 1.125rem;
-	font-weight: normal;
 }
 
 .docblock code, .docblock-short code,
@@ -921,7 +919,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	flex-flow: row wrap;
 }
 
-.search-results .result-name, .search-results div.desc, .search-results .result-description {
+.search-results .result-name, .search-results div.desc {
 	width: 50%;
 }
 .search-results .result-name {
@@ -1536,6 +1534,7 @@ details.dir-entry a {
 	https://developer.mozilla.org/en-US/docs/Web/CSS/contain */
 details.rustdoc-toggle {
 	contain: layout;
+	position: relative;
 }
 
 /* The hideme class is used on summary tags that contain a span with
@@ -1629,10 +1628,6 @@ details.rustdoc-toggle[open] > summary.hideme {
 	position: absolute;
 }
 
-details.rustdoc-toggle {
-	position: relative;
-}
-
 details.rustdoc-toggle[open] > summary.hideme > span {
 	display: none;
 }
@@ -1903,10 +1898,10 @@ in storage.js
 		border-bottom: 1px solid #aaa9;
 		padding: 5px 0px;
 	}
-	.search-results .result-name, .search-results div.desc, .search-results .result-description {
+	.search-results .result-name, .search-results div.desc {
 		width: 100%;
 	}
-	.search-results div.desc, .search-results .result-description, .item-right {
+	.search-results div.desc, .item-right {
 		padding-left: 2em;
 	}
 
@@ -1983,8 +1978,8 @@ in storage.js
 	}
 }
 
-.method-toggle summary,
-.implementors-toggle summary,
+.method-toggle > summary,
+.implementors-toggle > summary,
 .impl,
 #implementors-list > .docblock,
 .impl-items > section,
@@ -1993,10 +1988,7 @@ in storage.js
 	margin-bottom: 0.75em;
 }
 
-.method-toggle[open]:not(:last-child) {
-	margin-bottom: 2em;
-}
-
+.method-toggle[open]:not(:last-child),
 .implementors-toggle[open]:not(:last-child) {
 	margin-bottom: 2em;
 }
diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs
index 50dc26d768c..d121a3e2aa4 100644
--- a/src/librustdoc/passes/collect_intra_doc_links/early.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs
@@ -37,7 +37,6 @@ pub(crate) fn early_resolve_intra_doc_links(
         markdown_links: Default::default(),
         doc_link_resolutions: Default::default(),
         traits_in_scope: Default::default(),
-        all_traits: Default::default(),
         all_trait_impls: Default::default(),
         all_macro_rules: Default::default(),
         document_private_items,
@@ -63,7 +62,6 @@ pub(crate) fn early_resolve_intra_doc_links(
         markdown_links: Some(link_resolver.markdown_links),
         doc_link_resolutions: link_resolver.doc_link_resolutions,
         traits_in_scope: link_resolver.traits_in_scope,
-        all_traits: Some(link_resolver.all_traits),
         all_trait_impls: Some(link_resolver.all_trait_impls),
         all_macro_rules: link_resolver.all_macro_rules,
     }
@@ -81,7 +79,6 @@ struct EarlyDocLinkResolver<'r, 'ra> {
     markdown_links: FxHashMap<String, Vec<PreprocessedMarkdownLink>>,
     doc_link_resolutions: FxHashMap<(Symbol, Namespace, DefId), Option<Res<ast::NodeId>>>,
     traits_in_scope: DefIdMap<Vec<TraitCandidate>>,
-    all_traits: Vec<DefId>,
     all_trait_impls: Vec<DefId>,
     all_macro_rules: FxHashMap<Symbol, Res<ast::NodeId>>,
     document_private_items: bool,
@@ -122,8 +119,6 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
         loop {
             let crates = Vec::from_iter(self.resolver.cstore().crates_untracked());
             for &cnum in &crates[start_cnum..] {
-                let all_traits =
-                    Vec::from_iter(self.resolver.cstore().traits_in_crate_untracked(cnum));
                 let all_trait_impls =
                     Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum));
                 let all_inherent_impls =
@@ -132,20 +127,18 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
                     self.resolver.cstore().incoherent_impls_in_crate_untracked(cnum),
                 );
 
-                // Querying traits in scope is expensive so we try to prune the impl and traits lists
-                // using privacy, private traits and impls from other crates are never documented in
+                // Querying traits in scope is expensive so we try to prune the impl lists using
+                // privacy, private traits and impls from other crates are never documented in
                 // the current crate, and links in their doc comments are not resolved.
-                for &def_id in &all_traits {
-                    if self.resolver.cstore().visibility_untracked(def_id).is_public() {
-                        self.resolve_doc_links_extern_impl(def_id, false);
-                    }
-                }
                 for &(trait_def_id, impl_def_id, simplified_self_ty) in &all_trait_impls {
                     if self.resolver.cstore().visibility_untracked(trait_def_id).is_public()
                         && simplified_self_ty.and_then(|ty| ty.def()).map_or(true, |ty_def_id| {
                             self.resolver.cstore().visibility_untracked(ty_def_id).is_public()
                         })
                     {
+                        if self.visited_mods.insert(trait_def_id) {
+                            self.resolve_doc_links_extern_impl(trait_def_id, false);
+                        }
                         self.resolve_doc_links_extern_impl(impl_def_id, false);
                     }
                 }
@@ -158,7 +151,6 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
                     self.resolve_doc_links_extern_impl(impl_def_id, true);
                 }
 
-                self.all_traits.extend(all_traits);
                 self.all_trait_impls
                     .extend(all_trait_impls.into_iter().map(|(_, def_id, _)| def_id));
             }
@@ -307,15 +299,20 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
             {
                 if let Some(def_id) = child.res.opt_def_id() && !def_id.is_local() {
                     let scope_id = match child.res {
-                        Res::Def(DefKind::Variant, ..) => self.resolver.parent(def_id),
+                        Res::Def(
+                            DefKind::Variant
+                            | DefKind::AssocTy
+                            | DefKind::AssocFn
+                            | DefKind::AssocConst,
+                            ..,
+                        ) => self.resolver.parent(def_id),
                         _ => def_id,
                     };
                     self.resolve_doc_links_extern_outer(def_id, scope_id); // Outer attribute scope
                     if let Res::Def(DefKind::Mod, ..) = child.res {
                         self.resolve_doc_links_extern_inner(def_id); // Inner attribute scope
                     }
-                    // `DefKind::Trait`s are processed in `process_extern_impls`.
-                    if let Res::Def(DefKind::Mod | DefKind::Enum, ..) = child.res {
+                    if let Res::Def(DefKind::Mod | DefKind::Enum | DefKind::Trait, ..) = child.res {
                         self.process_module_children_or_reexports(def_id);
                     }
                     if let Res::Def(DefKind::Struct | DefKind::Union | DefKind::Variant, _) =
@@ -357,9 +354,6 @@ impl Visitor<'_> for EarlyDocLinkResolver<'_, '_> {
             self.parent_scope.module = old_module;
         } else {
             match &item.kind {
-                ItemKind::Trait(..) => {
-                    self.all_traits.push(self.resolver.local_def_id(item.id).to_def_id());
-                }
                 ItemKind::Impl(box ast::Impl { of_trait: Some(..), .. }) => {
                     self.all_trait_impls.push(self.resolver.local_def_id(item.id).to_def_id());
                 }
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 9567f08afc94332d59025744f3a8198104949d3
+Subproject 4b85255772114ca4946d95fe591933dae7d6199
diff --git a/src/test/codegen/deduced-param-attrs.rs b/src/test/codegen/deduced-param-attrs.rs
new file mode 100644
index 00000000000..153046eef3c
--- /dev/null
+++ b/src/test/codegen/deduced-param-attrs.rs
@@ -0,0 +1,60 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+#![allow(incomplete_features)]
+#![feature(unsized_locals, unsized_fn_params)]
+
+use std::cell::Cell;
+use std::hint;
+
+// Check to make sure that we can deduce the `readonly` attribute from function bodies for
+// parameters passed indirectly.
+
+pub struct BigStruct {
+    blah: [i32; 1024],
+}
+
+pub struct BigCellContainer {
+    blah: [Cell<i32>; 1024],
+}
+
+// The by-value parameter for this big struct can be marked readonly.
+//
+// CHECK: @use_big_struct_immutably({{.*}} readonly {{.*}} %big_struct)
+#[no_mangle]
+pub fn use_big_struct_immutably(big_struct: BigStruct) {
+    hint::black_box(&big_struct);
+}
+
+// The by-value parameter for this big struct can't be marked readonly, because we mutate it.
+//
+// CHECK-NOT: @use_big_struct_mutably({{.*}} readonly {{.*}} %big_struct)
+#[no_mangle]
+pub fn use_big_struct_mutably(mut big_struct: BigStruct) {
+    big_struct.blah[987] = 654;
+    hint::black_box(&big_struct);
+}
+
+// The by-value parameter for this big struct can't be marked readonly, because it contains
+// UnsafeCell.
+//
+// CHECK-NOT: @use_big_cell_container({{.*}} readonly {{.*}} %big_cell_container)
+#[no_mangle]
+pub fn use_big_cell_container(big_cell_container: BigCellContainer) {
+    hint::black_box(&big_cell_container);
+}
+
+// Make sure that we don't mistakenly mark a big struct as `readonly` when passed through a generic
+// type parameter if it contains UnsafeCell.
+//
+// CHECK-NOT: @use_something({{.*}} readonly {{.*}} %something)
+#[no_mangle]
+#[inline(never)]
+pub fn use_something<T>(something: T) {
+    hint::black_box(&something);
+}
+
+#[no_mangle]
+pub fn forward_big_cell_container(big_cell_container: BigCellContainer) {
+    use_something(big_cell_container)
+}
diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs
index bc650ebf5ee..44fee952307 100644
--- a/src/test/codegen/function-arguments.rs
+++ b/src/test/codegen/function-arguments.rs
@@ -127,7 +127,7 @@ pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {
 pub fn notunpin_borrow(_: &NotUnpin) {
 }
 
-// CHECK: @indirect_struct({{%S\*|ptr}} noalias nocapture noundef dereferenceable(32) %_1)
+// CHECK: @indirect_struct({{%S\*|ptr}} noalias nocapture noundef readonly dereferenceable(32) %_1)
 #[no_mangle]
 pub fn indirect_struct(_: S) {
 }
diff --git a/src/test/pretty/tests-are-sorted.pp b/src/test/pretty/tests-are-sorted.pp
new file mode 100644
index 00000000000..15dcd4ed97d
--- /dev/null
+++ b/src/test/pretty/tests-are-sorted.pp
@@ -0,0 +1,69 @@
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+// compile-flags: --crate-type=lib --test
+// pretty-compare-only
+// pretty-mode:expanded
+// pp-exact:tests-are-sorted.pp
+
+extern crate test;
+#[cfg(test)]
+#[rustc_test_marker = "m_test"]
+pub const m_test: test::TestDescAndFn =
+    test::TestDescAndFn {
+        desc: test::TestDesc {
+            name: test::StaticTestName("m_test"),
+            ignore: false,
+            ignore_message: ::core::option::Option::None,
+            compile_fail: false,
+            no_run: false,
+            should_panic: test::ShouldPanic::No,
+            test_type: test::TestType::Unknown,
+        },
+        testfn: test::StaticTestFn(|| test::assert_test_result(m_test())),
+    };
+fn m_test() {}
+
+extern crate test;
+#[cfg(test)]
+#[rustc_test_marker = "z_test"]
+pub const z_test: test::TestDescAndFn =
+    test::TestDescAndFn {
+        desc: test::TestDesc {
+            name: test::StaticTestName("z_test"),
+            ignore: false,
+            ignore_message: ::core::option::Option::None,
+            compile_fail: false,
+            no_run: false,
+            should_panic: test::ShouldPanic::No,
+            test_type: test::TestType::Unknown,
+        },
+        testfn: test::StaticTestFn(|| test::assert_test_result(z_test())),
+    };
+fn z_test() {}
+
+extern crate test;
+#[cfg(test)]
+#[rustc_test_marker = "a_test"]
+pub const a_test: test::TestDescAndFn =
+    test::TestDescAndFn {
+        desc: test::TestDesc {
+            name: test::StaticTestName("a_test"),
+            ignore: false,
+            ignore_message: ::core::option::Option::None,
+            compile_fail: false,
+            no_run: false,
+            should_panic: test::ShouldPanic::No,
+            test_type: test::TestType::Unknown,
+        },
+        testfn: test::StaticTestFn(|| test::assert_test_result(a_test())),
+    };
+fn a_test() {}
+#[rustc_main]
+pub fn main() -> () {
+    extern crate test;
+    test::test_main_static(&[&a_test, &m_test, &z_test])
+}
diff --git a/src/test/pretty/tests-are-sorted.rs b/src/test/pretty/tests-are-sorted.rs
new file mode 100644
index 00000000000..1f737d54719
--- /dev/null
+++ b/src/test/pretty/tests-are-sorted.rs
@@ -0,0 +1,13 @@
+// compile-flags: --crate-type=lib --test
+// pretty-compare-only
+// pretty-mode:expanded
+// pp-exact:tests-are-sorted.pp
+
+#[test]
+fn m_test() {}
+
+#[test]
+fn z_test() {}
+
+#[test]
+fn a_test() {}
diff --git a/src/test/rustdoc-gui/docblock-details.goml b/src/test/rustdoc-gui/docblock-details.goml
index f3cbe5767ae..9ae571efbb5 100644
--- a/src/test/rustdoc-gui/docblock-details.goml
+++ b/src/test/rustdoc-gui/docblock-details.goml
@@ -21,3 +21,14 @@ assert-property: (".top-doc .docblock summary h4", {"offsetHeight": "33"})
 assert-css: (".top-doc .docblock summary h4", {"margin-top": "15px", "margin-bottom": "5px"})
 // So `33 + 15 + 5` == `53`
 assert-property: (".top-doc .docblock summary", {"offsetHeight": "53"})
+
+// We now check the `<summary>` on a method.
+assert-css: (
+    ".method-toggle .docblock summary h4",
+    {"border-bottom-width": "0px"},
+)
+// This allows to ensure that summary is on one line only!
+assert-property: (".method-toggle .docblock summary h4", {"offsetHeight": "30"})
+assert-css: (".method-toggle .docblock summary h4", {"margin-top": "15px", "margin-bottom": "5px"})
+// So `30 + 15 + 5` == `50`
+assert-property: (".method-toggle .docblock summary", {"offsetHeight": "50"})
diff --git a/src/test/rustdoc-gui/headings.goml b/src/test/rustdoc-gui/headings.goml
index 9a77d8bbd15..85e17ca9551 100644
--- a/src/test/rustdoc-gui/headings.goml
+++ b/src/test/rustdoc-gui/headings.goml
@@ -150,109 +150,85 @@ assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
 assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "20px"})
 assert-css: ("h3#top-doc-prose-sub-heading", {"border-bottom-width": "1px"})
 
-// Checking colors now.
+// Needed to check colors
 show-text: true
-local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
 goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
-assert-css: (
-    ".top-doc .docblock h2",
-    {"color": "rgb(0, 0, 0)", "border-bottom": "1px solid rgb(221, 221, 221)"},
-)
-assert-css: (
-    ".top-doc .docblock h3",
-    {"color": "rgb(0, 0, 0)", "border-bottom": "1px solid rgb(221, 221, 221)"},
-)
-assert-css: (
-    ".top-doc .docblock h4",
-    {"color": "rgb(0, 0, 0)", "border-bottom": "1px solid rgb(221, 221, 221)"},
-)
-assert-css: (
-    ".top-doc .docblock h5",
-    {"color": "rgb(0, 0, 0)", "border-bottom-width": "0px"},
-)
-assert-css: (
-    "#implementations-list .docblock h4",
-    {"color": "rgb(0, 0, 0)", "border-bottom-width": "0px"},
-)
-assert-css: (
-    "#implementations-list .docblock h5",
-    {"color": "rgb(0, 0, 0)", "border-bottom-width": "0px"},
-)
-assert-css: (
-    "#implementations-list .docblock h6",
-    {"color": "rgb(0, 0, 0)", "border-bottom-width": "0px"},
-)
 
-local-storage: {"rustdoc-theme": "dark"}
-reload:
-assert-css: (
-    ".top-doc .docblock h2",
-    {"color": "rgb(221, 221, 221)", "border-bottom": "1px solid rgb(210, 210, 210)"},
-)
-assert-css: (
-    ".top-doc .docblock h3",
-    {"color": "rgb(221, 221, 221)", "border-bottom": "1px solid rgb(210, 210, 210)"},
-)
-assert-css: (
-    ".top-doc .docblock h4",
-    {"color": "rgb(221, 221, 221)", "border-bottom": "1px solid rgb(210, 210, 210)"},
-)
-assert-css: (
-    ".top-doc .docblock h5",
-    {"color": "rgb(221, 221, 221)", "border-bottom-width": "0px"},
-)
-assert-css: (
-    "#implementations-list .docblock h4",
-    {"color": "rgb(221, 221, 221)", "border-bottom-width": "0px"},
-)
-assert-css: (
-    "#implementations-list .docblock h5",
-    {"color": "rgb(221, 221, 221)", "border-bottom-width": "0px"},
-)
-assert-css: (
-    "#implementations-list .docblock h6",
-    {"color": "rgb(221, 221, 221)", "border-bottom-width": "0px"},
+define-function: (
+    "check-colors",
+    (theme, heading_color, small_heading_color, heading_border_color),
+    [
+        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+        ("reload"),
+        ("assert-css", (
+            ".top-doc .docblock h2",
+            {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
+        )),
+        ("assert-css", (
+            ".top-doc .docblock h3",
+            {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
+        )),
+        ("assert-css", (
+            ".top-doc .docblock h4",
+            {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
+        )),
+        ("assert-css", (
+            ".top-doc .docblock h5",
+            {"color": |small_heading_color|, "border-bottom-width": "0px"},
+        )),
+        ("assert-css", (
+            "#implementations-list .docblock h4",
+            {"color": |heading_color|, "border-bottom-width": "0px"},
+        )),
+        ("assert-css", (
+            "#implementations-list .docblock h5",
+            {"color": |small_heading_color|, "border-bottom-width": "0px"},
+        )),
+        ("assert-css", (
+            "#implementations-list .docblock h6",
+            {"color": |small_heading_color|, "border-bottom-width": "0px"},
+        )),
+    ],
+)
+call-function: (
+    "check-colors",
+    {
+        "theme": "ayu",
+        "heading_color": "rgb(255, 255, 255)",
+        "small_heading_color": "rgb(197, 197, 197)",
+        "heading_border_color": "rgb(92, 103, 115)",
+    },
+)
+call-function: (
+    "check-colors",
+    {
+        "theme": "dark",
+        "heading_color": "rgb(221, 221, 221)",
+        "small_heading_color": "rgb(221, 221, 221)",
+        "heading_border_color": "rgb(210, 210, 210)",
+    },
+)
+call-function: (
+    "check-colors",
+    {
+        "theme": "light",
+        "heading_color": "rgb(0, 0, 0)",
+        "small_heading_color": "rgb(0, 0, 0)",
+        "heading_border_color": "rgb(221, 221, 221)",
+    },
+)
+
+define-function: (
+    "check-since-color",
+    (theme),
+    [
+        ("local-storage", {"rustdoc-theme": |theme|}),
+        ("reload"),
+        ("assert-css", (".since", {"color": "rgb(128, 128, 128)"}, ALL)),
+    ],
 )
 
-local-storage: {"rustdoc-theme": "ayu"}
-reload:
-assert-css: (
-    ".top-doc .docblock h2",
-    {"color": "rgb(255, 255, 255)", "border-bottom": "1px solid rgb(92, 103, 115)"},
-)
-assert-css: (
-    ".top-doc .docblock h2",
-    {"color": "rgb(255, 255, 255)", "border-bottom": "1px solid rgb(92, 103, 115)"},
-)
-assert-css: (
-    ".top-doc .docblock h4",
-    {"color": "rgb(255, 255, 255)", "border-bottom": "1px solid rgb(92, 103, 115)"},
-)
-assert-css: (
-    ".top-doc .docblock h5",
-    {"color": "rgb(197, 197, 197)", "border-bottom-width": "0px"},
-)
-assert-css: (
-    "#implementations-list .docblock h4",
-    {"color": "rgb(255, 255, 255)", "border-bottom-width": "0px"},
-)
-assert-css: (
-    "#implementations-list .docblock h5",
-    {"color": "rgb(197, 197, 197)", "border-bottom-width": "0px"},
-)
-assert-css: (
-    "#implementations-list .docblock h6",
-    {"color": "rgb(197, 197, 197)", "border-bottom-width": "0px"},
-)
-
-local-storage: {"rustdoc-theme": "light"}
 goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
-assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
-
-local-storage: {"rustdoc-theme": "dark"}
-reload:
-assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
-
-local-storage: {"rustdoc-theme": "ayu"}
-reload:
-assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
+call-function: ("check-since-color", ("ayu"))
+call-function: ("check-since-color", ("dark"))
+call-function: ("check-since-color", ("light"))
diff --git a/src/test/rustdoc-gui/jump-to-def-background.goml b/src/test/rustdoc-gui/jump-to-def-background.goml
index 31c7d0ce3c8..b65faf13d0c 100644
--- a/src/test/rustdoc-gui/jump-to-def-background.goml
+++ b/src/test/rustdoc-gui/jump-to-def-background.goml
@@ -1,43 +1,22 @@
 // We check the background color on the jump to definition links in the source code page.
 goto: "file://" + |DOC_PATH| + "/src/link_to_definition/lib.rs.html"
 
-// Set the theme to dark.
-local-storage: {
-    "rustdoc-theme": "dark",
-    "rustdoc-preferred-dark-theme": "dark",
-    "rustdoc-use-system-theme": "false",
-}
-// We reload the page so the local storage settings are being used.
-reload:
-
-assert-css: (
-    "body.source .example-wrap pre.rust a",
-    {"background-color": "rgb(51, 51, 51)"},
-    ALL,
-)
-
-// Set the theme to ayu.
-local-storage: {
-    "rustdoc-theme": "ayu",
-    "rustdoc-preferred-dark-theme": "ayu",
-    "rustdoc-use-system-theme": "false",
-}
-// We reload the page so the local storage settings are being used.
-reload:
-
-assert-css: (
-    "body.source .example-wrap pre.rust a",
-    {"background-color": "rgb(51, 51, 51)"},
-    ALL,
+define-function: (
+    "check-background-color",
+    (theme, background_color),
+    [
+        // Set the theme.
+        ("local-storage", { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" }),
+        // We reload the page so the local storage settings are being used.
+        ("reload"),
+        ("assert-css", (
+            "body.source .example-wrap pre.rust a",
+            {"background-color": |background_color|},
+            ALL,
+        )),
+    ],
 )
 
-// Set the theme to light.
-local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
-// We reload the page so the local storage settings are being used.
-reload:
-
-assert-css: (
-    "body.source .example-wrap pre.rust a",
-    {"background-color": "rgb(238, 238, 238)"},
-    ALL,
-)
+call-function: ("check-background-color", ("ayu", "rgb(51, 51, 51)"))
+call-function: ("check-background-color", ("dark", "rgb(51, 51, 51)"))
+call-function: ("check-background-color", ("light", "rgb(238, 238, 238)"))
diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs
index 77617e10beb..fdf97e492aa 100644
--- a/src/test/rustdoc-gui/src/test_docs/lib.rs
+++ b/src/test/rustdoc-gui/src/test_docs/lib.rs
@@ -317,6 +317,18 @@ pub mod details {
     /// <div>I'm the content of the details!</div>
     /// </details>
     pub struct Details;
+
+    impl Details {
+        /// We check the appearance of the `<details>`/`<summary>` in here.
+        ///
+        /// ## Hello
+        ///
+        /// <details>
+        /// <summary><h4>I'm a summary</h4></summary>
+        /// <div>I'm the content of the details!</div>
+        /// </details>
+        pub fn method() {}
+    }
 }
 
 pub mod doc_block_table {
diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout
index dbf3a8f00ee..46f11d2e5d1 100644
--- a/src/test/rustdoc-ui/z-help.stdout
+++ b/src/test/rustdoc-ui/z-help.stdout
@@ -36,6 +36,7 @@
     -Z                       dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no)
     -Z                       dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans.
     -Z                           dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform)
+    -Z                               dylib-lto=val -- enables LTO for dylib crate type
     -Z                        emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
     -Z                           emit-thin-lto=val -- emit the bc module with thin LTO info (default: yes)
     -Z               export-executable-symbols=val -- export symbols from executables, as if they were dynamic libraries
diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html
new file mode 100644
index 00000000000..8934bc1ee33
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html
@@ -0,0 +1 @@
+<h4 class="code-header">type <a href="#associatedtype.Out0" class="associatedtype">Out0</a>: <a class="trait" href="../assoc_item_trait_bounds/trait.Support.html" title="trait assoc_item_trait_bounds::Support">Support</a>&lt;Item = <a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>&gt;</h4>
\ No newline at end of file
diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html
new file mode 100644
index 00000000000..bf330670ed0
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html
@@ -0,0 +1 @@
+<h4 class="code-header">type <a href="#associatedtype.Out2" class="associatedtype">Out2</a>&lt;T&gt;: <a class="trait" href="../assoc_item_trait_bounds/trait.Support.html" title="trait assoc_item_trait_bounds::Support">Support</a>&lt;Item = T&gt;</h4>
\ No newline at end of file
diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out9.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html
index 69d84e1b2c1..69d84e1b2c1 100644
--- a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out9.html
+++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html
diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.rs b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs
index 00976aa7442..5f4712aab5b 100644
--- a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.rs
+++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs
@@ -1,13 +1,10 @@
 // Regression test for issues #77763, #84579 and #102142.
 #![crate_name = "main"]
 
-// aux-build:assoc_item_trait_bounds_with_bindings.rs
+// aux-build:assoc_item_trait_bounds.rs
 // build-aux-docs
 // ignore-cross-compile
-extern crate assoc_item_trait_bounds_with_bindings as aux;
-
-// FIXME(fmease): Don't render an incorrect `T: ?Sized` where-clause for parameters
-//                of GATs like `Main::Out{2,4}`. Add a snapshot test once it's fixed.
+extern crate assoc_item_trait_bounds as aux;
 
 // @has main/trait.Main.html
 // @has - '//*[@id="associatedtype.Out0"]' 'type Out0: Support<Item = ()>'
@@ -24,11 +21,15 @@ extern crate assoc_item_trait_bounds_with_bindings as aux;
 // @has - '//*[@id="associatedtype.Out11"]' "type Out11: for<'r, 's> Helper<A<'s> = &'s (), B<'r> = ()>"
 // @has - '//*[@id="associatedtype.Out12"]' "type Out12: for<'w> Helper<B<'w> = Cow<'w, str>, A<'w> = bool>"
 // @has - '//*[@id="associatedtype.Out13"]' "type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>"
+// @has - '//*[@id="associatedtype.Out14"]' "type Out14<P: Copy + Eq, Q: ?Sized>"
 //
-// Snapshots: Check that we do not render any where-clauses for those associated types since all of
-// the trait bounds contained within were moved to the bounds of the respective item.
+// Snapshots:
+// Check that we don't render any where-clauses for the following associated types since
+// all corresponding projection equality predicates should have already been re-sugared
+// to associated type bindings:
 //
 // @snapshot out0 - '//*[@id="associatedtype.Out0"]/*[@class="code-header"]'
+// @snapshot out2 - '//*[@id="associatedtype.Out2"]/*[@class="code-header"]'
 // @snapshot out9 - '//*[@id="associatedtype.Out9"]/*[@class="code-header"]'
 //
 // @has - '//*[@id="tymethod.make"]' \
diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out0.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out0.html
deleted file mode 100644
index 927a1a42a1f..00000000000
--- a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out0.html
+++ /dev/null
@@ -1 +0,0 @@
-<h4 class="code-header">type <a href="#associatedtype.Out0" class="associatedtype">Out0</a>: <a class="trait" href="../assoc_item_trait_bounds_with_bindings/trait.Support.html" title="trait assoc_item_trait_bounds_with_bindings::Support">Support</a>&lt;Item = <a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>&gt;</h4>
\ No newline at end of file
diff --git a/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds_with_bindings.rs b/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
index f451b1a0e99..d326e61daea 100644
--- a/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds_with_bindings.rs
+++ b/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
@@ -15,6 +15,7 @@ pub trait Main {
     type Out11: for<'r, 's> Helper<A<'s> = &'s (), B<'r> = ()>;
     type Out12: for<'w> Helper<B<'w> = std::borrow::Cow<'w, str>, A<'w> = bool>;
     type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>;
+    type Out14<P: Copy + Eq, Q: ?Sized>;
 
     fn make<F>(_: F, _: impl FnMut(&str) -> bool)
     where
diff --git a/src/test/rustdoc/inline_cross/auxiliary/issue-24183.rs b/src/test/rustdoc/inline_cross/auxiliary/issue-24183.rs
new file mode 100644
index 00000000000..e7a13acc6f8
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/auxiliary/issue-24183.rs
@@ -0,0 +1,14 @@
+#![crate_type = "lib"]
+
+pub trait U/*: ?Sized */ {
+    fn modified(self) -> Self
+    where
+        Self: Sized
+    {
+        self
+    }
+
+    fn touch(&self)/* where Self: ?Sized */{}
+}
+
+pub trait S: Sized {}
diff --git a/src/test/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html b/src/test/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html
new file mode 100644
index 00000000000..6955a961499
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html
@@ -0,0 +1 @@
+<h4 class="code-header">fn <a href="#method.touch" class="fnname">touch</a>(&amp;self)</h4>
\ No newline at end of file
diff --git a/src/test/rustdoc/inline_cross/issue-24183.rs b/src/test/rustdoc/inline_cross/issue-24183.rs
new file mode 100644
index 00000000000..d11b6955f3c
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/issue-24183.rs
@@ -0,0 +1,18 @@
+#![crate_type = "lib"]
+#![crate_name = "usr"]
+
+// aux-crate:issue_24183=issue-24183.rs
+// edition: 2021
+
+// @has usr/trait.U.html
+// @has - '//*[@class="item-decl"]' "pub trait U {"
+// @has - '//*[@id="method.modified"]' \
+// "fn modified(self) -> Self\
+// where \
+//     Self: Sized"
+// @snapshot method_no_where_self_sized - '//*[@id="method.touch"]/*[@class="code-header"]'
+pub use issue_24183::U;
+
+// @has usr/trait.S.html
+// @has - '//*[@class="item-decl"]' 'pub trait S: Sized {'
+pub use issue_24183::S;
diff --git a/src/test/rustdoc/not-wf-ambiguous-normalization.rs b/src/test/rustdoc/not-wf-ambiguous-normalization.rs
new file mode 100644
index 00000000000..1e9f925f845
--- /dev/null
+++ b/src/test/rustdoc/not-wf-ambiguous-normalization.rs
@@ -0,0 +1,24 @@
+// compile-flags: -Znormalize-docs
+
+#![feature(type_alias_impl_trait)]
+
+trait Allocator {
+    type Buffer;
+}
+
+struct DefaultAllocator;
+
+// This unconstrained impl parameter causes the normalization of
+// `<DefaultAllocator as Allocator>::Buffer` to be ambiguous,
+// which caused an ICE with `-Znormalize-docs`.
+impl<T> Allocator for DefaultAllocator {
+    type Buffer = ();
+}
+
+type A = impl Fn(<DefaultAllocator as Allocator>::Buffer);
+
+fn foo() -> A {
+    |_| ()
+}
+
+fn main() {}
diff --git a/src/test/ui-fulldeps/fluent-messages/test.rs b/src/test/ui-fulldeps/fluent-messages/test.rs
index 256857e52a7..4e8147e2b76 100644
--- a/src/test/ui-fulldeps/fluent-messages/test.rs
+++ b/src/test/ui-fulldeps/fluent-messages/test.rs
@@ -49,6 +49,7 @@ mod duplicate {
     use super::fluent_messages;
 
     fluent_messages! {
+//~^ ERROR the name `a_b_key` is defined multiple times
         a => "./duplicate-a.ftl",
         a_b => "./duplicate-a-b.ftl",
 //~^ ERROR overrides existing message: `a_b_key`
@@ -80,7 +81,7 @@ mod valid {
         valid => "./valid.ftl",
     }
 
-    use self::fluent_generated::{DEFAULT_LOCALE_RESOURCES, valid::key};
+    use self::fluent_generated::{DEFAULT_LOCALE_RESOURCES, valid_key};
 }
 
 mod missing_crate_name {
@@ -93,5 +94,5 @@ mod missing_crate_name {
 //~| ERROR name `with-hyphens` does not start with the crate name
     }
 
-    use self::fluent_generated::{DEFAULT_LOCALE_RESOURCES, test_crate::{foo, with_hyphens}};
+    use self::fluent_generated::{DEFAULT_LOCALE_RESOURCES, test_crate_foo, with_hyphens};
 }
diff --git a/src/test/ui-fulldeps/fluent-messages/test.stderr b/src/test/ui-fulldeps/fluent-messages/test.stderr
index 26d87430a8f..d1cd4fe26da 100644
--- a/src/test/ui-fulldeps/fluent-messages/test.stderr
+++ b/src/test/ui-fulldeps/fluent-messages/test.stderr
@@ -30,19 +30,31 @@ error: expected a message field for "missing_message"
   |
 
 error: overrides existing message: `a_b_key`
-  --> $DIR/test.rs:53:16
+  --> $DIR/test.rs:54:16
    |
 LL |         a_b => "./duplicate-a-b.ftl",
    |                ^^^^^^^^^^^^^^^^^^^^^
    |
 help: previously defined in this resource
-  --> $DIR/test.rs:52:14
+  --> $DIR/test.rs:53:14
    |
 LL |         a => "./duplicate-a.ftl",
    |              ^^^^^^^^^^^^^^^^^^^
 
+error[E0428]: the name `a_b_key` is defined multiple times
+  --> $DIR/test.rs:51:5
+   |
+LL |     fluent_messages! {
+   |     ^^^^^^^^^^^^^^^^
+   |     |
+   |     `a_b_key` redefined here
+   |     previous definition of the value `a_b_key` here
+   |
+   = note: os-specific message
+   = note: os-specific message
+
 error: name `slug_with_hyphens_this-slug-has-hyphens` contains a '-' character
-  --> $DIR/test.rs:62:30
+  --> $DIR/test.rs:63:30
    |
 LL |         slug_with_hyphens => "./slug-with-hyphens.ftl",
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -50,7 +62,7 @@ LL |         slug_with_hyphens => "./slug-with-hyphens.ftl",
    = help: replace any '-'s with '_'s
 
 error: attribute `label-has-hyphens` contains a '-' character
-  --> $DIR/test.rs:71:31
+  --> $DIR/test.rs:72:31
    |
 LL |         label_with_hyphens => "./label-with-hyphens.ftl",
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -58,7 +70,7 @@ LL |         label_with_hyphens => "./label-with-hyphens.ftl",
    = help: replace any '-'s with '_'s
 
 error: name `with-hyphens` contains a '-' character
-  --> $DIR/test.rs:90:23
+  --> $DIR/test.rs:91:23
    |
 LL |         test_crate => "./missing-crate-name.ftl",
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -66,7 +78,7 @@ LL |         test_crate => "./missing-crate-name.ftl",
    = help: replace any '-'s with '_'s
 
 error: name `with-hyphens` does not start with the crate name
-  --> $DIR/test.rs:90:23
+  --> $DIR/test.rs:91:23
    |
 LL |         test_crate => "./missing-crate-name.ftl",
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -74,12 +86,13 @@ LL |         test_crate => "./missing-crate-name.ftl",
    = help: prepend `test_crate_` to the slug name: `test_crate_with_hyphens`
 
 error: name `test-crate_foo` contains a '-' character
-  --> $DIR/test.rs:90:23
+  --> $DIR/test.rs:91:23
    |
 LL |         test_crate => "./missing-crate-name.ftl",
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: replace any '-'s with '_'s
 
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
 
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.rs b/src/test/ui-fulldeps/internal-lints/diagnostics.rs
index 462f5e78498..643e81d99c6 100644
--- a/src/test/ui-fulldeps/internal-lints/diagnostics.rs
+++ b/src/test/ui-fulldeps/internal-lints/diagnostics.rs
@@ -19,14 +19,14 @@ use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::Span;
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example)]
+#[diag(compiletest_example)]
 struct DeriveDiagnostic {
     #[primary_span]
     span: Span,
 }
 
 #[derive(Subdiagnostic)]
-#[note(compiletest::example)]
+#[note(compiletest_example)]
 struct Note {
     #[primary_span]
     span: Span,
@@ -45,7 +45,7 @@ pub struct TranslatableInIntoDiagnostic;
 
 impl<'a> IntoDiagnostic<'a, ErrorGuaranteed> for TranslatableInIntoDiagnostic {
     fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
-        handler.struct_err(fluent::compiletest::example)
+        handler.struct_err(fluent::compiletest_example)
     }
 }
 
@@ -68,12 +68,12 @@ impl AddToDiagnostic for TranslatableInAddToDiagnostic {
     where
         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
     {
-        diag.note(fluent::compiletest::note);
+        diag.note(fluent::note);
     }
 }
 
 pub fn make_diagnostics<'a>(handler: &'a Handler) {
-    let _diag = handler.struct_err(fluent::compiletest::example);
+    let _diag = handler.struct_err(fluent::compiletest_example);
     //~^ ERROR diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
 
     let _diag = handler.struct_err("untranslatable diagnostic");
diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.stderr b/src/test/ui-fulldeps/internal-lints/diagnostics.stderr
index ac820a79db2..510d6a17108 100644
--- a/src/test/ui-fulldeps/internal-lints/diagnostics.stderr
+++ b/src/test/ui-fulldeps/internal-lints/diagnostics.stderr
@@ -19,7 +19,7 @@ LL |         diag.note("untranslatable diagnostic");
 error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
   --> $DIR/diagnostics.rs:76:25
    |
-LL |     let _diag = handler.struct_err(fluent::compiletest::example);
+LL |     let _diag = handler.struct_err(fluent::compiletest_example);
    |                         ^^^^^^^^^^
    |
 note: the lint level is defined here
diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index b8deb48d49a..46164d573b0 100644
--- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -28,15 +28,15 @@ use rustc_errors::{Applicability, MultiSpan};
 extern crate rustc_session;
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct Hello {}
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct HelloWarn {}
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 //~^ ERROR unsupported type attribute for diagnostic derive enum
 enum DiagnosticOnEnum {
     Foo,
@@ -46,13 +46,13 @@ enum DiagnosticOnEnum {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 #[diag = "E0123"]
 //~^ ERROR `#[diag = ...]` is not a valid attribute
 struct WrongStructAttrStyle {}
 
 #[derive(Diagnostic)]
-#[nonsense(compiletest::example, code = "E0123")]
+#[nonsense(compiletest_example, code = "E0123")]
 //~^ ERROR `#[nonsense(...)]` is not a valid attribute
 //~^^ ERROR diagnostic slug not specified
 //~^^^ ERROR cannot find attribute `nonsense` in this scope
@@ -90,12 +90,12 @@ struct InvalidNestedStructAttr2 {}
 struct InvalidNestedStructAttr3 {}
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123", slug = "foo")]
+#[diag(compiletest_example, code = "E0123", slug = "foo")]
 //~^ ERROR `#[diag(slug = ...)]` is not a valid attribute
 struct InvalidNestedStructAttr4 {}
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct WrongPlaceField {
     #[suggestion = "bar"]
     //~^ ERROR `#[suggestion = ...]` is not a valid attribute
@@ -103,20 +103,20 @@ struct WrongPlaceField {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
-#[diag(compiletest::example, code = "E0456")]
+#[diag(compiletest_example, code = "E0123")]
+#[diag(compiletest_example, code = "E0456")]
 //~^ ERROR specified multiple times
 //~^^ ERROR specified multiple times
 struct DiagSpecifiedTwice {}
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0456", code = "E0457")]
+#[diag(compiletest_example, code = "E0456", code = "E0457")]
 //~^ ERROR specified multiple times
 struct CodeSpecifiedTwice {}
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, compiletest::example, code = "E0456")]
-//~^ ERROR `#[diag(compiletest::example)]` is not a valid attribute
+#[diag(compiletest_example, compiletest_example, code = "E0456")]
+//~^ ERROR `#[diag(compiletest_example)]` is not a valid attribute
 struct SlugSpecifiedTwice {}
 
 #[derive(Diagnostic)]
@@ -128,11 +128,11 @@ struct KindNotProvided {} //~ ERROR diagnostic slug not specified
 struct SlugNotProvided {}
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example)]
+#[diag(compiletest_example)]
 struct CodeNotProvided {}
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct MessageWrongType {
     #[primary_span]
     //~^ ERROR `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -140,7 +140,7 @@ struct MessageWrongType {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct InvalidPathFieldAttr {
     #[nonsense]
     //~^ ERROR `#[nonsense]` is not a valid attribute
@@ -149,34 +149,34 @@ struct InvalidPathFieldAttr {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorWithField {
     name: String,
-    #[label(compiletest::label)]
+    #[label(label)]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorWithMessageAppliedToField {
-    #[label(compiletest::label)]
+    #[label(label)]
     //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
     name: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorWithNonexistentField {
-    #[suggestion(compiletest::suggestion, code = "{name}")]
+    #[suggestion(suggestion, code = "{name}")]
     //~^ ERROR `name` doesn't refer to a field on this type
     suggestion: (Span, Applicability),
 }
 
 #[derive(Diagnostic)]
 //~^ ERROR invalid format string: expected `'}'`
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorMissingClosingBrace {
-    #[suggestion(compiletest::suggestion, code = "{name")]
+    #[suggestion(suggestion, code = "{name")]
     suggestion: (Span, Applicability),
     name: String,
     val: usize,
@@ -184,49 +184,49 @@ struct ErrorMissingClosingBrace {
 
 #[derive(Diagnostic)]
 //~^ ERROR invalid format string: unmatched `}`
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorMissingOpeningBrace {
-    #[suggestion(compiletest::suggestion, code = "name}")]
+    #[suggestion(suggestion, code = "name}")]
     suggestion: (Span, Applicability),
     name: String,
     val: usize,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct LabelOnSpan {
-    #[label(compiletest::label)]
+    #[label(label)]
     sp: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct LabelOnNonSpan {
-    #[label(compiletest::label)]
+    #[label(label)]
     //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
     id: u32,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct Suggest {
-    #[suggestion(compiletest::suggestion, code = "This is the suggested code")]
-    #[suggestion_short(compiletest::suggestion, code = "This is the suggested code")]
-    #[suggestion_hidden(compiletest::suggestion, code = "This is the suggested code")]
-    #[suggestion_verbose(compiletest::suggestion, code = "This is the suggested code")]
+    #[suggestion(suggestion, code = "This is the suggested code")]
+    #[suggestion_short(suggestion, code = "This is the suggested code")]
+    #[suggestion_hidden(suggestion, code = "This is the suggested code")]
+    #[suggestion_verbose(suggestion, code = "This is the suggested code")]
     suggestion: (Span, Applicability),
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct SuggestWithoutCode {
-    #[suggestion(compiletest::suggestion)]
+    #[suggestion(suggestion)]
     //~^ ERROR suggestion without `code = "..."`
     suggestion: (Span, Applicability),
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct SuggestWithBadKey {
     #[suggestion(nonsense = "bar")]
     //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute
@@ -235,7 +235,7 @@ struct SuggestWithBadKey {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct SuggestWithShorthandMsg {
     #[suggestion(msg = "bar")]
     //~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute
@@ -244,52 +244,52 @@ struct SuggestWithShorthandMsg {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct SuggestWithoutMsg {
     #[suggestion(code = "bar")]
     suggestion: (Span, Applicability),
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct SuggestWithTypesSwapped {
-    #[suggestion(compiletest::suggestion, code = "This is suggested code")]
+    #[suggestion(suggestion, code = "This is suggested code")]
     suggestion: (Applicability, Span),
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct SuggestWithWrongTypeApplicabilityOnly {
-    #[suggestion(compiletest::suggestion, code = "This is suggested code")]
+    #[suggestion(suggestion, code = "This is suggested code")]
     //~^ ERROR wrong field type for suggestion
     suggestion: Applicability,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct SuggestWithSpanOnly {
-    #[suggestion(compiletest::suggestion, code = "This is suggested code")]
+    #[suggestion(suggestion, code = "This is suggested code")]
     suggestion: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct SuggestWithDuplicateSpanAndApplicability {
-    #[suggestion(compiletest::suggestion, code = "This is suggested code")]
+    #[suggestion(suggestion, code = "This is suggested code")]
     suggestion: (Span, Span, Applicability),
     //~^ ERROR specified multiple times
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct SuggestWithDuplicateApplicabilityAndSpan {
-    #[suggestion(compiletest::suggestion, code = "This is suggested code")]
+    #[suggestion(suggestion, code = "This is suggested code")]
     suggestion: (Applicability, Applicability, Span),
     //~^ ERROR specified multiple times
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct WrongKindOfAnnotation {
     #[label = "bar"]
     //~^ ERROR `#[label = ...]` is not a valid attribute
@@ -297,38 +297,38 @@ struct WrongKindOfAnnotation {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct OptionsInErrors {
-    #[label(compiletest::label)]
+    #[label(label)]
     label: Option<Span>,
-    #[suggestion(compiletest::suggestion, code = "...")]
+    #[suggestion(suggestion, code = "...")]
     opt_sugg: Option<(Span, Applicability)>,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0456")]
+#[diag(compiletest_example, code = "E0456")]
 struct MoveOutOfBorrowError<'tcx> {
     name: Ident,
     ty: Ty<'tcx>,
     #[primary_span]
-    #[label(compiletest::label)]
+    #[label(label)]
     span: Span,
-    #[label(compiletest::label)]
+    #[label(label)]
     other_span: Span,
-    #[suggestion(compiletest::suggestion, code = "{name}.clone()")]
+    #[suggestion(suggestion, code = "{name}.clone()")]
     opt_sugg: Option<(Span, Applicability)>,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorWithLifetime<'a> {
-    #[label(compiletest::label)]
+    #[label(label)]
     span: Span,
     name: &'a str,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorWithDefaultLabelAttr<'a> {
     #[label]
     span: Span,
@@ -337,7 +337,7 @@ struct ErrorWithDefaultLabelAttr<'a> {
 
 #[derive(Diagnostic)]
 //~^ ERROR the trait bound `Hello: IntoDiagnosticArg` is not satisfied
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ArgFieldWithoutSkip {
     #[primary_span]
     span: Span,
@@ -345,7 +345,7 @@ struct ArgFieldWithoutSkip {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ArgFieldWithSkip {
     #[primary_span]
     span: Span,
@@ -356,132 +356,132 @@ struct ArgFieldWithSkip {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorWithSpannedNote {
     #[note]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorWithSpannedNoteCustom {
-    #[note(compiletest::note)]
+    #[note(note)]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 #[note]
 struct ErrorWithNote {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
-#[note(compiletest::note)]
+#[diag(compiletest_example, code = "E0123")]
+#[note(note)]
 struct ErrorWithNoteCustom {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorWithSpannedHelp {
     #[help]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorWithSpannedHelpCustom {
-    #[help(compiletest::help)]
+    #[help(help)]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 #[help]
 struct ErrorWithHelp {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
-#[help(compiletest::help)]
+#[diag(compiletest_example, code = "E0123")]
+#[help(help)]
 struct ErrorWithHelpCustom {
     val: String,
 }
 
 #[derive(Diagnostic)]
 #[help]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorWithHelpWrongOrder {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[help(compiletest::help)]
-#[diag(compiletest::example, code = "E0123")]
+#[help(help)]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorWithHelpCustomWrongOrder {
     val: String,
 }
 
 #[derive(Diagnostic)]
 #[note]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorWithNoteWrongOrder {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[note(compiletest::note)]
-#[diag(compiletest::example, code = "E0123")]
+#[note(note)]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorWithNoteCustomWrongOrder {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ApplicabilityInBoth {
-    #[suggestion(compiletest::suggestion, code = "...", applicability = "maybe-incorrect")]
+    #[suggestion(suggestion, code = "...", applicability = "maybe-incorrect")]
     //~^ ERROR specified multiple times
     suggestion: (Span, Applicability),
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct InvalidApplicability {
-    #[suggestion(compiletest::suggestion, code = "...", applicability = "batman")]
+    #[suggestion(suggestion, code = "...", applicability = "batman")]
     //~^ ERROR invalid applicability
     suggestion: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ValidApplicability {
-    #[suggestion(compiletest::suggestion, code = "...", applicability = "maybe-incorrect")]
+    #[suggestion(suggestion, code = "...", applicability = "maybe-incorrect")]
     suggestion: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct NoApplicability {
-    #[suggestion(compiletest::suggestion, code = "...")]
+    #[suggestion(suggestion, code = "...")]
     suggestion: Span,
 }
 
 #[derive(Subdiagnostic)]
-#[note(parser::add_paren)]
+#[note(parser_add_paren)]
 struct Note;
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example)]
+#[diag(compiletest_example)]
 struct Subdiagnostic {
     #[subdiagnostic]
     note: Note,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct VecField {
     #[primary_span]
     #[label]
@@ -489,58 +489,58 @@ struct VecField {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct UnitField {
     #[primary_span]
     spans: Span,
     #[help]
     foo: (),
-    #[help(compiletest::help)]
+    #[help(help)]
     bar: (),
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct OptUnitField {
     #[primary_span]
     spans: Span,
     #[help]
     foo: Option<()>,
-    #[help(compiletest::help)]
+    #[help(help)]
     bar: Option<()>,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct LabelWithTrailingPath {
-    #[label(compiletest::label, foo)]
+    #[label(label, foo)]
     //~^ ERROR `#[label(foo)]` is not a valid attribute
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct LabelWithTrailingNameValue {
-    #[label(compiletest::label, foo = "...")]
+    #[label(label, foo = "...")]
     //~^ ERROR `#[label(foo = ...)]` is not a valid attribute
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct LabelWithTrailingList {
-    #[label(compiletest::label, foo("..."))]
+    #[label(label, foo("..."))]
     //~^ ERROR `#[label(foo(...))]` is not a valid attribute
     span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(compiletest::example)]
+#[diag(compiletest_example)]
 struct LintsGood {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(compiletest::example)]
+#[diag(compiletest_example)]
 struct PrimarySpanOnLint {
     #[primary_span]
     //~^ ERROR `#[primary_span]` is not a valid attribute
@@ -548,42 +548,42 @@ struct PrimarySpanOnLint {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct ErrorWithMultiSpan {
     #[primary_span]
     span: MultiSpan,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 #[warning]
 struct ErrorWithWarn {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[error(compiletest::example, code = "E0123")]
+#[error(compiletest_example, code = "E0123")]
 //~^ ERROR `#[error(...)]` is not a valid attribute
 //~| ERROR diagnostic slug not specified
 //~| ERROR cannot find attribute `error` in this scope
 struct ErrorAttribute {}
 
 #[derive(Diagnostic)]
-#[warn_(compiletest::example, code = "E0123")]
+#[warn_(compiletest_example, code = "E0123")]
 //~^ ERROR `#[warn_(...)]` is not a valid attribute
 //~| ERROR diagnostic slug not specified
 //~| ERROR cannot find attribute `warn_` in this scope
 struct WarnAttribute {}
 
 #[derive(Diagnostic)]
-#[lint(compiletest::example, code = "E0123")]
+#[lint(compiletest_example, code = "E0123")]
 //~^ ERROR `#[lint(...)]` is not a valid attribute
 //~| ERROR diagnostic slug not specified
 //~| ERROR cannot find attribute `lint` in this scope
 struct LintAttributeOnSessionDiag {}
 
 #[derive(LintDiagnostic)]
-#[lint(compiletest::example, code = "E0123")]
+#[lint(compiletest_example, code = "E0123")]
 //~^ ERROR `#[lint(...)]` is not a valid attribute
 //~| ERROR `#[lint(...)]` is not a valid attribute
 //~| ERROR diagnostic slug not specified
@@ -591,55 +591,55 @@ struct LintAttributeOnSessionDiag {}
 struct LintAttributeOnLintDiag {}
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct DuplicatedSuggestionCode {
-    #[suggestion(compiletest::suggestion, code = "...", code = ",,,")]
+    #[suggestion(suggestion, code = "...", code = ",,,")]
     //~^ ERROR specified multiple times
     suggestion: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct InvalidTypeInSuggestionTuple {
-    #[suggestion(compiletest::suggestion, code = "...")]
+    #[suggestion(suggestion, code = "...")]
     suggestion: (Span, usize),
     //~^ ERROR wrong types for suggestion
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct MissingApplicabilityInSuggestionTuple {
-    #[suggestion(compiletest::suggestion, code = "...")]
+    #[suggestion(suggestion, code = "...")]
     suggestion: (Span,),
     //~^ ERROR wrong types for suggestion
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct MissingCodeInSuggestion {
-    #[suggestion(compiletest::suggestion)]
+    #[suggestion(suggestion)]
     //~^ ERROR suggestion without `code = "..."`
     suggestion: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
-#[multipart_suggestion(compiletest::suggestion)]
+#[diag(compiletest_example, code = "E0123")]
+#[multipart_suggestion(suggestion)]
 //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
 //~| ERROR cannot find attribute `multipart_suggestion` in this scope
 #[multipart_suggestion()]
 //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
 //~| ERROR cannot find attribute `multipart_suggestion` in this scope
 struct MultipartSuggestion {
-    #[multipart_suggestion(compiletest::suggestion)]
+    #[multipart_suggestion(suggestion)]
     //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
     //~| ERROR cannot find attribute `multipart_suggestion` in this scope
     suggestion: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
-#[suggestion(compiletest::suggestion, code = "...")]
+#[diag(compiletest_example, code = "E0123")]
+#[suggestion(suggestion, code = "...")]
 //~^ ERROR `#[suggestion(...)]` is not a valid attribute
 struct SuggestionOnStruct {
     #[primary_span]
@@ -647,7 +647,7 @@ struct SuggestionOnStruct {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 #[label]
 //~^ ERROR `#[label]` is not a valid attribute
 struct LabelOnStruct {
@@ -657,30 +657,30 @@ struct LabelOnStruct {
 
 #[derive(Diagnostic)]
 enum ExampleEnum {
-    #[diag(compiletest::example)]
+    #[diag(compiletest_example)]
     Foo {
         #[primary_span]
         sp: Span,
         #[note]
         note_sp: Span,
     },
-    #[diag(compiletest::example)]
+    #[diag(compiletest_example)]
     Bar {
         #[primary_span]
         sp: Span,
     },
-    #[diag(compiletest::example)]
+    #[diag(compiletest_example)]
     Baz,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct RawIdentDiagnosticArg {
     pub r#type: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example)]
+#[diag(compiletest_example)]
 struct SubdiagnosticBad {
     #[subdiagnostic(bad)]
 //~^ ERROR `#[subdiagnostic(bad)]` is not a valid attribute
@@ -688,7 +688,7 @@ struct SubdiagnosticBad {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example)]
+#[diag(compiletest_example)]
 struct SubdiagnosticBadStr {
     #[subdiagnostic = "bad"]
 //~^ ERROR `#[subdiagnostic = ...]` is not a valid attribute
@@ -696,7 +696,7 @@ struct SubdiagnosticBadStr {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example)]
+#[diag(compiletest_example)]
 struct SubdiagnosticBadTwice {
     #[subdiagnostic(bad, bad)]
 //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
@@ -704,7 +704,7 @@ struct SubdiagnosticBadTwice {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example)]
+#[diag(compiletest_example)]
 struct SubdiagnosticBadLitStr {
     #[subdiagnostic("bad")]
 //~^ ERROR `#[subdiagnostic("...")]` is not a valid attribute
@@ -712,7 +712,7 @@ struct SubdiagnosticBadLitStr {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(compiletest::example)]
+#[diag(compiletest_example)]
 struct SubdiagnosticEagerLint {
     #[subdiagnostic(eager)]
 //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
@@ -720,7 +720,7 @@ struct SubdiagnosticEagerLint {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example)]
+#[diag(compiletest_example)]
 struct SubdiagnosticEagerCorrect {
     #[subdiagnostic(eager)]
     note: Note,
@@ -732,7 +732,7 @@ struct SubdiagnosticEagerCorrect {
 
 #[derive(Subdiagnostic)]
 #[suggestion_short(
-    parser::use_instead,
+    use_instead,
     applicability = "machine-applicable",
     code = "{correct}"
 )]
@@ -744,7 +744,7 @@ pub(crate) struct SubdiagnosticWithSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag(compiletest::example)]
+#[diag(compiletest_example)]
 struct SubdiagnosticEagerSuggestion {
     #[subdiagnostic(eager)]
     sub: SubdiagnosticWithSuggestion,
@@ -752,7 +752,7 @@ struct SubdiagnosticEagerSuggestion {
 
 /// with a doc comment on the type..
 #[derive(Diagnostic)]
-#[diag(compiletest::example, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
 struct WithDocComment {
     /// ..and the field
     #[primary_span]
diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index 7a42d618707..0a1c4bddb06 100644
--- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -1,8 +1,8 @@
 error: unsupported type attribute for diagnostic derive enum
   --> $DIR/diagnostic-derive.rs:39:1
    |
-LL | #[diag(compiletest::example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(compiletest_example, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:42:5
@@ -10,7 +10,7 @@ error: diagnostic slug not specified
 LL |     Foo,
    |     ^^^
    |
-   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:44:5
@@ -18,7 +18,7 @@ error: diagnostic slug not specified
 LL |     Bar,
    |     ^^^
    |
-   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[diag = ...]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:50:1
@@ -29,20 +29,20 @@ LL | #[diag = "E0123"]
 error: `#[nonsense(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:55:1
    |
-LL | #[nonsense(compiletest::example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[nonsense(compiletest_example, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:55:1
    |
-LL | / #[nonsense(compiletest::example, code = "E0123")]
+LL | / #[nonsense(compiletest_example, code = "E0123")]
 LL | |
 LL | |
 LL | |
 LL | | struct InvalidStructAttr {}
    | |___________________________^
    |
-   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[diag("...")]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:62:8
@@ -61,7 +61,7 @@ LL | |
 LL | | struct InvalidLitNestedAttr {}
    | |______________________________^
    |
-   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[diag(nonsense(...))]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:73:8
@@ -80,7 +80,7 @@ LL | |
 LL | | struct InvalidNestedStructAttr1 {}
    | |__________________________________^
    |
-   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[diag(nonsense = ...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:79:8
@@ -108,7 +108,7 @@ LL | |
 LL | | struct InvalidNestedStructAttr2 {}
    | |__________________________________^
    |
-   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[diag(nonsense = ...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:86:8
@@ -134,13 +134,13 @@ LL | |
 LL | | struct InvalidNestedStructAttr3 {}
    | |__________________________________^
    |
-   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[diag(slug = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:93:46
+  --> $DIR/diagnostic-derive.rs:93:45
    |
-LL | #[diag(compiletest::example, code = "E0123", slug = "foo")]
-   |                                              ^^^^^^^^^^^^
+LL | #[diag(compiletest_example, code = "E0123", slug = "foo")]
+   |                                             ^^^^^^^^^^^^
    |
    = help: only `code` is a valid nested attributes following the slug
 
@@ -153,44 +153,44 @@ LL |     #[suggestion = "bar"]
 error: specified multiple times
   --> $DIR/diagnostic-derive.rs:107:8
    |
-LL | #[diag(compiletest::example, code = "E0456")]
-   |        ^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(compiletest_example, code = "E0456")]
+   |        ^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
   --> $DIR/diagnostic-derive.rs:106:8
    |
-LL | #[diag(compiletest::example, code = "E0123")]
-   |        ^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(compiletest_example, code = "E0123")]
+   |        ^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:107:37
+  --> $DIR/diagnostic-derive.rs:107:36
    |
-LL | #[diag(compiletest::example, code = "E0456")]
-   |                                     ^^^^^^^
+LL | #[diag(compiletest_example, code = "E0456")]
+   |                                    ^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:106:37
+  --> $DIR/diagnostic-derive.rs:106:36
    |
-LL | #[diag(compiletest::example, code = "E0123")]
-   |                                     ^^^^^^^
+LL | #[diag(compiletest_example, code = "E0123")]
+   |                                    ^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:113:53
+  --> $DIR/diagnostic-derive.rs:113:52
    |
-LL | #[diag(compiletest::example, code = "E0456", code = "E0457")]
-   |                                                     ^^^^^^^
+LL | #[diag(compiletest_example, code = "E0456", code = "E0457")]
+   |                                                    ^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:113:37
+  --> $DIR/diagnostic-derive.rs:113:36
    |
-LL | #[diag(compiletest::example, code = "E0456", code = "E0457")]
-   |                                     ^^^^^^^
+LL | #[diag(compiletest_example, code = "E0456", code = "E0457")]
+   |                                    ^^^^^^^
 
-error: `#[diag(compiletest::example)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:118:30
+error: `#[diag(compiletest_example)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:118:29
    |
-LL | #[diag(compiletest::example, compiletest::example, code = "E0456")]
-   |                              ^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(compiletest_example, compiletest_example, code = "E0456")]
+   |                             ^^^^^^^^^^^^^^^^^^^
    |
    = help: diagnostic slug must be the first argument
 
@@ -200,7 +200,7 @@ error: diagnostic slug not specified
 LL | struct KindNotProvided {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:126:1
@@ -210,7 +210,7 @@ LL | |
 LL | | struct SlugNotProvided {}
    | |_________________________^
    |
-   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
   --> $DIR/diagnostic-derive.rs:137:5
@@ -227,14 +227,14 @@ LL |     #[nonsense]
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
   --> $DIR/diagnostic-derive.rs:162:5
    |
-LL |     #[label(compiletest::label)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[label(label)]
+   |     ^^^^^^^^^^^^^^^
 
 error: `name` doesn't refer to a field on this type
-  --> $DIR/diagnostic-derive.rs:170:50
+  --> $DIR/diagnostic-derive.rs:170:37
    |
-LL |     #[suggestion(compiletest::suggestion, code = "{name}")]
-   |                                                  ^^^^^^^^
+LL |     #[suggestion(suggestion, code = "{name}")]
+   |                                     ^^^^^^^^
 
 error: invalid format string: expected `'}'` but string was terminated
   --> $DIR/diagnostic-derive.rs:175:10
@@ -257,14 +257,14 @@ LL | #[derive(Diagnostic)]
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
   --> $DIR/diagnostic-derive.rs:205:5
    |
-LL |     #[label(compiletest::label)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[label(label)]
+   |     ^^^^^^^^^^^^^^^
 
 error: suggestion without `code = "..."`
   --> $DIR/diagnostic-derive.rs:223:5
    |
-LL |     #[suggestion(compiletest::suggestion)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[suggestion(suggestion)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[suggestion(nonsense = ...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:231:18
@@ -297,7 +297,7 @@ LL |     #[suggestion(msg = "bar")]
 error: wrong field type for suggestion
   --> $DIR/diagnostic-derive.rs:263:5
    |
-LL | /     #[suggestion(compiletest::suggestion, code = "This is suggested code")]
+LL | /     #[suggestion(suggestion, code = "This is suggested code")]
 LL | |
 LL | |     suggestion: Applicability,
    | |_____________________________^
@@ -335,10 +335,10 @@ LL |     #[label = "bar"]
    |     ^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:445:57
+  --> $DIR/diagnostic-derive.rs:445:44
    |
-LL |     #[suggestion(compiletest::suggestion, code = "...", applicability = "maybe-incorrect")]
-   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[suggestion(suggestion, code = "...", applicability = "maybe-incorrect")]
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
   --> $DIR/diagnostic-derive.rs:447:24
@@ -347,30 +347,30 @@ LL |     suggestion: (Span, Applicability),
    |                        ^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/diagnostic-derive.rs:453:57
+  --> $DIR/diagnostic-derive.rs:453:44
    |
-LL |     #[suggestion(compiletest::suggestion, code = "...", applicability = "batman")]
-   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[suggestion(suggestion, code = "...", applicability = "batman")]
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[label(foo)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:516:33
+  --> $DIR/diagnostic-derive.rs:516:20
    |
-LL |     #[label(compiletest::label, foo)]
-   |                                 ^^^
+LL |     #[label(label, foo)]
+   |                    ^^^
    |
    = help: a diagnostic slug must be the first argument to the attribute
 
 error: `#[label(foo = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:524:33
+  --> $DIR/diagnostic-derive.rs:524:20
    |
-LL |     #[label(compiletest::label, foo = "...")]
-   |                                 ^^^^^^^^^^^
+LL |     #[label(label, foo = "...")]
+   |                    ^^^^^^^^^^^
 
 error: `#[label(foo(...))]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:532:33
+  --> $DIR/diagnostic-derive.rs:532:20
    |
-LL |     #[label(compiletest::label, foo("..."))]
-   |                                 ^^^^^^^^^^
+LL |     #[label(label, foo("..."))]
+   |                    ^^^^^^^^^^
 
 error: `#[primary_span]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:545:5
@@ -383,73 +383,73 @@ LL |     #[primary_span]
 error: `#[error(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:565:1
    |
-LL | #[error(compiletest::example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[error(compiletest_example, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:565:1
    |
-LL | / #[error(compiletest::example, code = "E0123")]
+LL | / #[error(compiletest_example, code = "E0123")]
 LL | |
 LL | |
 LL | |
 LL | | struct ErrorAttribute {}
    | |________________________^
    |
-   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[warn_(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:572:1
    |
-LL | #[warn_(compiletest::example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[warn_(compiletest_example, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:572:1
    |
-LL | / #[warn_(compiletest::example, code = "E0123")]
+LL | / #[warn_(compiletest_example, code = "E0123")]
 LL | |
 LL | |
 LL | |
 LL | | struct WarnAttribute {}
    | |_______________________^
    |
-   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[lint(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:579:1
    |
-LL | #[lint(compiletest::example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[lint(compiletest_example, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:579:1
    |
-LL | / #[lint(compiletest::example, code = "E0123")]
+LL | / #[lint(compiletest_example, code = "E0123")]
 LL | |
 LL | |
 LL | |
 LL | | struct LintAttributeOnSessionDiag {}
    | |____________________________________^
    |
-   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[lint(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:586:1
    |
-LL | #[lint(compiletest::example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[lint(compiletest_example, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[lint(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:586:1
    |
-LL | #[lint(compiletest::example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[lint(compiletest_example, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:586:1
    |
-LL | / #[lint(compiletest::example, code = "E0123")]
+LL | / #[lint(compiletest_example, code = "E0123")]
 LL | |
 LL | |
 LL | |
@@ -457,19 +457,19 @@ LL | |
 LL | | struct LintAttributeOnLintDiag {}
    | |_________________________________^
    |
-   = help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest::example)]`
+   = help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]`
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:596:57
+  --> $DIR/diagnostic-derive.rs:596:44
    |
-LL |     #[suggestion(compiletest::suggestion, code = "...", code = ",,,")]
-   |                                                         ^^^^^^^^^^^^
+LL |     #[suggestion(suggestion, code = "...", code = ",,,")]
+   |                                            ^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:596:43
+  --> $DIR/diagnostic-derive.rs:596:30
    |
-LL |     #[suggestion(compiletest::suggestion, code = "...", code = ",,,")]
-   |                                           ^^^^^^^^^^^^
+LL |     #[suggestion(suggestion, code = "...", code = ",,,")]
+   |                              ^^^^^^^^^^^^
 
 error: wrong types for suggestion
   --> $DIR/diagnostic-derive.rs:605:24
@@ -490,14 +490,14 @@ LL |     suggestion: (Span,),
 error: suggestion without `code = "..."`
   --> $DIR/diagnostic-derive.rs:620:5
    |
-LL |     #[suggestion(compiletest::suggestion)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[suggestion(suggestion)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[multipart_suggestion(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:627:1
    |
-LL | #[multipart_suggestion(compiletest::suggestion)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[multipart_suggestion(suggestion)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider creating a `Subdiagnostic` instead
 
@@ -512,16 +512,16 @@ LL | #[multipart_suggestion()]
 error: `#[multipart_suggestion(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:634:5
    |
-LL |     #[multipart_suggestion(compiletest::suggestion)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[multipart_suggestion(suggestion)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider creating a `Subdiagnostic` instead
 
 error: `#[suggestion(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:642:1
    |
-LL | #[suggestion(compiletest::suggestion, code = "...")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion(suggestion, code = "...")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
@@ -576,7 +576,7 @@ LL |     #[subdiagnostic(eager)]
 error: cannot find attribute `nonsense` in this scope
   --> $DIR/diagnostic-derive.rs:55:3
    |
-LL | #[nonsense(compiletest::example, code = "E0123")]
+LL | #[nonsense(compiletest_example, code = "E0123")]
    |   ^^^^^^^^
 
 error: cannot find attribute `nonsense` in this scope
@@ -588,31 +588,31 @@ LL |     #[nonsense]
 error: cannot find attribute `error` in this scope
   --> $DIR/diagnostic-derive.rs:565:3
    |
-LL | #[error(compiletest::example, code = "E0123")]
+LL | #[error(compiletest_example, code = "E0123")]
    |   ^^^^^
 
 error: cannot find attribute `warn_` in this scope
   --> $DIR/diagnostic-derive.rs:572:3
    |
-LL | #[warn_(compiletest::example, code = "E0123")]
+LL | #[warn_(compiletest_example, code = "E0123")]
    |   ^^^^^ help: a built-in attribute with a similar name exists: `warn`
 
 error: cannot find attribute `lint` in this scope
   --> $DIR/diagnostic-derive.rs:579:3
    |
-LL | #[lint(compiletest::example, code = "E0123")]
+LL | #[lint(compiletest_example, code = "E0123")]
    |   ^^^^ help: a built-in attribute with a similar name exists: `link`
 
 error: cannot find attribute `lint` in this scope
   --> $DIR/diagnostic-derive.rs:586:3
    |
-LL | #[lint(compiletest::example, code = "E0123")]
+LL | #[lint(compiletest_example, code = "E0123")]
    |   ^^^^ help: a built-in attribute with a similar name exists: `link`
 
 error: cannot find attribute `multipart_suggestion` in this scope
   --> $DIR/diagnostic-derive.rs:627:3
    |
-LL | #[multipart_suggestion(compiletest::suggestion)]
+LL | #[multipart_suggestion(suggestion)]
    |   ^^^^^^^^^^^^^^^^^^^^
 
 error: cannot find attribute `multipart_suggestion` in this scope
@@ -624,7 +624,7 @@ LL | #[multipart_suggestion()]
 error: cannot find attribute `multipart_suggestion` in this scope
   --> $DIR/diagnostic-derive.rs:634:7
    |
-LL |     #[multipart_suggestion(compiletest::suggestion)]
+LL |     #[multipart_suggestion(suggestion)]
    |       ^^^^^^^^^^^^^^^^^^^^
 
 error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent`
diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
index 2fe93d46d0a..9088ca6ce46 100644
--- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
+++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
@@ -20,7 +20,7 @@ use rustc_span::Span;
 use rustc_macros::Subdiagnostic;
 
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren)]
+#[label(parser_add_paren)]
 struct A {
     #[primary_span]
     span: Span,
@@ -29,13 +29,13 @@ struct A {
 
 #[derive(Subdiagnostic)]
 enum B {
-    #[label(parser::add_paren)]
+    #[label(parser_add_paren)]
     A {
         #[primary_span]
         span: Span,
         var: String,
     },
-    #[label(parser::add_paren)]
+    #[label(parser_add_paren)]
     B {
         #[primary_span]
         span: Span,
@@ -44,7 +44,7 @@ enum B {
 }
 
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren)]
+#[label(parser_add_paren)]
 //~^ ERROR label without `#[primary_span]` field
 struct C {
     var: String,
@@ -138,7 +138,7 @@ struct M {
 }
 
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren, code = "...")]
+#[label(parser_add_paren, code = "...")]
 //~^ ERROR `#[label(code = ...)]` is not a valid attribute
 struct N {
     #[primary_span]
@@ -147,7 +147,7 @@ struct N {
 }
 
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren, applicability = "machine-applicable")]
+#[label(parser_add_paren, applicability = "machine-applicable")]
 //~^ ERROR `#[label(applicability = ...)]` is not a valid attribute
 struct O {
     #[primary_span]
@@ -160,7 +160,7 @@ struct O {
 //~^ ERROR cannot find attribute `foo` in this scope
 //~^^ ERROR unsupported type attribute for subdiagnostic enum
 enum P {
-    #[label(parser::add_paren)]
+    #[label(parser_add_paren)]
     A {
         #[primary_span]
         span: Span,
@@ -230,7 +230,7 @@ enum U {
 
 #[derive(Subdiagnostic)]
 enum V {
-    #[label(parser::add_paren)]
+    #[label(parser_add_paren)]
     A {
         #[primary_span]
         span: Span,
@@ -244,7 +244,7 @@ enum V {
 }
 
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren)]
+#[label(parser_add_paren)]
 //~^ ERROR label without `#[primary_span]` field
 struct W {
     #[primary_span]
@@ -253,7 +253,7 @@ struct W {
 }
 
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren)]
+#[label(parser_add_paren)]
 struct X {
     #[primary_span]
     span: Span,
@@ -263,7 +263,7 @@ struct X {
 }
 
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren)]
+#[label(parser_add_paren)]
 struct Y {
     #[primary_span]
     span: Span,
@@ -274,7 +274,7 @@ struct Y {
 }
 
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren)]
+#[label(parser_add_paren)]
 struct Z {
     #[primary_span]
     span: Span,
@@ -285,7 +285,7 @@ struct Z {
 }
 
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren)]
+#[label(parser_add_paren)]
 struct AA {
     #[primary_span]
     span: Span,
@@ -296,7 +296,7 @@ struct AA {
 }
 
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren)]
+#[label(parser_add_paren)]
 struct AB {
     #[primary_span]
     span: Span,
@@ -312,23 +312,23 @@ union AC {
 }
 
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren)]
-#[label(parser::add_paren)]
+#[label(parser_add_paren)]
+#[label(parser_add_paren)]
 struct AD {
     #[primary_span]
     span: Span,
 }
 
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren, parser::add_paren)]
-//~^ ERROR `#[label(parser::add_paren)]` is not a valid attribute
+#[label(parser_add_paren, parser_add_paren)]
+//~^ ERROR `#[label(parser_add_paren)]` is not a valid attribute
 struct AE {
     #[primary_span]
     span: Span,
 }
 
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren)]
+#[label(parser_add_paren)]
 struct AF {
     #[primary_span]
     //~^ NOTE previously specified here
@@ -346,7 +346,7 @@ struct AG {
 }
 
 #[derive(Subdiagnostic)]
-#[suggestion(parser::add_paren, code = "...")]
+#[suggestion(parser_add_paren, code = "...")]
 struct AH {
     #[primary_span]
     span: Span,
@@ -357,7 +357,7 @@ struct AH {
 
 #[derive(Subdiagnostic)]
 enum AI {
-    #[suggestion(parser::add_paren, code = "...")]
+    #[suggestion(parser_add_paren, code = "...")]
     A {
         #[primary_span]
         span: Span,
@@ -365,7 +365,7 @@ enum AI {
         applicability: Applicability,
         var: String,
     },
-    #[suggestion(parser::add_paren, code = "...")]
+    #[suggestion(parser_add_paren, code = "...")]
     B {
         #[primary_span]
         span: Span,
@@ -376,7 +376,7 @@ enum AI {
 }
 
 #[derive(Subdiagnostic)]
-#[suggestion(parser::add_paren, code = "...", code = "...")]
+#[suggestion(parser_add_paren, code = "...", code = "...")]
 //~^ ERROR specified multiple times
 //~^^ NOTE previously specified here
 struct AJ {
@@ -387,7 +387,7 @@ struct AJ {
 }
 
 #[derive(Subdiagnostic)]
-#[suggestion(parser::add_paren, code = "...")]
+#[suggestion(parser_add_paren, code = "...")]
 struct AK {
     #[primary_span]
     span: Span,
@@ -400,7 +400,7 @@ struct AK {
 }
 
 #[derive(Subdiagnostic)]
-#[suggestion(parser::add_paren, code = "...")]
+#[suggestion(parser_add_paren, code = "...")]
 struct AL {
     #[primary_span]
     span: Span,
@@ -410,14 +410,14 @@ struct AL {
 }
 
 #[derive(Subdiagnostic)]
-#[suggestion(parser::add_paren, code = "...")]
+#[suggestion(parser_add_paren, code = "...")]
 struct AM {
     #[primary_span]
     span: Span,
 }
 
 #[derive(Subdiagnostic)]
-#[suggestion(parser::add_paren)]
+#[suggestion(parser_add_paren)]
 //~^ ERROR suggestion without `code = "..."`
 struct AN {
     #[primary_span]
@@ -427,7 +427,7 @@ struct AN {
 }
 
 #[derive(Subdiagnostic)]
-#[suggestion(parser::add_paren, code ="...", applicability = "foo")]
+#[suggestion(parser_add_paren, code ="...", applicability = "foo")]
 //~^ ERROR invalid applicability
 struct AO {
     #[primary_span]
@@ -435,24 +435,24 @@ struct AO {
 }
 
 #[derive(Subdiagnostic)]
-#[help(parser::add_paren)]
+#[help(parser_add_paren)]
 struct AP {
     var: String
 }
 
 #[derive(Subdiagnostic)]
-#[note(parser::add_paren)]
+#[note(parser_add_paren)]
 struct AQ;
 
 #[derive(Subdiagnostic)]
-#[suggestion(parser::add_paren, code = "...")]
+#[suggestion(parser_add_paren, code = "...")]
 //~^ ERROR suggestion without `#[primary_span]` field
 struct AR {
     var: String,
 }
 
 #[derive(Subdiagnostic)]
-#[suggestion(parser::add_paren, code ="...", applicability = "machine-applicable")]
+#[suggestion(parser_add_paren, code ="...", applicability = "machine-applicable")]
 struct AS {
     #[primary_span]
     span: Span,
@@ -462,7 +462,7 @@ struct AS {
 #[label]
 //~^ ERROR unsupported type attribute for subdiagnostic enum
 enum AT {
-    #[label(parser::add_paren)]
+    #[label(parser_add_paren)]
     A {
         #[primary_span]
         span: Span,
@@ -471,7 +471,7 @@ enum AT {
 }
 
 #[derive(Subdiagnostic)]
-#[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+#[suggestion(parser_add_paren, code ="{var}", applicability = "machine-applicable")]
 struct AU {
     #[primary_span]
     span: Span,
@@ -479,7 +479,7 @@ struct AU {
 }
 
 #[derive(Subdiagnostic)]
-#[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+#[suggestion(parser_add_paren, code ="{var}", applicability = "machine-applicable")]
 //~^ ERROR `var` doesn't refer to a field on this type
 struct AV {
     #[primary_span]
@@ -488,7 +488,7 @@ struct AV {
 
 #[derive(Subdiagnostic)]
 enum AW {
-    #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+    #[suggestion(parser_add_paren, code ="{var}", applicability = "machine-applicable")]
     A {
         #[primary_span]
         span: Span,
@@ -498,7 +498,7 @@ enum AW {
 
 #[derive(Subdiagnostic)]
 enum AX {
-    #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+    #[suggestion(parser_add_paren, code ="{var}", applicability = "machine-applicable")]
 //~^ ERROR `var` doesn't refer to a field on this type
     A {
         #[primary_span]
@@ -507,18 +507,18 @@ enum AX {
 }
 
 #[derive(Subdiagnostic)]
-#[warning(parser::add_paren)]
+#[warning(parser_add_paren)]
 struct AY {}
 
 #[derive(Subdiagnostic)]
-#[warning(parser::add_paren)]
+#[warning(parser_add_paren)]
 struct AZ {
     #[primary_span]
     span: Span,
 }
 
 #[derive(Subdiagnostic)]
-#[suggestion(parser::add_paren, code = "...")]
+#[suggestion(parser_add_paren, code = "...")]
 //~^ ERROR suggestion without `#[primary_span]` field
 struct BA {
     #[suggestion_part]
@@ -533,7 +533,7 @@ struct BA {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
+#[multipart_suggestion(parser_add_paren, code = "...", applicability = "machine-applicable")]
 //~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields
 //~| ERROR `#[multipart_suggestion(code = ...)]` is not a valid attribute
 struct BBa {
@@ -541,7 +541,7 @@ struct BBa {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+#[multipart_suggestion(parser_add_paren, applicability = "machine-applicable")]
 struct BBb {
     #[suggestion_part]
     //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
@@ -549,7 +549,7 @@ struct BBb {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+#[multipart_suggestion(parser_add_paren, applicability = "machine-applicable")]
 struct BBc {
     #[suggestion_part()]
     //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
@@ -557,7 +557,7 @@ struct BBc {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::add_paren)]
+#[multipart_suggestion(parser_add_paren)]
 //~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields
 struct BC {
     #[primary_span]
@@ -566,7 +566,7 @@ struct BC {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::add_paren)]
+#[multipart_suggestion(parser_add_paren)]
 struct BD {
     #[suggestion_part]
     //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
@@ -586,7 +586,7 @@ struct BD {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+#[multipart_suggestion(parser_add_paren, applicability = "machine-applicable")]
 struct BE {
     #[suggestion_part(code = "...", code = ",,,")]
     //~^ ERROR specified multiple times
@@ -595,7 +595,7 @@ struct BE {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+#[multipart_suggestion(parser_add_paren, applicability = "machine-applicable")]
 struct BF {
     #[suggestion_part(code = "(")]
     first: Span,
@@ -604,7 +604,7 @@ struct BF {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::add_paren)]
+#[multipart_suggestion(parser_add_paren)]
 struct BG {
     #[applicability]
     appl: Applicability,
@@ -615,7 +615,7 @@ struct BG {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+#[multipart_suggestion(parser_add_paren, applicability = "machine-applicable")]
 struct BH {
     #[applicability]
     //~^ ERROR `#[applicability]` has no effect
@@ -627,14 +627,14 @@ struct BH {
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+#[multipart_suggestion(parser_add_paren, applicability = "machine-applicable")]
 struct BI {
     #[suggestion_part(code = "")]
     spans: Vec<Span>,
 }
 
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren)]
+#[label(parser_add_paren)]
 struct BJ {
     #[primary_span]
     span: Span,
@@ -643,7 +643,7 @@ struct BJ {
 
 /// with a doc comment on the type..
 #[derive(Subdiagnostic)]
-#[label(parser::add_paren)]
+#[label(parser_add_paren)]
 struct BK {
     /// ..and the field
     #[primary_span]
@@ -654,7 +654,7 @@ struct BK {
 #[derive(Subdiagnostic)]
 enum BL {
     /// ..and the variant..
-    #[label(parser::add_paren)]
+    #[label(parser_add_paren)]
     Foo {
         /// ..and the field
         #[primary_span]
diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
index 1173d24248b..b21f9cc94a9 100644
--- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
+++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
@@ -1,7 +1,7 @@
 error: label without `#[primary_span]` field
   --> $DIR/subdiagnostic-derive.rs:47:1
    |
-LL | / #[label(parser::add_paren)]
+LL | / #[label(parser_add_paren)]
 LL | |
 LL | | struct C {
 LL | |     var: String,
@@ -81,16 +81,16 @@ LL | #[label()]
    | ^^^^^^^^^^
 
 error: `#[label(code = ...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:141:28
+  --> $DIR/subdiagnostic-derive.rs:141:27
    |
-LL | #[label(parser::add_paren, code = "...")]
-   |                            ^^^^^^^^^^^^
+LL | #[label(parser_add_paren, code = "...")]
+   |                           ^^^^^^^^^^^^
 
 error: `#[label(applicability = ...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:150:28
+  --> $DIR/subdiagnostic-derive.rs:150:27
    |
-LL | #[label(parser::add_paren, applicability = "machine-applicable")]
-   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[label(parser_add_paren, applicability = "machine-applicable")]
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unsupported type attribute for subdiagnostic enum
   --> $DIR/subdiagnostic-derive.rs:159:1
@@ -143,7 +143,7 @@ LL |     #[primary_span]
 error: label without `#[primary_span]` field
   --> $DIR/subdiagnostic-derive.rs:247:1
    |
-LL | / #[label(parser::add_paren)]
+LL | / #[label(parser_add_paren)]
 LL | |
 LL | | struct W {
 LL | |     #[primary_span]
@@ -190,11 +190,11 @@ LL | |     b: u64
 LL | | }
    | |_^
 
-error: `#[label(parser::add_paren)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:323:28
+error: `#[label(parser_add_paren)]` is not a valid attribute
+  --> $DIR/subdiagnostic-derive.rs:323:27
    |
-LL | #[label(parser::add_paren, parser::add_paren)]
-   |                            ^^^^^^^^^^^^^^^^^
+LL | #[label(parser_add_paren, parser_add_paren)]
+   |                           ^^^^^^^^^^^^^^^^
    |
    = help: a diagnostic slug must be the first argument to the attribute
 
@@ -217,16 +217,16 @@ LL | struct AG {
    |        ^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:379:47
+  --> $DIR/subdiagnostic-derive.rs:379:46
    |
-LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
-   |                                               ^^^^^^^^^^^^
+LL | #[suggestion(parser_add_paren, code = "...", code = "...")]
+   |                                              ^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:379:33
+  --> $DIR/subdiagnostic-derive.rs:379:32
    |
-LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
-   |                                 ^^^^^^^^^^^^
+LL | #[suggestion(parser_add_paren, code = "...", code = "...")]
+   |                                ^^^^^^^^^^^^
 
 error: specified multiple times
   --> $DIR/subdiagnostic-derive.rs:397:5
@@ -249,19 +249,19 @@ LL |     #[applicability]
 error: suggestion without `code = "..."`
   --> $DIR/subdiagnostic-derive.rs:420:1
    |
-LL | #[suggestion(parser::add_paren)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion(parser_add_paren)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/subdiagnostic-derive.rs:430:46
+  --> $DIR/subdiagnostic-derive.rs:430:45
    |
-LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
-   |                                              ^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion(parser_add_paren, code ="...", applicability = "foo")]
+   |                                             ^^^^^^^^^^^^^^^^^^^^^
 
 error: suggestion without `#[primary_span]` field
   --> $DIR/subdiagnostic-derive.rs:448:1
    |
-LL | / #[suggestion(parser::add_paren, code = "...")]
+LL | / #[suggestion(parser_add_paren, code = "...")]
 LL | |
 LL | | struct AR {
 LL | |     var: String,
@@ -275,16 +275,16 @@ LL | #[label]
    | ^^^^^^^^
 
 error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:482:39
+  --> $DIR/subdiagnostic-derive.rs:482:38
    |
-LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
-   |                                       ^^^^^^^
+LL | #[suggestion(parser_add_paren, code ="{var}", applicability = "machine-applicable")]
+   |                                      ^^^^^^^
 
 error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:501:43
+  --> $DIR/subdiagnostic-derive.rs:501:42
    |
-LL |     #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
-   |                                           ^^^^^^^
+LL |     #[suggestion(parser_add_paren, code ="{var}", applicability = "machine-applicable")]
+   |                                          ^^^^^^^
 
 error: `#[suggestion_part]` is not a valid attribute
   --> $DIR/subdiagnostic-derive.rs:524:5
@@ -305,7 +305,7 @@ LL |     #[suggestion_part(code = "...")]
 error: suggestion without `#[primary_span]` field
   --> $DIR/subdiagnostic-derive.rs:521:1
    |
-LL | / #[suggestion(parser::add_paren, code = "...")]
+LL | / #[suggestion(parser_add_paren, code = "...")]
 LL | |
 LL | | struct BA {
 LL | |     #[suggestion_part]
@@ -315,17 +315,17 @@ LL | | }
    | |_^
 
 error: `#[multipart_suggestion(code = ...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:536:43
+  --> $DIR/subdiagnostic-derive.rs:536:42
    |
-LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
-   |                                           ^^^^^^^^^^^^
+LL | #[multipart_suggestion(parser_add_paren, code = "...", applicability = "machine-applicable")]
+   |                                          ^^^^^^^^^^^^
    |
    = help: only `applicability` is a valid nested attributes
 
 error: multipart suggestion without any `#[suggestion_part(...)]` fields
   --> $DIR/subdiagnostic-derive.rs:536:1
    |
-LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
+LL | / #[multipart_suggestion(parser_add_paren, code = "...", applicability = "machine-applicable")]
 LL | |
 LL | |
 LL | | struct BBa {
@@ -356,7 +356,7 @@ LL |     #[primary_span]
 error: multipart suggestion without any `#[suggestion_part(...)]` fields
   --> $DIR/subdiagnostic-derive.rs:560:1
    |
-LL | / #[multipart_suggestion(parser::add_paren)]
+LL | / #[multipart_suggestion(parser_add_paren)]
 LL | |
 LL | | struct BC {
 LL | |     #[primary_span]
diff --git a/src/test/ui/associated-type-bounds/inside-adt.rs b/src/test/ui/associated-type-bounds/inside-adt.rs
index f26037f0707..8eb8c44bb42 100644
--- a/src/test/ui/associated-type-bounds/inside-adt.rs
+++ b/src/test/ui/associated-type-bounds/inside-adt.rs
@@ -16,7 +16,7 @@ enum E2 { V(Box<dyn Iterator<Item: Copy>>) }
 //~^ ERROR associated type bounds are not allowed within structs, enums, or unions
 enum E3 { V(dyn Iterator<Item: 'static>) }
 //~^ ERROR associated type bounds are not allowed within structs, enums, or unions
-//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)`
+//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized + 'static> + 'static)`
 
 union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
 //~^ ERROR associated type bounds are not allowed within structs, enums, or unions
@@ -25,6 +25,6 @@ union U2 { f: ManuallyDrop<Box<dyn Iterator<Item: Copy>>> }
 //~^ ERROR associated type bounds are not allowed within structs, enums, or unions
 union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
 //~^ ERROR associated type bounds are not allowed within structs, enums, or unions
-//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)`
+//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized + 'static> + 'static)`
 
 fn main() {}
diff --git a/src/test/ui/associated-type-bounds/inside-adt.stderr b/src/test/ui/associated-type-bounds/inside-adt.stderr
index 978390fa712..dbfcfa58063 100644
--- a/src/test/ui/associated-type-bounds/inside-adt.stderr
+++ b/src/test/ui/associated-type-bounds/inside-adt.stderr
@@ -70,13 +70,13 @@ help: the `Box` type always has a statically known size and allocates its conten
 LL | enum E1 { V(Box<dyn Iterator<Item: Copy>>) }
    |             ++++                        +
 
-error[E0277]: the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)` cannot be known at compilation time
+error[E0277]: the size for values of type `(dyn Iterator<Item = impl Sized + 'static> + 'static)` cannot be known at compilation time
   --> $DIR/inside-adt.rs:17:13
    |
 LL | enum E3 { V(dyn Iterator<Item: 'static>) }
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Sized> + 'static)`
+   = help: the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Sized + 'static> + 'static)`
    = note: no field of an enum variant may have a dynamically sized type
    = help: change the field's type to have a statically known size
 help: borrowed types always have a statically known size
@@ -107,14 +107,14 @@ help: the `Box` type always has a statically known size and allocates its conten
 LL | union U1 { f: Box<ManuallyDrop<dyn Iterator<Item: Copy>>> }
    |               ++++                                      +
 
-error[E0277]: the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)` cannot be known at compilation time
+error[E0277]: the size for values of type `(dyn Iterator<Item = impl Sized + 'static> + 'static)` cannot be known at compilation time
   --> $DIR/inside-adt.rs:26:15
    |
 LL | union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `ManuallyDrop<(dyn Iterator<Item = impl Sized> + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Sized> + 'static)`
-   = note: required because it appears within the type `ManuallyDrop<(dyn Iterator<Item = impl Sized> + 'static)>`
+   = help: within `ManuallyDrop<(dyn Iterator<Item = impl Sized + 'static> + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Sized + 'static> + 'static)`
+   = note: required because it appears within the type `ManuallyDrop<(dyn Iterator<Item = impl Sized + 'static> + 'static)>`
    = note: no field of a union may have a dynamically sized type
    = help: change the field's type to have a statically known size
 help: borrowed types always have a statically known size
diff --git a/src/test/ui/associated-types/issue-87261.rs b/src/test/ui/associated-types/issue-87261.rs
index 384561f8ccd..e8548d402fa 100644
--- a/src/test/ui/associated-types/issue-87261.rs
+++ b/src/test/ui/associated-types/issue-87261.rs
@@ -77,10 +77,10 @@ where
 
 fn main() {
     accepts_trait(returns_opaque());
-    //~^ ERROR type mismatch resolving `<impl Trait as Trait>::Associated == ()`
+    //~^ ERROR type mismatch resolving `<impl Trait + 'static as Trait>::Associated == ()`
 
     accepts_trait(returns_opaque_derived());
-    //~^ ERROR type mismatch resolving `<impl DerivedTrait as Trait>::Associated == ()`
+    //~^ ERROR type mismatch resolving `<impl DerivedTrait + 'static as Trait>::Associated == ()`
 
     accepts_trait(returns_opaque_foo());
     //~^ ERROR type mismatch resolving `<impl Trait + Foo as Trait>::Associated == ()`
@@ -89,7 +89,7 @@ fn main() {
     //~^ ERROR type mismatch resolving `<impl DerivedTrait + Foo as Trait>::Associated == ()`
 
     accepts_generic_trait(returns_opaque_generic());
-    //~^ ERROR type mismatch resolving `<impl GenericTrait<()> as GenericTrait<()>>::Associated == ()`
+    //~^ ERROR type mismatch resolving `<impl GenericTrait<()> + 'static as GenericTrait<()>>::Associated == ()`
 
     accepts_generic_trait(returns_opaque_generic_foo());
     //~^ ERROR type mismatch resolving `<impl GenericTrait<()> + Foo as GenericTrait<()>>::Associated == ()`
diff --git a/src/test/ui/associated-types/issue-87261.stderr b/src/test/ui/associated-types/issue-87261.stderr
index f24423dd106..2cce6b94702 100644
--- a/src/test/ui/associated-types/issue-87261.stderr
+++ b/src/test/ui/associated-types/issue-87261.stderr
@@ -132,7 +132,7 @@ note: required by a bound in `accepts_generic_trait`
 LL | fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {}
    |                                              ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait`
 
-error[E0271]: type mismatch resolving `<impl Trait as Trait>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl Trait + 'static as Trait>::Associated == ()`
   --> $DIR/issue-87261.rs:79:19
    |
 LL | fn returns_opaque() -> impl Trait + 'static {
@@ -144,18 +144,18 @@ LL |     accepts_trait(returns_opaque());
    |     required by a bound introduced by this call
    |
    = note:    expected unit type `()`
-           found associated type `<impl Trait as Trait>::Associated`
+           found associated type `<impl Trait + 'static as Trait>::Associated`
 note: required by a bound in `accepts_trait`
   --> $DIR/issue-87261.rs:43:27
    |
 LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
    |                           ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait`
-help: consider constraining the associated type `<impl Trait as Trait>::Associated` to `()`
+help: consider constraining the associated type `<impl Trait + 'static as Trait>::Associated` to `()`
    |
 LL | fn returns_opaque() -> impl Trait<Associated = ()> + 'static {
    |                                  +++++++++++++++++
 
-error[E0271]: type mismatch resolving `<impl DerivedTrait as Trait>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl DerivedTrait + 'static as Trait>::Associated == ()`
   --> $DIR/issue-87261.rs:82:19
    |
 LL | fn returns_opaque_derived() -> impl DerivedTrait + 'static {
@@ -167,13 +167,13 @@ LL |     accepts_trait(returns_opaque_derived());
    |     required by a bound introduced by this call
    |
    = note:    expected unit type `()`
-           found associated type `<impl DerivedTrait as Trait>::Associated`
+           found associated type `<impl DerivedTrait + 'static as Trait>::Associated`
 note: required by a bound in `accepts_trait`
   --> $DIR/issue-87261.rs:43:27
    |
 LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
    |                           ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait`
-help: consider constraining the associated type `<impl DerivedTrait as Trait>::Associated` to `()`
+help: consider constraining the associated type `<impl DerivedTrait + 'static as Trait>::Associated` to `()`
    |
 LL | fn returns_opaque_derived() -> impl DerivedTrait<Associated = ()> + 'static {
    |                                                 +++++++++++++++++
@@ -222,7 +222,7 @@ note: required by a bound in `accepts_trait`
 LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
    |                           ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait`
 
-error[E0271]: type mismatch resolving `<impl GenericTrait<()> as GenericTrait<()>>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl GenericTrait<()> + 'static as GenericTrait<()>>::Associated == ()`
   --> $DIR/issue-87261.rs:91:27
    |
 LL | fn returns_opaque_generic() -> impl GenericTrait<()> + 'static {
@@ -234,13 +234,13 @@ LL |     accepts_generic_trait(returns_opaque_generic());
    |     required by a bound introduced by this call
    |
    = note:    expected unit type `()`
-           found associated type `<impl GenericTrait<()> as GenericTrait<()>>::Associated`
+           found associated type `<impl GenericTrait<()> + 'static as GenericTrait<()>>::Associated`
 note: required by a bound in `accepts_generic_trait`
   --> $DIR/issue-87261.rs:44:46
    |
 LL | fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {}
    |                                              ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait`
-help: consider constraining the associated type `<impl GenericTrait<()> as GenericTrait<()>>::Associated` to `()`
+help: consider constraining the associated type `<impl GenericTrait<()> + 'static as GenericTrait<()>>::Associated` to `()`
    |
 LL | fn returns_opaque_generic() -> impl GenericTrait<(), Associated = ()> + 'static {
    |                                                    +++++++++++++++++
diff --git a/src/test/ui/issues/issue-23338-params-outlive-temps-of-body.rs b/src/test/ui/borrowck/issue-23338-params-outlive-temps-of-body.rs
index d45aaa843fb..d45aaa843fb 100644
--- a/src/test/ui/issues/issue-23338-params-outlive-temps-of-body.rs
+++ b/src/test/ui/borrowck/issue-23338-params-outlive-temps-of-body.rs
diff --git a/src/test/ui/closures/issue-97607.rs b/src/test/ui/closures/issue-97607.rs
new file mode 100644
index 00000000000..74c910ad0bb
--- /dev/null
+++ b/src/test/ui/closures/issue-97607.rs
@@ -0,0 +1,12 @@
+// check-pass
+#[allow(unused)]
+
+fn test<T, F, U>(f: F) -> Box<dyn Fn(T) -> U + 'static>
+where
+    F: 'static + Fn(T) -> U,
+    for<'a> U: 'a, // < This is the problematic line, see #97607
+{
+    Box::new(move |t| f(t))
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr
index 828f0988a03..d674e3acdff 100644
--- a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr
@@ -1,5 +1,5 @@
 error: generic parameters may not be used in const operations
-  --> $DIR/dependence_lint.rs:13:32
+  --> $DIR/dependence_lint.rs:14:32
    |
 LL |     let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
    |                                ^ cannot perform const operation using `T`
@@ -8,7 +8,7 @@ LL |     let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/dependence_lint.rs:20:37
+  --> $DIR/dependence_lint.rs:21:37
    |
 LL |     let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce
    |                                     ^ cannot perform const operation using `T`
@@ -17,7 +17,7 @@ LL |     let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable,
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 warning: cannot use constants which depend on generic parameters in types
-  --> $DIR/dependence_lint.rs:9:9
+  --> $DIR/dependence_lint.rs:10:9
    |
 LL |     [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs`
    |         ^^^^^^^^^^^^^^^^^^^
@@ -27,7 +27,7 @@ LL |     [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_
    = note: `#[warn(const_evaluatable_unchecked)]` on by default
 
 warning: cannot use constants which depend on generic parameters in types
-  --> $DIR/dependence_lint.rs:16:9
+  --> $DIR/dependence_lint.rs:17:9
    |
 LL |     [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr
index b13bcdb2c47..74111ef1d38 100644
--- a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr
@@ -1,5 +1,5 @@
 error: overly complex generic constant
-  --> $DIR/dependence_lint.rs:16:9
+  --> $DIR/dependence_lint.rs:17:9
    |
 LL |     [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants
@@ -7,7 +7,7 @@ LL |     [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error w
    = help: consider moving this anonymous constant into a `const` function
 
 error: overly complex generic constant
-  --> $DIR/dependence_lint.rs:20:17
+  --> $DIR/dependence_lint.rs:21:17
    |
 LL |     let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants
@@ -15,7 +15,7 @@ LL |     let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable,
    = help: consider moving this anonymous constant into a `const` function
 
 error: unconstrained generic constant
-  --> $DIR/dependence_lint.rs:13:12
+  --> $DIR/dependence_lint.rs:14:12
    |
 LL |     let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL |     let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
    = help: try adding a `where` bound using this expression: `where [(); size_of::<*mut T>()]:`
 
 error: unconstrained generic constant
-  --> $DIR/dependence_lint.rs:9:9
+  --> $DIR/dependence_lint.rs:10:9
    |
 LL |     [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs`
    |         ^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs
index dcdfd75def9..b715e07f8fa 100644
--- a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs
+++ b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs
@@ -1,4 +1,5 @@
 // revisions: full gce
+// compile-flags: -Zdeduplicate-diagnostics=yes
 
 #![cfg_attr(gce, feature(generic_const_exprs))]
 #![allow(incomplete_features)]
diff --git a/src/test/ui/const-generics/generic_const_exprs/function-call.rs b/src/test/ui/const-generics/generic_const_exprs/function-call.rs
index b5de66621c5..3c866333d60 100644
--- a/src/test/ui/const-generics/generic_const_exprs/function-call.rs
+++ b/src/test/ui/const-generics/generic_const_exprs/function-call.rs
@@ -1,4 +1,5 @@
 // check-pass
+// compile-flags: -Zdeduplicate-diagnostics=yes
 
 const fn foo<T>() -> usize {
     // We might instead branch on `std::mem::size_of::<*mut T>() < 8` here,
diff --git a/src/test/ui/const-generics/generic_const_exprs/function-call.stderr b/src/test/ui/const-generics/generic_const_exprs/function-call.stderr
index 796dc01043c..84abfe57876 100644
--- a/src/test/ui/const-generics/generic_const_exprs/function-call.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/function-call.stderr
@@ -1,5 +1,5 @@
 warning: cannot use constants which depend on generic parameters in types
-  --> $DIR/function-call.rs:14:17
+  --> $DIR/function-call.rs:15:17
    |
 LL |     let _ = [0; foo::<T>()];
    |                 ^^^^^^^^^^
diff --git a/src/test/ui/const-generics/min_const_generics/complex-expression.rs b/src/test/ui/const-generics/min_const_generics/complex-expression.rs
index 7840989cb08..8e667aebaad 100644
--- a/src/test/ui/const-generics/min_const_generics/complex-expression.rs
+++ b/src/test/ui/const-generics/min_const_generics/complex-expression.rs
@@ -1,3 +1,4 @@
+// compile-flags: -Zdeduplicate-diagnostics=yes
 use std::mem::size_of;
 
 fn test<const N: usize>() {}
diff --git a/src/test/ui/const-generics/min_const_generics/complex-expression.stderr b/src/test/ui/const-generics/min_const_generics/complex-expression.stderr
index 0b051c6131b..deabd05a6d5 100644
--- a/src/test/ui/const-generics/min_const_generics/complex-expression.stderr
+++ b/src/test/ui/const-generics/min_const_generics/complex-expression.stderr
@@ -1,5 +1,5 @@
 error: generic parameters may not be used in const operations
-  --> $DIR/complex-expression.rs:9:38
+  --> $DIR/complex-expression.rs:10:38
    |
 LL | struct Break0<const N: usize>([u8; { N + 1 }]);
    |                                      ^ cannot perform const operation using `N`
@@ -8,7 +8,7 @@ LL | struct Break0<const N: usize>([u8; { N + 1 }]);
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/complex-expression.rs:12:40
+  --> $DIR/complex-expression.rs:13:40
    |
 LL | struct Break1<const N: usize>([u8; { { N } }]);
    |                                        ^ cannot perform const operation using `N`
@@ -17,7 +17,7 @@ LL | struct Break1<const N: usize>([u8; { { N } }]);
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/complex-expression.rs:16:17
+  --> $DIR/complex-expression.rs:17:17
    |
 LL |     let _: [u8; N + 1];
    |                 ^ cannot perform const operation using `N`
@@ -26,7 +26,7 @@ LL |     let _: [u8; N + 1];
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/complex-expression.rs:21:17
+  --> $DIR/complex-expression.rs:22:17
    |
 LL |     let _ = [0; N + 1];
    |                 ^ cannot perform const operation using `N`
@@ -35,7 +35,7 @@ LL |     let _ = [0; N + 1];
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/complex-expression.rs:25:45
+  --> $DIR/complex-expression.rs:26:45
    |
 LL | struct BreakTy0<T>(T, [u8; { size_of::<*mut T>() }]);
    |                                             ^ cannot perform const operation using `T`
@@ -44,7 +44,7 @@ LL | struct BreakTy0<T>(T, [u8; { size_of::<*mut T>() }]);
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/complex-expression.rs:28:47
+  --> $DIR/complex-expression.rs:29:47
    |
 LL | struct BreakTy1<T>(T, [u8; { { size_of::<*mut T>() } }]);
    |                                               ^ cannot perform const operation using `T`
@@ -53,7 +53,7 @@ LL | struct BreakTy1<T>(T, [u8; { { size_of::<*mut T>() } }]);
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/complex-expression.rs:32:32
+  --> $DIR/complex-expression.rs:33:32
    |
 LL |     let _: [u8; size_of::<*mut T>() + 1];
    |                                ^ cannot perform const operation using `T`
@@ -62,7 +62,7 @@ LL |     let _: [u8; size_of::<*mut T>() + 1];
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 warning: cannot use constants which depend on generic parameters in types
-  --> $DIR/complex-expression.rs:37:17
+  --> $DIR/complex-expression.rs:38:17
    |
 LL |     let _ = [0; size_of::<*mut T>() + 1];
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs b/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs
index 71d13ca61c9..e9d868093e7 100644
--- a/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs
+++ b/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs
@@ -1,4 +1,5 @@
 // check-pass
+// compile-flags: -Zdeduplicate-diagnostics=yes
 #![allow(dead_code)]
 
 fn foo<T>() {
diff --git a/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr b/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr
index f0ba7a39d1e..8003dfa4071 100644
--- a/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr
+++ b/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr
@@ -1,5 +1,5 @@
 warning: cannot use constants which depend on generic parameters in types
-  --> $DIR/const-evaluatable-unchecked.rs:5:9
+  --> $DIR/const-evaluatable-unchecked.rs:6:9
    |
 LL |     [0; std::mem::size_of::<*mut T>()];
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL |     [0; std::mem::size_of::<*mut T>()];
    = note: `#[warn(const_evaluatable_unchecked)]` on by default
 
 warning: cannot use constants which depend on generic parameters in types
-  --> $DIR/const-evaluatable-unchecked.rs:16:21
+  --> $DIR/const-evaluatable-unchecked.rs:17:21
    |
 LL |         let _ = [0; Self::ASSOC];
    |                     ^^^^^^^^^^^
@@ -18,7 +18,7 @@ LL |         let _ = [0; Self::ASSOC];
    = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
 
 warning: cannot use constants which depend on generic parameters in types
-  --> $DIR/const-evaluatable-unchecked.rs:28:21
+  --> $DIR/const-evaluatable-unchecked.rs:29:21
    |
 LL |         let _ = [0; Self::ASSOC];
    |                     ^^^^^^^^^^^
diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
index 168fa0ad0f0..12244450e7f 100644
--- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
+++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
@@ -10,16 +10,6 @@ note: the trait `PartialEq<_>` is implemented for `*const i32`, but that impleme
    |
 LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
    |                                           ^^
-   = help: the following other types implement trait `PartialEq<Rhs>`:
-             f32
-             f64
-             i128
-             i16
-             i32
-             i64
-             i8
-             isize
-           and 6 others
 
 error[E0277]: can't compare `*const i32` with `_` in const contexts
   --> $DIR/const_raw_ptr_ops.rs:6:44
@@ -33,16 +23,6 @@ note: the trait `PartialEq<_>` is implemented for `*const i32`, but that impleme
    |
 LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
    |                                            ^^
-   = help: the following other types implement trait `PartialEq<Rhs>`:
-             f32
-             f64
-             i128
-             i16
-             i32
-             i64
-             i8
-             isize
-           and 6 others
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/issue-25826.stderr b/src/test/ui/consts/issue-25826.stderr
index b80befa26f6..905c5ee6eb4 100644
--- a/src/test/ui/consts/issue-25826.stderr
+++ b/src/test/ui/consts/issue-25826.stderr
@@ -10,10 +10,6 @@ note: the trait `PartialOrd` is implemented for `*const ()`, but that implementa
    |
 LL |     const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
    |                                                    ^
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | fn main() where *const (): ~const PartialOrd {
-   |           ++++++++++++++++++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/issue-94675.stderr b/src/test/ui/consts/issue-94675.stderr
index 7ae293ffbf8..f4683f7f536 100644
--- a/src/test/ui/consts/issue-94675.stderr
+++ b/src/test/ui/consts/issue-94675.stderr
@@ -23,10 +23,6 @@ note: the trait `IndexMut<usize>` is implemented for `Vec<usize>`, but that impl
    |
 LL |         self.bar[0] = baz.len();
    |         ^^^^^^^^^^^
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | impl<'a> Foo<'a> where Vec<usize>: ~const IndexMut<usize> {
-   |                  ++++++++++++++++++++++++++++++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-23338-ensure-param-drop-order.rs b/src/test/ui/drop/issue-23338-ensure-param-drop-order.rs
index a99f260dde3..a99f260dde3 100644
--- a/src/test/ui/issues/issue-23338-ensure-param-drop-order.rs
+++ b/src/test/ui/drop/issue-23338-ensure-param-drop-order.rs
diff --git a/src/test/ui/issues/issue-24805-dropck-itemless.rs b/src/test/ui/dropck/issue-24805-dropck-itemless.rs
index 45761b61c3e..45761b61c3e 100644
--- a/src/test/ui/issues/issue-24805-dropck-itemless.rs
+++ b/src/test/ui/dropck/issue-24805-dropck-itemless.rs
diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr
deleted file mode 100644
index 3f72734efa1..00000000000
--- a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0271]: type mismatch resolving `<Empty<_> as Stream>::Item == Repr`
-  --> $DIR/issue-89008.rs:38:43
-   |
-LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {
-   |                        ----               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Empty<_> as Stream>::Item == Repr`
-   |                        |
-   |                        this type parameter
-   |
-note: expected this to be `()`
-  --> $DIR/issue-89008.rs:17:17
-   |
-LL |     type Item = ();
-   |                 ^^
-   = note:   expected unit type `()`
-           found type parameter `Repr`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-91762.rs b/src/test/ui/generic-associated-types/bugs/issue-91762.rs
index 796935cc06f..dec668bec10 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-91762.rs
+++ b/src/test/ui/generic-associated-types/bugs/issue-91762.rs
@@ -1,7 +1,7 @@
 // check-fail
 // known-bug
 
-// We almost certaintly want this to pass, but
+// We almost certainly want this to pass, but
 // it's particularly difficult currently, because we need a way of specifying
 // that `<Self::Base as Functor>::With<T> = Self` without using that when we have
 // a `U`. See `https://github.com/rust-lang/rust/pull/92728` for a (hacky)
diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.rs b/src/test/ui/generic-associated-types/issue-89008.rs
index 012aa8df2fc..669dbafb5d5 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-89008.rs
+++ b/src/test/ui/generic-associated-types/issue-89008.rs
@@ -1,42 +1,36 @@
-// check-fail
+// check-pass
 // edition:2021
-// known-bug: #88908
-
-// This should pass, but seems to run into a TAIT bug.
 
 #![feature(type_alias_impl_trait)]
 
 use std::future::Future;
+use std::marker::PhantomData;
 
 trait Stream {
     type Item;
 }
 
-struct Empty<T>(T);
-impl<T> Stream for Empty<T> {
-    type Item = ();
+struct Empty<T> {
+    _phantom: PhantomData<T>,
 }
-fn empty<T>() -> Empty<T> {
-    todo!()
+
+impl<T> Stream for Empty<T> {
+    type Item = T;
 }
 
 trait X {
     type LineStream<'a, Repr>: Stream<Item = Repr> where Self: 'a;
-
-    type LineStreamFut<'a,Repr>: Future<Output = Self::LineStream<'a, Repr>> where Self: 'a;
-
-    fn line_stream<'a,Repr>(&'a self) -> Self::LineStreamFut<'a,Repr>;
+    type LineStreamFut<'a, Repr>: Future<Output = Self::LineStream<'a, Repr>> where Self: 'a;
+    fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr>;
 }
 
 struct Y;
 
 impl X for Y {
     type LineStream<'a, Repr> = impl Stream<Item = Repr>;
-
-    type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>> ;
-
+    type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>>;
     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {
-        async {empty()}
+        async { Empty { _phantom: PhantomData } }
     }
 }
 
diff --git a/src/test/ui/impl-trait/hidden-lifetimes.stderr b/src/test/ui/impl-trait/hidden-lifetimes.stderr
index efc228de58b..de06ded7acd 100644
--- a/src/test/ui/impl-trait/hidden-lifetimes.stderr
+++ b/src/test/ui/impl-trait/hidden-lifetimes.stderr
@@ -1,4 +1,4 @@
-error[E0700]: hidden type for `impl Swap` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds
   --> $DIR/hidden-lifetimes.rs:29:5
    |
 LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
@@ -11,7 +11,7 @@ help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'
 LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b {
    |                                                                     ++++
 
-error[E0700]: hidden type for `impl Swap` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds
   --> $DIR/hidden-lifetimes.rs:46:5
    |
 LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
diff --git a/src/test/ui/impl-trait/in-trait/default-body-type-err-2.rs b/src/test/ui/impl-trait/in-trait/default-body-type-err-2.rs
new file mode 100644
index 00000000000..45ae2b8ad3a
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/default-body-type-err-2.rs
@@ -0,0 +1,13 @@
+// edition:2021
+
+#![allow(incomplete_features)]
+#![feature(async_fn_in_trait)]
+
+pub trait Foo {
+    async fn woopsie_async(&self) -> String {
+        42
+        //~^ ERROR mismatched types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/in-trait/default-body-type-err-2.stderr b/src/test/ui/impl-trait/in-trait/default-body-type-err-2.stderr
new file mode 100644
index 00000000000..142b1bff1a4
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/default-body-type-err-2.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/default-body-type-err-2.rs:8:9
+   |
+LL |         42
+   |         ^^- help: try using a conversion method: `.to_string()`
+   |         |
+   |         expected struct `String`, found integer
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/in-trait/default-body-type-err.rs b/src/test/ui/impl-trait/in-trait/default-body-type-err.rs
new file mode 100644
index 00000000000..ac9baf91cae
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/default-body-type-err.rs
@@ -0,0 +1,13 @@
+#![allow(incomplete_features)]
+#![feature(return_position_impl_trait_in_trait)]
+
+use std::ops::Deref;
+
+pub trait Foo {
+    fn lol(&self) -> impl Deref<Target = String> {
+        //~^ type mismatch resolving `<&i32 as Deref>::Target == String`
+        &1i32
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/in-trait/default-body-type-err.stderr b/src/test/ui/impl-trait/in-trait/default-body-type-err.stderr
new file mode 100644
index 00000000000..461247a3e3f
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/default-body-type-err.stderr
@@ -0,0 +1,12 @@
+error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
+  --> $DIR/default-body-type-err.rs:7:22
+   |
+LL |     fn lol(&self) -> impl Deref<Target = String> {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
+LL |
+LL |         &1i32
+   |         ----- return type was inferred to be `&i32` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs
index f0d407cd527..ad3cc7c2524 100644
--- a/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs
+++ b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs
@@ -1,4 +1,4 @@
-// known-bug: #102688
+// check-pass
 // edition:2021
 
 #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
diff --git a/src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr
deleted file mode 100644
index 4529d301f9e..00000000000
--- a/src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0720]: cannot resolve opaque type
-  --> $DIR/default-body-with-rpit.rs:10:28
-   |
-LL |     async fn baz(&self) -> impl Debug {
-   |                            ^^^^^^^^^^ cannot resolve opaque type
-   |
-   = note: these returned values have a concrete "never" type
-   = help: this error will resolve once the item's body returns a concrete type
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/issue-103181-1.rs b/src/test/ui/impl-trait/issue-103181-1.rs
new file mode 100644
index 00000000000..197aedf9d98
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-103181-1.rs
@@ -0,0 +1,85 @@
+// edition:2021
+
+mod hyper {
+    use std::{fmt::Debug, future::Future, marker::PhantomData, pin::Pin, task::Poll};
+
+    pub trait HttpBody {
+        type Error;
+    }
+    impl HttpBody for () {
+        //~^ ERROR not all trait items implemented, missing: `Error`
+        // don't implement `Error` here for the ICE
+    }
+
+    pub struct Server<I, S>(I, S);
+
+    pub fn serve<I, S>(_: S) -> Server<I, S> {
+        todo!()
+    }
+
+    impl<S, B> Future for Server<(), S>
+    where
+        S: MakeServiceRef<(), (), ResBody = B>,
+        B: HttpBody,
+        B::Error: Debug,
+    {
+        type Output = ();
+
+        fn poll(self: Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll<Self::Output> {
+            todo!()
+        }
+    }
+
+    pub trait MakeServiceRef<Target, ReqBody> {
+        type ResBody;
+    }
+
+    impl<T, S> MakeServiceRef<(), ()> for T
+    where
+        T: for<'a> Service<&'a (), Response = S>,
+        S: Service<()>,
+    {
+        type ResBody = ();
+    }
+
+    pub struct MakeServiceFn<F>(pub F);
+    pub struct ServiceFn<F, R>(pub PhantomData<(F, R)>);
+
+    pub trait Service<Request> {
+        type Response;
+    }
+
+    impl<'t, F, Ret, Target, Svc> Service<&'t Target> for MakeServiceFn<F>
+    where
+        F: Fn() -> Ret,
+        Ret: Future<Output = Result<Svc, ()>>,
+    {
+        type Response = Svc;
+    }
+
+    impl<F, ReqBody, Ret, ResBody, E> Service<ReqBody> for ServiceFn<F, ReqBody>
+    where
+        F: Fn() -> Ret,
+        Ret: Future<Output = Result<ResBody, E>>,
+    {
+        type Response = ResBody;
+    }
+}
+
+async fn smarvice() -> Result<(), ()> {
+    Ok(())
+}
+
+fn service_fn<F, R, S>(f: F) -> hyper::ServiceFn<F, R>
+where
+    F: Fn() -> S,
+{
+    hyper::ServiceFn(std::marker::PhantomData)
+}
+
+async fn iceice() {
+    let service = hyper::MakeServiceFn(|| async { Ok::<_, ()>(service_fn(|| smarvice())) });
+    hyper::serve::<(), _>(service).await;
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-103181-1.stderr b/src/test/ui/impl-trait/issue-103181-1.stderr
new file mode 100644
index 00000000000..cd026607d52
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-103181-1.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `Error`
+  --> $DIR/issue-103181-1.rs:9:5
+   |
+LL |         type Error;
+   |         ---------- `Error` from trait
+LL |     }
+LL |     impl HttpBody for () {
+   |     ^^^^^^^^^^^^^^^^^^^^ missing `Error` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/impl-trait/issue-103181-2.rs b/src/test/ui/impl-trait/issue-103181-2.rs
new file mode 100644
index 00000000000..b43ac45075e
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-103181-2.rs
@@ -0,0 +1,29 @@
+// edition:2021
+
+trait SendFuture: Send {
+    type Output;
+}
+
+impl<Fut: Send> SendFuture for Fut {
+    type Output = ();
+}
+
+async fn broken_fut() {
+    ident_error;
+    //~^ ERROR cannot find value `ident_error` in this scope
+}
+
+// triggers normalization of `<Fut as SendFuture>::Output`,
+// which requires `Fut: Send`.
+fn normalize<Fut: SendFuture>(_: Fut, _: Fut::Output) {}
+
+async fn iceice<A, B>()
+// <- async fn is necessary
+where
+    A: Send,
+    B: Send, // <- a second bound
+{
+    normalize(broken_fut(), ());
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-103181-2.stderr b/src/test/ui/impl-trait/issue-103181-2.stderr
new file mode 100644
index 00000000000..5eb2dd9184b
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-103181-2.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `ident_error` in this scope
+  --> $DIR/issue-103181-2.rs:12:5
+   |
+LL |     ident_error;
+   |     ^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/inference/char-as-str-single.fixed b/src/test/ui/inference/char-as-str-single.fixed
index e401492a830..bab1854dc51 100644
--- a/src/test/ui/inference/char-as-str-single.fixed
+++ b/src/test/ui/inference/char-as-str-single.fixed
@@ -8,4 +8,5 @@
 fn main() {
     let _: char = 'a'; //~ ERROR mismatched types
     let _: char = '人'; //~ ERROR mismatched types
+    let _: char = '\''; //~ ERROR mismatched types
 }
diff --git a/src/test/ui/inference/char-as-str-single.rs b/src/test/ui/inference/char-as-str-single.rs
index 4f23cea5354..736920643b2 100644
--- a/src/test/ui/inference/char-as-str-single.rs
+++ b/src/test/ui/inference/char-as-str-single.rs
@@ -8,4 +8,5 @@
 fn main() {
     let _: char = "a"; //~ ERROR mismatched types
     let _: char = "人"; //~ ERROR mismatched types
+    let _: char = "'"; //~ ERROR mismatched types
 }
diff --git a/src/test/ui/inference/char-as-str-single.stderr b/src/test/ui/inference/char-as-str-single.stderr
index 29075c15414..3375ec6ac32 100644
--- a/src/test/ui/inference/char-as-str-single.stderr
+++ b/src/test/ui/inference/char-as-str-single.stderr
@@ -24,6 +24,19 @@ help: if you meant to write a `char` literal, use single quotes
 LL |     let _: char = '人';
    |                   ~~~~
 
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+  --> $DIR/char-as-str-single.rs:11:19
+   |
+LL |     let _: char = "'";
+   |            ----   ^^^ expected `char`, found `&str`
+   |            |
+   |            expected due to this
+   |
+help: if you meant to write a `char` literal, use single quotes
+   |
+LL |     let _: char = '\'';
+   |                   ~~~~
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-36053.rs b/src/test/ui/inference/issue-36053.rs
index 5c6d0780416..5c6d0780416 100644
--- a/src/test/ui/issues/issue-36053.rs
+++ b/src/test/ui/inference/issue-36053.rs
diff --git a/src/test/ui/inference/str-as-char.fixed b/src/test/ui/inference/str-as-char.fixed
index 09f3dec5a17..6aea809cbdb 100644
--- a/src/test/ui/inference/str-as-char.fixed
+++ b/src/test/ui/inference/str-as-char.fixed
@@ -4,5 +4,7 @@
 // run-rustfix
 
 fn main() {
-    let _: &str = "a"; //~ ERROR mismatched types
+    let _: &str = "a";   //~ ERROR mismatched types
+    let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
+    let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
 }
diff --git a/src/test/ui/inference/str-as-char.rs b/src/test/ui/inference/str-as-char.rs
index 7092a612442..eaa8d788c34 100644
--- a/src/test/ui/inference/str-as-char.rs
+++ b/src/test/ui/inference/str-as-char.rs
@@ -4,5 +4,7 @@
 // run-rustfix
 
 fn main() {
-    let _: &str = 'a'; //~ ERROR mismatched types
+    let _: &str = 'a';   //~ ERROR mismatched types
+    let _: &str = '"""'; //~ ERROR character literal may only contain one codepoint
+    let _: &str = '\"\"\"'; //~ ERROR character literal may only contain one codepoint
 }
diff --git a/src/test/ui/inference/str-as-char.stderr b/src/test/ui/inference/str-as-char.stderr
index ebbe7c80f77..2c84dac8e0c 100644
--- a/src/test/ui/inference/str-as-char.stderr
+++ b/src/test/ui/inference/str-as-char.stderr
@@ -1,3 +1,25 @@
+error: character literal may only contain one codepoint
+  --> $DIR/str-as-char.rs:8:19
+   |
+LL |     let _: &str = '"""';
+   |                   ^^^^^
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let _: &str = "\"\"\"";
+   |                   ~~~~~~~~
+
+error: character literal may only contain one codepoint
+  --> $DIR/str-as-char.rs:9:19
+   |
+LL |     let _: &str = '\"\"\"';
+   |                   ^^^^^^^^
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let _: &str = "\"\"\"";
+   |                   ~~~~~~~~
+
 error[E0308]: mismatched types
   --> $DIR/str-as-char.rs:7:19
    |
@@ -11,6 +33,6 @@ help: if you meant to write a `str` literal, use double quotes
 LL |     let _: &str = "a";
    |                   ~~~
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/let-else/let-else-non-diverging.rs b/src/test/ui/let-else/let-else-non-diverging.rs
index 58d2c09776f..a5442dd82f0 100644
--- a/src/test/ui/let-else/let-else-non-diverging.rs
+++ b/src/test/ui/let-else/let-else-non-diverging.rs
@@ -11,7 +11,7 @@ fn main() {
 
     // Ensure that uninhabited types do not "diverge".
     // This might be relaxed in the future, but when it is,
-    // it should be an explicitly wanted descision.
+    // it should be an explicitly wanted decision.
     let Some(x) = Some(1) else { foo::<Uninhabited>() }; //~ ERROR does not diverge
 }
 
diff --git a/src/test/ui/lint/invalid_value.rs b/src/test/ui/lint/invalid_value.rs
index 946a0e38861..57d8cbe7c93 100644
--- a/src/test/ui/lint/invalid_value.rs
+++ b/src/test/ui/lint/invalid_value.rs
@@ -44,6 +44,10 @@ enum TwoUninhabited {
     B(Void),
 }
 
+#[rustc_layout_scalar_valid_range_start(254)]
+#[rustc_layout_scalar_valid_range_end(1)]
+pub(crate) struct WrapAroundRange(u8);
+
 #[allow(unused)]
 fn generic<T: 'static>() {
     unsafe {
@@ -131,6 +135,9 @@ fn main() {
         let _val: *const [()] = mem::zeroed();
         let _val: *const [()] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
 
+        let _val: WrapAroundRange = mem::zeroed();
+        let _val: WrapAroundRange = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
+
         // Things where 0 is okay due to rustc implementation details,
         // but that are not guaranteed to keep working.
         let _val: Result<i32, i32> = mem::zeroed();
diff --git a/src/test/ui/lint/invalid_value.stderr b/src/test/ui/lint/invalid_value.stderr
index 3901692001a..76afb765f0f 100644
--- a/src/test/ui/lint/invalid_value.stderr
+++ b/src/test/ui/lint/invalid_value.stderr
@@ -1,5 +1,5 @@
 error: the type `&T` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:50:32
+  --> $DIR/invalid_value.rs:54:32
    |
 LL |         let _val: &'static T = mem::zeroed();
    |                                ^^^^^^^^^^^^^
@@ -15,7 +15,7 @@ LL | #![deny(invalid_value)]
    |         ^^^^^^^^^^^^^
 
 error: the type `&T` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:51:32
+  --> $DIR/invalid_value.rs:55:32
    |
 LL |         let _val: &'static T = mem::uninitialized();
    |                                ^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL |         let _val: &'static T = mem::uninitialized();
    = note: references must be non-null
 
 error: the type `Wrap<&T>` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:53:38
+  --> $DIR/invalid_value.rs:57:38
    |
 LL |         let _val: Wrap<&'static T> = mem::zeroed();
    |                                      ^^^^^^^^^^^^^
@@ -41,7 +41,7 @@ LL | struct Wrap<T> { wrapped: T }
    |                  ^^^^^^^^^^
 
 error: the type `Wrap<&T>` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:54:38
+  --> $DIR/invalid_value.rs:58:38
    |
 LL |         let _val: Wrap<&'static T> = mem::uninitialized();
    |                                      ^^^^^^^^^^^^^^^^^^^^
@@ -56,7 +56,7 @@ LL | struct Wrap<T> { wrapped: T }
    |                  ^^^^^^^^^^
 
 error: the type `!` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:61:23
+  --> $DIR/invalid_value.rs:65:23
    |
 LL |         let _val: ! = mem::zeroed();
    |                       ^^^^^^^^^^^^^
@@ -67,7 +67,7 @@ LL |         let _val: ! = mem::zeroed();
    = note: the `!` type has no valid value
 
 error: the type `!` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:62:23
+  --> $DIR/invalid_value.rs:66:23
    |
 LL |         let _val: ! = mem::uninitialized();
    |                       ^^^^^^^^^^^^^^^^^^^^
@@ -78,7 +78,7 @@ LL |         let _val: ! = mem::uninitialized();
    = note: the `!` type has no valid value
 
 error: the type `(i32, !)` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:64:30
+  --> $DIR/invalid_value.rs:68:30
    |
 LL |         let _val: (i32, !) = mem::zeroed();
    |                              ^^^^^^^^^^^^^
@@ -89,7 +89,7 @@ LL |         let _val: (i32, !) = mem::zeroed();
    = note: the `!` type has no valid value
 
 error: the type `(i32, !)` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:65:30
+  --> $DIR/invalid_value.rs:69:30
    |
 LL |         let _val: (i32, !) = mem::uninitialized();
    |                              ^^^^^^^^^^^^^^^^^^^^
@@ -100,7 +100,7 @@ LL |         let _val: (i32, !) = mem::uninitialized();
    = note: integers must not be uninitialized
 
 error: the type `Void` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:67:26
+  --> $DIR/invalid_value.rs:71:26
    |
 LL |         let _val: Void = mem::zeroed();
    |                          ^^^^^^^^^^^^^
@@ -115,7 +115,7 @@ LL | enum Void {}
    | ^^^^^^^^^
 
 error: the type `Void` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:68:26
+  --> $DIR/invalid_value.rs:72:26
    |
 LL |         let _val: Void = mem::uninitialized();
    |                          ^^^^^^^^^^^^^^^^^^^^
@@ -130,7 +130,7 @@ LL | enum Void {}
    | ^^^^^^^^^
 
 error: the type `&i32` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:70:34
+  --> $DIR/invalid_value.rs:74:34
    |
 LL |         let _val: &'static i32 = mem::zeroed();
    |                                  ^^^^^^^^^^^^^
@@ -141,7 +141,7 @@ LL |         let _val: &'static i32 = mem::zeroed();
    = note: references must be non-null
 
 error: the type `&i32` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:71:34
+  --> $DIR/invalid_value.rs:75:34
    |
 LL |         let _val: &'static i32 = mem::uninitialized();
    |                                  ^^^^^^^^^^^^^^^^^^^^
@@ -152,7 +152,7 @@ LL |         let _val: &'static i32 = mem::uninitialized();
    = note: references must be non-null
 
 error: the type `Ref` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:73:25
+  --> $DIR/invalid_value.rs:77:25
    |
 LL |         let _val: Ref = mem::zeroed();
    |                         ^^^^^^^^^^^^^
@@ -167,7 +167,7 @@ LL | struct Ref(&'static i32);
    |            ^^^^^^^^^^^^
 
 error: the type `Ref` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:74:25
+  --> $DIR/invalid_value.rs:78:25
    |
 LL |         let _val: Ref = mem::uninitialized();
    |                         ^^^^^^^^^^^^^^^^^^^^
@@ -182,7 +182,7 @@ LL | struct Ref(&'static i32);
    |            ^^^^^^^^^^^^
 
 error: the type `fn()` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:76:26
+  --> $DIR/invalid_value.rs:80:26
    |
 LL |         let _val: fn() = mem::zeroed();
    |                          ^^^^^^^^^^^^^
@@ -193,7 +193,7 @@ LL |         let _val: fn() = mem::zeroed();
    = note: function pointers must be non-null
 
 error: the type `fn()` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:77:26
+  --> $DIR/invalid_value.rs:81:26
    |
 LL |         let _val: fn() = mem::uninitialized();
    |                          ^^^^^^^^^^^^^^^^^^^^
@@ -204,7 +204,7 @@ LL |         let _val: fn() = mem::uninitialized();
    = note: function pointers must be non-null
 
 error: the type `Wrap<fn()>` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:79:32
+  --> $DIR/invalid_value.rs:83:32
    |
 LL |         let _val: Wrap<fn()> = mem::zeroed();
    |                                ^^^^^^^^^^^^^
@@ -219,7 +219,7 @@ LL | struct Wrap<T> { wrapped: T }
    |                  ^^^^^^^^^^
 
 error: the type `Wrap<fn()>` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:80:32
+  --> $DIR/invalid_value.rs:84:32
    |
 LL |         let _val: Wrap<fn()> = mem::uninitialized();
    |                                ^^^^^^^^^^^^^^^^^^^^
@@ -234,7 +234,7 @@ LL | struct Wrap<T> { wrapped: T }
    |                  ^^^^^^^^^^
 
 error: the type `WrapEnum<fn()>` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:82:36
+  --> $DIR/invalid_value.rs:86:36
    |
 LL |         let _val: WrapEnum<fn()> = mem::zeroed();
    |                                    ^^^^^^^^^^^^^
@@ -249,7 +249,7 @@ LL | enum WrapEnum<T> { Wrapped(T) }
    |                            ^
 
 error: the type `WrapEnum<fn()>` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:83:36
+  --> $DIR/invalid_value.rs:87:36
    |
 LL |         let _val: WrapEnum<fn()> = mem::uninitialized();
    |                                    ^^^^^^^^^^^^^^^^^^^^
@@ -264,7 +264,7 @@ LL | enum WrapEnum<T> { Wrapped(T) }
    |                            ^
 
 error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:85:42
+  --> $DIR/invalid_value.rs:89:42
    |
 LL |         let _val: Wrap<(RefPair, i32)> = mem::zeroed();
    |                                          ^^^^^^^^^^^^^
@@ -279,7 +279,7 @@ LL | struct RefPair((&'static i32, i32));
    |                ^^^^^^^^^^^^^^^^^^^
 
 error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:86:42
+  --> $DIR/invalid_value.rs:90:42
    |
 LL |         let _val: Wrap<(RefPair, i32)> = mem::uninitialized();
    |                                          ^^^^^^^^^^^^^^^^^^^^
@@ -294,7 +294,7 @@ LL | struct RefPair((&'static i32, i32));
    |                ^^^^^^^^^^^^^^^^^^^
 
 error: the type `NonNull<i32>` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:88:34
+  --> $DIR/invalid_value.rs:92:34
    |
 LL |         let _val: NonNull<i32> = mem::zeroed();
    |                                  ^^^^^^^^^^^^^
@@ -305,7 +305,7 @@ LL |         let _val: NonNull<i32> = mem::zeroed();
    = note: `std::ptr::NonNull<i32>` must be non-null
 
 error: the type `NonNull<i32>` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:89:34
+  --> $DIR/invalid_value.rs:93:34
    |
 LL |         let _val: NonNull<i32> = mem::uninitialized();
    |                                  ^^^^^^^^^^^^^^^^^^^^
@@ -316,7 +316,7 @@ LL |         let _val: NonNull<i32> = mem::uninitialized();
    = note: `std::ptr::NonNull<i32>` must be non-null
 
 error: the type `(NonZeroU32, i32)` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:91:39
+  --> $DIR/invalid_value.rs:95:39
    |
 LL |         let _val: (NonZeroU32, i32) = mem::zeroed();
    |                                       ^^^^^^^^^^^^^
@@ -327,7 +327,7 @@ LL |         let _val: (NonZeroU32, i32) = mem::zeroed();
    = note: `std::num::NonZeroU32` must be non-null
 
 error: the type `(NonZeroU32, i32)` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:92:39
+  --> $DIR/invalid_value.rs:96:39
    |
 LL |         let _val: (NonZeroU32, i32) = mem::uninitialized();
    |                                       ^^^^^^^^^^^^^^^^^^^^
@@ -338,7 +338,7 @@ LL |         let _val: (NonZeroU32, i32) = mem::uninitialized();
    = note: `std::num::NonZeroU32` must be non-null
 
 error: the type `*const dyn Send` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:94:37
+  --> $DIR/invalid_value.rs:98:37
    |
 LL |         let _val: *const dyn Send = mem::zeroed();
    |                                     ^^^^^^^^^^^^^
@@ -349,7 +349,7 @@ LL |         let _val: *const dyn Send = mem::zeroed();
    = note: the vtable of a wide raw pointer must be non-null
 
 error: the type `*const dyn Send` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:95:37
+  --> $DIR/invalid_value.rs:99:37
    |
 LL |         let _val: *const dyn Send = mem::uninitialized();
    |                                     ^^^^^^^^^^^^^^^^^^^^
@@ -360,7 +360,7 @@ LL |         let _val: *const dyn Send = mem::uninitialized();
    = note: the vtable of a wide raw pointer must be non-null
 
 error: the type `[fn(); 2]` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:97:31
+  --> $DIR/invalid_value.rs:101:31
    |
 LL |         let _val: [fn(); 2] = mem::zeroed();
    |                               ^^^^^^^^^^^^^
@@ -371,7 +371,7 @@ LL |         let _val: [fn(); 2] = mem::zeroed();
    = note: function pointers must be non-null
 
 error: the type `[fn(); 2]` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:98:31
+  --> $DIR/invalid_value.rs:102:31
    |
 LL |         let _val: [fn(); 2] = mem::uninitialized();
    |                               ^^^^^^^^^^^^^^^^^^^^
@@ -382,7 +382,7 @@ LL |         let _val: [fn(); 2] = mem::uninitialized();
    = note: function pointers must be non-null
 
 error: the type `TwoUninhabited` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:100:36
+  --> $DIR/invalid_value.rs:104:36
    |
 LL |         let _val: TwoUninhabited = mem::zeroed();
    |                                    ^^^^^^^^^^^^^
@@ -397,7 +397,7 @@ LL | enum TwoUninhabited {
    | ^^^^^^^^^^^^^^^^^^^
 
 error: the type `TwoUninhabited` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:101:36
+  --> $DIR/invalid_value.rs:105:36
    |
 LL |         let _val: TwoUninhabited = mem::uninitialized();
    |                                    ^^^^^^^^^^^^^^^^^^^^
@@ -412,7 +412,7 @@ LL | enum TwoUninhabited {
    | ^^^^^^^^^^^^^^^^^^^
 
 error: the type `OneFruitNonZero` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:103:37
+  --> $DIR/invalid_value.rs:107:37
    |
 LL |         let _val: OneFruitNonZero = mem::zeroed();
    |                                     ^^^^^^^^^^^^^
@@ -427,7 +427,7 @@ LL |     Banana(NonZeroU32),
    |            ^^^^^^^^^^
 
 error: the type `OneFruitNonZero` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:104:37
+  --> $DIR/invalid_value.rs:108:37
    |
 LL |         let _val: OneFruitNonZero = mem::uninitialized();
    |                                     ^^^^^^^^^^^^^^^^^^^^
@@ -442,7 +442,7 @@ LL |     Banana(NonZeroU32),
    |            ^^^^^^^^^^
 
 error: the type `bool` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:108:26
+  --> $DIR/invalid_value.rs:112:26
    |
 LL |         let _val: bool = mem::uninitialized();
    |                          ^^^^^^^^^^^^^^^^^^^^
@@ -453,7 +453,7 @@ LL |         let _val: bool = mem::uninitialized();
    = note: booleans must be either `true` or `false`
 
 error: the type `Wrap<char>` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:111:32
+  --> $DIR/invalid_value.rs:115:32
    |
 LL |         let _val: Wrap<char> = mem::uninitialized();
    |                                ^^^^^^^^^^^^^^^^^^^^
@@ -468,7 +468,7 @@ LL | struct Wrap<T> { wrapped: T }
    |                  ^^^^^^^^^^
 
 error: the type `NonBig` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:114:28
+  --> $DIR/invalid_value.rs:118:28
    |
 LL |         let _val: NonBig = mem::uninitialized();
    |                            ^^^^^^^^^^^^^^^^^^^^
@@ -479,7 +479,7 @@ LL |         let _val: NonBig = mem::uninitialized();
    = note: `NonBig` must be initialized inside its custom valid range
 
 error: the type `Fruit` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:117:27
+  --> $DIR/invalid_value.rs:121:27
    |
 LL |         let _val: Fruit = mem::uninitialized();
    |                           ^^^^^^^^^^^^^^^^^^^^
@@ -494,7 +494,7 @@ LL | enum Fruit {
    | ^^^^^^^^^^
 
 error: the type `[bool; 2]` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:120:31
+  --> $DIR/invalid_value.rs:124:31
    |
 LL |         let _val: [bool; 2] = mem::uninitialized();
    |                               ^^^^^^^^^^^^^^^^^^^^
@@ -505,7 +505,7 @@ LL |         let _val: [bool; 2] = mem::uninitialized();
    = note: booleans must be either `true` or `false`
 
 error: the type `i32` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:123:25
+  --> $DIR/invalid_value.rs:127:25
    |
 LL |         let _val: i32 = mem::uninitialized();
    |                         ^^^^^^^^^^^^^^^^^^^^
@@ -516,7 +516,7 @@ LL |         let _val: i32 = mem::uninitialized();
    = note: integers must not be uninitialized
 
 error: the type `f32` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:126:25
+  --> $DIR/invalid_value.rs:130:25
    |
 LL |         let _val: f32 = mem::uninitialized();
    |                         ^^^^^^^^^^^^^^^^^^^^
@@ -527,7 +527,7 @@ LL |         let _val: f32 = mem::uninitialized();
    = note: floats must not be uninitialized
 
 error: the type `*const ()` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:129:31
+  --> $DIR/invalid_value.rs:133:31
    |
 LL |         let _val: *const () = mem::uninitialized();
    |                               ^^^^^^^^^^^^^^^^^^^^
@@ -538,7 +538,7 @@ LL |         let _val: *const () = mem::uninitialized();
    = note: raw pointers must not be uninitialized
 
 error: the type `*const [()]` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:132:33
+  --> $DIR/invalid_value.rs:136:33
    |
 LL |         let _val: *const [()] = mem::uninitialized();
    |                                 ^^^^^^^^^^^^^^^^^^^^
@@ -548,8 +548,19 @@ LL |         let _val: *const [()] = mem::uninitialized();
    |
    = note: raw pointers must not be uninitialized
 
+error: the type `WrapAroundRange` does not permit being left uninitialized
+  --> $DIR/invalid_value.rs:139:37
+   |
+LL |         let _val: WrapAroundRange = mem::uninitialized();
+   |                                     ^^^^^^^^^^^^^^^^^^^^
+   |                                     |
+   |                                     this code causes undefined behavior when executed
+   |                                     help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+   |
+   = note: `WrapAroundRange` must be initialized inside its custom valid range
+
 error: the type `Result<i32, i32>` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:137:38
+  --> $DIR/invalid_value.rs:144:38
    |
 LL |         let _val: Result<i32, i32> = mem::uninitialized();
    |                                      ^^^^^^^^^^^^^^^^^^^^
@@ -564,7 +575,7 @@ LL | pub enum Result<T, E> {
    | ^^^^^^^^^^^^^^^^^^^^^
 
 error: the type `&i32` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:145:34
+  --> $DIR/invalid_value.rs:152:34
    |
 LL |         let _val: &'static i32 = mem::transmute(0usize);
    |                                  ^^^^^^^^^^^^^^^^^^^^^^
@@ -575,7 +586,7 @@ LL |         let _val: &'static i32 = mem::transmute(0usize);
    = note: references must be non-null
 
 error: the type `&[i32]` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:146:36
+  --> $DIR/invalid_value.rs:153:36
    |
 LL |         let _val: &'static [i32] = mem::transmute((0usize, 0usize));
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -586,7 +597,7 @@ LL |         let _val: &'static [i32] = mem::transmute((0usize, 0usize));
    = note: references must be non-null
 
 error: the type `NonZeroU32` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:147:32
+  --> $DIR/invalid_value.rs:154:32
    |
 LL |         let _val: NonZeroU32 = mem::transmute(0);
    |                                ^^^^^^^^^^^^^^^^^
@@ -597,7 +608,7 @@ LL |         let _val: NonZeroU32 = mem::transmute(0);
    = note: `std::num::NonZeroU32` must be non-null
 
 error: the type `NonNull<i32>` does not permit zero-initialization
-  --> $DIR/invalid_value.rs:150:34
+  --> $DIR/invalid_value.rs:157:34
    |
 LL |         let _val: NonNull<i32> = MaybeUninit::zeroed().assume_init();
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -608,7 +619,7 @@ LL |         let _val: NonNull<i32> = MaybeUninit::zeroed().assume_init();
    = note: `std::ptr::NonNull<i32>` must be non-null
 
 error: the type `NonNull<i32>` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:151:34
+  --> $DIR/invalid_value.rs:158:34
    |
 LL |         let _val: NonNull<i32> = MaybeUninit::uninit().assume_init();
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -619,7 +630,7 @@ LL |         let _val: NonNull<i32> = MaybeUninit::uninit().assume_init();
    = note: `std::ptr::NonNull<i32>` must be non-null
 
 error: the type `bool` does not permit being left uninitialized
-  --> $DIR/invalid_value.rs:152:26
+  --> $DIR/invalid_value.rs:159:26
    |
 LL |         let _val: bool = MaybeUninit::uninit().assume_init();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -629,5 +640,5 @@ LL |         let _val: bool = MaybeUninit::uninit().assume_init();
    |
    = note: booleans must be either `true` or `false`
 
-error: aborting due to 50 previous errors
+error: aborting due to 51 previous errors
 
diff --git a/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr b/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
index 3f366bedbf3..2cc4d382d9d 100644
--- a/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
+++ b/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
@@ -37,3 +37,45 @@ LL | impl Foo for dyn Send + Sync + Send {}
 
 error: aborting due to 3 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:5:1
+   |
+LL | impl Foo for dyn Send {}
+   | --------------------- first implementation here
+LL |
+LL | impl Foo for dyn Send + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+   |
+   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+   = note: `#[deny(order_dependent_trait_objects)]` on by default
+
+Future breakage diagnostic:
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:11:1
+   |
+LL | impl Foo for dyn Send + Sync {}
+   | ---------------------------- first implementation here
+LL |
+LL | impl Foo for dyn Sync + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+   = note: `#[deny(order_dependent_trait_objects)]` on by default
+
+Future breakage diagnostic:
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:15:1
+   |
+LL | impl Foo for dyn Sync + Send {}
+   | ---------------------------- first implementation here
+...
+LL | impl Foo for dyn Send + Sync + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+   = note: `#[deny(order_dependent_trait_objects)]` on by default
+
diff --git a/src/test/ui/parser/issues/issue-93282.rs b/src/test/ui/parser/issues/issue-93282.rs
index 261fcb5f918..274245f1a46 100644
--- a/src/test/ui/parser/issues/issue-93282.rs
+++ b/src/test/ui/parser/issues/issue-93282.rs
@@ -12,4 +12,5 @@ fn foo() {
     let x = 1;
     bar('y, x);
     //~^ ERROR expected
+    //~| ERROR mismatched types
 }
diff --git a/src/test/ui/parser/issues/issue-93282.stderr b/src/test/ui/parser/issues/issue-93282.stderr
index ee554784b3a..c6140bb821e 100644
--- a/src/test/ui/parser/issues/issue-93282.stderr
+++ b/src/test/ui/parser/issues/issue-93282.stderr
@@ -3,6 +3,11 @@ error: expected `while`, `for`, `loop` or `{` after a label
    |
 LL |     f<'a,>
    |         ^ expected `while`, `for`, `loop` or `{` after a label
+   |
+help: add `'` to close the char literal
+   |
+LL |     f<'a',>
+   |         +
 
 error: expected one of `.`, `:`, `;`, `?`, `for`, `loop`, `while`, `}`, or an operator, found `,`
   --> $DIR/issue-93282.rs:2:9
@@ -20,6 +25,26 @@ error: expected `while`, `for`, `loop` or `{` after a label
    |
 LL |     bar('y, x);
    |           ^ expected `while`, `for`, `loop` or `{` after a label
+   |
+help: add `'` to close the char literal
+   |
+LL |     bar('y', x);
+   |           +
+
+error[E0308]: mismatched types
+  --> $DIR/issue-93282.rs:13:9
+   |
+LL |     bar('y, x);
+   |     --- ^^ expected `usize`, found `char`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/issue-93282.rs:7:4
+   |
+LL | fn bar(a: usize, b: usize) -> usize {
+   |    ^^^ --------
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/label-is-actually-char.rs b/src/test/ui/parser/label-is-actually-char.rs
new file mode 100644
index 00000000000..183da603da4
--- /dev/null
+++ b/src/test/ui/parser/label-is-actually-char.rs
@@ -0,0 +1,16 @@
+fn main() {
+    let c = 'a;
+    //~^ ERROR expected `while`, `for`, `loop` or `{` after a label
+    //~| HELP add `'` to close the char literal
+    match c {
+        'a'..='b => {}
+        //~^ ERROR unexpected token: `'b`
+        //~| HELP add `'` to close the char literal
+        _ => {}
+    }
+    let x = ['a, 'b];
+    //~^ ERROR expected `while`, `for`, `loop` or `{` after a label
+    //~| ERROR expected `while`, `for`, `loop` or `{` after a label
+    //~| HELP add `'` to close the char literal
+    //~| HELP add `'` to close the char literal
+}
diff --git a/src/test/ui/parser/label-is-actually-char.stderr b/src/test/ui/parser/label-is-actually-char.stderr
new file mode 100644
index 00000000000..28c8d2ada3a
--- /dev/null
+++ b/src/test/ui/parser/label-is-actually-char.stderr
@@ -0,0 +1,46 @@
+error: expected `while`, `for`, `loop` or `{` after a label
+  --> $DIR/label-is-actually-char.rs:2:15
+   |
+LL |     let c = 'a;
+   |               ^ expected `while`, `for`, `loop` or `{` after a label
+   |
+help: add `'` to close the char literal
+   |
+LL |     let c = 'a';
+   |               +
+
+error: unexpected token: `'b`
+  --> $DIR/label-is-actually-char.rs:6:15
+   |
+LL |         'a'..='b => {}
+   |               ^^
+   |
+help: add `'` to close the char literal
+   |
+LL |         'a'..='b' => {}
+   |                 +
+
+error: expected `while`, `for`, `loop` or `{` after a label
+  --> $DIR/label-is-actually-char.rs:11:16
+   |
+LL |     let x = ['a, 'b];
+   |                ^ expected `while`, `for`, `loop` or `{` after a label
+   |
+help: add `'` to close the char literal
+   |
+LL |     let x = ['a', 'b];
+   |                +
+
+error: expected `while`, `for`, `loop` or `{` after a label
+  --> $DIR/label-is-actually-char.rs:11:20
+   |
+LL |     let x = ['a, 'b];
+   |                    ^ expected `while`, `for`, `loop` or `{` after a label
+   |
+help: add `'` to close the char literal
+   |
+LL |     let x = ['a, 'b'];
+   |                    +
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/parser/numeric-lifetime.stderr b/src/test/ui/parser/numeric-lifetime.stderr
index 73a828952b2..7c1bcb72631 100644
--- a/src/test/ui/parser/numeric-lifetime.stderr
+++ b/src/test/ui/parser/numeric-lifetime.stderr
@@ -1,3 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-lifetime.rs:6:20
+   |
+LL |     let x: usize = "";
+   |            -----   ^^ expected `usize`, found `&str`
+   |            |
+   |            expected due to this
+
 error: lifetimes cannot start with a number
   --> $DIR/numeric-lifetime.rs:1:10
    |
@@ -10,14 +18,6 @@ error: lifetimes cannot start with a number
 LL | struct S<'1> { s: &'1 usize }
    |                    ^^
 
-error[E0308]: mismatched types
-  --> $DIR/numeric-lifetime.rs:6:20
-   |
-LL |     let x: usize = "";
-   |            -----   ^^ expected `usize`, found `&str`
-   |            |
-   |            expected due to this
-
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs
index f29fd7a5472..5b90e905a64 100644
--- a/src/test/ui/parser/require-parens-for-chained-comparison.rs
+++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs
@@ -23,11 +23,13 @@ fn main() {
     //~^ ERROR expected one of
     //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
     //~| ERROR expected
+    //~| HELP add `'` to close the char literal
 
     f<'_>();
     //~^ comparison operators cannot be chained
     //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
     //~| ERROR expected
+    //~| HELP add `'` to close the char literal
 
     let _ = f<u8>;
     //~^ ERROR comparison operators cannot be chained
diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr
index 0bf52854ec2..52e201c435c 100644
--- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr
+++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr
@@ -58,6 +58,11 @@ error: expected `while`, `for`, `loop` or `{` after a label
    |
 LL |     let _ = f<'_, i8>();
    |                 ^ expected `while`, `for`, `loop` or `{` after a label
+   |
+help: add `'` to close the char literal
+   |
+LL |     let _ = f<'_', i8>();
+   |                 +
 
 error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`, or an operator, found `,`
   --> $DIR/require-parens-for-chained-comparison.rs:22:17
@@ -71,13 +76,18 @@ LL |     let _ = f::<'_, i8>();
    |              ++
 
 error: expected `while`, `for`, `loop` or `{` after a label
-  --> $DIR/require-parens-for-chained-comparison.rs:27:9
+  --> $DIR/require-parens-for-chained-comparison.rs:28:9
    |
 LL |     f<'_>();
    |         ^ expected `while`, `for`, `loop` or `{` after a label
+   |
+help: add `'` to close the char literal
+   |
+LL |     f<'_'>();
+   |         +
 
 error: comparison operators cannot be chained
-  --> $DIR/require-parens-for-chained-comparison.rs:27:6
+  --> $DIR/require-parens-for-chained-comparison.rs:28:6
    |
 LL |     f<'_>();
    |      ^  ^
@@ -88,7 +98,7 @@ LL |     f::<'_>();
    |      ++
 
 error: comparison operators cannot be chained
-  --> $DIR/require-parens-for-chained-comparison.rs:32:14
+  --> $DIR/require-parens-for-chained-comparison.rs:34:14
    |
 LL |     let _ = f<u8>;
    |              ^  ^
diff --git a/src/test/ui/parser/semi-after-closure-in-macro.rs b/src/test/ui/parser/semi-after-closure-in-macro.rs
new file mode 100644
index 00000000000..14efb6100b0
--- /dev/null
+++ b/src/test/ui/parser/semi-after-closure-in-macro.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+// Checks that the fix in #103222 doesn't also disqualify semicolons after
+// closures within parentheses *in macros*, where they're totally allowed.
+
+macro_rules! m {
+    (($expr:expr ; )) => {
+        $expr
+    };
+}
+
+fn main() {
+    let x = m!(( ||() ; ));
+}
diff --git a/src/test/ui/privacy/access_levels.rs b/src/test/ui/privacy/access_levels.rs
index cc074a4f958..42c9975bedb 100644
--- a/src/test/ui/privacy/access_levels.rs
+++ b/src/test/ui/privacy/access_levels.rs
@@ -70,5 +70,6 @@ mod half_public_import {
 
 #[rustc_effective_visibility]
 pub use half_public_import::HalfPublicImport; //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+                                              //~^ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
 
 fn main() {}
diff --git a/src/test/ui/privacy/access_levels.stderr b/src/test/ui/privacy/access_levels.stderr
index 19199a3eb87..111e02bc329 100644
--- a/src/test/ui/privacy/access_levels.stderr
+++ b/src/test/ui/privacy/access_levels.stderr
@@ -112,6 +112,12 @@ error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
 LL | pub use half_public_import::HalfPublicImport;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+  --> $DIR/access_levels.rs:72:9
+   |
+LL | pub use half_public_import::HalfPublicImport;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
   --> $DIR/access_levels.rs:14:13
    |
@@ -124,5 +130,5 @@ error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait
 LL |             type B;
    |             ^^^^^^
 
-error: aborting due to 21 previous errors
+error: aborting due to 22 previous errors
 
diff --git a/src/test/ui/issues/issue-64620.rs b/src/test/ui/return/issue-64620.rs
index a62e5bf8d3c..a62e5bf8d3c 100644
--- a/src/test/ui/issues/issue-64620.rs
+++ b/src/test/ui/return/issue-64620.rs
diff --git a/src/test/ui/issues/issue-64620.stderr b/src/test/ui/return/issue-64620.stderr
index f40ac4de32d..f40ac4de32d 100644
--- a/src/test/ui/issues/issue-64620.stderr
+++ b/src/test/ui/return/issue-64620.stderr
diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr
index ce2425010ad..89177b0f1ac 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr
@@ -15,10 +15,6 @@ note: required by a bound in `Foo::Bar`
    |
 LL |     type Bar: ~const std::ops::Add;
    |               ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar`
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | impl const Foo for NonConstAdd where NonConstAdd: ~const Add {
-   |                                +++++++++++++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
index d9ad8043153..7350909ba8e 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
@@ -9,10 +9,6 @@ note: the trait `Plus` is implemented for `u32`, but that implementation is not
    |
 LL |     a.plus(b)
    |       ^^^^
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | pub const fn add_u32(a: u32, b: u32) -> u32 where u32: ~const Plus {
-   |                                             ++++++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
index 83d395dda19..31e6dbdab22 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
@@ -9,7 +9,6 @@ note: the trait `PartialEq<_>` is implemented for `T`, but that implementation i
    |
 LL |     *t == *t
    |        ^^
-   = help: the trait `PartialEq<&B>` is implemented for `&A`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
index fddc8d37f2f..c64930db9be 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
@@ -11,10 +11,6 @@ note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that imp
    |
 LL |     NonConstImpl.a();
    |     ^^^^^^^^^^^^
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | const fn test() where NonConstImpl: ~const ConstDefaultFn {
-   |                 +++++++++++++++++++++++++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
index ddf0e2d91c0..796c0d388ea 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
@@ -45,34 +45,55 @@ note: required by a bound in `check`
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^^^^^^^^^^ required by this bound in `check`
 
-error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Destruct` is not satisfied
+error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
+  --> $DIR/const-drop-fail.rs:48:47
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ----------------------------------------- ^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+  --> $DIR/const-drop-fail.rs:48:47
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |                                               ^^^^^^^^^^^
+note: required by a bound in `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:35
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
+  --> $DIR/const-drop-fail.rs:48:5
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
+   |
+note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
   --> $DIR/const-drop-fail.rs:48:5
    |
-LL |         const _: () = check($exp);
-   |                       ----- required by a bound introduced by this call
-...
 LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:35
    |
-note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
-  --> $DIR/const-drop-fail.rs:29:25
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
+  --> $DIR/const-drop-fail.rs:55:9
    |
-LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
-   |                         ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: 1 redundant requirement hidden
-   = note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
-note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:35:19
+LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
+   |         ^^^^^^^^
    |
-LL | const fn check<T: ~const Destruct>(_: T) {}
-   |                   ^^^^^^^^^^^^^^^ required by this bound in `check`
-help: consider borrowing here
+note: the implementor must specify the same requirement
+  --> $DIR/const-drop-fail.rs:53:1
    |
-LL |     &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
-   |     +
-LL |     &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
-   |     ++++
+LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0367.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
index 565e2c77ac5..d36c7f81ced 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
@@ -24,7 +24,7 @@ trait A { fn a() { } }
 
 impl A for NonTrivialDrop {}
 
-struct ConstDropImplWithBounds<T: A>(PhantomData<T>);
+struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
 
 impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
     fn drop(&mut self) {
@@ -47,6 +47,16 @@ check_all! {
     //~^ ERROR can't drop
     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
     //~^ ERROR the trait bound
+    //~| ERROR the trait bound
+}
+
+struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
+
+impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
+//~^ ERROR `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
+    fn drop(&mut self) {
+        T::a();
+    }
 }
 
 fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
index ddf0e2d91c0..796c0d388ea 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
@@ -45,34 +45,55 @@ note: required by a bound in `check`
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^^^^^^^^^^ required by this bound in `check`
 
-error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Destruct` is not satisfied
+error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
+  --> $DIR/const-drop-fail.rs:48:47
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ----------------------------------------- ^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+  --> $DIR/const-drop-fail.rs:48:47
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |                                               ^^^^^^^^^^^
+note: required by a bound in `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:35
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
+  --> $DIR/const-drop-fail.rs:48:5
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
+   |
+note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
   --> $DIR/const-drop-fail.rs:48:5
    |
-LL |         const _: () = check($exp);
-   |                       ----- required by a bound introduced by this call
-...
 LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:35
    |
-note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
-  --> $DIR/const-drop-fail.rs:29:25
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
+  --> $DIR/const-drop-fail.rs:55:9
    |
-LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
-   |                         ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: 1 redundant requirement hidden
-   = note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
-note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:35:19
+LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
+   |         ^^^^^^^^
    |
-LL | const fn check<T: ~const Destruct>(_: T) {}
-   |                   ^^^^^^^^^^^^^^^ required by this bound in `check`
-help: consider borrowing here
+note: the implementor must specify the same requirement
+  --> $DIR/const-drop-fail.rs:53:1
    |
-LL |     &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
-   |     +
-LL |     &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
-   |     ++++
+LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0367.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
index 8b4c4065815..b0fc3adf984 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
@@ -60,7 +60,7 @@ mod t {
         fn foo() {}
     }
 
-    pub struct ConstDropWithBound<T: SomeTrait>(pub core::marker::PhantomData<T>);
+    pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>);
 
     impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> {
         fn drop(&mut self) {
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
index d4fa44b4bfc..925ae53e324 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
@@ -11,10 +11,6 @@ note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst
    |
 LL |     NonConst.func();
    |     ^^^^^^^^
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | const fn const_context() where cross_crate::NonConst: ~const cross_crate::MyTrait {
-   |                          ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
index 71ecd9b0694..11db0c2b8f2 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
@@ -11,10 +11,6 @@ note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst
    |
 LL |     NonConst.func();
    |     ^^^^^^^^
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | const fn const_context() where cross_crate::NonConst: ~const cross_crate::MyTrait {
-   |                          ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
index d102956cd2e..a244ab10cab 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
@@ -14,10 +14,6 @@ note: required by a bound in `foo`
    |
 LL | const fn foo<T>() where T: ~const Tr {}
    |                            ^^^^^^^^^ required by this bound in `foo`
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | pub trait Foo where (): ~const Tr {
-   |               +++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
index 85285ba8497..c2c16921c2e 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
@@ -11,10 +11,6 @@ note: the trait `Tr` is implemented for `()`, but that implementation is not `co
    |
 LL |         ().a()
    |         ^^
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | pub trait Tr where (): ~const Tr {
-   |              +++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr
index 9787792ab13..1f8f312df01 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr
@@ -14,10 +14,6 @@ note: required by a bound in `Bar`
    |
 LL | trait Bar: ~const Foo {}
    |            ^^^^^^^^^^ required by this bound in `Bar`
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | impl const Bar for S where S: ~const Foo {}
-   |                      +++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs
new file mode 100644
index 00000000000..285cef571f3
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs
@@ -0,0 +1,17 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Foo {
+    fn foo(&self) {}
+}
+
+struct Bar<T>(T);
+
+impl<T: ~const Foo> Bar<T> {
+    const fn foo(&self) {
+        self.0.foo()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-2718-a.rs b/src/test/ui/structs-enums/issue-2718-a.rs
index 6c491584540..6c491584540 100644
--- a/src/test/ui/issues/issue-2718-a.rs
+++ b/src/test/ui/structs-enums/issue-2718-a.rs
diff --git a/src/test/ui/issues/issue-2718-a.stderr b/src/test/ui/structs-enums/issue-2718-a.stderr
index 7ea620f386a..7ea620f386a 100644
--- a/src/test/ui/issues/issue-2718-a.stderr
+++ b/src/test/ui/structs-enums/issue-2718-a.stderr
diff --git a/src/test/ui/suggestions/issue-103112.rs b/src/test/ui/suggestions/issue-103112.rs
new file mode 100644
index 00000000000..111ae7c7308
--- /dev/null
+++ b/src/test/ui/suggestions/issue-103112.rs
@@ -0,0 +1,4 @@
+fn main() {
+    std::process::abort!();
+    //~^ ERROR: failed to resolve
+}
diff --git a/src/test/ui/suggestions/issue-103112.stderr b/src/test/ui/suggestions/issue-103112.stderr
new file mode 100644
index 00000000000..4ca7fdf9b5a
--- /dev/null
+++ b/src/test/ui/suggestions/issue-103112.stderr
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve: could not find `abort` in `process`
+  --> $DIR/issue-103112.rs:2:19
+   |
+LL |     std::process::abort!();
+   |                   ^^^^^ could not find `abort` in `process`
+   |
+help: std::process::abort is not a macro, but a function, try to remove `!`
+   |
+LL -     std::process::abort!();
+LL +     std::process::abort();
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/suggestions/suggest-let-for-assignment.fixed b/src/test/ui/suggestions/suggest-let-for-assignment.fixed
new file mode 100644
index 00000000000..3a25e25eede
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-let-for-assignment.fixed
@@ -0,0 +1,17 @@
+// run-rustfix
+
+fn main() {
+    let demo = 1; //~ ERROR cannot find value `demo` in this scope
+    dbg!(demo); //~ ERROR cannot find value `demo` in this scope
+
+    let x = "x"; //~ ERROR cannot find value `x` in this scope
+    println!("x: {}", x); //~ ERROR cannot find value `x` in this scope
+
+    if x == "x" {
+        //~^ ERROR cannot find value `x` in this scope
+        println!("x is 1");
+    }
+
+    let y = 1 + 2; //~ ERROR cannot find value `y` in this scope
+    println!("y: {}", y); //~ ERROR cannot find value `y` in this scope
+}
diff --git a/src/test/ui/suggestions/suggest-let-for-assignment.rs b/src/test/ui/suggestions/suggest-let-for-assignment.rs
new file mode 100644
index 00000000000..67705fe063a
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-let-for-assignment.rs
@@ -0,0 +1,17 @@
+// run-rustfix
+
+fn main() {
+    demo = 1; //~ ERROR cannot find value `demo` in this scope
+    dbg!(demo); //~ ERROR cannot find value `demo` in this scope
+
+    x = "x"; //~ ERROR cannot find value `x` in this scope
+    println!("x: {}", x); //~ ERROR cannot find value `x` in this scope
+
+    if x == "x" {
+        //~^ ERROR cannot find value `x` in this scope
+        println!("x is 1");
+    }
+
+    y = 1 + 2; //~ ERROR cannot find value `y` in this scope
+    println!("y: {}", y); //~ ERROR cannot find value `y` in this scope
+}
diff --git a/src/test/ui/suggestions/suggest-let-for-assignment.stderr b/src/test/ui/suggestions/suggest-let-for-assignment.stderr
new file mode 100644
index 00000000000..3f6a3da4be2
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-let-for-assignment.stderr
@@ -0,0 +1,60 @@
+error[E0425]: cannot find value `demo` in this scope
+  --> $DIR/suggest-let-for-assignment.rs:4:5
+   |
+LL |     demo = 1;
+   |     ^^^^
+   |
+help: you might have meant to introduce a new binding
+   |
+LL |     let demo = 1;
+   |     +++
+
+error[E0425]: cannot find value `demo` in this scope
+  --> $DIR/suggest-let-for-assignment.rs:5:10
+   |
+LL |     dbg!(demo);
+   |          ^^^^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/suggest-let-for-assignment.rs:7:5
+   |
+LL |     x = "x";
+   |     ^
+   |
+help: you might have meant to introduce a new binding
+   |
+LL |     let x = "x";
+   |     +++
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/suggest-let-for-assignment.rs:8:23
+   |
+LL |     println!("x: {}", x);
+   |                       ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/suggest-let-for-assignment.rs:10:8
+   |
+LL |     if x == "x" {
+   |        ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/suggest-let-for-assignment.rs:15:5
+   |
+LL |     y = 1 + 2;
+   |     ^
+   |
+help: you might have meant to introduce a new binding
+   |
+LL |     let y = 1 + 2;
+   |     +++
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/suggest-let-for-assignment.rs:16:23
+   |
+LL |     println!("y: {}", y);
+   |                       ^ not found in this scope
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/traits/issue-33140-hack-boundaries.stderr b/src/test/ui/traits/issue-33140-hack-boundaries.stderr
index 62cfca545b2..58286648d4f 100644
--- a/src/test/ui/traits/issue-33140-hack-boundaries.stderr
+++ b/src/test/ui/traits/issue-33140-hack-boundaries.stderr
@@ -66,3 +66,20 @@ error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0119, E0751.
 For more information about an error, try `rustc --explain E0119`.
+Future incompatibility report: Future breakage diagnostic:
+warning: conflicting implementations of trait `Trait0` for type `(dyn std::marker::Send + 'static)`: (E0119)
+  --> $DIR/issue-33140-hack-boundaries.rs:10:1
+   |
+LL | impl Trait0 for dyn Send {}
+   | ------------------------ first implementation here
+LL | impl Trait0 for dyn Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+   |
+   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+note: the lint level is defined here
+  --> $DIR/issue-33140-hack-boundaries.rs:2:10
+   |
+LL | #![allow(order_dependent_trait_objects)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr b/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr
index 4ab777bd4df..0af4df2aecb 100644
--- a/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr
+++ b/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr
@@ -40,3 +40,56 @@ LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { }
 
 warning: 3 warnings emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/issue-33140-traitobject-crate.rs:86:1
+   |
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Sync { }
+   | ------------------------------------------------------ first implementation here
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+note: the lint level is defined here
+  --> $DIR/issue-33140-traitobject-crate.rs:3:9
+   |
+LL | #![warn(order_dependent_trait_objects)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/issue-33140-traitobject-crate.rs:89:1
+   |
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { }
+   | ------------------------------------------------------------- first implementation here
+...
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+note: the lint level is defined here
+  --> $DIR/issue-33140-traitobject-crate.rs:3:9
+   |
+LL | #![warn(order_dependent_trait_objects)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/issue-33140-traitobject-crate.rs:93:1
+   |
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { }
+   | ------------------------------------------------------ first implementation here
+...
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+note: the lint level is defined here
+  --> $DIR/issue-33140-traitobject-crate.rs:3:9
+   |
+LL | #![warn(order_dependent_trait_objects)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.rs b/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs
index 6986ad62172..6986ad62172 100644
--- a/src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.rs
+++ b/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs
diff --git a/src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.stderr b/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr
index e9670ad7def..9564813512c 100644
--- a/src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.stderr
+++ b/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/multiple-occurence-ambiguousity.rs:21:26
+  --> $DIR/multiple-occurrence-ambiguousity.rs:21:26
    |
 LL |     let t: &dyn Bar<_> = s;
    |            -----------   ^ expected trait `Bar`, found trait `Foo`
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 3ff044334f0567ce1481c78603aeee7211b9162
+Subproject 071eeaf210708219a5a1b2c4728ca2f97df7f2a
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index a15daec7c3c..3b5a9ba8356 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -657,21 +657,18 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
     let mut output = None;
     let lang_items = cx.tcx.lang_items();
 
-    for pred in cx
+    for (pred, _) in cx
         .tcx
         .bound_explicit_item_bounds(ty.item_def_id)
-        .transpose_iter()
-        .map(|x| x.map_bound(|(p, _)| p))
+        .subst_iter_copied(cx.tcx, ty.substs)
     {
-        match pred.0.kind().skip_binder() {
+        match pred.kind().skip_binder() {
             PredicateKind::Trait(p)
                 if (lang_items.fn_trait() == Some(p.def_id())
                     || lang_items.fn_mut_trait() == Some(p.def_id())
                     || lang_items.fn_once_trait() == Some(p.def_id())) =>
             {
-                let i = pred
-                    .map_bound(|pred| pred.kind().rebind(p.trait_ref.substs.type_at(1)))
-                    .subst(cx.tcx, ty.substs);
+                let i = pred.kind().rebind(p.trait_ref.substs.type_at(1));
 
                 if inputs.map_or(false, |inputs| inputs != i) {
                     // Multiple different fn trait impls. Is this even allowed?
@@ -684,10 +681,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
                     // Multiple different fn trait impls. Is this even allowed?
                     return None;
                 }
-                output = Some(
-                    pred.map_bound(|pred| pred.kind().rebind(p.term.ty().unwrap()))
-                        .subst(cx.tcx, ty.substs),
-                );
+                output = pred.kind().rebind(p.term.ty()).transpose();
             },
             _ => (),
         }
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 417b429161f..a8cf6623f35 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -397,6 +397,8 @@ pub fn run_tests(config: Config) {
         make_tests(c, &mut tests);
     }
 
+    tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice()));
+
     let res = test::run_tests_console(&opts, tests);
     match res {
         Ok(true) => {}
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index b9e0d48c9bc..8a0239eceff 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -259,7 +259,9 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
     "ahash",
     "anyhow",
     "ar",
+    "arrayvec",
     "autocfg",
+    "bumpalo",
     "bitflags",
     "byteorder",
     "cfg-if",
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 3815259c9aa..c600f99c2c4 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -8,7 +8,7 @@ use std::path::Path;
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
 const ROOT_ENTRY_LIMIT: usize = 948;
-const ISSUES_ENTRY_LIMIT: usize = 2126;
+const ISSUES_ENTRY_LIMIT: usize = 2117;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     let dirs = walkdir::WalkDir::new(&path.join("test/ui"))